@ai-sdk/perplexity 3.0.62 → 3.1.0

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.
@@ -1,13 +1,32 @@
1
1
  import type { LanguageModelV3FinishReason } from '@ai-sdk/provider';
2
2
 
3
- export function mapPerplexityFinishReason(
4
- finishReason: string | null | undefined,
5
- ): LanguageModelV3FinishReason['unified'] {
6
- switch (finishReason) {
7
- case 'stop':
8
- case 'length':
9
- return finishReason;
3
+ export function mapPerplexityFinishReason({
4
+ status,
5
+ incompleteReason,
6
+ hasFunctionCall,
7
+ }: {
8
+ status: string | null | undefined;
9
+ incompleteReason: string | null | undefined;
10
+ hasFunctionCall: boolean;
11
+ }): LanguageModelV3FinishReason['unified'] {
12
+ switch (incompleteReason) {
13
+ case 'max_output_tokens':
14
+ return 'length';
15
+ case 'content_filter':
16
+ return 'content-filter';
17
+ }
18
+
19
+ switch (status) {
20
+ case 'completed':
21
+ return hasFunctionCall ? 'tool-calls' : 'stop';
22
+ case 'requires_action':
23
+ return 'tool-calls';
24
+ case 'failed':
25
+ return 'error';
26
+ case 'cancelled':
27
+ case 'queued':
28
+ case 'in_progress':
10
29
  default:
11
- return 'other';
30
+ return hasFunctionCall ? 'tool-calls' : 'other';
12
31
  }
13
32
  }
@@ -0,0 +1,206 @@
1
+ import type { JSONSchema7 } from '@ai-sdk/provider';
2
+ import { z } from 'zod/v4';
3
+
4
+ export type PerplexityAgentTool =
5
+ | {
6
+ type: 'function';
7
+ name: string;
8
+ description?: string;
9
+ parameters: JSONSchema7;
10
+ strict?: boolean;
11
+ }
12
+ | ({ type: string } & Record<string, unknown>);
13
+
14
+ export const perplexitySearchResultSchema = z.looseObject({
15
+ id: z.number().optional(),
16
+ title: z.string(),
17
+ url: z.string(),
18
+ snippet: z.string().optional(),
19
+ date: z.string().nullish(),
20
+ last_updated: z.string().nullish(),
21
+ source: z.string().optional(),
22
+ });
23
+
24
+ const perplexityFetchedContentSchema = z.looseObject({
25
+ title: z.string(),
26
+ url: z.string(),
27
+ snippet: z.string().optional(),
28
+ });
29
+
30
+ const perplexityContentPartSchema = z.looseObject({
31
+ type: z.string(),
32
+ text: z.string().optional(),
33
+ annotations: z
34
+ .array(
35
+ z.looseObject({
36
+ type: z.string().optional(),
37
+ url: z.string().optional(),
38
+ title: z.string().optional(),
39
+ }),
40
+ )
41
+ .nullish(),
42
+ });
43
+
44
+ const handledOutputTypes = [
45
+ 'message',
46
+ 'search_results',
47
+ 'fetch_url_results',
48
+ 'function_call',
49
+ ];
50
+
51
+ export const perplexityOutputItemSchema = z.union([
52
+ z.looseObject({
53
+ type: z.literal('message'),
54
+ id: z.string().nullish(),
55
+ content: z.array(perplexityContentPartSchema).nullish(),
56
+ }),
57
+ z.looseObject({
58
+ type: z.literal('search_results'),
59
+ results: z.array(perplexitySearchResultSchema).nullish(),
60
+ }),
61
+ z.looseObject({
62
+ type: z.literal('fetch_url_results'),
63
+ contents: z.array(perplexityFetchedContentSchema).nullish(),
64
+ }),
65
+ z.looseObject({
66
+ type: z.literal('function_call'),
67
+ id: z.string().nullish(),
68
+ call_id: z.string().nullish(),
69
+ name: z.string().nullish(),
70
+ arguments: z.string().nullish(),
71
+ thought_signature: z.string().nullish(),
72
+ }),
73
+ // Native tool traces remain available in raw responses and raw stream chunks.
74
+ // Their fields (e.g. finance_results.results) have different shapes. Do not
75
+ // validate them as search results, or let malformed handled items fall back.
76
+ z
77
+ .object({
78
+ type: z.string().refine(type => !handledOutputTypes.includes(type)),
79
+ })
80
+ .transform(() => ({ type: 'unhandled' as const })),
81
+ ]);
82
+
83
+ const perplexityCostSchema = z.looseObject({
84
+ currency: z.string().optional(),
85
+ input_cost: z.number().optional(),
86
+ output_cost: z.number().optional(),
87
+ total_cost: z.number().optional(),
88
+ cache_creation_cost: z.number().nullish(),
89
+ cache_read_cost: z.number().nullish(),
90
+ tool_calls_cost: z.number().nullish(),
91
+ });
92
+
93
+ export const perplexityUsageSchema = z.looseObject({
94
+ input_tokens: z.number(),
95
+ output_tokens: z.number(),
96
+ total_tokens: z.number(),
97
+ input_tokens_details: z
98
+ .looseObject({
99
+ cached_tokens: z.number().optional(),
100
+ cache_creation_input_tokens: z.number().optional(),
101
+ cache_read_input_tokens: z.number().optional(),
102
+ })
103
+ .nullish(),
104
+ output_tokens_details: z
105
+ .looseObject({
106
+ reasoning_tokens: z.number().optional(),
107
+ })
108
+ .nullish(),
109
+ tool_calls_details: z
110
+ .record(
111
+ z.string(),
112
+ z.looseObject({
113
+ invocation: z.number().optional(),
114
+ }),
115
+ )
116
+ .nullish(),
117
+ cost: perplexityCostSchema.nullish(),
118
+ });
119
+
120
+ export const perplexityAgentResponseSchema = z.looseObject({
121
+ id: z.string(),
122
+ created_at: z.number(),
123
+ model: z.string(),
124
+ object: z.literal('response'),
125
+ output: z.array(perplexityOutputItemSchema),
126
+ status: z.string(),
127
+ incomplete_details: z
128
+ .looseObject({
129
+ reason: z.string(),
130
+ })
131
+ .nullish(),
132
+ error: z
133
+ .looseObject({
134
+ code: z.string().optional(),
135
+ message: z.string(),
136
+ type: z.string().optional(),
137
+ })
138
+ .nullish(),
139
+ usage: perplexityUsageSchema.nullish(),
140
+ });
141
+
142
+ export const perplexityAgentChunkSchema = z.looseObject({
143
+ type: z.string(),
144
+ sequence_number: z.number().nullish(),
145
+ response: perplexityAgentResponseSchema.nullish(),
146
+ item: perplexityOutputItemSchema.nullish(),
147
+ output_index: z.number().nullish(),
148
+ item_id: z.string().nullish(),
149
+ content_index: z.number().nullish(),
150
+ delta: z.string().nullish(),
151
+ text: z.string().nullish(),
152
+ thought: z.string().nullish(),
153
+ queries: z.array(z.string()).nullish(),
154
+ urls: z.array(z.string()).nullish(),
155
+ results: z.array(perplexitySearchResultSchema).nullish(),
156
+ contents: z.array(perplexityFetchedContentSchema).nullish(),
157
+ error: z
158
+ .looseObject({
159
+ code: z.string().nullish(),
160
+ message: z.string(),
161
+ type: z.string().nullish(),
162
+ })
163
+ .nullish(),
164
+ });
165
+
166
+ export const perplexityErrorSchema = z.looseObject({
167
+ error: z
168
+ .union([
169
+ z.string(),
170
+ z.looseObject({
171
+ code: z.union([z.string(), z.number()]).optional(),
172
+ message: z.string().nullish(),
173
+ type: z.string().nullish(),
174
+ }),
175
+ ])
176
+ .optional(),
177
+ detail: z
178
+ .union([
179
+ z.string(),
180
+ z.array(
181
+ z.looseObject({
182
+ msg: z.string(),
183
+ }),
184
+ ),
185
+ ])
186
+ .optional(),
187
+ message: z.string().optional(),
188
+ });
189
+
190
+ export type PerplexityErrorData = z.infer<typeof perplexityErrorSchema>;
191
+
192
+ export function perplexityErrorToMessage(data: PerplexityErrorData): string {
193
+ if (typeof data.error === 'string') {
194
+ return data.error;
195
+ }
196
+ if (data.error != null) {
197
+ return data.error.message ?? data.error.type ?? 'unknown error';
198
+ }
199
+ if (typeof data.detail === 'string') {
200
+ return data.detail;
201
+ }
202
+ if (Array.isArray(data.detail)) {
203
+ return data.detail.map(detail => detail.msg).join(', ');
204
+ }
205
+ return data.message ?? 'unknown error';
206
+ }
@@ -16,7 +16,10 @@ import {
16
16
  perplexityEmbeddingModelOptions,
17
17
  type PerplexityEmbeddingModelId,
18
18
  } from './perplexity-embedding-model-options';
19
- import { perplexityErrorSchema } from './perplexity-language-model';
19
+ import {
20
+ perplexityErrorSchema,
21
+ perplexityErrorToMessage,
22
+ } from './perplexity-language-model';
20
23
 
21
24
  type PerplexityEmbeddingConfig = {
22
25
  provider: string;
@@ -88,7 +91,7 @@ export class PerplexityEmbeddingModel implements EmbeddingModelV3 {
88
91
  },
89
92
  failedResponseHandler: createJsonErrorResponseHandler({
90
93
  errorSchema: perplexityErrorSchema,
91
- errorToMessage: data => data.error.message ?? 'Unknown error',
94
+ errorToMessage: perplexityErrorToMessage,
92
95
  }),
93
96
  successfulResponseHandler: createJsonResponseHandler(
94
97
  perplexityEmbeddingResponseSchema,
@@ -1,8 +1,124 @@
1
- // https://docs.perplexity.ai/models/model-cards
2
- export type PerplexityLanguageModelId =
3
- | 'sonar-deep-research'
4
- | 'sonar-reasoning-pro'
5
- | 'sonar-reasoning'
6
- | 'sonar-pro'
7
- | 'sonar'
8
- | (string & {});
1
+ import { z } from 'zod/v4';
2
+
3
+ const userLocationSchema = z.looseObject({
4
+ latitude: z.number().optional(),
5
+ longitude: z.number().optional(),
6
+ country: z.string().optional(),
7
+ city: z.string().optional(),
8
+ region: z.string().optional(),
9
+ });
10
+
11
+ const webSearchFiltersSchema = z.looseObject({
12
+ search_domain_filter: z.array(z.string()).optional(),
13
+ search_recency_filter: z
14
+ .enum(['hour', 'day', 'week', 'month', 'year'])
15
+ .optional(),
16
+ search_after_date_filter: z.string().optional(),
17
+ search_before_date_filter: z.string().optional(),
18
+ last_updated_after_filter: z.string().optional(),
19
+ last_updated_before_filter: z.string().optional(),
20
+ });
21
+
22
+ const webSearchToolSchema = z.looseObject({
23
+ type: z.literal('web_search'),
24
+ filters: webSearchFiltersSchema.optional(),
25
+ max_results: z.number().int().positive().optional(),
26
+ max_tokens: z.number().optional(),
27
+ max_tokens_per_page: z.number().optional(),
28
+ search_context_size: z.enum(['low', 'medium', 'high']).optional(),
29
+ user_location: userLocationSchema.optional(),
30
+ });
31
+
32
+ const nativeToolSchema = z.union([
33
+ webSearchToolSchema,
34
+ z.looseObject({
35
+ type: z.literal('fetch_url'),
36
+ max_urls: z.number().optional(),
37
+ }),
38
+ z.looseObject({ type: z.literal('people_search') }),
39
+ z.looseObject({ type: z.literal('finance_search') }),
40
+ z.looseObject({ type: z.literal('sandbox') }),
41
+ z.looseObject({
42
+ type: z.literal('mcp'),
43
+ server_label: z.string(),
44
+ server_url: z.string(),
45
+ allowed_tools: z.array(z.string()).optional(),
46
+ authorization: z.string().optional(),
47
+ defer_loading: z.boolean().optional(),
48
+ headers: z.record(z.string(), z.string()).optional(),
49
+ }),
50
+ z.looseObject({
51
+ type: z.literal('connector'),
52
+ id: z.string(),
53
+ server_label: z.string(),
54
+ server_description: z.string().optional(),
55
+ allowed_tools: z.array(z.string()).optional(),
56
+ }),
57
+ ]);
58
+
59
+ export const perplexityLanguageModelOptions = z.looseObject({
60
+ /** Top-level Agent API instructions. */
61
+ instructions: z.string().optional(),
62
+
63
+ /**
64
+ * Native Agent API tools. AI SDK function tools can also be supplied through
65
+ * the top-level `tools` option on `generateText` and `streamText`.
66
+ */
67
+ tools: z.array(nativeToolSchema).optional(),
68
+
69
+ /** A fallback model list for Agent API routing. */
70
+ models: z.array(z.string()).optional(),
71
+
72
+ /** Maximum number of agentic steps. */
73
+ max_steps: z.number().int().positive().optional(),
74
+
75
+ /** Maximum number of native tool calls. */
76
+ max_tool_calls: z.number().int().nonnegative().optional(),
77
+
78
+ /** Continue a conversation from an earlier Agent API response. */
79
+ previous_response_id: z.string().optional(),
80
+
81
+ /**
82
+ * Whether the response can be retrieved later. Setting this to false does
83
+ * not disable persistence or prevent previous_response_id continuations.
84
+ */
85
+ store: z.boolean().optional(),
86
+
87
+ /** Preferred response language as an ISO 639-1 language code. */
88
+ language_preference: z.string().optional(),
89
+
90
+ /** Agent API reasoning configuration. */
91
+ reasoning: z
92
+ .looseObject({
93
+ effort: z.enum(['minimal', 'low', 'medium', 'high', 'xhigh']).optional(),
94
+ })
95
+ .optional(),
96
+
97
+ /** Agent API skill configuration. */
98
+ skills: z
99
+ .array(
100
+ z.union([
101
+ z.looseObject({
102
+ type: z.literal('builtin'),
103
+ name: z.enum([
104
+ 'office',
105
+ 'office/docx',
106
+ 'office/pdf',
107
+ 'office/pptx',
108
+ 'office/xlsx',
109
+ ]),
110
+ }),
111
+ z.looseObject({
112
+ type: z.literal('inline'),
113
+ name: z.string(),
114
+ description: z.string(),
115
+ instructions: z.string(),
116
+ }),
117
+ ]),
118
+ )
119
+ .optional(),
120
+ });
121
+
122
+ export type PerplexityLanguageModelOptions = z.infer<
123
+ typeof perplexityLanguageModelOptions
124
+ >;
@@ -1,25 +1,32 @@
1
- export type PerplexityPrompt = Array<PerplexityMessage>;
1
+ export type PerplexityAgentInput = Array<PerplexityAgentInputItem>;
2
2
 
3
- export type PerplexityMessage = {
4
- role: 'system' | 'user' | 'assistant';
5
- content: string | PerplexityMessageContent[];
6
- };
7
-
8
- export type PerplexityMessageContent =
3
+ export type PerplexityAgentInputItem =
9
4
  | {
10
- type: 'text';
11
- text: string;
5
+ type: 'message';
6
+ role: 'system' | 'developer' | 'user' | 'assistant';
7
+ content: string | PerplexityAgentInputContent[];
8
+ }
9
+ | {
10
+ type: 'function_call';
11
+ call_id: string;
12
+ name: string;
13
+ arguments: string;
14
+ thought_signature?: string;
12
15
  }
13
16
  | {
14
- type: 'image_url';
15
- image_url: {
16
- url: string;
17
- };
17
+ type: 'function_call_output';
18
+ call_id: string;
19
+ name?: string;
20
+ output: string;
21
+ thought_signature?: string;
22
+ };
23
+
24
+ export type PerplexityAgentInputContent =
25
+ | {
26
+ type: 'input_text';
27
+ text: string;
18
28
  }
19
29
  | {
20
- type: 'file_url';
21
- file_url: {
22
- url: string;
23
- };
24
- file_name?: string;
30
+ type: 'input_image';
31
+ image_url: string;
25
32
  };