@ai-sdk/perplexity 4.0.50 → 5.0.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 { LanguageModelV4FinishReason } from '@ai-sdk/provider';
2
2
 
3
- export function mapPerplexityFinishReason(
4
- finishReason: string | null | undefined,
5
- ): LanguageModelV4FinishReason['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
+ }): LanguageModelV4FinishReason['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().optional(),
145
+ response: perplexityAgentResponseSchema.optional(),
146
+ item: perplexityOutputItemSchema.optional(),
147
+ output_index: z.number().optional(),
148
+ item_id: z.string().optional(),
149
+ content_index: z.number().optional(),
150
+ delta: z.string().optional(),
151
+ text: z.string().optional(),
152
+ thought: z.string().optional(),
153
+ queries: z.array(z.string()).optional(),
154
+ urls: z.array(z.string()).optional(),
155
+ results: z.array(perplexitySearchResultSchema).optional(),
156
+ contents: z.array(perplexityFetchedContentSchema).optional(),
157
+ error: z
158
+ .looseObject({
159
+ code: z.string().optional(),
160
+ message: z.string(),
161
+ type: z.string().optional(),
162
+ })
163
+ .optional(),
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
+ }
@@ -19,7 +19,10 @@ import {
19
19
  perplexityEmbeddingModelOptions,
20
20
  type PerplexityEmbeddingModelId,
21
21
  } from './perplexity-embedding-model-options';
22
- import { perplexityErrorSchema } from './perplexity-language-model';
22
+ import {
23
+ perplexityErrorSchema,
24
+ perplexityErrorToMessage,
25
+ } from './perplexity-language-model';
23
26
 
24
27
  type PerplexityEmbeddingConfig = {
25
28
  provider: string;
@@ -105,7 +108,7 @@ export class PerplexityEmbeddingModel implements EmbeddingModelV4 {
105
108
  },
106
109
  failedResponseHandler: createJsonErrorResponseHandler({
107
110
  errorSchema: perplexityErrorSchema,
108
- errorToMessage: data => data.error.message ?? 'Unknown error',
111
+ errorToMessage: perplexityErrorToMessage,
109
112
  }),
110
113
  successfulResponseHandler: createJsonResponseHandler(
111
114
  perplexityEmbeddingResponseSchema,
@@ -1,146 +1,122 @@
1
1
  import { z } from 'zod/v4';
2
2
 
3
- export const perplexityLanguageModelOptions = z.looseObject({
4
- /**
5
- * Filters search results to those published within the specified time window.
6
- * Cannot be combined with other date filters.
7
- */
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(),
8
13
  search_recency_filter: z
9
14
  .enum(['hour', 'day', 'week', 'month', 'year'])
10
15
  .optional(),
11
-
12
- /**
13
- * Restrict web search results to specific domains or URLs.
14
- * Prefix a domain with "-" to exclude it.
15
- */
16
- search_domain_filter: z.array(z.string()).optional(),
17
-
18
- /**
19
- * Filter search results by language using ISO 639-1 codes.
20
- */
21
- search_language_filter: z.array(z.string()).optional(),
22
-
23
- /**
24
- * Return search results published after this date.
25
- */
26
16
  search_after_date_filter: z.string().optional(),
27
-
28
- /**
29
- * Return search results published before this date.
30
- */
31
17
  search_before_date_filter: z.string().optional(),
32
-
33
- /**
34
- * Return search results last updated after this date.
35
- */
36
18
  last_updated_after_filter: z.string().optional(),
37
-
38
- /**
39
- * Return search results last updated before this date.
40
- */
41
19
  last_updated_before_filter: z.string().optional(),
20
+ });
42
21
 
43
- /**
44
- * Source of search results.
45
- */
46
- search_mode: z.enum(['web', 'academic', 'sec']).optional(),
47
-
48
- /**
49
- * If true, the model decides whether web search is needed.
50
- */
51
- enable_search_classifier: z.boolean().optional(),
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
+ });
52
31
 
