diff --git a/js/plugins/anthropic/src/runner/beta.ts b/js/plugins/anthropic/src/runner/beta.ts index 4efcd1fd13..24fcac60d8 100644 --- a/js/plugins/anthropic/src/runner/beta.ts +++ b/js/plugins/anthropic/src/runner/beta.ts @@ -51,7 +51,6 @@ import { unsupportedServerToolError, } from './converters/beta.js'; import { - inputJsonDeltaError, redactedThinkingBlockToPart, textBlockToPart, textDeltaToPart, @@ -464,7 +463,7 @@ export class BetaRunner extends BaseRunner { return thinkingDeltaToPart(event.delta); } if (event.delta.type === 'input_json_delta') { - throw inputJsonDeltaError(); + return { data: event.delta.partial_json }; } // signature_delta - ignore return undefined; diff --git a/js/plugins/anthropic/src/runner/converters/shared.ts b/js/plugins/anthropic/src/runner/converters/shared.ts index 6d6faf6091..ddb2fc0772 100644 --- a/js/plugins/anthropic/src/runner/converters/shared.ts +++ b/js/plugins/anthropic/src/runner/converters/shared.ts @@ -102,12 +102,3 @@ export function textDeltaToPart(delta: { text: string }): Part { export function thinkingDeltaToPart(delta: { thinking: string }): Part { return { reasoning: delta.thinking }; } - -/** - * Error for unsupported input_json_delta in streaming. - */ -export function inputJsonDeltaError(): Error { - return new Error( - 'Anthropic streaming tool input (input_json_delta) is not yet supported. Please disable streaming or upgrade this plugin.' - ); -} diff --git a/js/plugins/anthropic/src/runner/stable.ts b/js/plugins/anthropic/src/runner/stable.ts index 61c921b97c..e08031e85e 100644 --- a/js/plugins/anthropic/src/runner/stable.ts +++ b/js/plugins/anthropic/src/runner/stable.ts @@ -45,7 +45,6 @@ import { AnthropicConfigSchema, type ClaudeRunnerParams } from '../types.js'; import { removeUndefinedProperties } from '../utils.js'; import { BaseRunner } from './base.js'; import { - inputJsonDeltaError, redactedThinkingBlockToPart, textBlockToPart, textDeltaToPart, @@ -356,7 +355,7 @@ export class Runner extends BaseRunner { } if (delta.type === 'input_json_delta') { - throw inputJsonDeltaError(); + return { data: delta.partial_json }; } // signature_delta - ignore diff --git a/js/plugins/anthropic/tests/stable_runner_test.ts b/js/plugins/anthropic/tests/stable_runner_test.ts index 28e1834e2a..478a9c1015 100644 --- a/js/plugins/anthropic/tests/stable_runner_test.ts +++ b/js/plugins/anthropic/tests/stable_runner_test.ts @@ -762,19 +762,18 @@ describe('fromAnthropicContentBlockChunk', () => { }); } - it('should throw for unsupported tool input streaming deltas', () => { - assert.throws( - () => - testRunner.fromAnthropicContentBlockChunk({ - index: 0, - type: 'content_block_delta', - delta: { - type: 'input_json_delta', - partial_json: '{"foo":', - }, - } as MessageStreamEvent), - /Anthropic streaming tool input \(input_json_delta\) is not yet supported/ - ); + it('should handle tool input streaming deltas', () => { + const actualOutput = testRunner.fromAnthropicContentBlockChunk({ + index: 0, + type: 'content_block_delta', + delta: { + type: 'input_json_delta', + partial_json: '{"foo":', + }, + } as MessageStreamEvent); + assert.deepStrictEqual(actualOutput, { + data: '{"foo":', + }); }); }); diff --git a/js/testapps/anthropic/README.md b/js/testapps/anthropic/README.md index b209958e68..82f9182b69 100644 --- a/js/testapps/anthropic/README.md +++ b/js/testapps/anthropic/README.md @@ -72,4 +72,8 @@ Each source file defines flows that can be invoked from the Dev UI or the Genkit - `stable-vision-base64` – Analyze an image from a local file (base64 encoded) - `stable-vision-conversation` – Multi-turn conversation about an image +### Tools +- `anthropic-stable-tools` – Get the weather in a given location using a Genkit tool +- `anthropic-stable-tools-stream` – Streaming response with Genkit tools + Example: `genkit flow:run anthropic-stable-hello` diff --git a/js/testapps/anthropic/src/stable/tools.ts b/js/testapps/anthropic/src/stable/tools.ts index 95c62c5870..6947971600 100644 --- a/js/testapps/anthropic/src/stable/tools.ts +++ b/js/testapps/anthropic/src/stable/tools.ts @@ -54,3 +54,24 @@ ai.defineFlow( return text; } ); + +ai.defineFlow( + 'anthropic-stable-tools-stream', + async ({ place }: { place: string }, { sendChunk }) => { + const { stream } = ai.generateStream({ + model: anthropic.model('claude-sonnet-4-5'), + tools: [getWeather], + prompt: `What is the weather in ${place}?`, + }); + + let response = ''; + for await (const chunk of stream) { + response += chunk.text ?? ''; + if (chunk.text) { + sendChunk(chunk.text); + } + } + + return response; + } +);