Skip to content

Commit c2709b2

Browse files
committed
fix(messages): updates for server tools
1 parent cb620bb commit c2709b2

File tree

6 files changed

+176
-16
lines changed

6 files changed

+176
-16
lines changed

examples/tools.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ async function main() {
4949
{
5050
type: 'tool_result',
5151
tool_use_id: tool.id,
52-
content: [{ type: 'text', text: 'The weather is 73f' }],
52+
content: 'The weather is 73f',
5353
},
5454
],
5555
},

examples/web-search-stream.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#!/usr/bin/env -S npm run tsn -T
2+
3+
import Anthropic from '@anthropic-ai/sdk';
4+
5+
const client = new Anthropic();
6+
7+
async function main() {
8+
console.log('Claude with Web Search (Streaming)');
9+
console.log('==================================');
10+
11+
// Create a stream with web search enabled
12+
const stream = client.messages
13+
.stream({
14+
model: 'claude-3-5-sonnet-latest',
15+
max_tokens: 1024,
16+
messages: [
17+
{
18+
role: 'user',
19+
content: "What's the weather in New York?",
20+
},
21+
],
22+
tools: [
23+
{
24+
name: 'web_search',
25+
type: 'web_search_20250305',
26+
},
27+
],
28+
})
29+
.on('text', (text) => {
30+
// Print text as it arrives
31+
process.stdout.write(text);
32+
})
33+
.on('streamEvent', (event) => {
34+
// Track when web search is being used
35+
if (event.type === 'content_block_start' && event.content_block.type === 'web_search_tool_result') {
36+
process.stdout.write('\n[Web search started...]');
37+
}
38+
});
39+
40+
// Wait for the stream to complete
41+
const message = await stream.finalMessage();
42+
43+
console.log('\n\nFinal usage statistics:');
44+
console.log(`Input tokens: ${message.usage.input_tokens}`);
45+
console.log(`Output tokens: ${message.usage.output_tokens}`);
46+
47+
if (message.usage.server_tool_use) {
48+
console.log(`Web search requests: ${message.usage.server_tool_use.web_search_requests}`);
49+
} else {
50+
console.log('No web search requests recorded in usage');
51+
}
52+
53+
// Display message content types for debugging
54+
console.log('\nMessage Content Types:');
55+
message.content.forEach((block, i) => {
56+
console.log(`Content Block ${i + 1}: Type = ${block.type}`);
57+
});
58+
59+
// Show full message for debugging
60+
console.log('\nComplete message structure:');
61+
console.dir(message, { depth: 4 });
62+
}
63+
64+
main().catch(console.error);

examples/web-search.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#!/usr/bin/env -S npm run tsn -T
2+
3+
import Anthropic from '@anthropic-ai/sdk';
4+
5+
const client = new Anthropic();
6+
7+
async function main() {
8+
console.log('Web Search Example');
9+
console.log('=================');
10+
11+
// Create a message with web search enabled
12+
const message = await client.messages.create({
13+
model: 'claude-3-5-sonnet-latest',
14+
max_tokens: 1024,
15+
messages: [
16+
{
17+
role: 'user',
18+
content:
19+
"What's the current weather in San Francisco? Please search the web for up-to-date information.",
20+
},
21+
],
22+
tools: [
23+
{
24+
name: 'web_search',
25+
type: 'web_search_20250305',
26+
},
27+
],
28+
});
29+
30+
// Print the full response
31+
console.log('\nFull response:');
32+
console.dir(message, { depth: 4 });
33+
34+
// Extract and print the content
35+
console.log('\nResponse content:');
36+
for (const contentBlock of message.content) {
37+
if (contentBlock.type === 'text') {
38+
console.log(contentBlock.text);
39+
}
40+
}
41+
42+
// Print usage information
43+
console.log('\nUsage statistics:');
44+
console.log(`Input tokens: ${message.usage.input_tokens}`);
45+
console.log(`Output tokens: ${message.usage.output_tokens}`);
46+
47+
if (message.usage.server_tool_use) {
48+
console.log(`Web search requests: ${message.usage.server_tool_use.web_search_requests}`);
49+
}
50+
}
51+
52+
main().catch(console.error);

