diff --git a/open-sse/handlers/search/chatSearch.js b/open-sse/handlers/search/chatSearch.js index a8a7841e..c5bfb3ad 100644 --- a/open-sse/handlers/search/chatSearch.js +++ b/open-sse/handlers/search/chatSearch.js @@ -273,6 +273,53 @@ const CHAT_SEARCH_CONFIG = { const tokens = data?.usage?.total_tokens || 0; return { text, citations, tokens }; } + }, + + "perplexity-agent": { + endpoint: () => searchEndpoint("perplexity-agent"), + buildBody: (query, model) => ({ + model, + input: query, + tools: [{ type: "web_search" }] + }), + buildHeaders: (token) => ({ + "Content-Type": "application/json", + Authorization: `Bearer ${token}` + }), + extractAnswer: (data) => { + const output = Array.isArray(data?.output) ? data.output : []; + let text = ""; + const citations = []; + for (const item of output) { + const parts = Array.isArray(item?.content) ? item.content : []; + for (const p of parts) { + if (typeof p?.text === "string") text += p.text; + const anns = Array.isArray(p?.annotations) ? p.annotations : []; + for (const a of anns) { + const c = normalizeCitation(a?.url ? a : a?.url_citation); + if (c) citations.push(c); + } + } + const results = Array.isArray(item?.results) ? item.results : []; + for (const r of results) { + const url = r?.url || r?.link; + if (!url) continue; + citations.push({ + url, + title: r?.title || "", + snippet: r?.snippet || "" + }); + } + } + if (!citations.length && Array.isArray(data?.citations)) { + for (const c of data.citations) { + const n = normalizeCitation(c); + if (n) citations.push(n); + } + } + const tokens = data?.usage?.total_tokens || 0; + return { text, citations, tokens }; + } } }; diff --git a/open-sse/providers/registry/index.js b/open-sse/providers/registry/index.js index 686c8a46..e4cf5439 100644 --- a/open-sse/providers/registry/index.js +++ b/open-sse/providers/registry/index.js @@ -73,31 +73,32 @@ import p70 from "./opencode.js"; import p71 from "./openrouter.js"; import p72 from "./perplexity-web.js"; import p73 from "./perplexity.js"; -import p74 from "./playht.js"; -import p75 from "./qoder.js"; -import p76 from "./qwen.js"; -import p77 from "./recraft.js"; -import p78 from "./runwayml.js"; -import p79 from "./sdwebui.js"; -import p80 from "./searchapi.js"; -import p81 from "./searxng.js"; -import p82 from "./serper.js"; -import p83 from "./siliconflow.js"; -import p84 from "./stability-ai.js"; -import p85 from "./tavily.js"; -import p86 from "./together.js"; -import p87 from "./topaz.js"; -import p88 from "./tortoise.js"; -import p89 from "./venice.js"; -import p90 from "./vercel-ai-gateway.js"; -import p91 from "./vertex-partner.js"; -import p92 from "./vertex.js"; -import p93 from "./volcengine-ark.js"; -import p94 from "./voyage-ai.js"; -import p95 from "./xai.js"; -import p96 from "./xiaomi-mimo.js"; -import p97 from "./xiaomi-tokenplan.js"; -import p98 from "./youcom.js"; +import p74 from "./perplexity-agent.js"; +import p75 from "./playht.js"; +import p76 from "./qoder.js"; +import p77 from "./qwen.js"; +import p78 from "./recraft.js"; +import p79 from "./runwayml.js"; +import p80 from "./sdwebui.js"; +import p81 from "./searchapi.js"; +import p82 from "./searxng.js"; +import p83 from "./serper.js"; +import p84 from "./siliconflow.js"; +import p85 from "./stability-ai.js"; +import p86 from "./tavily.js"; +import p87 from "./together.js"; +import p88 from "./topaz.js"; +import p89 from "./tortoise.js"; +import p90 from "./venice.js"; +import p91 from "./vercel-ai-gateway.js"; +import p92 from "./vertex-partner.js"; +import p93 from "./vertex.js"; +import p94 from "./volcengine-ark.js"; +import p95 from "./voyage-ai.js"; +import p96 from "./xai.js"; +import p97 from "./xiaomi-mimo.js"; +import p98 from "./xiaomi-tokenplan.js"; +import p99 from "./youcom.js"; export default [ p0, @@ -199,4 +200,5 @@ export default [ p96, p97, p98, + p99 ]; diff --git a/open-sse/providers/registry/perplexity-agent.js b/open-sse/providers/registry/perplexity-agent.js new file mode 100644 index 00000000..5c8785eb --- /dev/null +++ b/open-sse/providers/registry/perplexity-agent.js @@ -0,0 +1,49 @@ +export default { + id: "perplexity-agent", + priority: 181, + alias: "perplexity-agent", + aliases: [ + "pplx-agent", + "pplx-responses", + ], + uiAlias: "pa", + display: { + name: "Perplexity Agent", + icon: "travel_explore", + color: "#20808D", + textIcon: "PA", + website: "https://www.perplexity.ai", + notice: { + text: "Perplexity Agent API exposes GPT, Claude, Gemini, Grok, GLM, Kimi, and Sonar models through one OpenAI-compatible Responses API.", + apiKeyUrl: "https://www.perplexity.ai/settings/api", + }, + }, + category: "apikey", + authType: "apikey", + transport: { + baseUrl: "https://api.perplexity.ai/v1/responses", + validateUrl: "https://api.perplexity.ai/v1/models", + format: "openai-responses", + }, + models: [ + { id: "perplexity/sonar", name: "Perplexity Sonar" }, + { id: "openai/gpt-5.5", name: "GPT-5.5" }, + { id: "openai/gpt-5.4", name: "GPT-5.4" }, + { id: "openai/gpt-5.4-mini", name: "GPT-5.4 Mini" }, + { id: "anthropic/claude-sonnet-4-6", name: "Claude Sonnet 4.6" }, + { id: "anthropic/claude-opus-4-8", name: "Claude Opus 4.8" }, + { id: "google/gemini-3.1-pro-preview", name: "Gemini 3.1 Pro" }, + { id: "xai/grok-4.20-reasoning", name: "Grok 4.20 Reasoning" }, + { id: "perplexity/glm-5.2", name: "GLM 5.2" }, + { id: "perplexity/kimi-k2.7-code", name: "Kimi K2.7 Code" }, + { id: "nvidia/nemotron-3-super-120b-a12b", name: "Nemotron 3 Super 120B" }, + ], + serviceKinds: ["llm", "webSearch"], + searchViaChat: { + defaultModel: "perplexity/sonar", + endpoint: "https://api.perplexity.ai/v1/responses", + pricingUrl: "https://docs.perplexity.ai/docs/agent-api/models", + }, + modelsFetcher: { url: "https://api.perplexity.ai/v1/models", type: "openai" }, + passthroughModels: true, +}; diff --git a/src/app/api/providers/[id]/models/route.js b/src/app/api/providers/[id]/models/route.js index bc31306a..52f0291b 100644 --- a/src/app/api/providers/[id]/models/route.js +++ b/src/app/api/providers/[id]/models/route.js @@ -236,6 +236,7 @@ const PROVIDER_MODELS_CONFIG = { xai: createOpenAIModelsConfig("https://api.x.ai/v1/models"), mistral: createOpenAIModelsConfig("https://api.mistral.ai/v1/models"), perplexity: createOpenAIModelsConfig("https://api.perplexity.ai/v1/models"), + "perplexity-agent": createOpenAIModelsConfig("https://api.perplexity.ai/v1/models"), together: createOpenAIModelsConfig("https://api.together.xyz/v1/models"), fireworks: createOpenAIModelsConfig("https://api.fireworks.ai/inference/v1/models"), cerebras: createOpenAIModelsConfig("https://api.cerebras.ai/v1/models"),