@ai-sdk/google 3.0.74 → 3.0.75

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.
@@ -2,11 +2,9 @@ import type { LanguageModelV3FinishReason } from '@ai-sdk/provider';
2
2
  import type { GoogleInteractionsStatus } from './google-interactions-prompt';
3
3
 
4
4
  /*
5
- * Mapping is intentionally conservative for TASK-1; later tasks may refine the
6
- * `incomplete` and `cancelled` cases once we observe their wire-format
7
- * companions. `tool-calls` is selected when the response includes a
8
- * client-side function call (the API itself signals this via `requires_action`,
9
- * but `completed + hasFunctionCall` also occurs in practice).
5
+ * `tool-calls` is selected when the response includes a client-side function
6
+ * call. The API itself signals this via `requires_action`, but
7
+ * `completed + hasFunctionCall` also occurs in practice.
10
8
  */
11
9
  export function mapGoogleInteractionsFinishReason({
12
10
  status,
@@ -1,5 +1,5 @@
1
1
  import type { JSONValue, LanguageModelV3Content } from '@ai-sdk/provider';
2
- import type { GoogleInteractionsContentBlock } from './google-interactions-api';
2
+ import type { GoogleInteractionsStep } from './google-interactions-api';
3
3
  import {
4
4
  annotationsToSources,
5
5
  builtinToolResultToSources,
@@ -16,7 +16,7 @@ export type ParseGoogleInteractionsOutputsResult = {
16
16
 
17
17
  /*
18
18
  * Builds a `providerMetadata.google` payload for an output part so the
19
- * Interactions converter on the next turn can read both the per-block
19
+ * Interactions converter on the next turn can read both the per-step
20
20
  * `signature` (round-trip) and the parent `interactionId` (history compaction
21
21
  * under `previousInteractionId`).
22
22
  */
@@ -37,9 +37,6 @@ function googleProviderMetadata({
37
37
  return Object.keys(google).length > 0 ? { providerMetadata: { google } } : {};
38
38
  }
39
39
 
40
- /**
41
- * Set of built-in tool *call* discriminators emitted by the Interactions API.
42
- */
43
40
  const BUILTIN_TOOL_CALL_TYPES = new Set([
44
41
  'google_search_call',
45
42
  'code_execution_call',
@@ -49,9 +46,6 @@ const BUILTIN_TOOL_CALL_TYPES = new Set([
49
46
  'mcp_server_tool_call',
50
47
  ]);
51
48
 
52
- /**
53
- * Set of built-in tool *result* discriminators.
54
- */
55
49
  const BUILTIN_TOOL_RESULT_TYPES = new Set([
56
50
  'google_search_result',
57
51
  'code_execution_result',
@@ -70,24 +64,24 @@ function builtinToolNameFromResultType(type: string): string {
70
64
  }
71
65
 
72
66
  /**
73
- * Walks the `outputs[]` array of an Interaction response and emits AI SDK
67
+ * Walks the `steps[]` array of an Interactions response and emits AI SDK
74
68
  * `LanguageModelV3Content[]`. Surfaces:
75
69
  *
76
- * - `text` blocks (with annotations -> source parts)
77
- * - `thought` blocks (reasoning)
78
- * - `function_call` blocks (client-executed tool calls)
79
- * - Built-in tool `*_call` / `*_result` blocks (Google Search, Code Execution,
80
- * URL Context, File Search, Google Maps, MCP Server) as
70
+ * - `model_output` steps: iterates `step.content[]` for `text` (with
71
+ * annotations source parts) and `image` content blocks.
72
+ * - `thought` steps: emits a single `reasoning` part from `summary[*]`.
73
+ * - `function_call` steps: emits a `tool-call` part directly.
74
+ * - Built-in tool `*_call` / `*_result` steps (Google Search, Code Execution,
75
+ * URL Context, File Search, Google Maps, MCP Server): emits
81
76
  * `tool-call`/`tool-result` parts with `providerExecuted: true`.
82
- * - `text_annotation`-derived sources from the URL / file / place citations
83
- * carried on text blocks.
77
+ * - `user_input` steps are skipped (they echo the client's input).
84
78
  */
85
79
  export function parseGoogleInteractionsOutputs({
86
- outputs,
80
+ steps,
87
81
  generateId,
88
82
  interactionId,
89
83
  }: {
90
- outputs: Array<GoogleInteractionsContentBlock> | null | undefined;
84
+ steps: Array<GoogleInteractionsStep> | null | undefined;
91
85
  generateId: () => string;
92
86
  /**
93
87
  * Top-level `Interaction.id` on the response. Stamped onto each output
@@ -100,34 +94,80 @@ export function parseGoogleInteractionsOutputs({
100
94
  const content: Array<LanguageModelV3Content> = [];
101
95
  let hasFunctionCall = false;
102
96
 
103
- if (outputs == null) {
97
+ if (steps == null) {
104
98
  return { content, hasFunctionCall };
105
99
  }
106
100
 
107
- for (const block of outputs) {
108
- if (block == null || typeof block !== 'object') continue;
109
- const type = (block as { type?: string }).type;
101
+ for (const step of steps) {
102
+ if (step == null || typeof step !== 'object') continue;
103
+ const type = (step as { type?: string }).type;
110
104
  if (typeof type !== 'string') continue;
111
105
 
112
106
  switch (type) {
113
- case 'text': {
114
- const text = (block as { text?: string }).text ?? '';
115
- const annotations = (
116
- block as { annotations?: Array<GoogleInteractionsAnnotation> }
117
- ).annotations;
118
- content.push({
119
- type: 'text',
120
- text,
121
- ...googleProviderMetadata({ interactionId }),
122
- });
123
- const sources = annotationsToSources({ annotations, generateId });
124
- for (const source of sources) {
125
- content.push(source);
107
+ case 'user_input': {
108
+ break;
109
+ }
110
+ case 'model_output': {
111
+ const blocks =
112
+ (step as { content?: Array<{ type?: string; [k: string]: unknown }> })
113
+ .content ?? [];
114
+ for (const block of blocks) {
115
+ if (block == null || typeof block !== 'object') continue;
116
+ const blockType = block.type;
117
+ if (blockType === 'text') {
118
+ const text = (block as { text?: string }).text ?? '';
119
+ const annotations = (
120
+ block as {
121
+ annotations?: Array<GoogleInteractionsAnnotation>;
122
+ }
123
+ ).annotations;
124
+ content.push({
125
+ type: 'text',
126
+ text,
127
+ ...googleProviderMetadata({ interactionId }),
128
+ });
129
+ const sources = annotationsToSources({ annotations, generateId });
130
+ for (const source of sources) {
131
+ content.push(source);
132
+ }
133
+ } else if (blockType === 'image') {
134
+ const image = block as {
135
+ data?: string;
136
+ mime_type?: string;
137
+ uri?: string;
138
+ };
139
+ if (image.data != null && image.data.length > 0) {
140
+ content.push({
141
+ type: 'file',
142
+ mediaType: image.mime_type ?? 'image/png',
143
+ data: image.data,
144
+ ...googleProviderMetadata({ interactionId }),
145
+ });
146
+ } else if (image.uri != null && image.uri.length > 0) {
147
+ /*
148
+ * V3 `LanguageModelV3File` only supports inline data (`string` /
149
+ * `Uint8Array`). URL-only image outputs cannot be represented as
150
+ * a file content part on the v3 spec; surface the URI through
151
+ * provider metadata so callers can still recover it.
152
+ */
153
+ content.push({
154
+ type: 'file',
155
+ mediaType: image.mime_type ?? 'image/png',
156
+ data: '',
157
+ providerMetadata: {
158
+ google: {
159
+ ...(interactionId != null ? { interactionId } : {}),
160
+ imageUri: image.uri,
161
+ },
162
+ },
163
+ });
164
+ }
165
+ }
126
166
  }
127
167
  break;
128
168
  }
129
169
  case 'thought': {
130
- const thought = block as {
170
+ const thought = step as {
131
171
  signature?: string;
132
172
  summary?: Array<{ type: string; text?: string }>;
133
173
  };
@@ -148,43 +188,9 @@ export function parseGoogleInteractionsOutputs({
148
188
  });
149
189
  break;
150
190
  }
151
- case 'image': {
152
- const image = block as {
153
- data?: string;
154
- mime_type?: string;
155
- uri?: string;
156
- };
157
- if (image.data != null && image.data.length > 0) {
158
- content.push({
159
- type: 'file',
160
- mediaType: image.mime_type ?? 'image/png',
161
- data: image.data,
162
- ...googleProviderMetadata({ interactionId }),
163
- });
164
- } else if (image.uri != null && image.uri.length > 0) {
165
- /*
166
- * V3 `LanguageModelV3File` only supports inline data (`string` /
167
- * `Uint8Array`). URL-only image outputs cannot be represented as a
168
- * file content part on the v3 spec; surface the URI through provider
169
- * metadata so callers can still recover it.
170
- */
171
- content.push({
172
- type: 'file',
173
- mediaType: image.mime_type ?? 'image/png',
174
- data: '',
175
- providerMetadata: {
176
- google: {
177
- ...(interactionId != null ? { interactionId } : {}),
178
- imageUri: image.uri,
179
- },
180
- },
181
- });
182
- }
183
- break;
184
- }
185
191
  case 'function_call': {
186
192
  hasFunctionCall = true;
187
- const call = block as {
193
+ const call = step as {
188
194
  id: string;
189
195
  name: string;
190
196
  arguments?: Record<string, unknown> | null;
@@ -204,7 +210,7 @@ export function parseGoogleInteractionsOutputs({
204
210
  }
205
211
  default: {
206
212
  if (BUILTIN_TOOL_CALL_TYPES.has(type)) {
207
- const call = block as {
213
+ const call = step as {
208
214
  id?: string;
209
215
  arguments?: Record<string, unknown>;
210
216
  name?: string;
@@ -223,7 +229,7 @@ export function parseGoogleInteractionsOutputs({
223
229
  providerExecuted: true,
224
230
  });
225
231
  } else if (BUILTIN_TOOL_RESULT_TYPES.has(type)) {
226
- const result = block as {
232
+ const result = step as {
227
233
  call_id?: string;
228
234
  result?: unknown;
229
235
  is_error?: boolean;
@@ -241,7 +247,7 @@ export function parseGoogleInteractionsOutputs({
241
247
  });
242
248
  const sources = builtinToolResultToSources({
243
249
  block:
244
- block as unknown as GoogleInteractionsBuiltinToolResultContent,
250
+ step as unknown as GoogleInteractionsBuiltinToolResultContent,
245
251
  generateId,
246
252
  });
247
253
  for (const source of sources) {
@@ -24,7 +24,7 @@ export type PrepareGoogleInteractionsToolsResult = {
24
24
  * `src/interactions/resources/interactions.ts` `Function.parameters: unknown`).
25
25
  *
26
26
  * Provider-defined tools (`{ type: 'provider', id: 'google.<name>', args }`)
27
- * map to the discriminated `Tool` union (TASK-7). The full set of
27
+ * map to the discriminated `Tool` union. The full set of
28
28
  * provider-defined tool ids supported here:
29
29
  *
30
30
  * - `google.google_search` -> `{ type: 'google_search', search_types? }`
@@ -178,7 +178,7 @@ export function streamGoogleInteractionEvents({
178
178
  lastEventId = ev.event_id;
179
179
  }
180
180
  if (
181
- ev.event_type === 'interaction.complete' ||
181
+ ev.event_type === 'interaction.completed' ||
182
182
  ev.event_type === 'error'
183
183
  ) {
184
184
  complete = true;
@@ -63,7 +63,7 @@ export function synthesizeGoogleInteractionsAgentStream({
63
63
  }
64
64
 
65
65
  const { content, hasFunctionCall } = parseGoogleInteractionsOutputs({
66
- outputs: response.outputs ?? null,
66
+ steps: response.steps ?? null,
67
67
  generateId,
68
68
  interactionId,
69
69
  });