src/lib/BetaMessageStream.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,15 @@ export class BetaMessageStream implements AsyncIterable<BetaMessageStreamEvent>
531531
snapshot.stop_reason = event.delta.stop_reason;
532532
snapshot.stop_sequence = event.delta.stop_sequence;
533533
snapshot.usage.output_tokens = event.usage.output_tokens;
534+
535+
// Update other usage fields if they exist in the event
536+
if (event.usage.input_tokens) {
537+
snapshot.usage.input_tokens = event.usage.input_tokens;
538+
}
539+
snapshot.usage.cache_creation_input_tokens = event.usage.cache_creation_input_tokens;
540+
snapshot.usage.cache_read_input_tokens = event.usage.cache_read_input_tokens;
541+
snapshot.usage.server_tool_use = event.usage.server_tool_use;
542+
534543
return snapshot;
535544
case 'content_block_start':
536545
snapshot.content.push(event.content_block);

src/lib/MessageStream.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,15 @@ export class MessageStream implements AsyncIterable<MessageStreamEvent> {
531531
snapshot.stop_reason = event.delta.stop_reason;
532532
snapshot.stop_sequence = event.delta.stop_sequence;
533533
snapshot.usage.output_tokens = event.usage.output_tokens;
534+
535+
// Update other usage fields if they exist in the event
536+
if (event.usage.input_tokens) {
537+
snapshot.usage.input_tokens = event.usage.input_tokens;
538+
}
539+
snapshot.usage.cache_creation_input_tokens = event.usage.cache_creation_input_tokens;
540+
snapshot.usage.cache_read_input_tokens = event.usage.cache_read_input_tokens;
541+
snapshot.usage.server_tool_use = event.usage.server_tool_use;
542+
534543
return snapshot;
535544
case 'content_block_start':
536545
snapshot.content.push(event.content_block);

tests/api-resources/MessageStream.test.ts

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,19 @@ async function* messageIterable(message: Message): AsyncGenerator<MessageStreamE
3434
}
3535
: content.type === 'thinking' ? { type: 'thinking', thinking: '', signature: '' }
3636
: content.type === 'redacted_thinking' ? { type: 'redacted_thinking', data: '' }
37+
: content.type === 'server_tool_use' ?
38+
{
39+
type: 'server_tool_use',
40+
id: 'toolu_01Up7oRoHeGvhded7n66nPzP',
41+
name: 'web_search',
42+
input: {},
43+
}
44+
: content.type === 'web_search_tool_result' ?
45+
{
46+
type: 'web_search_tool_result',
47+
tool_use_id: 'toolu_01Up7oRoHeGvhded7n66nPzP',
48+
content: [],
49+
}
3750
: assertNever(content),
3851
index: idx,
3952
};
@@ -60,6 +73,10 @@ async function* messageIterable(message: Message): AsyncGenerator<MessageStreamE
6073
throw new Error('thinking not implemented yet');
6174
} else if (content.type === 'redacted_thinking') {
6275
throw new Error('redacted_thinking not implemented yet');
76+
} else if (content.type === 'server_tool_use') {
77+
throw new Error('server_tool_use not implemented yet');
78+
} else if (content.type === 'web_search_tool_result') {
79+
throw new Error('web_search_tool_result not implemented yet');
6380
} else {
6481
assertNever(content);
6582
}
@@ -72,7 +89,13 @@ async function* messageIterable(message: Message): AsyncGenerator<MessageStreamE
7289

