ai 6.0.169 → 6.0.170

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.
@@ -255,6 +255,13 @@ To see `streamUI` in action, check out [these examples](#examples).
255
255
  },
256
256
  ],
257
257
  },
258
+ {
259
+ name: 'allowSystemInMessages',
260
+ type: 'boolean',
261
+ isOptional: true,
262
+ description:
263
+ 'Whether system messages are allowed in the `prompt` or `messages` fields. When unset, system messages are allowed with a warning because they can create a prompt injection attack risk. Ideally, use the `system` option instead. Set to `true` to suppress the warning, or `false` to reject system messages in `prompt` or `messages`.',
264
+ },
258
265
  {
259
266
  name: 'maxOutputTokens',
260
267
  type: 'number',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai",
3
- "version": "6.0.169",
3
+ "version": "6.0.170",
4
4
  "description": "AI SDK by Vercel - build apps like ChatGPT, Claude, Gemini, and more with a single interface for any model using the Vercel AI Gateway or go direct to OpenAI, Anthropic, Google, or any other model provider.",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": false,
@@ -55,6 +55,7 @@ const originalGenerateId = createIdGenerator({ prefix: 'aiobj', size: 24 });
55
55
  * @param system - A system message that will be part of the prompt.
56
56
  * @param prompt - A simple text prompt. You can either use `prompt` or `messages` but not both.
57
57
  * @param messages - A list of messages. You can either use `prompt` or `messages` but not both.
58
+ * @param allowSystemInMessages - Whether system messages are allowed in the `prompt` or `messages` fields. When unset, system messages are allowed with a warning.
58
59
  *
59
60
  * @param maxOutputTokens - Maximum number of tokens to generate.
60
61
  * @param temperature - Temperature setting.
@@ -197,6 +198,7 @@ export async function generateObject<
197
198
  system,
198
199
  prompt,
199
200
  messages,
201
+ allowSystemInMessages,
200
202
  maxRetries: maxRetriesArg,
201
203
  abortSignal,
202
204
  headers,
@@ -295,6 +297,7 @@ export async function generateObject<
295
297
  system,
296
298
  prompt,
297
299
  messages,
300
+ allowSystemInMessages,
298
301
  } as Prompt);
299
302
 
