feat: add Perplexity models, connectors, and Computer mode - #11
Conversation
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 9 minutes and 39 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
📝 WalkthroughWalkthroughThis PR extends the Perplexity Web API MCP server with support for a new Computer search mode (ASI agentic), including a new Changes
Sequence DiagramsequenceDiagram
participant Client as MCP Client
participant Server as PerplexityServer
participant Validator as Validation Logic
participant APIClient as Perplexity API Client
participant API as Perplexity API
Client->>Server: Call perplexity_computer(request)
Server->>Validator: validate_request(query, sources, api_key)
alt Connector source requires auth
Validator->>APIClient: Check if sources contain non-public connector
APIClient->>APIClient: is_public() check
APIClient-->>Validator: ConnectorRequiresAuth error
Validator-->>Server: Return Error
Server-->>Client: CallToolResult with error
else Auth valid or no connectors
Server->>APIClient: Build SearchMode::Computer request
APIClient->>APIClient: Map Computer → API_MODE_COPILOT
APIClient->>APIClient: Apply computer_model preference
APIClient->>APIClient: Set query_source = "computer"
APIClient->>API: POST to Perplexity with Computer mode
API-->>APIClient: Search results
APIClient-->>Server: Result object
Server->>Server: Serialize to JSON tool result
Server-->>Client: CallToolResult with response
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
crates/perplexity-web-api-mcp/src/server.rs (1)
134-150:⚠️ Potential issue | 🟡 MinorDoc for
new()is stale andperplexity_computeris silently exposed in tokenless mode.Two related concerns here:
- The doc comment still claims only
perplexity_researchandperplexity_reasonrequire authenticated session cookies. With this PR,perplexity_computeralso requires auth (ASI/connector backends) and should be listed alongside them, or — better — the doc should match the actual runtime behavior.- The
perplexity_computerhandler added below has no tokenless guard. In tokenless mode the tool is still registered and advertised; invocations will only fail later in the client withServer/ConnectorRequiresAuth. Consider mirroring the pattern used for file attachments: short-circuit with anMcpError::invalid_params(...)explaining the required tokens, so clients get an actionable error before paying for a round-trip.As per coding guidelines: "Update documentation and examples when API behavior changes".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/perplexity-web-api-mcp/src/server.rs` around lines 134 - 150, Update the stale doc comment on PerplexityServer::new to reflect that perplexity_computer also requires authenticated session cookies (or reword to match actual runtime behavior), and add a tokenless guard to the perplexity_computer handler so it is not silently exposed: mirror the existing pattern used for file attachments by checking the PerplexityServer.tokenless flag in the perplexity_computer request handler and short-circuit with McpError::invalid_params(...) providing a clear message that ASI/connector auth is required — this ensures the tool is not advertised/usable in tokenless mode and clients receive an actionable error before a round-trip to the client/connector.crates/perplexity-web-api/src/types.rs (2)
161-194:⚠️ Potential issue | 🟠 Major
Source::FromStrbecame infallible — typos silently become "connector" sources.The fallthrough now maps every unknown string to
Source::Custom(other.to_owned()). Combined withSource::is_public()returningfalseforCustom, the effects are:
- In tokenless mode, a user passing
sources: ["wbe"](typo for"web") fails withConnectorRequiresAuthinstead of an intuitive "unknown source" error.- In authenticated mode, the typo is forwarded verbatim to Perplexity's backend and will either be ignored or return an opaque server error.
- The
Err = Stringassociated type is unreachable, andfilter_map(|s| s.parse::<Source>().ok())atcrates/perplexity-web-api-mcp/src/server.rs:248is now a dead filter.A safer pattern is to keep
FromStrstrict for the known connector set and expose a separate explicit constructor (e.g.Source::custom(name)) for user-defined remote MCP connectors, so typos are caught at parse time andCustomis only produced intentionally.Sketch
- other => Ok(Self::Custom(other.to_owned())), + other => Err(format!( + "unknown source '{other}'. Use Source::custom(...) for user-defined MCP connectors." + )),Plus an inherent
pub fn custom(name: impl Into<String>) -> Self { Self::Custom(name.into()) }for callers who genuinely want to opt into an unknown connector name.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/perplexity-web-api/src/types.rs` around lines 161 - 194, The FromStr impl for Source is currently infallible and maps any unknown string to Source::Custom, which hides typos and breaks validation; change impl FromStr for Source to be strict: only match the known literal variants and return Err(String) (e.g. Err(format!("unknown source: {}", s))) for any other input, and add an explicit constructor pub fn custom(name: impl Into<String>) -> Self { Self::Custom(name.into()) } for callers who really intend a custom connector; update call sites that relied on infallible parsing (e.g., uses of s.parse::<Source>().ok() / filter_map) to either handle the Err or call Source::custom when appropriate.
1-1:⚠️ Potential issue | 🔴 CriticalCompile error:
DEEP_RESEARCH_MODEL_PREFERENCEimported but not defined inmodels.rsLine 1 imports
DEEP_RESEARCH_MODEL_PREFERENCEfrommodels, and line 32 uses it in theDeepResearcharm of the match statement. The constant no longer exists inmodels.rs(it was replaced with three new preference constants). This will fail to compile.Either restore the constant in
models.rsor replace line 32 with an enum-based call matching the pattern of other arms, e.g.,DeepResearchModel::SomeVariant.api_preference().as_str()or a new constant that actually exists.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/perplexity-web-api/src/types.rs` at line 1, The code imports and uses the removed DEEP_RESEARCH_MODEL_PREFERENCE constant in the DeepResearch match arm; remove that import and replace the constant usage with the enum-based call pattern used by the other arms (i.e., call the DeepResearch model enum variant's api_preference() and .as_str()). Locate the import of DEEP_RESEARCH_MODEL_PREFERENCE and the DeepResearch match arm in types.rs and change the match to something like <DeepResearchModelEnum>::<appropriate_variant>.api_preference().as_str() (or call whichever DeepResearch enum method mirrors other ModelPreference usages) and keep the ModelPreference type import intact.
🧹 Nitpick comments (1)
crates/perplexity-web-api/src/types.rs (1)
27-44: Prefer theComputerModelenum over a hardcoded preference string indefault_preference.Every other arm delegates to
SearchModel/ReasonModel'sapi_preference().as_str(), which keeps the preference strings in a single source of truth (models.rs). The newComputerarm hardcodes"pplx_asi_opus_thinking"inline, which will silently drift ifComputerModel::Claude46OpusThinking's preference is ever renamed.Also worth updating the small doc comments below:
Proposed change
- Self::DeepResearch => DEEP_RESEARCH_MODEL_PREFERENCE, - Self::Computer => "pplx_asi_opus_thinking", + Self::DeepResearch => DEEP_RESEARCH_MODEL_PREFERENCE, + Self::Computer => ComputerModel::Claude46OpusThinking.api_preference().as_str(),- /// Search mode: Auto, Pro, Reasoning, or DeepResearch. + /// Search mode: Auto, Pro, Reasoning, DeepResearch, or Computer. pub mode: SearchMode, /// Optional explicit model preference. pub model_preference: Option<ModelPreference>, - /// Information sources: Web, Scholar, Social. + /// Information sources: public (Web, Scholar, Social) or connector-based + /// (Google Drive, Notion, GitHub, …) — connectors require auth cookies. pub sources: Vec<Source>,As per coding guidelines: "Update documentation and examples when API behavior changes".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/perplexity-web-api/src/types.rs` around lines 27 - 44, The Computer arm in default_preference currently hardcodes "pplx_asi_opus_thinking"; replace that with the canonical preference from the ComputerModel enum (e.g., use ComputerModel::Claude46OpusThinking.api_preference().as_str() or the appropriate variant) so the preference stays in sync with models.rs, and update the doc comment on query_source if needed to reflect the change; modify the match arm in default_preference to call the enum's api_preference() rather than a literal string.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@crates/perplexity-web-api-mcp/src/main.rs`:
- Around line 115-129: The check that rejects PERPLEXITY_* model env vars uses
env::var(name).is_ok(), which treats empty strings as present; update this logic
to treat empty or whitespace-only values as absent by reusing the same trimming
semantics as optional_model_env (or replicate its trim-and-empty->None behavior)
when inspecting each name in the array, so only non-empty trimmed values trigger
the error in the loop that currently references env::var(name).
In `@crates/perplexity-web-api/src/models.rs`:
- Around line 9-16: The three new public constants
BUSINESS_ASSISTANT_PREFERENCE, DOCUMENT_REVIEW_PREFERENCE, and STUDY_PREFERENCE
are currently unused; wire them into the runtime by mapping them to SearchMode
(update SearchMode::default_preference() and/or add new SearchMode variants that
return these constants) and add the corresponding tool handler(s) in server.rs
(e.g., a perplexity_study handler or extend existing tool dispatch) so the
constants are actually consumed; alternatively remove the public constants if
you prefer not to implement Study/Business/Document modes now. Ensure you
reference the constants by name and update SearchMode and server.rs dispatch to
use them.
---
Outside diff comments:
In `@crates/perplexity-web-api-mcp/src/server.rs`:
- Around line 134-150: Update the stale doc comment on PerplexityServer::new to
reflect that perplexity_computer also requires authenticated session cookies (or
reword to match actual runtime behavior), and add a tokenless guard to the
perplexity_computer handler so it is not silently exposed: mirror the existing
pattern used for file attachments by checking the PerplexityServer.tokenless
flag in the perplexity_computer request handler and short-circuit with
McpError::invalid_params(...) providing a clear message that ASI/connector auth
is required — this ensures the tool is not advertised/usable in tokenless mode
and clients receive an actionable error before a round-trip to the
client/connector.
In `@crates/perplexity-web-api/src/types.rs`:
- Around line 161-194: The FromStr impl for Source is currently infallible and
maps any unknown string to Source::Custom, which hides typos and breaks
validation; change impl FromStr for Source to be strict: only match the known
literal variants and return Err(String) (e.g. Err(format!("unknown source: {}",
s))) for any other input, and add an explicit constructor pub fn custom(name:
impl Into<String>) -> Self { Self::Custom(name.into()) } for callers who really
intend a custom connector; update call sites that relied on infallible parsing
(e.g., uses of s.parse::<Source>().ok() / filter_map) to either handle the Err
or call Source::custom when appropriate.
- Line 1: The code imports and uses the removed DEEP_RESEARCH_MODEL_PREFERENCE
constant in the DeepResearch match arm; remove that import and replace the
constant usage with the enum-based call pattern used by the other arms (i.e.,
call the DeepResearch model enum variant's api_preference() and .as_str()).
Locate the import of DEEP_RESEARCH_MODEL_PREFERENCE and the DeepResearch match
arm in types.rs and change the match to something like
<DeepResearchModelEnum>::<appropriate_variant>.api_preference().as_str() (or
call whichever DeepResearch enum method mirrors other ModelPreference usages)
and keep the ModelPreference type import intact.
---
Nitpick comments:
In `@crates/perplexity-web-api/src/types.rs`:
- Around line 27-44: The Computer arm in default_preference currently hardcodes
"pplx_asi_opus_thinking"; replace that with the canonical preference from the
ComputerModel enum (e.g., use
ComputerModel::Claude46OpusThinking.api_preference().as_str() or the appropriate
variant) so the preference stays in sync with models.rs, and update the doc
comment on query_source if needed to reflect the change; modify the match arm in
default_preference to call the enum's api_preference() rather than a literal
string.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 1924c803-f90d-443c-9d48-f71033db174b
📒 Files selected for processing (7)
crates/perplexity-web-api-mcp/src/main.rscrates/perplexity-web-api-mcp/src/server.rscrates/perplexity-web-api/src/client.rscrates/perplexity-web-api/src/error.rscrates/perplexity-web-api/src/lib.rscrates/perplexity-web-api/src/models.rscrates/perplexity-web-api/src/types.rs
- Fix tokenless env-var check: use optional_env() trim semantics instead of env::var().is_ok() so empty/whitespace-only values are treated as unset (previously rejected as "cannot be used without auth"). - Remove unused DEEP_RESEARCH_MODEL_PREFERENCE constant; inline "pplx_alpha" at its single use site in SearchMode::DeepResearch. - Add SearchMode::Study and SearchMode::DocumentReview, wired through client.rs copilot-mode match. - Add perplexity_study and perplexity_document_review MCP tools following the perplexity_computer pattern. - Update server instructions to document the new tools. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace hardcoded 'pplx_asi_opus_thinking' in SearchMode::Computer's default_preference() with ComputerModel::Claude46OpusThinking.api_preference() .as_str() to ensure the preference stays synchronized with the model enum definition. This follows the same pattern as Auto/Pro/Reasoning modes and prevents divergence if the default model is ever updated. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This PR adds support for Perplexity Computer, MAX models, Study Mode and Connectors.
I found a large variety of models that you didn't include, I had no time testing all these endpoints.
I included the ones which I am aware people have access to.