Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions js/plugins/anthropic/src/runner/beta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ import {
unsupportedServerToolError,
} from './converters/beta.js';
import {
inputJsonDeltaError,
redactedThinkingBlockToPart,
textBlockToPart,
textDeltaToPart,
Expand Down Expand Up @@ -464,7 +463,7 @@ export class BetaRunner extends BaseRunner<BetaRunnerTypes> {
return thinkingDeltaToPart(event.delta);
}
if (event.delta.type === 'input_json_delta') {
throw inputJsonDeltaError();
return { data: event.delta.partial_json };
}
// signature_delta - ignore
return undefined;
Expand Down
9 changes: 0 additions & 9 deletions js/plugins/anthropic/src/runner/converters/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.'
);
}
3 changes: 1 addition & 2 deletions js/plugins/anthropic/src/runner/stable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -356,7 +355,7 @@ export class Runner extends BaseRunner<RunnerTypes> {
}

if (delta.type === 'input_json_delta') {
throw inputJsonDeltaError();
return { data: delta.partial_json };
}

// signature_delta - ignore
Expand Down
25 changes: 12 additions & 13 deletions js/plugins/anthropic/tests/stable_runner_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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":',
});
});
});

Expand Down
4 changes: 4 additions & 0 deletions js/testapps/anthropic/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`
21 changes: 21 additions & 0 deletions js/testapps/anthropic/src/stable/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
);