300
303
  const promptMessages = await convertToLanguageModelPrompt({
@@ -119,6 +119,7 @@ export type StreamObjectOnFinishCallback<RESULT> = (event: {
119
119
  * @param system - A system message that will be part of the prompt.
120
120
  * @param prompt - A simple text prompt. You can either use `prompt` or `messages` but not both.
121
121
  * @param messages - A list of messages. You can either use `prompt` or `messages` but not both.
122
+ * @param allowSystemInMessages - Whether system messages are allowed in the `prompt` or `messages` fields. When unset, system messages are allowed with a warning.
122
123
  *
123
124
  * @param maxOutputTokens - Maximum number of tokens to generate.
124
125
  * @param temperature - Temperature setting.
@@ -284,6 +285,7 @@ export function streamObject<
284
285
  system,
285
286
  prompt,
286
287
  messages,
288
+ allowSystemInMessages,
287
289
  maxRetries,
288
290
  abortSignal,
289
291
  headers,
@@ -337,6 +339,7 @@ export function streamObject<
337
339
  system,
338
340
  prompt,
339
341
  messages,
342
+ allowSystemInMessages,
340
343
  schemaName,
341
344
  schemaDescription,
342
345
  providerOptions,
@@ -386,6 +389,7 @@ class DefaultStreamObjectResult<
386
389
  system,
387
390
  prompt,
388
391
  messages,
392
+ allowSystemInMessages,
389
393
  schemaName,
390
394
  schemaDescription,
391
395
  providerOptions,
@@ -407,6 +411,7 @@ class DefaultStreamObjectResult<
407
411
  system: Prompt['system'];
408
412
  prompt: Prompt['prompt'];
409
413
  messages: Prompt['messages'];
414
+ allowSystemInMessages: Prompt['allowSystemInMessages'];
410
415
  schemaName: string | undefined;
411
416
  schemaDescription: string | undefined;
412
417
  providerOptions: ProviderOptions | undefined;
@@ -485,6 +490,7 @@ class DefaultStreamObjectResult<
485
490
  system,
486
491
  prompt,
487
492
  messages,
493
+ allowSystemInMessages,
488
494
  } as Prompt);
489
495
 
490
496
  const callOptions = {
@@ -201,6 +201,7 @@ export type GenerateTextOnFinishCallback<TOOLS extends ToolSet> = (
201
201
  * @param system - A system message that will be part of the prompt.
202
202
  * @param prompt - A simple text prompt. You can either use `prompt` or `messages` but not both.
203
203
  * @param messages - A list of messages. You can either use `prompt` or `messages` but not both.
204
+ * @param allowSystemInMessages - Whether system messages are allowed in the `prompt` or `messages` fields. When unset, system messages are allowed with a warning.
204
205
  *
205
206
  * @param maxOutputTokens - Maximum number of tokens to generate.
206
207
  * @param temperature - Temperature setting.
@@ -252,6 +253,7 @@ export async function generateText<
252
253
  system,
253
254
  prompt,
254
255
  messages,
256
+ allowSystemInMessages,
255
257
  maxRetries: maxRetriesArg,
256
258
  abortSignal,
257
259
  timeout,
@@ -477,6 +479,7 @@ export async function generateText<
477
479
  system,
478
480
  prompt,
479
481
  messages,
482
+ allowSystemInMessages,
480
483
  } as Prompt);
481
484
 
482
485
  const globalTelemetry = createGlobalTelemetry(telemetry?.integrations);
@@ -252,6 +252,7 @@ export type StreamTextOnToolCallFinishCallback<
252
252
  * @param system - A system message that will be part of the prompt.
253
253
  * @param prompt - A simple text prompt. You can either use `prompt` or `messages` but not both.
254
254
  * @param messages - A list of messages. You can either use `prompt` or `messages` but not both.
255
+ * @param allowSystemInMessages - Whether system messages are allowed in the `prompt` or `messages` fields. When unset, system messages are allowed with a warning.
255
256
  *
256
257
  * @param maxOutputTokens - Maximum number of tokens to generate.
257
258
  * @param temperature - Temperature setting.
@@ -297,6 +298,7 @@ export function streamText<
297
298
  system,
298
299
  prompt,
299
300
  messages,
301
+ allowSystemInMessages,
300
302
  maxRetries,
301
303
  abortSignal,
302
304
  timeout,
@@ -548,6 +550,7 @@ export function streamText<
548
550
  system,
549
551
  prompt,
550
552
  messages,
553
+ allowSystemInMessages,
551
554
  tools,
552
555
  toolChoice,
553
556
  transforms: asArray(transform),
@@ -731,6 +734,7 @@ class DefaultStreamTextResult<
731
734
  system,
732
735
  prompt,
733
736
  messages,
737
+ allowSystemInMessages,
734
738
  tools,
735
739
  toolChoice,
736
740
  transforms,
@@ -772,6 +776,7 @@ class DefaultStreamTextResult<
772
776
  system: Prompt['system'];
773
777
  prompt: Prompt['prompt'];
774
778
  messages: Prompt['messages'];
779
+ allowSystemInMessages: Prompt['allowSystemInMessages'];
775
780
  tools: TOOLS | undefined;
776
781
  toolChoice: ToolChoice<TOOLS> | undefined;
777
782
  transforms: Array<StreamTextTransform<TOOLS>>;
@@ -1307,6 +1312,7 @@ class DefaultStreamTextResult<
1307
1312
  system,
1308
1313
  prompt,
1309
1314
  messages,
1315
+ allowSystemInMessages,
1310
1316
  } as Prompt);
1311
1317
 
