Skip to content

Commit 8549328

Browse files
committed
chore(deps): upgrade @google/genai to 2.13.0 and @anthropic-ai/sdk to 0.115.0
@google/genai 2.x reworks the Interactions API, which the Gemini deep-research provider is built on. Migrate it: - `Interaction.outputs` (a flat content array) is now `steps`, a discriminated timeline; the report text lives in the `model_output` steps' text content, alongside thought and tool steps we skip. - `Usage.total_reasoning_tokens` is now `total_thought_tokens`. The old code already fell back to that name through a cast, so this just makes the field the SDK actually returns the typed one. - SSE events renamed: `content.delta` -> `step.delta`, `interaction.start` -> `interaction.created`, `interaction.complete` -> `interaction.completed`. The new event types are discriminated, so the payload casts are gone. Both `interactions.create` calls also stop annotating their params with `Interactions.CreateAgentInteractionParams{,Non}Streaming`. In 2.13.0 those namespace aliases resolve to `CreateAgentInteraction`, whose `stream` is a plain `boolean` rather than a literal — annotating with them erases the discriminant and the call resolves to the union-returning overload, so the result is typed as `Interaction | Stream` at every use. An inline `stream: true as const` keeps the correct overload. Neither upgrade required a `minimum-release-age` waiver: 2.15.0 and 0.115.0 were checked and 2.13.0 is the newest genai release clearing the 7-day window.
1 parent 2a80121 commit 8549328

3 files changed

Lines changed: 41 additions & 35 deletions

File tree