53
- /**
54
- * If true, disables web search.
55
- */
56
- disable_search: z.boolean().optional(),
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
+ ]);
57
58
 
58
- /**
59
- * If true, a list of related questions is included in the response.
60
- */
61
- return_related_questions: z.boolean().optional(),
59
+ export const perplexityLanguageModelOptions = z.looseObject({
60
+ /** Top-level Agent API instructions. */
61
+ instructions: z.string().optional(),
62
62
 
63
63
  /**
64
- * If true, image search results are included in the response.
64
+ * Native Agent API tools. AI SDK function tools can also be supplied through
65
+ * the top-level `tools` option on `generateText` and `streamText`.
65
66
  */
66
- return_images: z.boolean().optional(),
67
+ tools: z.array(nativeToolSchema).optional(),
67
68
 
68
- /**
69
- * Restrict image results to specific domains.
70
- * Prefix a domain with "-" to exclude it.
71
- */
72
- image_domain_filter: z.array(z.string()).optional(),
69
+ /** A fallback model list for Agent API routing. */
70
+ models: z.array(z.string()).optional(),
73
71
 
74
- /**
75
- * Restrict image results to specific file formats.
76
- */
77
- image_format_filter: z.array(z.string()).optional(),
72
+ /** Maximum number of agentic steps. */
73
+ max_steps: z.number().int().positive().optional(),
78
74
 
79
- /**
80
- * Additional media response configuration.
81
- */
82
- media_response: z
83
- .looseObject({
84
- overrides: z
85
- .looseObject({
86
- /**
87
- * If true, video results are included in the response.
88
- */
89
- return_videos: z.boolean().optional(),
90
- })
91
- .optional(),
92
- })
93
- .optional(),
75
+ /** Maximum number of native tool calls. */
76
+ max_tool_calls: z.number().int().nonnegative().optional(),
94
77
 
95
- /**
96
- * Controls the format of streaming events.
97
- */
98
- stream_mode: z.enum(['full', 'concise']).optional(),
78
+ /** Continue a conversation from an earlier Agent API response. */
79
+ previous_response_id: z.string().optional(),
99
80
 
100
81
  /**
101
- * Controls how much effort the model spends on reasoning.
82
+ * Whether the response can be retrieved later. Setting this to false does
83
+ * not disable persistence or prevent previous_response_id continuations.
102
84
  */
103
- reasoning_effort: z.enum(['minimal', 'low', 'medium', 'high']).optional(),
85
+ store: z.boolean().optional(),
104
86
 
105
- /**
106
- * Preferred response language as an ISO 639-1 language code.
107
- */
87
+ /** Preferred response language as an ISO 639-1 language code. */
108
88
  language_preference: z.string().optional(),
109
89
 
110
- /**
111
- * Additional web search configuration.
112
- */
113
- web_search_options: z
90
+ /** Agent API reasoning configuration. */
91
+ reasoning: z
114
92
  .looseObject({
115
- /**
116
- * Controls the size of search context injected into the model.
117
- */
118
- search_context_size: z.enum(['low', 'medium', 'high']).optional(),
119
-
120
- /**
121
- * Controls whether to use fast search, pro search, or automatic routing.
122
- */
123
- search_type: z.enum(['fast', 'pro', 'auto']).optional(),
124
-
125
- /**
126
- * User location for search result personalization.
127
- */
128
- user_location: z
129
- .looseObject({
130
- latitude: z.number().optional(),
131
- longitude: z.number().optional(),
132
- country: z.string().optional(),
133
- city: z.string().optional(),
134
- region: z.string().optional(),
135
- })
136
- .optional(),
137
-
138
- /**
139
- * If true, applies enhanced relevance filtering to image results.
140
- */
141
- image_results_enhanced_relevance: z.boolean().optional(),
93
+ effort: z.enum(['minimal', 'low', 'medium', 'high', 'xhigh']).optional(),
142
94
  })
143
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(),
144
120
  });
145
121
 
146
122
  export type PerplexityLanguageModelOptions = z.infer<
@@ -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
  };