feat: add Perplexity Search integration - #516
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds Perplexity adapter docs and navigation, plus the new TypeScript package ChangesPerplexity adapter docs and package
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ 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: 8
🧹 Nitpick comments (2)
packages/typescript/ai-perplexity/tests/search-client.test.ts (1)
105-111: ⚡ Quick winConsider adding boundary tests for stricter input validation paths.
If you adopt stricter validation in
PerplexitySearchClient.search, add tests for whitespace-onlyqueryand out-of-rangemax_resultsto prevent regressions.Suggested test additions
+ it('throws when query is whitespace-only', async () => { + const client = new PerplexitySearchClient({ fetch: vi.fn() as any, apiKey: 'k' }) + await expect(client.search({ query: ' ' })).rejects.toThrow(/non-empty `query`/i) + }) + + it('throws when max_results is out of range', async () => { + const client = new PerplexitySearchClient({ fetch: vi.fn() as any, apiKey: 'k' }) + await expect(client.search({ query: 'q', max_results: 21 })).rejects.toThrow( + /max_results/i, + ) + })Also applies to: 66-90
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/typescript/ai-perplexity/tests/search-client.test.ts` around lines 105 - 111, Add boundary tests to cover stricter validation in PerplexitySearchClient.search: add one test that calls client.search with a whitespace-only query (e.g., " ") and expects it to reject with the same non-empty `query` error, and add tests that pass invalid `max_results` values (e.g., 0 and a value > allowed max) and expect rejects with the out-of-range validation error; reference the PerplexitySearchClient class and its search method when locating where to extend tests so future tightening of validation won't regress.packages/typescript/ai-perplexity/tests/chat-client.test.ts (1)
22-26: ⚡ Quick winAdd a regression test for blank explicit
apiKey.Current coverage checks explicit non-empty keys, but not
''/whitespace keys. Adding that case will lock in expected behavior after key normalization.Suggested test case
+ it('rejects blank explicit apiKey values', () => { + expect(() => + createPerplexityChatClient({ apiKey: ' ' }), + ).toThrow(/PERPLEXITY_API_KEY/) + })Also applies to: 42-46
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/typescript/ai-perplexity/tests/chat-client.test.ts` around lines 22 - 26, Add regression tests that assert blank explicit apiKey values are normalized and do not fall back to env: extend the existing test block that uses createPerplexityChatClient and the other similar test around the second case to include checks for apiKey='' and apiKey=' ' (or other whitespace) verifying client.apiKey is treated as blank/normalized per spec; update/insert tests named e.g. "uses an explicit apiKey over the env var" and the analogous second test to cover these blank/whitespace cases so future changes to createPerplexityChatClient's normalization logic are caught.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/typescript/ai-perplexity/package.json`:
- Line 59: The peerDependency entry for "@tanstack/ai" in the package.json uses
"workspace:^" which violates the repo guideline; change that value to
"workspace:*" in the peerDependencies block of the ai-perplexity package.json
(update the "@tanstack/ai" entry), and mirror the same replacement for any other
provider adapter packages that currently use "workspace:^" so all internal peer
deps use "workspace:*".
In `@packages/typescript/ai-perplexity/src/chat/client.ts`:
- Around line 36-40: The config destructuring passes an empty string as apiKey
into the OpenAI constructor because the current `apiKey ??
getPerplexityApiKeyFromEnv()` treats '' as provided; fix by normalizing `apiKey`
first (e.g., compute an `effectiveApiKey` using `apiKey` trimmed and treated as
missing when empty, falling back to `getPerplexityApiKeyFromEnv()`), validate
that `effectiveApiKey` is non-empty (throw or log/exit early if still missing),
and then pass `effectiveApiKey` into the `new OpenAI({...})` call instead of the
raw `apiKey`.
In `@packages/typescript/ai-perplexity/src/search/client.ts`:
- Around line 69-77: PerplexitySearchClient.search currently accepts
whitespace-only queries and forwards max_results without enforcing the
documented 1–20 bounds; update the input validation in the search implementation
to trim request.query and reject it if the trimmed string is empty (throwing a
clear Error), and validate request.max_results (when defined) to be an integer
between 1 and 20 inclusive (throwing an Error if out of range) before assigning
to the body; keep existing validateDomainFilter usage and only set
body.max_results after this new validation.
- Around line 59-61: The constructor currently accepts blank strings for
config.apiKey which bypasses getPerplexityApiKeyFromEnv and causes opaque auth
errors; in the PerplexitySearchClient constructor validate config.apiKey: if
config.apiKey is provided but after trimming is empty, throw a clear Error (or
reject) stating the apiKey is invalid; otherwise use the trimmed config.apiKey
or fallback to getPerplexityApiKeyFromEnv() to set this.apiKey. Reference the
constructor, PerplexitySearchClientConfig, apiKey, and
getPerplexityApiKeyFromEnv when making the change.
- Around line 12-33: Add Zod runtime schemas for the request and response and
use them to validate wire data: create a PerplexitySearchRequestSchema (matching
the PerplexitySearchRequest interface) and a PerplexitySearchResponseSchema,
export their inferred types, and use PerplexitySearchRequestSchema.parse() to
validate the payload before sending in the client functions that accept
PerplexitySearchRequest; replace the current ad-hoc/runtime type assertions used
in the response parsing block (the response handling around the previous
"response parsing with runtime type assertions" area) with
PerplexitySearchResponseSchema.parse() to safely parse/throw on invalid
responses; ensure schemas cover optional fields (max_results,
max_tokens_per_page, search_domain_filter, search_recency_filter,
search_after_date_filter, search_before_date_filter) and include any nested
shapes asserted earlier, and update any tool definitions to reference the new
schemas.
In `@packages/typescript/ai-perplexity/src/search/tool.ts`:
- Around line 31-36: The destructured defaultMaxResults from config must be
validated before being used as a fallback: ensure defaultMaxResults is a finite
integer and within the model/schema allowed range (e.g., >= min and <= max
provided by the model or a safe capped constant); if it is missing or
out-of-range (0, negative, or too large) ignore it and fall back to the
model-provided limits or a safe cap. Add this validation where defaultMaxResults
is extracted (the const { defaultMaxResults, ...clientConfig } = config) and
again before the other usage site referenced in the review (the place that
builds the Search API request around line ~121), so the request never sends an
invalid maxResults value. Use clear checks (Number.isInteger, bounds) and a
single source of truth for the allowed min/max to apply consistently.
In `@packages/typescript/ai-perplexity/src/utils/api-key.ts`:
- Around line 15-23: The current API key selection returns whitespace-only
values (const key = env?.PERPLEXITY_API_KEY || env?.PPLX_API_KEY) which should
be rejected; update the logic in the api-key util so you trim the chosen value,
treat empty/whitespace-only strings as missing (e.g., if (!trimmedKey) throw the
existing Error), and return the trimmedKey instead of the raw value—apply this
change to the function that reads/returns the key in
packages/typescript/ai-perplexity/src/utils/api-key.ts.
In `@packages/typescript/ai-perplexity/tests/search-tool.test.ts`:
- Around line 5-11: The test mutates process.env.PERPLEXITY_API_KEY but doesn't
restore it; modify the beforeEach/afterEach in search-tool.test.ts to save the
original value into a local variable (e.g., let prevPerplexityKey) in beforeEach
and then restore it in afterEach (set process.env.PERPLEXITY_API_KEY back to
prevPerplexityKey or delete it if undefined) while keeping vi.restoreAllMocks()
intact.
---
Nitpick comments:
In `@packages/typescript/ai-perplexity/tests/chat-client.test.ts`:
- Around line 22-26: Add regression tests that assert blank explicit apiKey
values are normalized and do not fall back to env: extend the existing test
block that uses createPerplexityChatClient and the other similar test around the
second case to include checks for apiKey='' and apiKey=' ' (or other
whitespace) verifying client.apiKey is treated as blank/normalized per spec;
update/insert tests named e.g. "uses an explicit apiKey over the env var" and
the analogous second test to cover these blank/whitespace cases so future
changes to createPerplexityChatClient's normalization logic are caught.
In `@packages/typescript/ai-perplexity/tests/search-client.test.ts`:
- Around line 105-111: Add boundary tests to cover stricter validation in
PerplexitySearchClient.search: add one test that calls client.search with a
whitespace-only query (e.g., " ") and expects it to reject with the same
non-empty `query` error, and add tests that pass invalid `max_results` values
(e.g., 0 and a value > allowed max) and expect rejects with the out-of-range
validation error; reference the PerplexitySearchClient class and its search
method when locating where to extend tests so future tightening of validation
won't regress.
🪄 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: 5ea96be4-75fd-4fab-ab1e-2d8c75325e1c
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (17)
docs/adapters/perplexity.mddocs/config.jsonpackages/typescript/ai-perplexity/README.mdpackages/typescript/ai-perplexity/package.jsonpackages/typescript/ai-perplexity/src/chat/client.tspackages/typescript/ai-perplexity/src/chat/index.tspackages/typescript/ai-perplexity/src/index.tspackages/typescript/ai-perplexity/src/search/client.tspackages/typescript/ai-perplexity/src/search/index.tspackages/typescript/ai-perplexity/src/search/tool.tspackages/typescript/ai-perplexity/src/utils/api-key.tspackages/typescript/ai-perplexity/src/utils/index.tspackages/typescript/ai-perplexity/tests/chat-client.test.tspackages/typescript/ai-perplexity/tests/search-client.test.tspackages/typescript/ai-perplexity/tests/search-tool.test.tspackages/typescript/ai-perplexity/tsconfig.jsonpackages/typescript/ai-perplexity/vite.config.ts
| export interface PerplexitySearchRequest { | ||
| /** The search query. */ | ||
| query: string | ||
| /** Maximum number of results to return (1–20). Defaults to the API default (10). */ | ||
| max_results?: number | ||
| /** Maximum tokens of content to return per page. */ | ||
| max_tokens_per_page?: number | ||
| /** | ||
| * Restrict (or exclude) results by domain. | ||
| * | ||
| * Use bare hostnames to allowlist (`["nytimes.com"]`) or `-` prefixed entries | ||
| * to denylist (`["-pinterest.com"]`). Allow and deny entries must NOT be | ||
| * mixed in the same request. | ||
| */ | ||
| search_domain_filter?: Array<string> | ||
| /** Restrict results by recency: `hour | day | week | month | year`. */ | ||
| search_recency_filter?: 'hour' | 'day' | 'week' | 'month' | 'year' | ||
| /** Only include results published on or after this date (m/d/yyyy). */ | ||
| search_after_date_filter?: string | ||
| /** Only include results published on or before this date (m/d/yyyy). */ | ||
| search_before_date_filter?: string | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Read-only check: verify whether zod schemas are currently used in ai-perplexity source.
rg -n --type=ts "from 'zod'|from \"zod\"|z\\.object\\(" packages/typescript/ai-perplexity/srcRepository: TanStack/ai
Length of output: 37
🏁 Script executed:
# Get the full file to see lines 12-33 and 107-118
head -n 130 packages/typescript/ai-perplexity/src/search/client.ts | tail -n +1Repository: TanStack/ai
Length of output: 4496
🏁 Script executed:
# Check if Zod is used in other packages/typescript packages for comparison
rg -l "from 'zod'|from \"zod\"" packages/typescript --type=ts | head -20Repository: TanStack/ai
Length of output: 1301
🏁 Script executed:
# Check the overall structure of ai-perplexity package
ls -la packages/typescript/ai-perplexity/src/Repository: TanStack/ai
Length of output: 383
🏁 Script executed:
# Check if other packages in packages/typescript/ai-* also use Zod
rg "from 'zod'|from \"zod\"" packages/typescript/ai-*/src --type=ts | head -10Repository: TanStack/ai
Length of output: 329
🏁 Script executed:
# Check what files are in the ai-perplexity package
find packages/typescript/ai-perplexity -name "*.ts" -type f | grep -v node_modulesRepository: TanStack/ai
Length of output: 708
🏁 Script executed:
# Check the main entry point of ai-perplexity to understand its scope
cat packages/typescript/ai-perplexity/src/index.tsRepository: TanStack/ai
Length of output: 517
🏁 Script executed:
# Check the search/tool.ts to see if it uses Zod
cat packages/typescript/ai-perplexity/src/search/tool.tsRepository: TanStack/ai
Length of output: 4473
🏁 Script executed:
# Check if other low-level clients in packages/typescript use Zod for validation
rg -A 5 "interface.*Request\|interface.*Response" packages/typescript/ai-openai/src --type=ts | head -40Repository: TanStack/ai
Length of output: 37
🏁 Script executed:
# Check the chat client as well since the comment mentions "Also applies to: 107-118"
sed -n '107,118p' packages/typescript/ai-perplexity/src/search/client.tsRepository: TanStack/ai
Length of output: 403
🏁 Script executed:
# Check how ai-openai (another API client) handles request/response validation
cat packages/typescript/ai-openai/src/create-openai-client.ts | head -100Repository: TanStack/ai
Length of output: 145
🏁 Script executed:
# Check if the main ai package uses Zod for toolDefinition
grep -A 20 "export.*toolDefinition" packages/typescript/ai/src/activities/chat/tools/tool-definition.ts | head -30Repository: TanStack/ai
Length of output: 734
🏁 Script executed:
# Look for any chat client in ai-perplexity to see the "107-118" reference
wc -l packages/typescript/ai-perplexity/src/chat/client.tsRepository: TanStack/ai
Length of output: 111
🏁 Script executed:
# Check the length of search/client.ts
wc -l packages/typescript/ai-perplexity/src/search/client.tsRepository: TanStack/ai
Length of output: 114
🏁 Script executed:
# Let's see what's around lines 107-118 in search/client.ts
sed -n '100,125p' packages/typescript/ai-perplexity/src/search/client.tsRepository: TanStack/ai
Length of output: 749
🏁 Script executed:
# Check how other packages in packages/typescript handle client configs and validation
ls -la packages/typescript/ai-openai/src/ | grep -i clientRepository: TanStack/ai
Length of output: 37
🏁 Script executed:
# Check the pattern in ai-code-mode to understand how Zod is used for tool definitions
cat packages/typescript/ai-code-mode/src/create-code-mode-tool.ts | head -80Repository: TanStack/ai
Length of output: 2292
🏁 Script executed:
# Check if there's a pattern in how other providers define their schemas
cat packages/typescript/ai-gemini/src/tools/tool-definition.ts 2>/dev/null || echo "File not found"Repository: TanStack/ai
Length of output: 70
🏁 Script executed:
# Verify the full validateDomainFilter function to understand the scope
sed -n '119,144p' packages/typescript/ai-perplexity/src/search/client.tsRepository: TanStack/ai
Length of output: 747
Add Zod schemas for request and response validation in this client.
This source currently relies on TypeScript types only, but wire payloads are runtime data. Add Zod schemas for both request validation and response parsing to align runtime guarantees with the public interfaces.
Per the coding guidelines, Zod should be used for schema validation and tool definition across the library (packages/typescript/**/src/**/*.ts).
Applies to:
- Lines 12–33:
PerplexitySearchRequestinterface - Lines 107–118: Response parsing with runtime type assertions
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/typescript/ai-perplexity/src/search/client.ts` around lines 12 - 33,
Add Zod runtime schemas for the request and response and use them to validate
wire data: create a PerplexitySearchRequestSchema (matching the
PerplexitySearchRequest interface) and a PerplexitySearchResponseSchema, export
their inferred types, and use PerplexitySearchRequestSchema.parse() to validate
the payload before sending in the client functions that accept
PerplexitySearchRequest; replace the current ad-hoc/runtime type assertions used
in the response parsing block (the response handling around the previous
"response parsing with runtime type assertions" area) with
PerplexitySearchResponseSchema.parse() to safely parse/throw on invalid
responses; ensure schemas cover optional fields (max_results,
max_tokens_per_page, search_domain_filter, search_recency_filter,
search_after_date_filter, search_before_date_filter) and include any nested
shapes asserted earlier, and update any tool definitions to reference the new
schemas.
| const { | ||
| name, | ||
| description, | ||
| defaultMaxResults, | ||
| ...clientConfig | ||
| } = config |
There was a problem hiding this comment.
Validate defaultMaxResults before using it as a fallback.
An out-of-range value (e.g. 0 or 50) bypasses model-provided schema limits and can generate invalid Search API requests.
Proposed guard
const {
name,
description,
defaultMaxResults,
...clientConfig
} = config
+
+ if (
+ defaultMaxResults !== undefined &&
+ (!Number.isInteger(defaultMaxResults) ||
+ defaultMaxResults < 1 ||
+ defaultMaxResults > 20)
+ ) {
+ throw new Error('defaultMaxResults must be an integer between 1 and 20.')
+ }Also applies to: 121-121
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/typescript/ai-perplexity/src/search/tool.ts` around lines 31 - 36,
The destructured defaultMaxResults from config must be validated before being
used as a fallback: ensure defaultMaxResults is a finite integer and within the
model/schema allowed range (e.g., >= min and <= max provided by the model or a
safe capped constant); if it is missing or out-of-range (0, negative, or too
large) ignore it and fall back to the model-provided limits or a safe cap. Add
this validation where defaultMaxResults is extracted (the const {
defaultMaxResults, ...clientConfig } = config) and again before the other usage
site referenced in the review (the place that builds the Search API request
around line ~121), so the request never sends an invalid maxResults value. Use
clear checks (Number.isInteger, bounds) and a single source of truth for the
allowed min/max to apply consistently.
| const key = env?.PERPLEXITY_API_KEY || env?.PPLX_API_KEY | ||
|
|
||
| if (!key) { | ||
| throw new Error( | ||
| 'PERPLEXITY_API_KEY (or PPLX_API_KEY) is required. Set it in your environment or pass an explicit apiKey.', | ||
| ) | ||
| } | ||
|
|
||
| return key |
There was a problem hiding this comment.
Reject whitespace-only API keys before returning.
On Line 15, a value like ' ' is treated as valid and returned, which later yields confusing auth failures. Trim and validate before returning.
Suggested fix
- const key = env?.PERPLEXITY_API_KEY || env?.PPLX_API_KEY
+ const key = [env?.PERPLEXITY_API_KEY, env?.PPLX_API_KEY].find(
+ (value): value is string =>
+ typeof value === 'string' && value.trim().length > 0,
+ )
...
- return key
+ return key.trim()📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const key = env?.PERPLEXITY_API_KEY || env?.PPLX_API_KEY | |
| if (!key) { | |
| throw new Error( | |
| 'PERPLEXITY_API_KEY (or PPLX_API_KEY) is required. Set it in your environment or pass an explicit apiKey.', | |
| ) | |
| } | |
| return key | |
| const key = [env?.PERPLEXITY_API_KEY, env?.PPLX_API_KEY].find( | |
| (value): value is string => | |
| typeof value === 'string' && value.trim().length > 0, | |
| ) | |
| if (!key) { | |
| throw new Error( | |
| 'PERPLEXITY_API_KEY (or PPLX_API_KEY) is required. Set it in your environment or pass an explicit apiKey.', | |
| ) | |
| } | |
| return key.trim() |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/typescript/ai-perplexity/src/utils/api-key.ts` around lines 15 - 23,
The current API key selection returns whitespace-only values (const key =
env?.PERPLEXITY_API_KEY || env?.PPLX_API_KEY) which should be rejected; update
the logic in the api-key util so you trim the chosen value, treat
empty/whitespace-only strings as missing (e.g., if (!trimmedKey) throw the
existing Error), and return the trimmedKey instead of the raw value—apply this
change to the function that reads/returns the key in
packages/typescript/ai-perplexity/src/utils/api-key.ts.
Add @tanstack/ai-perplexity with: - Search API tool (POST https://api.perplexity.ai/search) wired as a TanStack AI tool definition. Returns {title, url, snippet, date?} per result and surfaces max_results, search_domain_filter, search_recency_filter, and date filters. - OpenAI-compatible chat client factory pointed at https://api.perplexity.ai so existing openai-SDK code can target Perplexity by swapping baseURL. - API key resolution from PERPLEXITY_API_KEY (falls back to PPLX_API_KEY). - Tests with mocked fetch covering auth, body shape, filter pass-through, domain-allow/deny mixing guard, error surface, and env-var fallback. - README + docs/adapters/perplexity.md page wired into docs/config.json.
|
Thanks for the review. I have rebased onto current main (db5bd3f) and addressed all 8 CodeRabbit items in packages/typescript/ai-perplexity. Validation: No projects found in "/home/user/workspace", No projects found in "/home/user/workspace", and all pass. Ready for re-review. |
- Use workspace:* for @tanstack/ai in both devDependencies and peerDependencies (matches repo convention per CLAUDE.md)
|
Addressed remaining review feedback in 618af4c:
Previously addressed items (already present in db5bd3f, confirmed stale):
Local unit tests: all 25 tests pass (search-client: 14, search-tool: 5, chat-client: 6). |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/typescript/ai-perplexity/package.json`:
- Around line 15-27: The package.json exports currently expose "." and the
subpaths "./search" and "./chat" but missing the required tree-shakeable adapter
entrypoints; update the "exports" map in package.json to include a
"./adapters/*" pattern (and optionally a root "./adapters" entry) that maps
"types" to the corresponding "./dist/esm/adapters/*.d.ts" and "import" to
"./dist/esm/adapters/*.js" so adapter consumers can import e.g.
"ai-perplexity/adapters/<adapterName>" in a tree-shakeable way; modify the
existing exports block (next to the "./search" and "./chat" entries) to add
these "./adapters/*" and "./adapters" keys referencing the dist/esm/adapters
output.
🪄 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: 41fceacb-29da-426b-8fd2-026ce716969e
📒 Files selected for processing (1)
packages/typescript/ai-perplexity/package.json
# Conflicts: # pnpm-lock.yaml
|
Addressed regression(s) in
Previously verified stale at HEAD
|
|
Added the Perplexity attribution header on the What changed:
Validation:
🤖 Comment from PSI |
Resolve docs/config.json and pnpm-lock.yaml conflicts, and relocate @tanstack/ai-perplexity from packages/typescript/ to packages/ so it matches the current workspace layout.
Sonar chat belongs on openaiCompatible. This package now ships the Search client, perplexitySearchTool, and the attribution header helper.
Pair the search tool with function-calling adapters instead of Sonar, forward abortSignal, validate Search JSON, switch the tool to Zod, and keep last_updated.
tombeckenham
left a comment
There was a problem hiding this comment.
I've added the perplexity search tool so that it can be used with other adpters eg openai etc. This is the primary use case. Perplexity itself is openai compatible and we have an adapter to support it.
|
View your CI Pipeline Execution ↗ for commit f82f099
☁️ Nx Cloud last updated this comment at |
@tanstack/ai
@tanstack/ai-acp
@tanstack/ai-angular
@tanstack/ai-anthropic
@tanstack/ai-bedrock
@tanstack/ai-byteplus
@tanstack/ai-claude-code
@tanstack/ai-client
@tanstack/ai-code-mode
@tanstack/ai-code-mode-skills
@tanstack/ai-codex
@tanstack/ai-cohere
@tanstack/ai-devtools-core
@tanstack/ai-durable-stream
@tanstack/ai-elevenlabs
@tanstack/ai-event-client
@tanstack/ai-fal
@tanstack/ai-gemini
@tanstack/ai-grok
@tanstack/ai-grok-build
@tanstack/ai-groq
@tanstack/ai-isolate-cloudflare
@tanstack/ai-isolate-daytona
@tanstack/ai-isolate-node
@tanstack/ai-isolate-quickjs
@tanstack/ai-isolate-quickjs-bun
@tanstack/ai-mcp
@tanstack/ai-memory
@tanstack/ai-mistral
@tanstack/ai-ollama
@tanstack/ai-openai
@tanstack/ai-opencode
@tanstack/ai-openrouter
@tanstack/ai-perplexity
@tanstack/ai-persistence
@tanstack/ai-preact
@tanstack/ai-react
@tanstack/ai-react-ui
@tanstack/ai-sandbox
@tanstack/ai-sandbox-cloudflare
@tanstack/ai-sandbox-daytona
@tanstack/ai-sandbox-docker
@tanstack/ai-sandbox-local-process
@tanstack/ai-sandbox-sprites
@tanstack/ai-sandbox-vercel
@tanstack/ai-solid
@tanstack/ai-solid-ui
@tanstack/ai-svelte
@tanstack/ai-utils
@tanstack/ai-vercel-gateway
@tanstack/ai-vue
@tanstack/ai-vue-ui
@tanstack/openai-base
@tanstack/preact-ai-devtools
@tanstack/react-ai-devtools
@tanstack/solid-ai-devtools
commit: |
scan-dangling-dts rejects the directory barrel './search' in published .d.ts under bundler/node16/nodenext resolution.
Adds
@tanstack/ai-perplexity— a Search-only package for the Perplexity Search API.This is not a TanStack text adapter. Pair
perplexitySearchToolwith a function-calling adapter such asopenaiTextoranthropicText. Sonarchat()stays onopenaiCompatible(@tanstack/ai-openai/compatible); Sonar already searches the web and does not accept custom tools.What
perplexitySearchTool—POST https://api.perplexity.ai/searchwrapped as a TanStack AItoolDefinition(Zod input/output). Returns{ results: Array<{ title, url, snippet, date?, last_updated? }> }. ForwardsabortSignal, appliesdefaultMaxResultswhen the model omitsmax_results, and rejects mixed allow/denysearch_domain_filterentries.PerplexitySearchClient— low-level Search API HTTP client.queryisstring | string[](max 5). Validates Search JSON (throws on a malformed 200) and keepslast_updated.getPerplexityIntegrationHeaders()— optionalX-Pplx-Integration: tanstack/<version>helper for Sonar chat viaopenaiCompatible({ defaultHeaders }). The Search client sends this automatically.PERPLEXITY_API_KEY, falling back toPPLX_API_KEY.Files
packages/ai-perplexity/— new package (search client + tool, README, LICENSE).docs/adapters/perplexity.md— Search docs; Sonar chat pointed atopenaiCompatible.docs/adapters/openai-compatible.md— notes that@tanstack/ai-perplexityis Search-only.docs/config.json— “Perplexity Search” under Adapters..changeset/perplexity-search.md— minor for@tanstack/ai-perplexity.Tests
pnpm --filter @tanstack/ai-perplexity test:lib(28 unit tests, mockedfetch):/searchwith bearer auth, JSON body, and attribution headermax_results,max_tokens_per_page, domain/recency/date)string[](max 5); empty/whitespace rejectionmax_results/defaultMaxResultsrange (throw, not clamp); model value wins over defaultabortSignalforwarded from the tool tofetch{ results: [] })date/last_updatedomitted when the API does not return themPERPLEXITY_API_KEY/PPLX_API_KEY)baseURLDocs
Get a Perplexity API key at https://console.perplexity.ai/group/keys.