@ai-sdk/perplexity 5.0.2 → 5.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,1390 +1,1126 @@
1
- // src/perplexity-provider.ts
2
- import {
3
- NoSuchModelError
4
- } from "@ai-sdk/provider";
5
- import {
6
- generateId,
7
- loadApiKey,
8
- withoutTrailingSlash,
9
- withUserAgentSuffix
10
- } from "@ai-sdk/provider-utils";
11
-
12
- // src/perplexity-embedding-model.ts
13
- import {
14
- TooManyEmbeddingValuesForCallError
15
- } from "@ai-sdk/provider";
16
- import {
17
- combineHeaders as combineHeaders2,
18
- convertBase64ToUint8Array,
19
- createJsonErrorResponseHandler as createJsonErrorResponseHandler2,
20
- createJsonResponseHandler as createJsonResponseHandler2,
21
- parseProviderOptions as parseProviderOptions2,
22
- postJsonToApi as postJsonToApi2,
23
- serializeModelOptions as serializeModelOptions2,
24
- WORKFLOW_DESERIALIZE as WORKFLOW_DESERIALIZE2,
25
- WORKFLOW_SERIALIZE as WORKFLOW_SERIALIZE2
26
- } from "@ai-sdk/provider-utils";
27
- import { z as z4 } from "zod/v4";
28
-
29
- // src/perplexity-embedding-model-options.ts
1
+ import { APICallError, NoSuchModelError, TooManyEmbeddingValuesForCallError, UnsupportedFunctionalityError } from "@ai-sdk/provider";
2
+ import { WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE, combineHeaders, convertBase64ToUint8Array, convertUint8ArrayToBase64, createEventSourceResponseHandler, createJsonErrorResponseHandler, createJsonResponseHandler, createLanguageModelResponseMetadata, createNullLanguageModelUsage, generateId, getTopLevelMediaType, isCustomReasoning, loadApiKey, parseProviderOptions, postJsonToApi, resolveFullMediaType, serializeModelOptions, withUserAgentSuffix, withoutTrailingSlash } from "@ai-sdk/provider-utils";
30
3
  import { z } from "zod/v4";