7390
yield {
7491
type: 'message_delta',
75-
usage: { output_tokens: 6 },
92+
usage: {
93+
output_tokens: 6,
94+
input_tokens: null,
95+
cache_creation_input_tokens: null,
96+
cache_read_input_tokens: null,
97+
server_tool_use: null,
98+
},
7699
// @ts-ignore
77100
delta: { stop_reason: message.stop_reason, stop_sequence: message.stop_sequence },
78101
};
@@ -166,6 +189,7 @@ describe('MessageStream class', () => {
166189
input_tokens: 10,
167190
cache_creation_input_tokens: null,
168191
cache_read_input_tokens: null,
192+
server_tool_use: null,
169193
},
170194
}),
171195
);
@@ -226,22 +250,22 @@ describe('MessageStream class', () => {
226250
},
227251
{
228252
"args": [
229-
"{"type":"message_start","message":{"type":"message","id":"msg_01hhptzfxdaeehfxfv070yb6b8","role":"assistant","content":[],"model":"claude-3-opus-20240229","stop_reason":null,"stop_sequence":null,"usage":{"output_tokens":6,"input_tokens":10,"cache_creation_input_tokens":null,"cache_read_input_tokens":null}}}",
230-
"{"type":"message","id":"msg_01hhptzfxdaeehfxfv070yb6b8","role":"assistant","content":[],"model":"claude-3-opus-20240229","stop_reason":null,"stop_sequence":null,"usage":{"output_tokens":6,"input_tokens":10,"cache_creation_input_tokens":null,"cache_read_input_tokens":null}}",
253+
"{"type":"message_start","message":{"type":"message","id":"msg_01hhptzfxdaeehfxfv070yb6b8","role":"assistant","content":[],"model":"claude-3-opus-20240229","stop_reason":null,"stop_sequence":null,"usage":{"output_tokens":6,"input_tokens":10,"cache_creation_input_tokens":null,"cache_read_input_tokens":null,"server_tool_use":null}}}",
254+
"{"type":"message","id":"msg_01hhptzfxdaeehfxfv070yb6b8","role":"assistant","content":[],"model":"claude-3-opus-20240229","stop_reason":null,"stop_sequence":null,"usage":{"output_tokens":6,"input_tokens":10,"cache_creation_input_tokens":null,"cache_read_input_tokens":null,"server_tool_use":null}}",
231255
],
232256
"type": "streamEvent",
233257
},
234258
{
235259
"args": [
236260
"{"type":"content_block_start","content_block":{"type":"text","text":"","citations":null},"index":0}",
237-
"{"type":"message","id":"msg_01hhptzfxdaeehfxfv070yb6b8","role":"assistant","content":[{"type":"text","text":"","citations":null}],"model":"claude-3-opus-20240229","stop_reason":null,"stop_sequence":null,"usage":{"output_tokens":6,"input_tokens":10,"cache_creation_input_tokens":null,"cache_read_input_tokens":null}}",
261+
"{"type":"message","id":"msg_01hhptzfxdaeehfxfv070yb6b8","role":"assistant","content":[{"type":"text","text":"","citations":null}],"model":"claude-3-opus-20240229","stop_reason":null,"stop_sequence":null,"usage":{"output_tokens":6,"input_tokens":10,"cache_creation_input_tokens":null,"cache_read_input_tokens":null,"server_tool_use":null}}",
238262
],
239263
"type": "streamEvent",
240264
},
241265
{
242266
"args": [
243267
"{"type":"content_block_delta","delta":{"type":"text_delta","text":"Hello"},"index":0}",
244-
"{"type":"message","id":"msg_01hhptzfxdaeehfxfv070yb6b8","role":"assistant","content":[{"type":"text","text":"Hello","citations":null}],"model":"claude-3-opus-20240229","stop_reason":null,"stop_sequence":null,"usage":{"output_tokens":6,"input_tokens":10,"cache_creation_input_tokens":null,"cache_read_input_tokens":null}}",
268+
"{"type":"message","id":"msg_01hhptzfxdaeehfxfv070yb6b8","role":"assistant","content":[{"type":"text","text":"Hello","citations":null}],"model":"claude-3-opus-20240229","stop_reason":null,"stop_sequence":null,"usage":{"output_tokens":6,"input_tokens":10,"cache_creation_input_tokens":null,"cache_read_input_tokens":null,"server_tool_use":null}}",
245269
],
246270
"type": "streamEvent",
247271
},
@@ -255,7 +279,7 @@ describe('MessageStream class', () => {
255279
{
256280
"args": [
257281
"{"type":"content_block_delta","delta":{"type":"text_delta","text":" ther"},"index":0}",
258-
"{"type":"message","id":"msg_01hhptzfxdaeehfxfv070yb6b8","role":"assistant","content":[{"type":"text","text":"Hello ther","citations":null}],"model":"claude-3-opus-20240229","stop_reason":null,"stop_sequence":null,"usage":{"output_tokens":6,"input_tokens":10,"cache_creation_input_tokens":null,"cache_read_input_tokens":null}}",
282+
"{"type":"message","id":"msg_01hhptzfxdaeehfxfv070yb6b8","role":"assistant","content":[{"type":"text","text":"Hello ther","citations":null}],"model":"claude-3-opus-20240229","stop_reason":null,"stop_sequence":null,"usage":{"output_tokens":6,"input_tokens":10,"cache_creation_input_tokens":null,"cache_read_input_tokens":null,"server_tool_use":null}}",
259283
],
260284
"type": "streamEvent",
261285
},
@@ -269,7 +293,7 @@ describe('MessageStream class', () => {
269293
{
270294
"args": [
271295
"{"type":"content_block_delta","delta":{"type":"text_delta","text":"e!"},"index":0}",
272-
"{"type":"message","id":"msg_01hhptzfxdaeehfxfv070yb6b8","role":"assistant","content":[{"type":"text","text":"Hello there!","citations":null}],"model":"claude-3-opus-20240229","stop_reason":null,"stop_sequence":null,"usage":{"output_tokens":6,"input_tokens":10,"cache_creation_input_tokens":null,"cache_read_input_tokens":null}}",
296+
"{"type":"message","id":"msg_01hhptzfxdaeehfxfv070yb6b8","role":"assistant","content":[{"type":"text","text":"Hello there!","citations":null}],"model":"claude-3-opus-20240229","stop_reason":null,"stop_sequence":null,"usage":{"output_tokens":6,"input_tokens":10,"cache_creation_input_tokens":null,"cache_read_input_tokens":null,"server_tool_use":null}}",
273297
],
274298
"type": "streamEvent",
275299
},
@@ -283,7 +307,7 @@ describe('MessageStream class', () => {
283307
{
284308
"args": [
285309
"{"type":"content_block_stop","index":0}",
286-
"{"type":"message","id":"msg_01hhptzfxdaeehfxfv070yb6b8","role":"assistant","content":[{"type":"text","text":"Hello there!","citations":null}],"model":"claude-3-opus-20240229","stop_reason":null,"stop_sequence":null,"usage":{"output_tokens":6,"input_tokens":10,"cache_creation_input_tokens":null,"cache_read_input_tokens":null}}",
310+
"{"type":"message","id":"msg_01hhptzfxdaeehfxfv070yb6b8","role":"assistant","content":[{"type":"text","text":"Hello there!","citations":null}],"model":"claude-3-opus-20240229","stop_reason":null,"stop_sequence":null,"usage":{"output_tokens":6,"input_tokens":10,"cache_creation_input_tokens":null,"cache_read_input_tokens":null,"server_tool_use":null}}",
287311
],
288312
"type": "streamEvent",
289313
},
@@ -295,27 +319,27 @@ describe('MessageStream class', () => {
295319
},
296320
{
297321
"args": [
298-
"{"type":"message_delta","usage":{"output_tokens":6},"delta":{"stop_reason":"end_turn","stop_sequence":null}}",
299-
"{"type":"message","id":"msg_01hhptzfxdaeehfxfv070yb6b8","role":"assistant","content":[{"type":"text","text":"Hello there!","citations":null}],"model":"claude-3-opus-20240229","stop_reason":"end_turn","stop_sequence":null,"usage":{"output_tokens":6,"input_tokens":10,"cache_creation_input_tokens":null,"cache_read_input_tokens":null}}",
322+
"{"type":"message_delta","usage":{"output_tokens":6,"input_tokens":null,"cache_creation_input_tokens":null,"cache_read_input_tokens":null,"server_tool_use":null},"delta":{"stop_reason":"end_turn","stop_sequence":null}}",
323+
"{"type":"message","id":"msg_01hhptzfxdaeehfxfv070yb6b8","role":"assistant","content":[{"type":"text","text":"Hello there!","citations":null}],"model":"claude-3-opus-20240229","stop_reason":"end_turn","stop_sequence":null,"usage":{"output_tokens":6,"input_tokens":10,"cache_creation_input_tokens":null,"cache_read_input_tokens":null,"server_tool_use":null}}",
300324
],
301325
"type": "streamEvent",
302326
},
303327
{
304328
"args": [
305329
"{"type":"message_stop"}",
306-
"{"type":"message","id":"msg_01hhptzfxdaeehfxfv070yb6b8","role":"assistant","content":[{"type":"text","text":"Hello there!","citations":null}],"model":"claude-3-opus-20240229","stop_reason":"end_turn","stop_sequence":null,"usage":{"output_tokens":6,"input_tokens":10,"cache_creation_input_tokens":null,"cache_read_input_tokens":null}}",
330+
"{"type":"message","id":"msg_01hhptzfxdaeehfxfv070yb6b8","role":"assistant","content":[{"type":"text","text":"Hello there!","citations":null}],"model":"claude-3-opus-20240229","stop_reason":"end_turn","stop_sequence":null,"usage":{"output_tokens":6,"input_tokens":10,"cache_creation_input_tokens":null,"cache_read_input_tokens":null,"server_tool_use":null}}",
307331
],
308332
"type": "streamEvent",
309333
},
310334
{
311335
"args": [
312-
"{"type":"message","id":"msg_01hhptzfxdaeehfxfv070yb6b8","role":"assistant","content":[{"type":"text","text":"Hello there!","citations":null}],"model":"claude-3-opus-20240229","stop_reason":"end_turn","stop_sequence":null,"usage":{"output_tokens":6,"input_tokens":10,"cache_creation_input_tokens":null,"cache_read_input_tokens":null}}",
336+
"{"type":"message","id":"msg_01hhptzfxdaeehfxfv070yb6b8","role":"assistant","content":[{"type":"text","text":"Hello there!","citations":null}],"model":"claude-3-opus-20240229","stop_reason":"end_turn","stop_sequence":null,"usage":{"output_tokens":6,"input_tokens":10,"cache_creation_input_tokens":null,"cache_read_input_tokens":null,"server_tool_use":null}}",
313337
],
314338
"type": "message",
315339
},
316340
{
317341
"args": [
318-
"{"type":"message","id":"msg_01hhptzfxdaeehfxfv070yb6b8","role":"assistant","content":[{"type":"text","text":"Hello there!","citations":null}],"model":"claude-3-opus-20240229","stop_reason":"end_turn","stop_sequence":null,"usage":{"output_tokens":6,"input_tokens":10,"cache_creation_input_tokens":null,"cache_read_input_tokens":null}}",
342+
"{"type":"message","id":"msg_01hhptzfxdaeehfxfv070yb6b8","role":"assistant","content":[{"type":"text","text":"Hello there!","citations":null}],"model":"claude-3-opus-20240229","stop_reason":"end_turn","stop_sequence":null,"usage":{"output_tokens":6,"input_tokens":10,"cache_creation_input_tokens":null,"cache_read_input_tokens":null,"server_tool_use":null}}",
319343
],
320344
"type": "finalMessage",
321345
},
@@ -348,6 +372,7 @@ describe('MessageStream class', () => {
348372
"cache_read_input_tokens": null,
349373
"input_tokens": 10,
350374
"output_tokens": 6,
375+
"server_tool_use": null,
351376
},
352377
}
353378
`);
@@ -378,6 +403,7 @@ describe('MessageStream class', () => {
378403
input_tokens: 10,
379404
cache_creation_input_tokens: null,
380405
cache_read_input_tokens: null,
406+
server_tool_use: null,
381407
},
382408
}),
383409
);
@@ -405,7 +431,7 @@ describe('MessageStream class', () => {
405431
const stream = anthropic.messages.stream(
406432
{
407433
max_tokens: 1024,
408-
model: 'claude-2.1',
434+
model: 'claude-3-7-sonnet-20250219',
409435
messages: [{ role: 'user', content: 'Say hello there!' }],
410436
},
411437
{ maxRetries: 0 },
@@ -430,7 +456,7 @@ describe('MessageStream class', () => {
430456
const stream = anthropic.messages.stream(
431457
{
432458
max_tokens: 1024,
433-
model: 'claude-2.1',
459+
model: 'claude-3-7-sonnet-20250219',
434460
messages: [{ role: 'user', content: 'Say hello there!' }],
435461
},
436462
{ maxRetries: 0 },

0 commit comments

Comments
 (0)