1312
1318
  await notify({
@@ -9,6 +9,16 @@ export type Prompt = {
9
9
  * System message to include in the prompt. Can be used with `prompt` or `messages`.
10
10
  */
11
11
  system?: string | SystemModelMessage | Array<SystemModelMessage>;
12
+
13
+ /**
14
+ * Whether system messages are allowed in the `prompt` or `messages` fields.
15
+ *
16
+ * When disabled, system messages must be provided through the `system`
17
+ * option. When unset, system messages are allowed with a warning.
18
+ *
19
+ * @default undefined
20
+ */
21
+ allowSystemInMessages?: boolean;
12
22
  } & (
13
23
  | {
14
24
  /**
@@ -21,17 +21,31 @@ export type StandardizedPrompt = {
21
21
  messages: ModelMessage[];
22
22
  };
23
23
 
24
- export async function standardizePrompt(
25
- prompt: Prompt,
26
- ): Promise<StandardizedPrompt> {
27
- if (prompt.prompt == null && prompt.messages == null) {
24
+ /**
25
+ * Converts a prompt input into a standardized prompt with validated model
26
+ * messages.
27
+ *
28
+ * @param prompt - The prompt definition to standardize.
29
+ * Set `allowSystemInMessages` to false to reject system messages in the
30
+ * `prompt` or `messages` fields. When unset, system messages are allowed with a
31
+ * warning. System messages in the `system` option are always allowed.
32
+ * @returns The standardized prompt.
33
+ * @throws {InvalidPromptError} When the prompt is invalid.
34
+ */
35
+ export async function standardizePrompt({
36
+ allowSystemInMessages,
37
+ system,
38
+ prompt,
39
+ messages,
40
+ }: Prompt): Promise<StandardizedPrompt> {
41
+ if (prompt == null && messages == null) {
28
42
  throw new InvalidPromptError({
29
43
  prompt,
30
44
  message: 'prompt or messages must be defined',
31
45
  });
32
46
  }
33
47
 
34
- if (prompt.prompt != null && prompt.messages != null) {
48
+ if (prompt != null && messages != null) {
35
49
  throw new InvalidPromptError({
36
50
  prompt,
37
51
  message: 'prompt and messages cannot be defined at the same time',
@@ -40,15 +54,8 @@ export async function standardizePrompt(
40
54
 
41
55
  // validate that system is a string or a SystemModelMessage
42
56
  if (
43
- prompt.system != null &&
44
- typeof prompt.system !== 'string' &&
45
- !asArray(prompt.system).every(
46
- message =>
47
- typeof message === 'object' &&
48
- message !== null &&
49
- 'role' in message &&
50
- message.role === 'system',
51
- )
57
+ typeof system !== 'string' &&
58
+ !asArray(system).every(message => message.role === 'system')
52
59
  ) {
53
60
  throw new InvalidPromptError({
54
61
  prompt,
@@ -57,15 +64,11 @@ export async function standardizePrompt(
57
64
  });
58
65
  }
59
66
 
60
- let messages: ModelMessage[];
61
-
62
- if (prompt.prompt != null && typeof prompt.prompt === 'string') {
63
- messages = [{ role: 'user', content: prompt.prompt }];
64
- } else if (prompt.prompt != null && Array.isArray(prompt.prompt)) {
65
- messages = prompt.prompt;
66
- } else if (prompt.messages != null) {
67
- messages = prompt.messages;
68
- } else {
67
+ if (prompt != null && typeof prompt === 'string') {
68
+ messages = [{ role: 'user', content: prompt }];
69
+ } else if (prompt != null && Array.isArray(prompt)) {
70
+ messages = prompt;
71
+ } else if (messages == null) {
69
72
  throw new InvalidPromptError({
70
73
  prompt,
71
74
  message: 'prompt or messages must be defined',
@@ -79,6 +82,26 @@ export async function standardizePrompt(
79
82
  });
80
83
  }
81
84
 
85
+ if (messages.some(message => message.role === 'system')) {
86
+ if (allowSystemInMessages === false) {
87
+ throw new InvalidPromptError({
88
+ prompt,
89
+ message:
90
+ 'System messages are not allowed in the prompt or messages fields. Use the system option instead.',
91
+ });
92
+ }
93
+
94
+ if (allowSystemInMessages === undefined) {
95
+ console.warn(
96
+ 'AI SDK Warning: System messages in the prompt or messages fields ' +
97
+ 'can be a security risk because they may enable prompt injection ' +
98
+ 'attacks. Use the system option instead when possible. Set ' +
99
+ 'allowSystemInMessages to true to suppress this warning, or false ' +
100
+ 'to throw an error.',
101
+ );
102
+ }
103
+ }
104
+
82
105
  const validationResult = await safeValidateTypes({
83
106
  value: messages,
84
107
  schema: z.array(modelMessageSchema),
@@ -92,8 +115,5 @@ export async function standardizePrompt(
92
115
  });
93
116
  }
94
117
 
95
- return {
96
- messages,
97
- system: prompt.system,
98
- };
118
+ return { messages, system };
99
119
  }