apps/sim/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
"dependencies": {
3838
"@1password/sdk": "0.3.1",
3939
"@a2a-js/sdk": "1.0.0-alpha.0",
40-
"@anthropic-ai/sdk": "0.114.0",
40+
"@anthropic-ai/sdk": "0.115.0",
4141
"@aws-sdk/client-appconfig": "3.1032.0",
4242
"@aws-sdk/client-appconfigdata": "3.1032.0",
4343
"@aws-sdk/client-athena": "3.1032.0",
@@ -73,7 +73,7 @@
7373
"@earendil-works/pi-coding-agent": "0.80.10",
7474
"@floating-ui/dom": "1.7.6",
7575
"@google-cloud/storage": "7.21.0",
76-
"@google/genai": "1.34.0",
76+
"@google/genai": "2.13.0",
7777
"@hookform/resolvers": "5.2.2",
7878
"@linear/sdk": "40.0.0",
7979
"@marsidev/react-turnstile": "1.4.2",

apps/sim/providers/gemini/core.ts

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -476,18 +476,20 @@ function collapseMessagesToInput(request: ProviderRequest): {
476476
}
477477

478478
/**
479-
* Extracts text content from a completed interaction's outputs array.
480-
* The outputs array can contain text, thought, google_search_result, and other types.
481-
* We concatenate all text outputs to get the full research report.
479+
* Extracts the report text from a completed interaction's step timeline.
480+
*
481+
* The v2 Interactions schema replaced the flat `outputs` array with `steps`, a
482+
* type-discriminated timeline: the model's prose lives in `model_output` steps as text
483+
* content, alongside thought, tool-call, and tool-result steps we deliberately skip.
482484
*/
483-
function extractTextFromInteractionOutputs(outputs: Interactions.Interaction['outputs']): string {
484-
if (!outputs || outputs.length === 0) return ''
485+
function extractTextFromInteractionSteps(steps: Interactions.Interaction['steps']): string {
486+
if (!steps || steps.length === 0) return ''
485487

486488
const textParts: string[] = []
487-
for (const output of outputs) {
488-
if (output.type === 'text') {
489-
const text = (output as Interactions.TextContent).text
490-
if (text) textParts.push(text)
489+
for (const step of steps) {
490+
if (step.type !== 'model_output') continue
491+
for (const content of step.content ?? []) {
492+
if (content.type === 'text' && content.text) textParts.push(content.text)
491493
}
492494
}
493495

@@ -506,10 +508,7 @@ interface DeepResearchUsage {
506508
/**
507509
* Extracts token usage from an Interaction's Usage object.
508510
* The Interactions API provides total_input_tokens, total_output_tokens, total_tokens,
509-
* total_cached_tokens, and total_reasoning_tokens (for thinking models).
510-
*
511-
* Also handles the raw API field name total_thought_tokens which the SDK may
512-
* map to total_reasoning_tokens.
511+
* total_cached_tokens, and total_thought_tokens (for thinking models).
513512
*
514513
* The Interactions API supports implicit caching, and `total_cached_tokens` is a
515514
* subset of `total_input_tokens` there just as `cachedContentTokenCount` is of
@@ -525,10 +524,7 @@ function extractInteractionUsage(usage: Interactions.Usage | undefined): DeepRes
525524

526525
const inputTokens = usage.total_input_tokens ?? 0
527526
const outputTokens = usage.total_output_tokens ?? 0
528-
const reasoningTokens =
529-
usage.total_reasoning_tokens ??
530-
((usage as Record<string, unknown>).total_thought_tokens as number) ??
531-
0
527+
const reasoningTokens = usage.total_thought_tokens ?? 0
532528
const cachedTokens = usage.total_cached_tokens ?? 0
533529
const totalTokens = usage.total_tokens ?? inputTokens + outputTokens
534530

@@ -613,20 +609,20 @@ function createDeepResearchStream(
613609
async start(controller) {
614610
try {
615611
for await (const event of stream) {
616-
if (event.event_type === 'content.delta') {
617-
const delta = (event as Interactions.ContentDelta).delta
618-
if (delta?.type === 'text' && 'text' in delta && delta.text) {
612+
if (event.event_type === 'step.delta') {
613+
const { delta } = event
614+
if (delta?.type === 'text' && delta.text) {
619615
fullContent += delta.text
620616
controller.enqueue(new TextEncoder().encode(delta.text))
621617
}
622-
} else if (event.event_type === 'interaction.complete') {
623-
const interaction = (event as Interactions.InteractionEvent).interaction
618+
} else if (event.event_type === 'interaction.completed') {
619+
const { interaction } = event
624620
if (interaction?.usage) {
625621
completionUsage = extractInteractionUsage(interaction.usage)
626622
}
627623
completedInteractionId = interaction?.id
628-
} else if (event.event_type === 'interaction.start') {
629-
const interaction = (event as Interactions.InteractionEvent).interaction
624+
} else if (event.event_type === 'interaction.created') {
625+
const { interaction } = event
630626
if (interaction?.id) {
631627
completedInteractionId = interaction.id
632628
}
@@ -722,9 +718,16 @@ export async function executeDeepResearchRequest(
722718

723719
// Streaming mode: create a streaming interaction and return a StreamingExecution
724720
if (request.stream) {
725-
const streamParams: Interactions.CreateAgentInteractionParamsStreaming = {
721+
/**
722+
* `stream` is annotated inline rather than via
723+
* `Interactions.CreateAgentInteractionParamsStreaming`: as of @google/genai 2.13.0 that
724+
* namespace alias resolves to `CreateAgentInteraction`, whose `stream` is a plain
725+
* `boolean`. Annotating with it loses the literal that discriminates `interactions.create`'s
726+
* overloads, so the call falls through to the union-returning signature.
727+
*/
728+
const streamParams = {
726729
...baseParams,
727-
stream: true,
730+
stream: true as const,
728731
}
729732

730733
const streamResponse = await ai.interactions.create(
@@ -805,9 +808,10 @@ export async function executeDeepResearchRequest(
805808
}
806809

807810
// Non-streaming mode: create and poll
808-
const createParams: Interactions.CreateAgentInteractionParamsNonStreaming = {
811+
/** Inline literal for the same overload-discrimination reason as `streamParams` above. */
812+
const createParams = {
809813
...baseParams,
810-
stream: false,
814+
stream: false as const,
811815
}
812816

813817
const interaction = await ai.interactions.create(
@@ -855,7 +859,7 @@ export async function executeDeepResearchRequest(
855859
)
856860
}
857861

858-
const content = extractTextFromInteractionOutputs(result.outputs)
862+
const content = extractTextFromInteractionSteps(result.steps)
859863
const usage = extractInteractionUsage(result.usage)
860864

861865
logger.info('Deep research completed', {

bun.lock

Lines changed: 6 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)