31
- var perplexityEmbeddingModelOptions = z.object({
32
- /**
33
- * The number of dimensions the resulting output embeddings should have
34
- * (Matryoshka truncation). Ranges from 128 up to the model's full size
35
- * (1024 for 0.6b models, 2560 for 4b models).
36
- */
37
- dimensions: z.number().int().positive().optional(),
38
- /**
39
- * The quantized encoding format returned by the API. Perplexity does not
40
- * return floating point embeddings; values are decoded to numbers:
41
- * - `base64_int8` (default): signed int8 values, compare via cosine similarity.
42
- * - `base64_binary`: packed bits per byte (0-255), compare via Hamming distance.
43
- */
44
- encodingFormat: z.enum(["base64_int8", "base64_binary"]).optional()
4
+ //#region src/perplexity-embedding-model-options.ts
5
+ const perplexityEmbeddingModelOptions = z.object({
6
+ /**
7
+ * The number of dimensions the resulting output embeddings should have
8
+ * (Matryoshka truncation). Ranges from 128 up to the model's full size
9
+ * (1024 for 0.6b models, 2560 for 4b models).
10
+ */
11
+ dimensions: z.number().int().positive().optional(),
12
+ /**
13
+ * The quantized encoding format returned by the API. Perplexity does not
14
+ * return floating point embeddings; values are decoded to numbers:
15
+ * - `base64_int8` (default): signed int8 values, compare via cosine similarity.
16
+ * - `base64_binary`: packed bits per byte (0-255), compare via Hamming distance.
17
+ */
18
+ encodingFormat: z.enum(["base64_int8", "base64_binary"]).optional()
45
19
  });
46
-
47
- // src/perplexity-language-model.ts
48
- import {
49
- APICallError
50
- } from "@ai-sdk/provider";
51
- import {
52
- combineHeaders,
53
- createEventSourceResponseHandler,
54
- createJsonErrorResponseHandler,
55
- createJsonResponseHandler,
56
- createLanguageModelResponseMetadata,
57
- isCustomReasoning,
58
- parseProviderOptions,
59
- postJsonToApi,
60
- serializeModelOptions,
61
- WORKFLOW_DESERIALIZE,
62
- WORKFLOW_SERIALIZE
63
- } from "@ai-sdk/provider-utils";
64
-
65
- // src/convert-perplexity-usage.ts
66
- import { createNullLanguageModelUsage } from "@ai-sdk/provider-utils";
20
+ //#endregion
21
+ //#region src/convert-perplexity-usage.ts
67
22
  function convertPerplexityUsage(usage) {
68
- if (usage == null) {
69
- return createNullLanguageModelUsage();
70
- }
71
- const inputTokens = usage.input_tokens ?? 0;
72
- const outputTokens = usage.output_tokens ?? 0;
73
- const cacheReadTokens = usage.input_tokens_details?.cache_read_input_tokens ?? usage.input_tokens_details?.cached_tokens ?? 0;
74
- const cacheWriteTokens = usage.input_tokens_details?.cache_creation_input_tokens ?? 0;
75
- const reasoningTokens = usage.output_tokens_details?.reasoning_tokens ?? 0;
76
- return {
77
- inputTokens: {
78
- total: inputTokens,
79
- noCache: Math.max(0, inputTokens - cacheReadTokens - cacheWriteTokens),
80
- cacheRead: cacheReadTokens,
81
- cacheWrite: cacheWriteTokens
82
- },
83
- outputTokens: {
84
- total: outputTokens,
85
- text: Math.max(0, outputTokens - reasoningTokens),
86
- reasoning: reasoningTokens
87
- },
88
- raw: usage
89
- };
23
+ if (usage == null) return createNullLanguageModelUsage();
24
+ const inputTokens = usage.input_tokens ?? 0;
25
+ const outputTokens = usage.output_tokens ?? 0;
26
+ const cacheReadTokens = usage.input_tokens_details?.cache_read_input_tokens ?? usage.input_tokens_details?.cached_tokens ?? 0;
27
+ const cacheWriteTokens = usage.input_tokens_details?.cache_creation_input_tokens ?? 0;
28
+ const reasoningTokens = usage.output_tokens_details?.reasoning_tokens ?? 0;
29
+ return {
30
+ inputTokens: {
31
+ total: inputTokens,
32
+ noCache: Math.max(0, inputTokens - cacheReadTokens - cacheWriteTokens),
33
+ cacheRead: cacheReadTokens,
34
+ cacheWrite: cacheWriteTokens
35
+ },
36
+ outputTokens: {
37
+ total: outputTokens,
38
+ text: Math.max(0, outputTokens - reasoningTokens),
39
+ reasoning: reasoningTokens
40
+ },
41
+ raw: usage
42
+ };
90
43
  }
91
-
92
- // src/convert-to-perplexity-input.ts
93
- import {
94
- UnsupportedFunctionalityError
95
- } from "@ai-sdk/provider";
96
- import {
97
- convertUint8ArrayToBase64,
98
- getTopLevelMediaType,
99
- resolveFullMediaType
100
- } from "@ai-sdk/provider-utils";
44
+ //#endregion
45
+ //#region src/convert-to-perplexity-input.ts
101
46
  function serializeToolOutput(output) {
102
- switch (output.type) {
103
- case "text":
104
- case "error-text":
105
- return output.value;
106
- case "json":
107
- case "error-json":
108
- return JSON.stringify(output.value);
109
- case "execution-denied":
110
- return output.reason ?? "Tool call execution denied.";
111
- case "content": {
112
- if (output.value.some((part) => part.type !== "text")) {
113
- throw new UnsupportedFunctionalityError({
114
- functionality: "file and custom tool result content"
115
- });
116
- }
117
- return output.value.map((part) => part.type === "text" ? part.text : "").join("");
118
- }
119
- default: {
120
- const _exhaustiveCheck = output;
121
- throw new Error(`Unsupported tool output: ${_exhaustiveCheck}`);
122
- }
123
- }
47
+ switch (output.type) {
48
+ case "text":
49
+ case "error-text": return output.value;
50
+ case "json":
51
+ case "error-json": return JSON.stringify(output.value);
52
+ case "execution-denied": return output.reason ?? "Tool call execution denied.";
53
+ case "content":
54
+ if (output.value.some((part) => part.type !== "text")) throw new UnsupportedFunctionalityError({ functionality: "file and custom tool result content" });
55
+ return output.value.map((part) => part.type === "text" ? part.text : "").join("");
56
+ default: throw new Error(`Unsupported tool output: ${output}`);
57
+ }
124
58
  }
125
59
  function getThoughtSignature(providerOptions) {
126
- const thoughtSignature = providerOptions?.perplexity?.thoughtSignature;
127
- return typeof thoughtSignature === "string" ? thoughtSignature : void 0;
60
+ const thoughtSignature = providerOptions?.perplexity?.thoughtSignature;
61
+ return typeof thoughtSignature === "string" ? thoughtSignature : void 0;
128
62
  }
129
63
  function convertToPerplexityInput(prompt) {
130
- const input = [];
131
- const warnings = [];
132
- for (const { role, content } of prompt) {
133
- switch (role) {
134
- case "system": {
135
- input.push({ type: "message", role: "system", content });
136
- break;
137
- }
138
- case "user": {
139
- const convertedContent = content.map(
140
- (part) => {
141
- switch (part.type) {
142
- case "text":
143
- return { type: "input_text", text: part.text };
144
- case "file": {
145
- if (getTopLevelMediaType(part.mediaType) !== "image") {
146
- throw new UnsupportedFunctionalityError({
147
- functionality: `file part media type ${part.mediaType}`
148
- });
149
- }
150
- switch (part.data.type) {
151
- case "url":
152
- return {
153
- type: "input_image",
154
- image_url: part.data.url.toString()
155
- };
156
- case "data":
157
- return {
158
- type: "input_image",
159
- image_url: `data:${resolveFullMediaType({ part })};base64,${typeof part.data.data === "string" ? part.data.data : convertUint8ArrayToBase64(part.data.data)}`
160
- };
161
- case "reference":
162
- throw new UnsupportedFunctionalityError({
163
- functionality: "file parts with provider references"
164
- });
165
- case "text":
166
- throw new UnsupportedFunctionalityError({
167
- functionality: "text file parts"
168
- });
169
- }
170
- }
171
- }
172
- }
173
- );
174
- const isTextOnly = convertedContent.every(
175
- (part) => part.type === "input_text"
176
- );
177
- input.push({
178
- type: "message",
179
- role: "user",
180
- content: isTextOnly ? convertedContent.map((part) => part.type === "input_text" ? part.text : "").join("") : convertedContent
181
- });
182
- break;
183
- }
184
- case "assistant": {
185
- const text = content.filter((part) => part.type === "text").map((part) => part.text).join("");
186
- if (text.length > 0) {
187
- input.push({ type: "message", role: "assistant", content: text });
188
- }
189
- for (const part of content) {
190
- switch (part.type) {
191
- case "text":
192
- break;
193
- case "tool-call":
194
- input.push({
195
- type: "function_call",
196
- call_id: part.toolCallId,
197
- name: part.toolName,
198
- arguments: JSON.stringify(part.input ?? {}),
199
- thought_signature: getThoughtSignature(part.providerOptions)
200
- });
201
- break;
202
- case "tool-result":
203
- input.push({
204
- type: "function_call_output",
205
- call_id: part.toolCallId,
206
- name: part.toolName,
207
- output: serializeToolOutput(part.output),
208
- thought_signature: getThoughtSignature(part.providerOptions)
209
- });
210
- break;
211
- case "reasoning":
212
- warnings.push({
213
- type: "unsupported",
214
- feature: "reasoning content in prompt"
215
- });
216
- break;
217
- case "file":
218
- case "reasoning-file":
219
- case "custom":
220
- throw new UnsupportedFunctionalityError({
221
- functionality: `assistant ${part.type} parts`
222
- });
223
- default: {
224
- const _exhaustiveCheck = part;
225
- throw new Error(
226
- `Unsupported assistant part: ${_exhaustiveCheck}`
227
- );
228
- }
229
- }
230
- }
231
- break;
232
- }
233
- case "tool": {
234
- for (const part of content) {
235
- if (part.type === "tool-approval-response") {
236
- throw new UnsupportedFunctionalityError({
237
- functionality: "tool approval responses"
238
- });
239
- }
240
- input.push({
241
- type: "function_call_output",
242
- call_id: part.toolCallId,
243
- name: part.toolName,
244
- output: serializeToolOutput(part.output),
245
- thought_signature: getThoughtSignature(part.providerOptions)
246
- });
247
- }
248
- break;
249
- }
250
- default: {
251
- const _exhaustiveCheck = role;
252
- throw new Error(`Unsupported role: ${_exhaustiveCheck}`);
253
- }
254
- }
255
- }
256
- return { input, warnings };
64
+ const input = [];
65
+ const warnings = [];
66
+ for (const { role, content } of prompt) switch (role) {
67
+ case "system":
68
+ input.push({
69
+ type: "message",
70
+ role: "system",
71
+ content
72
+ });
73
+ break;
74
+ case "user": {
75
+ const convertedContent = content.map((part) => {
76
+ switch (part.type) {
77
+ case "text": return {
78
+ type: "input_text",
79
+ text: part.text
80
+ };
81
+ case "file":
82
+ if (getTopLevelMediaType(part.mediaType) !== "image") throw new UnsupportedFunctionalityError({ functionality: `file part media type ${part.mediaType}` });
83
+ switch (part.data.type) {
84
+ case "url": return {
85
+ type: "input_image",
86
+ image_url: part.data.url.toString()
87
+ };
88
+ case "data": return {
89
+ type: "input_image",
90
+ image_url: `data:${resolveFullMediaType({ part })};base64,${typeof part.data.data === "string" ? part.data.data : convertUint8ArrayToBase64(part.data.data)}`
91
+ };
92
+ case "reference": throw new UnsupportedFunctionalityError({ functionality: "file parts with provider references" });
93
+ case "text": throw new UnsupportedFunctionalityError({ functionality: "text file parts" });
94
+ }
95
+ }
96
+ });
97
+ const isTextOnly = convertedContent.every((part) => part.type === "input_text");
98
+ input.push({
99
+ type: "message",
100
+ role: "user",
101
+ content: isTextOnly ? convertedContent.map((part) => part.type === "input_text" ? part.text : "").join("") : convertedContent
102
+ });
103
+ break;
104
+ }
105
+ case "assistant": {
106
+ const text = content.filter((part) => part.type === "text").map((part) => part.text).join("");
107
+ if (text.length > 0) input.push({
108
+ type: "message",
109
+ role: "assistant",
110
+ content: text
111
+ });
112
+ for (const part of content) switch (part.type) {
113
+ case "text": break;
114
+ case "tool-call":
115
+ input.push({
116
+ type: "function_call",
117
+ call_id: part.toolCallId,
118
+ name: part.toolName,
119
+ arguments: JSON.stringify(part.input ?? {}),
120
+ thought_signature: getThoughtSignature(part.providerOptions)
121
+ });
122
+ break;
123
+ case "tool-result":
124
+ input.push({
125
+ type: "function_call_output",
126
+ call_id: part.toolCallId,
127
+ name: part.toolName,
128
+ output: serializeToolOutput(part.output),
129
+ thought_signature: getThoughtSignature(part.providerOptions)
130
+ });
131
+ break;
132
+ case "reasoning":
133
+ warnings.push({
134
+ type: "unsupported",
135
+ feature: "reasoning content in prompt"
136
+ });
137
+ break;
138
+ case "file":
139
+ case "reasoning-file":
140
+ case "custom": throw new UnsupportedFunctionalityError({ functionality: `assistant ${part.type} parts` });
141
+ default: throw new Error(`Unsupported assistant part: ${part}`);
142
+ }
143
+ break;
144
+ }
145
+ case "tool":
146
+ for (const part of content) {
147
+ if (part.type === "tool-approval-response") throw new UnsupportedFunctionalityError({ functionality: "tool approval responses" });
148
+ input.push({
149
+ type: "function_call_output",
150
+ call_id: part.toolCallId,
151
+ name: part.toolName,
152
+ output: serializeToolOutput(part.output),
153
+ thought_signature: getThoughtSignature(part.providerOptions)
154
+ });
155
+ }
156
+ break;
157
+ default: throw new Error(`Unsupported role: ${role}`);
158
+ }
159
+ return {
160
+ input,
161
+ warnings
162
+ };
257
163
  }
258
-
259
- // src/map-perplexity-finish-reason.ts
260
- function mapPerplexityFinishReason({
261
- status,
262
- incompleteReason,
263
- hasFunctionCall
264
- }) {
265
- switch (incompleteReason) {
266
- case "max_output_tokens":
267
- return "length";
268
- case "content_filter":
269
- return "content-filter";
270
- }
271
- switch (status) {
272
- case "completed":
273
- return hasFunctionCall ? "tool-calls" : "stop";
274
- case "requires_action":
275
- return "tool-calls";
276
- case "failed":
277
- return "error";
278
- case "cancelled":
279
- case "queued":
280
- case "in_progress":
281
- default:
282
- return hasFunctionCall ? "tool-calls" : "other";
283
- }
164
+ //#endregion
165
+ //#region src/map-perplexity-finish-reason.ts
166
+ function mapPerplexityFinishReason({ status, incompleteReason, hasFunctionCall }) {
167
+ switch (incompleteReason) {
168
+ case "max_output_tokens": return "length";
169
+ case "content_filter": return "content-filter";
170
+ }
171
+ switch (status) {
172
+ case "completed": return hasFunctionCall ? "tool-calls" : "stop";
173
+ case "requires_action": return "tool-calls";
174
+ case "failed": return "error";
175
+ default: return hasFunctionCall ? "tool-calls" : "other";
176
+ }
284
177
  }
285
-
286
- // src/perplexity-agent-api.ts
287
- import { z as z2 } from "zod/v4";
288
- var perplexitySearchResultSchema = z2.looseObject({
289
- id: z2.number().optional(),
290
- title: z2.string(),
291
- url: z2.string(),
292
- snippet: z2.string().optional(),
293
- date: z2.string().nullish(),
294
- last_updated: z2.string().nullish(),
295
- source: z2.string().optional()
178
+ //#endregion
179
+ //#region src/perplexity-agent-api.ts
180
+ const perplexitySearchResultSchema = z.looseObject({
181
+ id: z.number().optional(),
182
+ title: z.string(),
183
+ url: z.string(),
184
+ snippet: z.string().optional(),
185
+ date: z.string().nullish(),
186
+ last_updated: z.string().nullish(),
187
+ source: z.string().optional()
296
188
  });
297
- var perplexityFetchedContentSchema = z2.looseObject({
298
- title: z2.string(),
299
- url: z2.string(),
300
- snippet: z2.string().optional()
189
+ const perplexityFetchedContentSchema = z.looseObject({
190
+ title: z.string(),
191
+ url: z.string(),
192
+ snippet: z.string().optional()
301
193
  });
302
- var perplexityContentPartSchema = z2.looseObject({
303
- type: z2.string(),
304
- text: z2.string().optional(),
305
- annotations: z2.array(
306
- z2.looseObject({
307
- type: z2.string().optional(),
308
- url: z2.string().optional(),
309
- title: z2.string().optional()
310
- })
311
- ).nullish()
194
+ const perplexityContentPartSchema = z.looseObject({
195
+ type: z.string(),
196
+ text: z.string().optional(),
197
+ annotations: z.array(z.looseObject({
198
+ type: z.string().optional(),
199
+ url: z.string().optional(),
200
+ title: z.string().optional()
201
+ })).nullish()
312
202
  });
313
- var handledOutputTypes = [
314
- "message",
315
- "search_results",
316
- "fetch_url_results",
317
- "function_call"
203
+ const handledOutputTypes = [
204
+ "message",
205
+ "search_results",
206
+ "fetch_url_results",
207
+ "function_call"
318
208
  ];
319
- var perplexityOutputItemSchema = z2.union([
320
- z2.looseObject({
321
- type: z2.literal("message"),
322
- id: z2.string().nullish(),
323
- content: z2.array(perplexityContentPartSchema).nullish()
324
- }),
325
- z2.looseObject({
326
- type: z2.literal("search_results"),
327
- results: z2.array(perplexitySearchResultSchema).nullish()
328
- }),
329
- z2.looseObject({
330
- type: z2.literal("fetch_url_results"),
331
- contents: z2.array(perplexityFetchedContentSchema).nullish()
332
- }),
333
- z2.looseObject({
334
- type: z2.literal("function_call"),
335
- id: z2.string().nullish(),
336
- call_id: z2.string().nullish(),
337
- name: z2.string().nullish(),
338
- arguments: z2.string().nullish(),
339
- thought_signature: z2.string().nullish()
340
- }),
341
- // Native tool traces remain available in raw responses and raw stream chunks.
342
- // Their fields (e.g. finance_results.results) have different shapes. Do not
343
- // validate them as search results, or let malformed handled items fall back.
344
- z2.object({
345
- type: z2.string().refine((type) => !handledOutputTypes.includes(type))
346
- }).transform(() => ({ type: "unhandled" }))
209
+ const perplexityOutputItemSchema = z.union([
210
+ z.looseObject({
211
+ type: z.literal("message"),
212
+ id: z.string().nullish(),
213
+ content: z.array(perplexityContentPartSchema).nullish()
214
+ }),
215
+ z.looseObject({
216
+ type: z.literal("search_results"),
217
+ results: z.array(perplexitySearchResultSchema).nullish()
218
+ }),
219
+ z.looseObject({
220
+ type: z.literal("fetch_url_results"),
221
+ contents: z.array(perplexityFetchedContentSchema).nullish()
222
+ }),
223
+ z.looseObject({
224
+ type: z.literal("function_call"),
225
+ id: z.string().nullish(),
226
+ call_id: z.string().nullish(),
227
+ name: z.string().nullish(),
228
+ arguments: z.string().nullish(),
229
+ thought_signature: z.string().nullish()
230
+ }),
231
+ z.object({ type: z.string().refine((type) => !handledOutputTypes.includes(type)) }).transform(() => ({ type: "unhandled" }))
347
232
  ]);
348
- var perplexityCostSchema = z2.looseObject({
349
- currency: z2.string().optional(),
350
- input_cost: z2.number().optional(),
351
- output_cost: z2.number().optional(),
352
- total_cost: z2.number().optional(),
353
- cache_creation_cost: z2.number().nullish(),
354
- cache_read_cost: z2.number().nullish(),
355
- tool_calls_cost: z2.number().nullish()
233
+ const perplexityCostSchema = z.looseObject({
234
+ currency: z.string().optional(),
235
+ input_cost: z.number().optional(),
236
+ output_cost: z.number().optional(),
237
+ total_cost: z.number().optional(),
238
+ cache_creation_cost: z.number().nullish(),
239
+ cache_read_cost: z.number().nullish(),
240
+ tool_calls_cost: z.number().nullish()
356
241
  });
357
- var perplexityUsageSchema = z2.looseObject({
358
- input_tokens: z2.number(),
359
- output_tokens: z2.number(),
360
- total_tokens: z2.number(),
361
- input_tokens_details: z2.looseObject({
362
- cached_tokens: z2.number().optional(),
363
- cache_creation_input_tokens: z2.number().optional(),
364
- cache_read_input_tokens: z2.number().optional()
365
- }).nullish(),
366
- output_tokens_details: z2.looseObject({
367
- reasoning_tokens: z2.number().optional()
368
- }).nullish(),
369
- tool_calls_details: z2.record(
370
- z2.string(),
371
- z2.looseObject({
372
- invocation: z2.number().optional()
373
- })
374
- ).nullish(),
375
- cost: perplexityCostSchema.nullish()
242
+ const perplexityUsageSchema = z.looseObject({
243
+ input_tokens: z.number(),
244
+ output_tokens: z.number(),
245
+ total_tokens: z.number(),
246
+ input_tokens_details: z.looseObject({
247
+ cached_tokens: z.number().optional(),
248
+ cache_creation_input_tokens: z.number().optional(),
249
+ cache_read_input_tokens: z.number().optional()
250
+ }).nullish(),
251
+ output_tokens_details: z.looseObject({ reasoning_tokens: z.number().optional() }).nullish(),
252
+ tool_calls_details: z.record(z.string(), z.looseObject({ invocation: z.number().optional() })).nullish(),
253
+ cost: perplexityCostSchema.nullish()
376
254
  });
377
- var perplexityAgentResponseSchema = z2.looseObject({
378
- id: z2.string(),
379
- created_at: z2.number(),
380
- model: z2.string(),
381
- object: z2.literal("response"),
382
- output: z2.array(perplexityOutputItemSchema),
383
- status: z2.string(),
384
- incomplete_details: z2.looseObject({
385
- reason: z2.string()
386
- }).nullish(),
387
- error: z2.looseObject({
388
- code: z2.string().optional(),
389
- message: z2.string(),
390
- type: z2.string().optional()
391
- }).nullish(),
392
- usage: perplexityUsageSchema.nullish()
255
+ const perplexityAgentResponseSchema = z.looseObject({
256
+ id: z.string(),
257
+ created_at: z.number(),
258
+ model: z.string(),
259
+ object: z.literal("response"),
260
+ output: z.array(perplexityOutputItemSchema),
261
+ status: z.string(),
262
+ incomplete_details: z.looseObject({ reason: z.string() }).nullish(),
263
+ error: z.looseObject({
264
+ code: z.string().optional(),
265
+ message: z.string(),
266
+ type: z.string().optional()
267
+ }).nullish(),
268
+ usage: perplexityUsageSchema.nullish()
393
269
  });
394
- var perplexityAgentChunkSchema = z2.looseObject({
395
- type: z2.string(),
396
- sequence_number: z2.number().nullish(),
397
- response: perplexityAgentResponseSchema.nullish(),
398
- item: perplexityOutputItemSchema.nullish(),
399
- output_index: z2.number().nullish(),
400
- item_id: z2.string().nullish(),
401
- content_index: z2.number().nullish(),
402
- delta: z2.string().nullish(),
403
- text: z2.string().nullish(),
404
- thought: z2.string().nullish(),
405
- queries: z2.array(z2.string()).nullish(),
406
- urls: z2.array(z2.string()).nullish(),
407
- results: z2.array(perplexitySearchResultSchema).nullish(),
408
- contents: z2.array(perplexityFetchedContentSchema).nullish(),
409
- error: z2.looseObject({
410
- code: z2.string().nullish(),
411
- message: z2.string(),
412
- type: z2.string().nullish()
413
- }).nullish()
270
+ const perplexityAgentChunkSchema = z.looseObject({
271
+ type: z.string(),
272
+ sequence_number: z.number().nullish(),
273
+ response: perplexityAgentResponseSchema.nullish(),
274
+ item: perplexityOutputItemSchema.nullish(),
275
+ output_index: z.number().nullish(),
276
+ item_id: z.string().nullish(),
277
+ content_index: z.number().nullish(),
278
+ delta: z.string().nullish(),
279
+ text: z.string().nullish(),
280
+ thought: z.string().nullish(),
281
+ queries: z.array(z.string()).nullish(),
282
+ urls: z.array(z.string()).nullish(),
283
+ results: z.array(perplexitySearchResultSchema).nullish(),
284
+ contents: z.array(perplexityFetchedContentSchema).nullish(),
285
+ error: z.looseObject({
286
+ code: z.string().nullish(),
287
+ message: z.string(),
288
+ type: z.string().nullish()
289
+ }).nullish()
414
290
  });
415
- var perplexityErrorSchema = z2.looseObject({
416
- error: z2.union([
417
- z2.string(),
418
- z2.looseObject({
419
- code: z2.union([z2.string(), z2.number()]).optional(),
420
- message: z2.string().nullish(),
421
- type: z2.string().nullish()
422
- })
423
- ]).optional(),
424
- detail: z2.union([
425
- z2.string(),
426
- z2.array(
427
- z2.looseObject({
428
- msg: z2.string()
429
- })
430
- )
431
- ]).optional(),
432
- message: z2.string().optional()
291
+ const perplexityErrorSchema = z.looseObject({
292
+ error: z.union([z.string(), z.looseObject({
293
+ code: z.union([z.string(), z.number()]).optional(),
294
+ message: z.string().nullish(),
295
+ type: z.string().nullish()
296
+ })]).optional(),
297
+ detail: z.union([z.string(), z.array(z.looseObject({ msg: z.string() }))]).optional(),
298
+ message: z.string().optional()
433
299
  });
434
300
  function perplexityErrorToMessage(data) {
435
- if (typeof data.error === "string") {
436
- return data.error;
437
- }
438
- if (data.error != null) {
439
- return data.error.message ?? data.error.type ?? "unknown error";
440
- }
441
- if (typeof data.detail === "string") {
442
- return data.detail;
443
- }
444
- if (Array.isArray(data.detail)) {
445
- return data.detail.map((detail) => detail.msg).join(", ");
446
- }
447
- return data.message ?? "unknown error";
301
+ if (typeof data.error === "string") return data.error;
302
+ if (data.error != null) return data.error.message ?? data.error.type ?? "unknown error";
303
+ if (typeof data.detail === "string") return data.detail;
304
+ if (Array.isArray(data.detail)) return data.detail.map((detail) => detail.msg).join(", ");
305
+ return data.message ?? "unknown error";
448
306
  }
449
-
450
- // src/perplexity-language-model-options.ts
451
- import { z as z3 } from "zod/v4";
452
- var userLocationSchema = z3.looseObject({
453
- latitude: z3.number().optional(),
454
- longitude: z3.number().optional(),
455
- country: z3.string().optional(),
456
- city: z3.string().optional(),
457
- region: z3.string().optional()
307
+ //#endregion
308
+ //#region src/perplexity-language-model-options.ts
309
+ const userLocationSchema = z.looseObject({
310
+ latitude: z.number().optional(),
311
+ longitude: z.number().optional(),
312
+ country: z.string().optional(),
313
+ city: z.string().optional(),
314
+ region: z.string().optional()
458
315
  });
459
- var webSearchFiltersSchema = z3.looseObject({
460
- search_domain_filter: z3.array(z3.string()).optional(),
461
- search_recency_filter: z3.enum(["hour", "day", "week", "month", "year"]).optional(),
462
- search_after_date_filter: z3.string().optional(),
463
- search_before_date_filter: z3.string().optional(),
464
- last_updated_after_filter: z3.string().optional(),
465
- last_updated_before_filter: z3.string().optional()
316
+ const webSearchFiltersSchema = z.looseObject({
317
+ search_domain_filter: z.array(z.string()).optional(),
318
+ search_recency_filter: z.enum([
319
+ "hour",
320
+ "day",
321
+ "week",
322
+ "month",
323
+ "year"
324
+ ]).optional(),
325
+ search_after_date_filter: z.string().optional(),
326
+ search_before_date_filter: z.string().optional(),
327
+ last_updated_after_filter: z.string().optional(),
328
+ last_updated_before_filter: z.string().optional()
466
329
  });
467
- var webSearchToolSchema = z3.looseObject({
468
- type: z3.literal("web_search"),
469
- filters: webSearchFiltersSchema.optional(),
470
- max_results: z3.number().int().positive().optional(),
471
- max_tokens: z3.number().optional(),
472
- max_tokens_per_page: z3.number().optional(),
473
- search_context_size: z3.enum(["low", "medium", "high"]).optional(),
474
- user_location: userLocationSchema.optional()
330
+ const webSearchToolSchema = z.looseObject({
331
+ type: z.literal("web_search"),
332
+ filters: webSearchFiltersSchema.optional(),
333
+ max_results: z.number().int().positive().optional(),
334
+ max_tokens: z.number().optional(),
335
+ max_tokens_per_page: z.number().optional(),
336
+ search_context_size: z.enum([
337
+ "low",
338
+ "medium",
339
+ "high"
340
+ ]).optional(),
341
+ user_location: userLocationSchema.optional()
475
342
  });
476
- var nativeToolSchema = z3.union([
477
- webSearchToolSchema,
478
- z3.looseObject({
479
- type: z3.literal("fetch_url"),
480
- max_urls: z3.number().optional()
481
- }),
482
- z3.looseObject({ type: z3.literal("people_search") }),
483
- z3.looseObject({ type: z3.literal("finance_search") }),
484
- z3.looseObject({ type: z3.literal("sandbox") }),
485
- z3.looseObject({
486
- type: z3.literal("mcp"),
487
- server_label: z3.string(),
488
- server_url: z3.string(),
489
- allowed_tools: z3.array(z3.string()).optional(),
490
- authorization: z3.string().optional(),
491
- defer_loading: z3.boolean().optional(),
492
- headers: z3.record(z3.string(), z3.string()).optional()
493
- }),
494
- z3.looseObject({
495
- type: z3.literal("connector"),
496
- id: z3.string(),
497
- server_label: z3.string(),
498
- server_description: z3.string().optional(),
499
- allowed_tools: z3.array(z3.string()).optional()
500
- })
343
+ const nativeToolSchema = z.union([
344
+ webSearchToolSchema,
345
+ z.looseObject({
346
+ type: z.literal("fetch_url"),
347
+ max_urls: z.number().optional()
348
+ }),
349
+ z.looseObject({ type: z.literal("people_search") }),
350
+ z.looseObject({ type: z.literal("finance_search") }),
351
+ z.looseObject({ type: z.literal("sandbox") }),
352
+ z.looseObject({
353
+ type: z.literal("mcp"),
354
+ server_label: z.string(),
355
+ server_url: z.string(),
356
+ allowed_tools: z.array(z.string()).optional(),
357
+ authorization: z.string().optional(),
358
+ defer_loading: z.boolean().optional(),
359
+ headers: z.record(z.string(), z.string()).optional()
360
+ }),
361
+ z.looseObject({
362
+ type: z.literal("connector"),
363
+ id: z.string(),
364
+ server_label: z.string(),
365
+ server_description: z.string().optional(),
366
+ allowed_tools: z.array(z.string()).optional()
367
+ })
501
368
  ]);
502
- var perplexityLanguageModelOptions = z3.looseObject({
503
- /** Top-level Agent API instructions. */
504
- instructions: z3.string().optional(),
505
- /**
506
- * Native Agent API tools. AI SDK function tools can also be supplied through
507
- * the top-level `tools` option on `generateText` and `streamText`.
508
- */
509
- tools: z3.array(nativeToolSchema).optional(),
510
- /** A fallback model list for Agent API routing. */
511
- models: z3.array(z3.string()).optional(),
512
- /** Maximum number of agentic steps. */
513
- max_steps: z3.number().int().positive().optional(),
514
- /** Maximum number of native tool calls. */
515
- max_tool_calls: z3.number().int().nonnegative().optional(),
516
- /** Continue a conversation from an earlier Agent API response. */
517
- previous_response_id: z3.string().optional(),
518
- /**
519
- * Whether the response can be retrieved later. Setting this to false does
520
- * not disable persistence or prevent previous_response_id continuations.
521
- */
522
- store: z3.boolean().optional(),
523
- /** Preferred response language as an ISO 639-1 language code. */
524
- language_preference: z3.string().optional(),
525
- /** Agent API reasoning configuration. */
526
- reasoning: z3.looseObject({
527
- effort: z3.enum(["minimal", "low", "medium", "high", "xhigh"]).optional()
528
- }).optional(),
529
- /** Agent API skill configuration. */
530
- skills: z3.array(
531
- z3.union([
532
- z3.looseObject({
533
- type: z3.literal("builtin"),
534
- name: z3.enum([
535
- "office",
536
- "office/docx",
537
- "office/pdf",
538
- "office/pptx",
539
- "office/xlsx"
540
- ])
541
- }),
542
- z3.looseObject({
543
- type: z3.literal("inline"),
544
- name: z3.string(),
545
- description: z3.string(),
546
- instructions: z3.string()
547
- })
548
- ])
549
- ).optional()
369
+ const perplexityLanguageModelOptions = z.looseObject({
370
+ /** Top-level Agent API instructions. */
371
+ instructions: z.string().optional(),
372
+ /**
373
+ * Native Agent API tools. AI SDK function tools can also be supplied through
374
+ * the top-level `tools` option on `generateText` and `streamText`.
375
+ */
376
+ tools: z.array(nativeToolSchema).optional(),
377
+ /** A fallback model list for Agent API routing. */
378
+ models: z.array(z.string()).optional(),
379
+ /** Maximum number of agentic steps. */
380
+ max_steps: z.number().int().positive().optional(),
381
+ /** Maximum number of native tool calls. */
382
+ max_tool_calls: z.number().int().nonnegative().optional(),
383
+ /** Continue a conversation from an earlier Agent API response. */
384
+ previous_response_id: z.string().optional(),
385
+ /**
386
+ * Whether the response can be retrieved later. Setting this to false does
387
+ * not disable persistence or prevent previous_response_id continuations.
388
+ */
389
+ store: z.boolean().optional(),
390
+ /** Preferred response language as an ISO 639-1 language code. */
391
+ language_preference: z.string().optional(),
392
+ /** Agent API reasoning configuration. */
393
+ reasoning: z.looseObject({ effort: z.enum([
394
+ "minimal",
395
+ "low",
396
+ "medium",
397
+ "high",
398
+ "xhigh"
399
+ ]).optional() }).optional(),
400
+ /** Agent API skill configuration. */
401
+ skills: z.array(z.union([z.looseObject({
402
+ type: z.literal("builtin"),
403
+ name: z.enum([
404
+ "office",
405
+ "office/docx",
406
+ "office/pdf",
407
+ "office/pptx",
408
+ "office/xlsx"
409
+ ])
410
+ }), z.looseObject({
411
+ type: z.literal("inline"),
412
+ name: z.string(),
413
+ description: z.string(),
414
+ instructions: z.string()
415
+ })])).optional()
550
416
  });
551
-
552
- // src/perplexity-prepare-tools.ts
553
- function preparePerplexityTools({
554
- tools,
555
- toolChoice
556
- }) {
557
- const preparedTools = [];
558
- const warnings = [];
559
- for (const tool of tools ?? []) {
560
- if (tool.type === "provider") {
561
- warnings.push({
562
- type: "unsupported",
563
- feature: `provider-defined tool ${tool.name}`
564
- });
565
- continue;
566
- }
567
- preparedTools.push({
568
- type: "function",
569
- name: tool.name,
570
- description: tool.description,
571
- parameters: tool.inputSchema,
572
- strict: tool.strict
573
- });
574
- }
575
- if (toolChoice != null && toolChoice.type !== "auto") {
576
- warnings.push({
577
- type: "unsupported",
578
- feature: "toolChoice",
579
- details: "The Perplexity Agent API currently selects tools automatically."
580
- });
581
- }
582
- return { tools: preparedTools, warnings };
417
+ //#endregion
418
+ //#region src/perplexity-prepare-tools.ts
419
+ function preparePerplexityTools({ tools, toolChoice }) {
420
+ const preparedTools = [];
421
+ const warnings = [];
422
+ for (const tool of tools ?? []) {
423
+ if (tool.type === "provider") {
424
+ warnings.push({
425
+ type: "unsupported",
426
+ feature: `provider-defined tool ${tool.name}`
427
+ });
428
+ continue;
429
+ }
430
+ preparedTools.push({
431
+ type: "function",
432
+ name: tool.name,
433
+ description: tool.description,
434
+ parameters: tool.inputSchema,
435
+ strict: tool.strict
436
+ });
437
+ }
438
+ if (toolChoice != null && toolChoice.type !== "auto") warnings.push({
439
+ type: "unsupported",
440
+ feature: "toolChoice",
441
+ details: "The Perplexity Agent API currently selects tools automatically."
442
+ });
443
+ return {
444
+ tools: preparedTools,
445
+ warnings
446
+ };
583
447
  }
584
-
585
- // src/perplexity-language-model.ts
586
- var presetIds = /* @__PURE__ */ new Set([
587
- "fast",
588
- "low",
589
- "medium",
590
- "high",
591
- "xhigh"
448
+ //#endregion
449
+ //#region src/perplexity-language-model.ts
450
+ const presetIds = /* @__PURE__ */ new Set([
451
+ "fast",
452
+ "low",
453
+ "medium",
454
+ "high",
455
+ "xhigh"
592
456
  ]);
593
457
  function getModelSelection(modelId) {
594
- if (presetIds.has(modelId)) {
595
- return { preset: modelId };
596
- }
597
- return { model: modelId };
458
+ if (presetIds.has(modelId)) return { preset: modelId };
459
+ return { model: modelId };
598
460
  }
599
461
  function getResponseMetadata(response) {
600
- return createLanguageModelResponseMetadata({
601
- id: response.id,
602
- model: response.model,
603
- created: response.created_at
604
- });
462
+ return createLanguageModelResponseMetadata({
463
+ id: response.id,
464
+ model: response.model,
465
+ created: response.created_at
466
+ });
605
467
  }
606
468
  function getProviderMetadata(usage) {
607
- const cost = usage?.cost;
608
- const numSearchQueries = usage?.tool_calls_details ? Object.entries(usage.tool_calls_details).filter(([name]) => name.includes("search")).reduce((total, [, details]) => total + (details.invocation ?? 0), 0) : null;
609
- return {
610
- perplexity: {
611
- usage: {
612
- citationTokens: null,
613
- numSearchQueries
614
- },
615
- images: null,
616
- cost: cost == null ? null : {
617
- inputTokensCost: cost.input_cost ?? null,
618
- outputTokensCost: cost.output_cost ?? null,
619
- requestCost: null,
620
- totalCost: cost.total_cost ?? null,
621
- currency: cost.currency ?? null,
622
- cacheCreationCost: cost.cache_creation_cost ?? null,
623
- cacheReadCost: cost.cache_read_cost ?? null,
624
- toolCallsCost: cost.tool_calls_cost ?? null
625
- },
626
- toolCalls: usage?.tool_calls_details == null ? null : Object.fromEntries(
627
- Object.entries(usage.tool_calls_details).map(
628
- ([name, details]) => [
629
- name,
630
- { invocation: details.invocation ?? null }
631
- ]
632
- )
633
- )
634
- }
635
- };
469
+ const cost = usage?.cost;
470
+ return { perplexity: {
471
+ usage: {
472
+ citationTokens: null,
473
+ numSearchQueries: usage?.tool_calls_details ? Object.entries(usage.tool_calls_details).filter(([name]) => name.includes("search")).reduce((total, [, details]) => total + (details.invocation ?? 0), 0) : null
474
+ },
475
+ images: null,
476
+ cost: cost == null ? null : {
477
+ inputTokensCost: cost.input_cost ?? null,
478
+ outputTokensCost: cost.output_cost ?? null,
479
+ requestCost: null,
480
+ totalCost: cost.total_cost ?? null,
481
+ currency: cost.currency ?? null,
482
+ cacheCreationCost: cost.cache_creation_cost ?? null,
483
+ cacheReadCost: cost.cache_read_cost ?? null,
484
+ toolCallsCost: cost.tool_calls_cost ?? null
485
+ },
486
+ toolCalls: usage?.tool_calls_details == null ? null : Object.fromEntries(Object.entries(usage.tool_calls_details).map(([name, details]) => [name, { invocation: details.invocation ?? null }]))
487
+ } };
636
488
  }
637
- function createSource(result, generateId2) {
638
- return {
639
- type: "source",
640
- sourceType: "url",
641
- id: result.id == null ? generateId2() : String(result.id),
642
- url: result.url,
643
- title: result.title,
644
- providerMetadata: {
645
- perplexity: {
646
- resultId: result.id ?? null,
647
- snippet: result.snippet ?? null,
648
- date: result.date ?? null,
649
- lastUpdated: result.last_updated ?? null,
650
- source: result.source ?? null
651
- }
652
- }
653
- };
489
+ function createSource(result, generateId) {
490
+ return {
491
+ type: "source",
492
+ sourceType: "url",
493
+ id: result.id == null ? generateId() : String(result.id),
494
+ url: result.url,
495
+ title: result.title,
496
+ providerMetadata: { perplexity: {
497
+ resultId: result.id ?? null,
498
+ snippet: result.snippet ?? null,
499
+ date: result.date ?? null,
500
+ lastUpdated: result.last_updated ?? null,
501
+ source: result.source ?? null
502
+ } }
503
+ };
654
504
  }
655
505
  function hasSearchResultId(source) {
656
- return typeof source.providerMetadata?.perplexity?.resultId === "number";
506
+ return typeof source.providerMetadata?.perplexity?.resultId === "number";
657
507
  }
658
508
  function getSearchResults(item) {
659
- return item.type === "search_results" ? item.results ?? [] : [];
509
+ return item.type === "search_results" ? item.results ?? [] : [];
660
510
  }
661
511
  function getFetchedSources(item) {
662
- return item.type === "fetch_url_results" ? item.contents ?? [] : [];
512
+ return item.type === "fetch_url_results" ? item.contents ?? [] : [];
663
513
  }
664
- var PerplexityLanguageModel = class _PerplexityLanguageModel {
665
- constructor(modelId, config) {
666
- this.specificationVersion = "v4";
667
- this.provider = "perplexity";
668
- this.supportedUrls = {
669
- "image/*": [/^https?:\/\/.*$/]
670
- };
671
- this.modelId = modelId;
672
- this.config = config;
673
- }
674
- static [WORKFLOW_SERIALIZE](model) {
675
- return serializeModelOptions({
676
- modelId: model.modelId,
677
- config: model.config
678
- });
679
- }
680
- static [WORKFLOW_DESERIALIZE](options) {
681
- return new _PerplexityLanguageModel(options.modelId, options.config);
682
- }
683
- async getArgs({
684
- prompt,
685
- maxOutputTokens,
686
- temperature,
687
- topP,
688
- topK,
689
- frequencyPenalty,
690
- presencePenalty,
691
- stopSequences,
692
- reasoning,
693
- responseFormat,
694
- seed,
695
- providerOptions,
696
- tools,
697
- toolChoice
698
- }) {
699
- const warnings = [];
700
- const perplexityOptions = await parseProviderOptions({
701
- provider: "perplexity",
702
- providerOptions,
703
- schema: perplexityLanguageModelOptions
704
- }) ?? {};
705
- if (topK != null) {
706
- warnings.push({ type: "unsupported", feature: "topK" });
707
- }
708
- if (frequencyPenalty != null) {
709
- warnings.push({ type: "unsupported", feature: "frequencyPenalty" });
710
- }
711
- if (presencePenalty != null) {
712
- warnings.push({ type: "unsupported", feature: "presencePenalty" });
713
- }
714
- if (stopSequences != null) {
715
- warnings.push({ type: "unsupported", feature: "stopSequences" });
716
- }
717
- if (seed != null) {
718
- warnings.push({ type: "unsupported", feature: "seed" });
719
- }
720
- const { tools: nativeTools, ...agentOptions } = perplexityOptions;
721
- const modelSelection = getModelSelection(this.modelId);
722
- const { input, warnings: inputWarnings } = convertToPerplexityInput(prompt);
723
- warnings.push(...inputWarnings);
724
- const { tools: functionTools, warnings: toolWarnings } = preparePerplexityTools({ tools, toolChoice });
725
- warnings.push(...toolWarnings);
726
- const agentTools = [
727
- ...nativeTools ?? [],
728
- ...functionTools
729
- ];
730
- let reasoningConfig = agentOptions.reasoning;
731
- if (reasoningConfig == null && isCustomReasoning(reasoning)) {
732
- if (reasoning === "none") {
733
- warnings.push({
734
- type: "unsupported",
735
- feature: 'reasoning "none"'
736
- });
737
- } else {
738
- reasoningConfig = { effort: reasoning };
739
- }
740
- }
741
- const body = {
742
- ...agentOptions,
743
- ...modelSelection,
744
- input,
745
- max_output_tokens: maxOutputTokens,
746
- temperature,
747
- top_p: topP,
748
- reasoning: reasoningConfig,
749
- response_format: responseFormat?.type === "json" && responseFormat.schema != null ? {
750
- type: "json_schema",
751
- json_schema: {
752
- name: responseFormat.name ?? "response",
753
- description: responseFormat.description,
754
- schema: responseFormat.schema,
755
- strict: true
756
- }
757
- } : void 0,
758
- tools: agentTools.length > 0 ? agentTools : void 0
759
- };
760
- if (responseFormat?.type === "json" && responseFormat.schema == null) {
761
- warnings.push({
762
- type: "unsupported",
763
- feature: "JSON response format without a schema"
764
- });
765
- }
766
- return { args: body, warnings };
767
- }
768
- async doGenerate(options) {
769
- const { args: body, warnings } = await this.getArgs(options);
770
- const url = `${this.config.baseURL}/v1/agent`;
771
- const {
772
- responseHeaders,
773
- value: response,
774
- rawValue: rawResponse
775
- } = await postJsonToApi({
776
- url,
777
- headers: combineHeaders(this.config.headers?.(), options.headers),
778
- body,
779
- failedResponseHandler: createJsonErrorResponseHandler({
780
- errorSchema: perplexityErrorSchema,
781
- errorToMessage: perplexityErrorToMessage
782
- }),
783
- successfulResponseHandler: createJsonResponseHandler(
784
- perplexityAgentResponseSchema
785
- ),
786
- abortSignal: options.abortSignal,
787
- fetch: this.config.fetch
788
- });
789
- if (response.error != null || response.status === "failed") {
790
- throw new APICallError({
791
- message: response.error?.message ?? "Perplexity response failed",
792
- url,
793
- requestBodyValues: body,
794
- statusCode: 400,
795
- responseHeaders,
796
- responseBody: rawResponse,
797
- isRetryable: false
798
- });
799
- }
800
- const content = [];
801
- const sourceIndexesByUrl = /* @__PURE__ */ new Map();
802
- let hasFunctionCall = false;
803
- const addSource = (source) => {
804
- const existingIndex = sourceIndexesByUrl.get(source.url);
805
- if (existingIndex == null) {
806
- sourceIndexesByUrl.set(source.url, content.length);
807
- content.push(source);
808
- } else if (hasSearchResultId(source) && !hasSearchResultId(content[existingIndex])) {
809
- content[existingIndex] = source;
810
- }
811
- };
812
- for (const item of response.output) {
813
- if (item.type === "message") {
814
- for (const part of item.content ?? []) {
815
- if (part.type === "output_text" && part.text != null) {
816
- content.push({ type: "text", text: part.text });
817
- }
818
- for (const annotation of part.annotations ?? []) {
819
- if (annotation.url != null) {
820
- addSource({
821
- type: "source",
822
- sourceType: "url",
823
- id: this.config.generateId(),
824
- url: annotation.url,
825
- title: annotation.title
826
- });
827
- }
828
- }
829
- }
830
- } else if (item.type === "search_results") {
831
- for (const result of getSearchResults(item)) {
832
- addSource(createSource(result, this.config.generateId));
833
- }
834
- } else if (item.type === "fetch_url_results") {
835
- for (const result of getFetchedSources(item)) {
836
- addSource({
837
- type: "source",
838
- sourceType: "url",
839
- id: this.config.generateId(),
840
- url: result.url,
841
- title: result.title,
842
- providerMetadata: {
843
- perplexity: { snippet: result.snippet ?? null }
844
- }
845
- });
846
- }
847
- } else if (item.type === "function_call" && item.call_id != null && item.name != null && item.arguments != null) {
848
- hasFunctionCall = true;
849
- content.push({
850
- type: "tool-call",
851
- toolCallId: item.call_id,
852
- toolName: item.name,
853
- input: item.arguments,
854
- providerMetadata: {
855
- perplexity: {
856
- itemId: item.id ?? null,
857
- ...item.thought_signature != null && {
858
- thoughtSignature: item.thought_signature
859
- }
860
- }
861
- }
862
- });
863
- }
864
- }
865
- const finishReason = response.incomplete_details?.reason ?? response.status;
866
- return {
867
- content,
868
- finishReason: {
869
- unified: mapPerplexityFinishReason({
870
- status: response.status,
871
- incompleteReason: response.incomplete_details?.reason,
872
- hasFunctionCall
873
- }),
874
- raw: finishReason
875
- },
876
- usage: convertPerplexityUsage(response.usage),
877
- request: { body },
878
- response: {
879
- ...getResponseMetadata(response),
880
- headers: responseHeaders,
881
- body: rawResponse
882
- },
883
- warnings,
884
- providerMetadata: getProviderMetadata(response.usage)
885
- };
886
- }
887
- async doStream(options) {
888
- const { args, warnings } = await this.getArgs(options);
889
- const body = { ...args, stream: true };
890
- const { responseHeaders, value: response } = await postJsonToApi({
891
- url: `${this.config.baseURL}/v1/agent`,
892
- headers: combineHeaders(this.config.headers?.(), options.headers),
893
- body,
894
- failedResponseHandler: createJsonErrorResponseHandler({
895
- errorSchema: perplexityErrorSchema,
896
- errorToMessage: perplexityErrorToMessage
897
- }),
898
- successfulResponseHandler: createEventSourceResponseHandler(
899
- perplexityAgentChunkSchema
900
- ),
901
- abortSignal: options.abortSignal,
902
- fetch: this.config.fetch
903
- });
904
- let finishReason = {
905
- unified: "other",
906
- raw: void 0
907
- };
908
- let usage;
909
- let hasFunctionCall = false;
910
- let hasResponseMetadata = false;
911
- let activeReasoningId;
912
- const textStates = /* @__PURE__ */ new Map();
913
- const emittedSourceUrls = /* @__PURE__ */ new Set();
914
- const pendingSourcesByUrl = /* @__PURE__ */ new Map();
915
- const seenFunctionCalls = /* @__PURE__ */ new Set();
916
- const generateId2 = this.config.generateId;
917
- return {
918
- stream: response.pipeThrough(
919
- new TransformStream({
920
- start(controller) {
921
- controller.enqueue({ type: "stream-start", warnings });
922
- },
923
- transform(chunk, controller) {
924
- if (options.includeRawChunks) {
925
- controller.enqueue({ type: "raw", rawValue: chunk.rawValue });
926
- }
927
- if (!chunk.success) {
928
- finishReason = { unified: "error", raw: void 0 };
929
- controller.enqueue({ type: "error", error: chunk.error });
930
- return;
931
- }
932
- const value = chunk.value;
933
- const getTextId = (itemId, outputIndex, contentIndex = 0) => {
934
- const id = itemId ?? String(outputIndex ?? "text");
935
- return contentIndex == null || contentIndex === 0 ? id : `${id}:${contentIndex}`;
936
- };
937
- const emitTextDelta = (id, delta) => {
938
- let state = textStates.get(id);
939
- if (state?.ended) {
940
- return;
941
- }
942
- if (state == null) {
943
- state = { text: "", ended: false };
944
- textStates.set(id, state);
945
- controller.enqueue({ type: "text-start", id });
946
- }
947
- state.text += delta;
948
- controller.enqueue({ type: "text-delta", id, delta });
949
- };
950
- const finishText = (id, text) => {
951
- const state = textStates.get(id);
952
- if (state?.ended) {
953
- return;
954
- }
955
- const emittedText = state?.text ?? "";
956
- if (text != null && text.startsWith(emittedText) && text.length > emittedText.length) {
957
- emitTextDelta(id, text.slice(emittedText.length));
958
- }
959
- const finalState = textStates.get(id);
960
- if (finalState != null) {
961
- finalState.ended = true;
962
- controller.enqueue({ type: "text-end", id });
963
- }
964
- };
965
- const finishOutputText = (item, outputIndex) => {
966
- if (item.type === "message") {
967
- for (const [contentIndex, part] of (item.content ?? []).entries()) {
968
- if (part.type === "output_text") {
969
- finishText(
970
- getTextId(item.id, outputIndex, contentIndex),
971
- part.text
972
- );
973
- }
974
- }
975
- }
976
- };
977
- const emitSource = (source) => {
978
- if (emittedSourceUrls.has(source.url)) {
979
- return;
980
- }
981
- if (hasSearchResultId(source)) {
982
- pendingSourcesByUrl.delete(source.url);
983
- emittedSourceUrls.add(source.url);
984
- controller.enqueue(source);
985
- } else if (!pendingSourcesByUrl.has(source.url)) {
986
- pendingSourcesByUrl.set(source.url, source);
987
- }
988
- };
989
- const emitReasoningThought = (thought) => {
990
- if (activeReasoningId != null && thought != null) {
991
- controller.enqueue({
992
- type: "reasoning-delta",
993
- id: activeReasoningId,
994
- delta: thought
995
- });
996
- }
997
- };
998
- const emitFunctionCall = (item) => {
999
- if (item.type !== "function_call" || item.call_id == null || item.name == null || item.arguments == null || seenFunctionCalls.has(item.call_id)) {
1000
- return;
1001
- }
1002
- seenFunctionCalls.add(item.call_id);
1003
- hasFunctionCall = true;
1004
- controller.enqueue({
1005
- type: "tool-input-start",
1006
- id: item.call_id,
1007
- toolName: item.name
1008
- });
1009
- controller.enqueue({
1010
- type: "tool-input-delta",
1011
- id: item.call_id,
1012
- delta: item.arguments
1013
- });
1014
- controller.enqueue({ type: "tool-input-end", id: item.call_id });
1015
- controller.enqueue({
1016
- type: "tool-call",
1017
- toolCallId: item.call_id,
1018
- toolName: item.name,
1019
- input: item.arguments,
1020
- providerMetadata: {
1021
- perplexity: {
1022
- itemId: item.id ?? null,
1023
- ...item.thought_signature != null && {
1024
- thoughtSignature: item.thought_signature
1025
- }
1026
- }
1027
- }
1028
- });
1029
- };
1030
- const emitOutputSources = (item) => {
1031
- if (item.type === "message") {
1032
- for (const part of item.content ?? []) {
1033
- for (const annotation of part.annotations ?? []) {
1034
- if (annotation.url != null) {
1035
- emitSource({
1036
- type: "source",
1037
- sourceType: "url",
1038
- id: generateId2(),
1039
- url: annotation.url,
1040
- title: annotation.title
1041
- });
1042
- }
1043
- }
1044
- }
1045
- }
1046
- for (const result of getSearchResults(item)) {
1047
- emitSource(createSource(result, generateId2));
1048
- }
1049
- for (const result of getFetchedSources(item)) {
1050
- emitSource({
1051
- type: "source",
1052
- sourceType: "url",
1053
- id: generateId2(),
1054
- url: result.url,
1055
- title: result.title,
1056
- providerMetadata: {
1057
- perplexity: { snippet: result.snippet ?? null }
1058
- }
1059
- });
1060
- }
1061
- };
1062
- switch (value.type) {
1063
- case "response.created":
1064
- case "response.in_progress": {
1065
- if (!hasResponseMetadata && value.response != null) {
1066
- controller.enqueue({
1067
- type: "response-metadata",
1068
- ...getResponseMetadata(value.response)
1069
- });
1070
- hasResponseMetadata = true;
1071
- }
1072
- break;
1073
- }
1074
- case "response.output_text.delta": {
1075
- if (value.delta != null) {
1076
- emitTextDelta(
1077
- getTextId(
1078
- value.item_id,
1079
- value.output_index,
1080
- value.content_index
1081
- ),
1082
- value.delta
1083
- );
1084
- }
1085
- break;
1086
- }
1087
- case "response.output_text.done": {
1088
- finishText(
1089
- getTextId(
1090
- value.item_id,
1091
- value.output_index,
1092
- value.content_index
1093
- ),
1094
- value.text
1095
- );
1096
- break;
1097
- }
1098
- case "response.reasoning.started": {
1099
- if (activeReasoningId != null) {
1100
- controller.enqueue({
1101
- type: "reasoning-end",
1102
- id: activeReasoningId
1103
- });
1104
- }
1105
- activeReasoningId = `reasoning-${value.sequence_number ?? generateId2()}`;
1106
- controller.enqueue({
1107
- type: "reasoning-start",
1108
- id: activeReasoningId
1109
- });
1110
- emitReasoningThought(value.thought);
1111
- break;
1112
- }
1113
- case "response.reasoning.search_queries":
1114
- case "response.reasoning.fetch_url_queries": {
1115
- emitReasoningThought(value.thought);
1116
- break;
1117
- }
1118
- case "response.reasoning.search_results": {
1119
- emitReasoningThought(value.thought);
1120
- for (const result of value.results ?? []) {
1121
- emitSource(createSource(result, generateId2));
1122
- }
1123
- break;
1124
- }
1125
- case "response.reasoning.fetch_url_results": {
1126
- emitReasoningThought(value.thought);
1127
- for (const result of value.contents ?? []) {
1128
- emitSource({
1129
- type: "source",
1130
- sourceType: "url",
1131
- id: generateId2(),
1132
- url: result.url,
1133
- title: result.title,
1134
- providerMetadata: {
1135
- perplexity: { snippet: result.snippet ?? null }
1136
- }
1137
- });
1138
- }
1139
- break;
1140
- }
1141
- case "response.reasoning.stopped": {
1142
- emitReasoningThought(value.thought);
1143
- if (activeReasoningId != null) {
1144
- controller.enqueue({
1145
- type: "reasoning-end",
1146
- id: activeReasoningId
1147
- });
1148
- activeReasoningId = void 0;
1149
- }
1150
- break;
1151
- }
1152
- case "response.output_item.done": {
1153
- if (value.item != null) {
1154
- finishOutputText(value.item, value.output_index);
1155
- emitOutputSources(value.item);
1156
- emitFunctionCall(value.item);
1157
- }
1158
- break;
1159
- }
1160
- case "response.completed":
1161
- case "response.incomplete": {
1162
- if (value.response != null) {
1163
- if (!hasResponseMetadata) {
1164
- controller.enqueue({
1165
- type: "response-metadata",
1166
- ...getResponseMetadata(value.response)
1167
- });
1168
- hasResponseMetadata = true;
1169
- }
1170
- for (const [
1171
- outputIndex,
1172
- item
1173
- ] of value.response.output.entries()) {
1174
- finishOutputText(item, outputIndex);
1175
- emitOutputSources(item);
1176
- emitFunctionCall(item);
1177
- }
1178
- usage = value.response.usage ?? void 0;
1179
- const rawFinishReason = value.response.incomplete_details?.reason ?? value.response.status;
1180
- finishReason = {
1181
- unified: mapPerplexityFinishReason({
1182
- status: value.response.status,
1183
- incompleteReason: value.response.incomplete_details?.reason,
1184
- hasFunctionCall
1185
- }),
1186
- raw: rawFinishReason
1187
- };
1188
- }
1189
- break;
1190
- }
1191
- case "response.failed": {
1192
- finishReason = { unified: "error", raw: "failed" };
1193
- controller.enqueue({
1194
- type: "error",
1195
- error: value.error ?? new Error("Perplexity response failed")
1196
- });
1197
- break;
1198
- }
1199
- }
1200
- },
1201
- flush(controller) {
1202
- for (const source of pendingSourcesByUrl.values()) {
1203
- controller.enqueue(source);
1204
- }
1205
- if (activeReasoningId != null) {
1206
- controller.enqueue({
1207
- type: "reasoning-end",
1208
- id: activeReasoningId
1209
- });
1210
- }
1211
- for (const [id, state] of textStates) {
1212
- if (!state.ended) {
1213
- controller.enqueue({ type: "text-end", id });
1214
- }
1215
- }
1216
- controller.enqueue({
1217
- type: "finish",
1218
- finishReason,
1219
- usage: convertPerplexityUsage(usage),
1220
- providerMetadata: getProviderMetadata(usage)
1221
- });
1222
- }
1223
- })
1224
- ),
1225
- request: { body },
1226
- response: { headers: responseHeaders }
1227
- };
1228
- }
514
+ var PerplexityLanguageModel = class PerplexityLanguageModel {
515
+ static [WORKFLOW_SERIALIZE](model) {
516
+ return serializeModelOptions({
517
+ modelId: model.modelId,
518
+ config: model.config
519
+ });
520
+ }
521
+ static [WORKFLOW_DESERIALIZE](options) {
522
+ return new PerplexityLanguageModel(options.modelId, options.config);
523
+ }
524
+ constructor(modelId, config) {
525
+ this.specificationVersion = "v4";
526
+ this.provider = "perplexity";
527
+ this.supportedUrls = { "image/*": [/^https?:\/\/.*$/] };
528
+ this.modelId = modelId;
529
+ this.config = config;
530
+ }
531
+ async getArgs({ prompt, maxOutputTokens, temperature, topP, topK, frequencyPenalty, presencePenalty, stopSequences, reasoning, responseFormat, seed, providerOptions, tools, toolChoice }) {
532
+ const warnings = [];
533
+ const perplexityOptions = await parseProviderOptions({
534
+ provider: "perplexity",
535
+ providerOptions,
536
+ schema: perplexityLanguageModelOptions
537
+ }) ?? {};
538
+ if (topK != null) warnings.push({
539
+ type: "unsupported",
540
+ feature: "topK"
541
+ });
542
+ if (frequencyPenalty != null) warnings.push({
543
+ type: "unsupported",
544
+ feature: "frequencyPenalty"
545
+ });
546
+ if (presencePenalty != null) warnings.push({
547
+ type: "unsupported",
548
+ feature: "presencePenalty"
549
+ });
550
+ if (stopSequences != null) warnings.push({
551
+ type: "unsupported",
552
+ feature: "stopSequences"
553
+ });
554
+ if (seed != null) warnings.push({
555
+ type: "unsupported",
556
+ feature: "seed"
557
+ });
558
+ const { tools: nativeTools, ...agentOptions } = perplexityOptions;
559
+ const modelSelection = getModelSelection(this.modelId);
560
+ const { input, warnings: inputWarnings } = convertToPerplexityInput(prompt);
561
+ warnings.push(...inputWarnings);
562
+ const { tools: functionTools, warnings: toolWarnings } = preparePerplexityTools({
563
+ tools,
564
+ toolChoice
565
+ });
566
+ warnings.push(...toolWarnings);
567
+ const agentTools = [...nativeTools ?? [], ...functionTools];
568
+ let reasoningConfig = agentOptions.reasoning;
569
+ if (reasoningConfig == null && isCustomReasoning(reasoning)) {
570
+ if (reasoning === "none") warnings.push({
571
+ type: "unsupported",
572
+ feature: "reasoning \"none\""
573
+ });
574
+ else reasoningConfig = { effort: reasoning };
575
+ }
576
+ const body = {
577
+ ...agentOptions,
578
+ ...modelSelection,
579
+ input,
580
+ max_output_tokens: maxOutputTokens,
581
+ temperature,
582
+ top_p: topP,
583
+ reasoning: reasoningConfig,
584
+ response_format: responseFormat?.type === "json" && responseFormat.schema != null ? {
585
+ type: "json_schema",
586
+ json_schema: {
587
+ name: responseFormat.name ?? "response",
588
+ description: responseFormat.description,
589
+ schema: responseFormat.schema,
590
+ strict: true
591
+ }
592
+ } : void 0,
593
+ tools: agentTools.length > 0 ? agentTools : void 0
594
+ };
595
+ if (responseFormat?.type === "json" && responseFormat.schema == null) warnings.push({
596
+ type: "unsupported",
597
+ feature: "JSON response format without a schema"
598
+ });
599
+ return {
600
+ args: body,
601
+ warnings
602
+ };
603
+ }
604
+ async doGenerate(options) {
605
+ const { args: body, warnings } = await this.getArgs(options);
606
+ const url = `${this.config.baseURL}/v1/agent`;
607
+ const { responseHeaders, value: response, rawValue: rawResponse } = await postJsonToApi({
608
+ url,
609
+ headers: combineHeaders(this.config.headers?.(), options.headers),
610
+ body,
611
+ failedResponseHandler: createJsonErrorResponseHandler({
612
+ errorSchema: perplexityErrorSchema,
613
+ errorToMessage: perplexityErrorToMessage
614
+ }),
615
+ successfulResponseHandler: createJsonResponseHandler(perplexityAgentResponseSchema),
616
+ abortSignal: options.abortSignal,
617
+ fetch: this.config.fetch
618
+ });
619
+ if (response.error != null || response.status === "failed") throw new APICallError({
620
+ message: response.error?.message ?? "Perplexity response failed",
621
+ url,
622
+ requestBodyValues: body,
623
+ statusCode: 400,
624
+ responseHeaders,
625
+ responseBody: rawResponse,
626
+ isRetryable: false
627
+ });
628
+ const content = [];
629
+ const sourceIndexesByUrl = /* @__PURE__ */ new Map();
630
+ let hasFunctionCall = false;
631
+ const addSource = (source) => {
632
+ const existingIndex = sourceIndexesByUrl.get(source.url);
633
+ if (existingIndex == null) {
634
+ sourceIndexesByUrl.set(source.url, content.length);
635
+ content.push(source);
636
+ } else if (hasSearchResultId(source) && !hasSearchResultId(content[existingIndex])) content[existingIndex] = source;
637
+ };
638
+ for (const item of response.output) if (item.type === "message") for (const part of item.content ?? []) {
639
+ if (part.type === "output_text" && part.text != null) content.push({
640
+ type: "text",
641
+ text: part.text
642
+ });
643
+ for (const annotation of part.annotations ?? []) if (annotation.url != null) addSource({
644
+ type: "source",
645
+ sourceType: "url",
646
+ id: this.config.generateId(),
647
+ url: annotation.url,
648
+ title: annotation.title
649
+ });
650
+ }
651
+ else if (item.type === "search_results") for (const result of getSearchResults(item)) addSource(createSource(result, this.config.generateId));
652
+ else if (item.type === "fetch_url_results") for (const result of getFetchedSources(item)) addSource({
653
+ type: "source",
654
+ sourceType: "url",
655
+ id: this.config.generateId(),
656
+ url: result.url,
657
+ title: result.title,
658
+ providerMetadata: { perplexity: { snippet: result.snippet ?? null } }
659
+ });
660
+ else if (item.type === "function_call" && item.call_id != null && item.name != null && item.arguments != null) {
661
+ hasFunctionCall = true;
662
+ content.push({
663
+ type: "tool-call",
664
+ toolCallId: item.call_id,
665
+ toolName: item.name,
666
+ input: item.arguments,
667
+ providerMetadata: { perplexity: {
668
+ itemId: item.id ?? null,
669
+ ...item.thought_signature != null && { thoughtSignature: item.thought_signature }
670
+ } }
671
+ });
672
+ }
673
+ const finishReason = response.incomplete_details?.reason ?? response.status;
674
+ return {
675
+ content,
676
+ finishReason: {
677
+ unified: mapPerplexityFinishReason({
678
+ status: response.status,
679
+ incompleteReason: response.incomplete_details?.reason,
680
+ hasFunctionCall
681
+ }),
682
+ raw: finishReason
683
+ },
684
+ usage: convertPerplexityUsage(response.usage),
685
+ request: { body },
686
+ response: {
687
+ ...getResponseMetadata(response),
688
+ headers: responseHeaders,
689
+ body: rawResponse
690
+ },
691
+ warnings,
692
+ providerMetadata: getProviderMetadata(response.usage)
693
+ };
694
+ }
695
+ async doStream(options) {
696
+ const { args, warnings } = await this.getArgs(options);
697
+ const body = {
698
+ ...args,
699
+ stream: true
700
+ };
701
+ const { responseHeaders, value: response } = await postJsonToApi({
702
+ url: `${this.config.baseURL}/v1/agent`,
703
+ headers: combineHeaders(this.config.headers?.(), options.headers),
704
+ body,
705
+ failedResponseHandler: createJsonErrorResponseHandler({
706
+ errorSchema: perplexityErrorSchema,
707
+ errorToMessage: perplexityErrorToMessage
708
+ }),
709
+ successfulResponseHandler: createEventSourceResponseHandler(perplexityAgentChunkSchema),
710
+ abortSignal: options.abortSignal,
711
+ fetch: this.config.fetch
712
+ });
713
+ let finishReason = {
714
+ unified: "other",
715
+ raw: void 0
716
+ };
717
+ let usage;
718
+ let hasFunctionCall = false;
719
+ let hasResponseMetadata = false;
720
+ let activeReasoningId;
721
+ const textStates = /* @__PURE__ */ new Map();
722
+ const emittedSourceUrls = /* @__PURE__ */ new Set();
723
+ const pendingSourcesByUrl = /* @__PURE__ */ new Map();
724
+ const seenFunctionCalls = /* @__PURE__ */ new Set();
725
+ const generateId = this.config.generateId;
726
+ return {
727
+ stream: response.pipeThrough(new TransformStream({
728
+ start(controller) {
729
+ controller.enqueue({
730
+ type: "stream-start",
731
+ warnings
732
+ });
733
+ },
734
+ transform(chunk, controller) {
735
+ if (options.includeRawChunks) controller.enqueue({
736
+ type: "raw",
737
+ rawValue: chunk.rawValue
738
+ });
739
+ if (!chunk.success) {
740
+ finishReason = {
741
+ unified: "error",
742
+ raw: void 0
743
+ };
744
+ controller.enqueue({
745
+ type: "error",
746
+ error: chunk.error
747
+ });
748
+ return;
749
+ }
750
+ const value = chunk.value;
751
+ const getTextId = (itemId, outputIndex, contentIndex = 0) => {
752
+ const id = itemId ?? String(outputIndex ?? "text");
753
+ return contentIndex == null || contentIndex === 0 ? id : `${id}:${contentIndex}`;
754
+ };
755
+ const emitTextDelta = (id, delta) => {
756
+ let state = textStates.get(id);
757
+ if (state?.ended) return;
758
+ if (state == null) {
759
+ state = {
760
+ text: "",
761
+ ended: false
762
+ };
763
+ textStates.set(id, state);
764
+ controller.enqueue({
765
+ type: "text-start",
766
+ id
767
+ });
768
+ }
769
+ state.text += delta;
770
+ controller.enqueue({
771
+ type: "text-delta",
772
+ id,
773
+ delta
774
+ });
775
+ };
776
+ const finishText = (id, text) => {
777
+ const state = textStates.get(id);
778
+ if (state?.ended) return;
779
+ const emittedText = state?.text ?? "";
780
+ if (text != null && text.startsWith(emittedText) && text.length > emittedText.length) emitTextDelta(id, text.slice(emittedText.length));
781
+ const finalState = textStates.get(id);
782
+ if (finalState != null) {
783
+ finalState.ended = true;
784
+ controller.enqueue({
785
+ type: "text-end",
786
+ id
787
+ });
788
+ }
789
+ };
790
+ const finishOutputText = (item, outputIndex) => {
791
+ if (item.type === "message") {
792
+ for (const [contentIndex, part] of (item.content ?? []).entries()) if (part.type === "output_text") finishText(getTextId(item.id, outputIndex, contentIndex), part.text);
793
+ }
794
+ };
795
+ const emitSource = (source) => {
796
+ if (emittedSourceUrls.has(source.url)) return;
797
+ if (hasSearchResultId(source)) {
798
+ pendingSourcesByUrl.delete(source.url);
799
+ emittedSourceUrls.add(source.url);
800
+ controller.enqueue(source);
801
+ } else if (!pendingSourcesByUrl.has(source.url)) pendingSourcesByUrl.set(source.url, source);
802
+ };
803
+ const emitReasoningThought = (thought) => {
804
+ if (activeReasoningId != null && thought != null) controller.enqueue({
805
+ type: "reasoning-delta",
806
+ id: activeReasoningId,
807
+ delta: thought
808
+ });
809
+ };
810
+ const emitFunctionCall = (item) => {
811
+ if (item.type !== "function_call" || item.call_id == null || item.name == null || item.arguments == null || seenFunctionCalls.has(item.call_id)) return;
812
+ seenFunctionCalls.add(item.call_id);
813
+ hasFunctionCall = true;
814
+ controller.enqueue({
815
+ type: "tool-input-start",
816
+ id: item.call_id,
817
+ toolName: item.name
818
+ });
819
+ controller.enqueue({
820
+ type: "tool-input-delta",
821
+ id: item.call_id,
822
+ delta: item.arguments
823
+ });
824
+ controller.enqueue({
825
+ type: "tool-input-end",
826
+ id: item.call_id
827
+ });
828
+ controller.enqueue({
829
+ type: "tool-call",
830
+ toolCallId: item.call_id,
831
+ toolName: item.name,
832
+ input: item.arguments,
833
+ providerMetadata: { perplexity: {
834
+ itemId: item.id ?? null,
835
+ ...item.thought_signature != null && { thoughtSignature: item.thought_signature }
836
+ } }
837
+ });
838
+ };
839
+ const emitOutputSources = (item) => {
840
+ if (item.type === "message") {
841
+ for (const part of item.content ?? []) for (const annotation of part.annotations ?? []) if (annotation.url != null) emitSource({
842
+ type: "source",
843
+ sourceType: "url",
844
+ id: generateId(),
845
+ url: annotation.url,
846
+ title: annotation.title
847
+ });
848
+ }
849
+ for (const result of getSearchResults(item)) emitSource(createSource(result, generateId));
850
+ for (const result of getFetchedSources(item)) emitSource({
851
+ type: "source",
852
+ sourceType: "url",
853
+ id: generateId(),
854
+ url: result.url,
855
+ title: result.title,
856
+ providerMetadata: { perplexity: { snippet: result.snippet ?? null } }
857
+ });
858
+ };
859
+ switch (value.type) {
860
+ case "response.created":
861
+ case "response.in_progress":
862
+ if (!hasResponseMetadata && value.response != null) {
863
+ controller.enqueue({
864
+ type: "response-metadata",
865
+ ...getResponseMetadata(value.response)
866
+ });
867
+ hasResponseMetadata = true;
868
+ }
869
+ break;
870
+ case "response.output_text.delta":
871
+ if (value.delta != null) emitTextDelta(getTextId(value.item_id, value.output_index, value.content_index), value.delta);
872
+ break;
873
+ case "response.output_text.done":
874
+ finishText(getTextId(value.item_id, value.output_index, value.content_index), value.text);
875
+ break;
876
+ case "response.reasoning.started":
877
+ if (activeReasoningId != null) controller.enqueue({
878
+ type: "reasoning-end",
879
+ id: activeReasoningId
880
+ });
881
+ activeReasoningId = `reasoning-${value.sequence_number ?? generateId()}`;
882
+ controller.enqueue({
883
+ type: "reasoning-start",
884
+ id: activeReasoningId
885
+ });
886
+ emitReasoningThought(value.thought);
887
+ break;
888
+ case "response.reasoning.search_queries":
889
+ case "response.reasoning.fetch_url_queries":
890
+ emitReasoningThought(value.thought);
891
+ break;
892
+ case "response.reasoning.search_results":
893
+ emitReasoningThought(value.thought);
894
+ for (const result of value.results ?? []) emitSource(createSource(result, generateId));
895
+ break;
896
+ case "response.reasoning.fetch_url_results":
897
+ emitReasoningThought(value.thought);
898
+ for (const result of value.contents ?? []) emitSource({
899
+ type: "source",
900
+ sourceType: "url",
901
+ id: generateId(),
902
+ url: result.url,
903
+ title: result.title,
904
+ providerMetadata: { perplexity: { snippet: result.snippet ?? null } }
905
+ });
906
+ break;
907
+ case "response.reasoning.stopped":
908
+ emitReasoningThought(value.thought);
909
+ if (activeReasoningId != null) {
910
+ controller.enqueue({
911
+ type: "reasoning-end",
912
+ id: activeReasoningId
913
+ });
914
+ activeReasoningId = void 0;
915
+ }
916
+ break;
917
+ case "response.output_item.done":
918
+ if (value.item != null) {
919
+ finishOutputText(value.item, value.output_index);
920
+ emitOutputSources(value.item);
921
+ emitFunctionCall(value.item);
922
+ }
923
+ break;
924
+ case "response.completed":
925
+ case "response.incomplete":
926
+ if (value.response != null) {
927
+ if (!hasResponseMetadata) {
928
+ controller.enqueue({
929
+ type: "response-metadata",
930
+ ...getResponseMetadata(value.response)
931
+ });
932
+ hasResponseMetadata = true;
933
+ }
934
+ for (const [outputIndex, item] of value.response.output.entries()) {
935
+ finishOutputText(item, outputIndex);
936
+ emitOutputSources(item);
937
+ emitFunctionCall(item);
938
+ }
939
+ usage = value.response.usage ?? void 0;
940
+ const rawFinishReason = value.response.incomplete_details?.reason ?? value.response.status;
941
+ finishReason = {
942
+ unified: mapPerplexityFinishReason({
943
+ status: value.response.status,
944
+ incompleteReason: value.response.incomplete_details?.reason,
945
+ hasFunctionCall
946
+ }),
947
+ raw: rawFinishReason
948
+ };
949
+ }
950
+ break;
951
+ case "response.failed":
952
+ finishReason = {
953
+ unified: "error",
954
+ raw: "failed"
955
+ };
956
+ controller.enqueue({
957
+ type: "error",
958
+ error: value.error ?? /* @__PURE__ */ new Error("Perplexity response failed")
959
+ });
960
+ }
961
+ },
962
+ flush(controller) {
963
+ for (const source of pendingSourcesByUrl.values()) controller.enqueue(source);
964
+ if (activeReasoningId != null) controller.enqueue({
965
+ type: "reasoning-end",
966
+ id: activeReasoningId
967
+ });
968
+ for (const [id, state] of textStates) if (!state.ended) controller.enqueue({
969
+ type: "text-end",
970
+ id
971
+ });
972
+ controller.enqueue({
973
+ type: "finish",
974
+ finishReason,
975
+ usage: convertPerplexityUsage(usage),
976
+ providerMetadata: getProviderMetadata(usage)
977
+ });
978
+ }
979
+ })),
980
+ request: { body },
981
+ response: { headers: responseHeaders }
982
+ };
983
+ }
1229
984
  };
1230
-
1231
- // src/perplexity-embedding-model.ts
1232
- var PerplexityEmbeddingModel = class _PerplexityEmbeddingModel {
1233
- constructor(modelId, config) {
1234
- this.specificationVersion = "v4";
1235
- // https://docs.perplexity.ai/docs/embeddings/standard-embeddings
1236
- this.maxEmbeddingsPerCall = 512;
1237
- this.supportsParallelCalls = true;
1238
- this.modelId = modelId;
1239
- this.config = config;
1240
- }
1241
- get provider() {
1242
- return this.config.provider;
1243
- }
1244
- static [WORKFLOW_SERIALIZE2](model) {
1245
- return serializeModelOptions2({
1246
- modelId: model.modelId,
1247
- config: model.config
1248
- });
1249
- }
1250
- static [WORKFLOW_DESERIALIZE2](options) {
1251
- return new _PerplexityEmbeddingModel(options.modelId, options.config);
1252
- }
1253
- async doEmbed({
1254
- values,
1255
- abortSignal,
1256
- headers,
1257
- providerOptions
1258
- }) {
1259
- if (values.length > this.maxEmbeddingsPerCall) {
1260
- throw new TooManyEmbeddingValuesForCallError({
1261
- provider: this.provider,
1262
- modelId: this.modelId,
1263
- maxEmbeddingsPerCall: this.maxEmbeddingsPerCall,
1264
- values
1265
- });
1266
- }
1267
- const perplexityOptions = await parseProviderOptions2({
1268
- provider: "perplexity",
1269
- providerOptions,
1270
- schema: perplexityEmbeddingModelOptions
1271
- }) ?? {};
1272
- const encodingFormat = perplexityOptions.encodingFormat ?? "base64_int8";
1273
- const {
1274
- responseHeaders,
1275
- value: response,
1276
- rawValue
1277
- } = await postJsonToApi2({
1278
- url: `${this.config.baseURL}/v1/embeddings`,
1279
- headers: combineHeaders2(this.config.headers(), headers),
1280
- body: {
1281
- model: this.modelId,
1282
- input: values,
1283
- dimensions: perplexityOptions.dimensions,
1284
- encoding_format: encodingFormat
1285
- },
1286
- failedResponseHandler: createJsonErrorResponseHandler2({
1287
- errorSchema: perplexityErrorSchema,
1288
- errorToMessage: perplexityErrorToMessage
1289
- }),
1290
- successfulResponseHandler: createJsonResponseHandler2(
1291
- perplexityEmbeddingResponseSchema
1292
- ),
1293
- abortSignal,
1294
- fetch: this.config.fetch
1295
- });
1296
- const cost = response.usage?.cost;
1297
- return {
1298
- embeddings: response.data.map(
1299
- (item) => decodeEmbedding(item.embedding, encodingFormat)
1300
- ),
1301
- usage: response.usage ? { tokens: response.usage.prompt_tokens } : void 0,
1302
- providerMetadata: cost ? {
1303
- perplexity: {
1304
- cost: {
1305
- inputCost: cost.input_cost ?? null,
1306
- totalCost: cost.total_cost ?? null,
1307
- currency: cost.currency ?? null
1308
- }
1309
- }
1310
- } : void 0,
1311
- response: { headers: responseHeaders, body: rawValue },
1312
- warnings: []
1313
- };
1314
- }
985
+ //#endregion
986
+ //#region src/perplexity-embedding-model.ts
987
+ var PerplexityEmbeddingModel = class PerplexityEmbeddingModel {
988
+ get provider() {
989
+ return this.config.provider;
990
+ }
991
+ static [WORKFLOW_SERIALIZE](model) {
992
+ return serializeModelOptions({
993
+ modelId: model.modelId,
994
+ config: model.config
995
+ });
996
+ }
997
+ static [WORKFLOW_DESERIALIZE](options) {
998
+ return new PerplexityEmbeddingModel(options.modelId, options.config);
999
+ }
1000
+ constructor(modelId, config) {
1001
+ this.specificationVersion = "v4";
1002
+ this.maxEmbeddingsPerCall = 512;
1003
+ this.supportsParallelCalls = true;
1004
+ this.modelId = modelId;
1005
+ this.config = config;
1006
+ }
1007
+ async doEmbed({ values, abortSignal, headers, providerOptions }) {
1008
+ if (values.length > this.maxEmbeddingsPerCall) throw new TooManyEmbeddingValuesForCallError({
1009
+ provider: this.provider,
1010
+ modelId: this.modelId,
1011
+ maxEmbeddingsPerCall: this.maxEmbeddingsPerCall,
1012
+ values
1013
+ });
1014
+ const perplexityOptions = await parseProviderOptions({
1015
+ provider: "perplexity",
1016
+ providerOptions,
1017
+ schema: perplexityEmbeddingModelOptions
1018
+ }) ?? {};
1019
+ const encodingFormat = perplexityOptions.encodingFormat ?? "base64_int8";
1020
+ const { responseHeaders, value: response, rawValue } = await postJsonToApi({
1021
+ url: `${this.config.baseURL}/v1/embeddings`,
1022
+ headers: combineHeaders(this.config.headers(), headers),
1023
+ body: {
1024
+ model: this.modelId,
1025
+ input: values,
1026
+ dimensions: perplexityOptions.dimensions,
1027
+ encoding_format: encodingFormat
1028
+ },
1029
+ failedResponseHandler: createJsonErrorResponseHandler({
1030
+ errorSchema: perplexityErrorSchema,
1031
+ errorToMessage: perplexityErrorToMessage
1032
+ }),
1033
+ successfulResponseHandler: createJsonResponseHandler(perplexityEmbeddingResponseSchema),
1034
+ abortSignal,
1035
+ fetch: this.config.fetch
1036
+ });
1037
+ const cost = response.usage?.cost;
1038
+ return {
1039
+ embeddings: response.data.map((item) => decodeEmbedding(item.embedding, encodingFormat)),
1040
+ usage: response.usage ? { tokens: response.usage.prompt_tokens } : void 0,
1041
+ providerMetadata: cost ? { perplexity: { cost: {
1042
+ inputCost: cost.input_cost ?? null,
1043
+ totalCost: cost.total_cost ?? null,
1044
+ currency: cost.currency ?? null
1045
+ } } } : void 0,
1046
+ response: {
1047
+ headers: responseHeaders,
1048
+ body: rawValue
1049
+ },
1050
+ warnings: []
1051
+ };
1052
+ }
1315
1053
  };
1054
+ /**
1055
+ * Decodes a base64-encoded Perplexity embedding into a numeric vector.
1056
+ * For `base64_int8` the bytes are reinterpreted as signed int8 values;
1057
+ * for `base64_binary` the raw unsigned bytes (packed bits) are returned.
1058
+ */
1316
1059
  function decodeEmbedding(base64, encodingFormat) {
1317
- const bytes = convertBase64ToUint8Array(base64);
1318
- if (encodingFormat === "base64_int8") {
1319
- const int8 = new Int8Array(
1320
- bytes.buffer,
1321
- bytes.byteOffset,
1322
- bytes.byteLength
1323
- );
1324
- return Array.from(int8);
1325
- }
1326
- return Array.from(bytes);
1060
+ const bytes = convertBase64ToUint8Array(base64);
1061
+ if (encodingFormat === "base64_int8") {
1062
+ const int8 = new Int8Array(bytes.buffer, bytes.byteOffset, bytes.byteLength);
1063
+ return Array.from(int8);
1064
+ }
1065
+ return Array.from(bytes);
1327
1066
  }
1328
- var perplexityEmbeddingResponseSchema = z4.object({
1329
- data: z4.array(z4.object({ embedding: z4.string() })),
1330
- usage: z4.object({
1331
- prompt_tokens: z4.number(),
1332
- cost: z4.object({
1333
- input_cost: z4.number().nullish(),
1334
- total_cost: z4.number().nullish(),
1335
- currency: z4.string().nullish()
1336
- }).nullish()
1337
- }).nullish()
1067
+ const perplexityEmbeddingResponseSchema = z.object({
1068
+ data: z.array(z.object({ embedding: z.string() })),
1069
+ usage: z.object({
1070
+ prompt_tokens: z.number(),
1071
+ cost: z.object({
1072
+ input_cost: z.number().nullish(),
1073
+ total_cost: z.number().nullish(),
1074
+ currency: z.string().nullish()
1075
+ }).nullish()
1076
+ }).nullish()
1338
1077
  });
1339
-
1340
- // src/version.ts
1341
- var VERSION = true ? "5.0.2" : "0.0.0-test";
1342
-
1343
- // src/perplexity-provider.ts
1078
+ //#endregion
1079
+ //#region src/version.ts
1080
+ const VERSION = "5.0.4";
1081
+ //#endregion
1082
+ //#region src/perplexity-provider.ts
1344
1083
  function createPerplexity(options = {}) {
1345
- const getHeaders = () => withUserAgentSuffix(
1346
- {
1347
- Authorization: `Bearer ${loadApiKey({
1348
- apiKey: options.apiKey,
1349
- environmentVariableName: "PERPLEXITY_API_KEY",
1350
- description: "Perplexity"
1351
- })}`,
1352
- ...options.headers
1353
- },
1354
- `ai-sdk/perplexity/${VERSION}`
1355
- );
1356
- const baseURL = withoutTrailingSlash(
1357
- options.baseURL ?? "https://api.perplexity.ai"
1358
- );
1359
- const createLanguageModel = (modelId) => {
1360
- return new PerplexityLanguageModel(modelId, {
1361
- baseURL,
1362
- headers: getHeaders,
1363
- generateId,
1364
- fetch: options.fetch
1365
- });
1366
- };
1367
- const createEmbeddingModel = (modelId) => new PerplexityEmbeddingModel(modelId, {
1368
- provider: "perplexity.embedding",
1369
- baseURL,
1370
- headers: getHeaders,
1371
- fetch: options.fetch
1372
- });
1373
- const provider = (modelId) => createLanguageModel(modelId);
1374
- provider.specificationVersion = "v4";
1375
- provider.languageModel = createLanguageModel;
1376
- provider.embedding = createEmbeddingModel;
1377
- provider.embeddingModel = createEmbeddingModel;
1378
- provider.textEmbeddingModel = createEmbeddingModel;
1379
- provider.imageModel = (modelId) => {
1380
- throw new NoSuchModelError({ modelId, modelType: "imageModel" });
1381
- };
1382
- return provider;
1084
+ const getHeaders = () => withUserAgentSuffix({
1085
+ Authorization: `Bearer ${loadApiKey({
1086
+ apiKey: options.apiKey,
1087
+ environmentVariableName: "PERPLEXITY_API_KEY",
1088
+ description: "Perplexity"
1089
+ })}`,
1090
+ "X-Pplx-Integration": "vercel-ai-sdk",
1091
+ ...options.headers
1092
+ }, `ai-sdk-perplexity/${VERSION}`);
1093
+ const baseURL = withoutTrailingSlash(options.baseURL ?? "https://api.perplexity.ai");
1094
+ const createLanguageModel = (modelId) => {
1095
+ return new PerplexityLanguageModel(modelId, {
1096
+ baseURL,
1097
+ headers: getHeaders,
1098
+ generateId,
1099
+ fetch: options.fetch
1100
+ });
1101
+ };
1102
+ const createEmbeddingModel = (modelId) => new PerplexityEmbeddingModel(modelId, {
1103
+ provider: "perplexity.embedding",
1104
+ baseURL,
1105
+ headers: getHeaders,
1106
+ fetch: options.fetch
1107
+ });
1108
+ const provider = (modelId) => createLanguageModel(modelId);
1109
+ provider.specificationVersion = "v4";
1110
+ provider.languageModel = createLanguageModel;
1111
+ provider.embedding = createEmbeddingModel;
1112
+ provider.embeddingModel = createEmbeddingModel;
1113
+ provider.textEmbeddingModel = createEmbeddingModel;
1114
+ provider.imageModel = (modelId) => {
1115
+ throw new NoSuchModelError({
1116
+ modelId,
1117
+ modelType: "imageModel"
1118
+ });
1119
+ };
1120
+ return provider;
1383
1121
  }
1384
- var perplexity = createPerplexity();
1385
- export {
1386
- VERSION,
1387
- createPerplexity,
1388
- perplexity
1389
- };
1122
+ const perplexity = createPerplexity();
1123
+ //#endregion
1124
+ export { VERSION, createPerplexity, perplexity };
1125
+
1390
1126
  //# sourceMappingURL=index.js.map