@tanstack/ai-anthropic 0.7.5 → 0.8.1
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.
- package/dist/esm/adapters/summarize.js +79 -49
- package/dist/esm/adapters/summarize.js.map +1 -1
- package/dist/esm/adapters/text.d.ts +5 -4
- package/dist/esm/adapters/text.js +28 -2
- package/dist/esm/adapters/text.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/model-meta.d.ts +28 -0
- package/dist/esm/model-meta.js.map +1 -1
- package/dist/esm/tools/bash-tool.d.ts +7 -4
- package/dist/esm/tools/bash-tool.js +8 -0
- package/dist/esm/tools/bash-tool.js.map +1 -1
- package/dist/esm/tools/code-execution-tool.d.ts +7 -4
- package/dist/esm/tools/code-execution-tool.js +8 -0
- package/dist/esm/tools/code-execution-tool.js.map +1 -1
- package/dist/esm/tools/computer-use-tool.d.ts +7 -4
- package/dist/esm/tools/computer-use-tool.js +8 -0
- package/dist/esm/tools/computer-use-tool.js.map +1 -1
- package/dist/esm/tools/custom-tool.d.ts +4 -2
- package/dist/esm/tools/custom-tool.js +12 -1
- package/dist/esm/tools/custom-tool.js.map +1 -1
- package/dist/esm/tools/index.d.ts +8 -1
- package/dist/esm/tools/index.js +19 -0
- package/dist/esm/tools/index.js.map +1 -0
- package/dist/esm/tools/memory-tool.d.ts +7 -4
- package/dist/esm/tools/memory-tool.js +9 -1
- package/dist/esm/tools/memory-tool.js.map +1 -1
- package/dist/esm/tools/text-editor-tool.d.ts +7 -4
- package/dist/esm/tools/text-editor-tool.js +9 -1
- package/dist/esm/tools/text-editor-tool.js.map +1 -1
- package/dist/esm/tools/web-fetch-tool.d.ts +7 -4
- package/dist/esm/tools/web-fetch-tool.js +9 -1
- package/dist/esm/tools/web-fetch-tool.js.map +1 -1
- package/dist/esm/tools/web-search-tool.d.ts +7 -4
- package/dist/esm/tools/web-search-tool.js +41 -1
- package/dist/esm/tools/web-search-tool.js.map +1 -1
- package/package.json +7 -3
- package/src/adapters/summarize.ts +88 -54
- package/src/adapters/text.ts +45 -6
- package/src/index.ts +2 -1
- package/src/model-meta.ts +126 -0
- package/src/tools/bash-tool.ts +13 -6
- package/src/tools/code-execution-tool.ts +17 -6
- package/src/tools/computer-use-tool.ts +14 -6
- package/src/tools/custom-tool.ts +5 -3
- package/src/tools/index.ts +49 -12
- package/src/tools/memory-tool.ts +12 -6
- package/src/tools/text-editor-tool.ts +14 -6
- package/src/tools/web-fetch-tool.ts +15 -7
- package/src/tools/web-search-tool.ts +17 -7
|
@@ -1,3 +1,33 @@
|
|
|
1
|
+
const validateDomains = (tool) => {
|
|
2
|
+
if (tool.allowed_domains && tool.blocked_domains) {
|
|
3
|
+
throw new Error(
|
|
4
|
+
"allowed_domains and blocked_domains cannot be used together."
|
|
5
|
+
);
|
|
6
|
+
}
|
|
7
|
+
};
|
|
8
|
+
const validateUserLocation = (tool) => {
|
|
9
|
+
const userLocation = tool.user_location;
|
|
10
|
+
if (userLocation) {
|
|
11
|
+
if (userLocation.city && (userLocation.city.length < 1 || userLocation.city.length > 255)) {
|
|
12
|
+
throw new Error(
|
|
13
|
+
"user_location.city must be between 1 and 255 characters."
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
if (userLocation.country && userLocation.country.length !== 2) {
|
|
17
|
+
throw new Error("user_location.country must be exactly 2 characters.");
|
|
18
|
+
}
|
|
19
|
+
if (userLocation.region && (userLocation.region.length < 1 || userLocation.region.length > 255)) {
|
|
20
|
+
throw new Error(
|
|
21
|
+
"user_location.region must be between 1 and 255 characters."
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
if (userLocation.timezone && (userLocation.timezone.length < 1 || userLocation.timezone.length > 255)) {
|
|
25
|
+
throw new Error(
|
|
26
|
+
"user_location.timezone must be between 1 and 255 characters."
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
};
|
|
1
31
|
function convertWebSearchToolToAdapterFormat(tool) {
|
|
2
32
|
const metadata = tool.metadata;
|
|
3
33
|
return {
|
|
@@ -10,7 +40,17 @@ function convertWebSearchToolToAdapterFormat(tool) {
|
|
|
10
40
|
cache_control: metadata.cacheControl || null
|
|
11
41
|
};
|
|
12
42
|
}
|
|
43
|
+
function webSearchTool(config) {
|
|
44
|
+
validateDomains(config);
|
|
45
|
+
validateUserLocation(config);
|
|
46
|
+
return {
|
|
47
|
+
name: "web_search",
|
|
48
|
+
description: "",
|
|
49
|
+
metadata: config
|
|
50
|
+
};
|
|
51
|
+
}
|
|
13
52
|
export {
|
|
14
|
-
convertWebSearchToolToAdapterFormat
|
|
53
|
+
convertWebSearchToolToAdapterFormat,
|
|
54
|
+
webSearchTool
|
|
15
55
|
};
|
|
16
56
|
//# sourceMappingURL=web-search-tool.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web-search-tool.js","sources":["../../../src/tools/web-search-tool.ts"],"sourcesContent":["import type { WebSearchTool20250305 } from '@anthropic-ai/sdk/resources/messages'\nimport type { CacheControl } from '../text/text-provider-options'\nimport type { Tool } from '@tanstack/ai'\n\nexport type
|
|
1
|
+
{"version":3,"file":"web-search-tool.js","sources":["../../../src/tools/web-search-tool.ts"],"sourcesContent":["import type { WebSearchTool20250305 } from '@anthropic-ai/sdk/resources/messages'\nimport type { CacheControl } from '../text/text-provider-options'\nimport type { ProviderTool, Tool } from '@tanstack/ai'\n\nexport type WebSearchToolConfig = WebSearchTool20250305\n\n/** @deprecated Renamed to `WebSearchToolConfig`. Will be removed in a future release. */\nexport type WebSearchTool = WebSearchToolConfig\n\nexport type AnthropicWebSearchTool = ProviderTool<'anthropic', 'web_search'>\n\nconst validateDomains = (tool: WebSearchToolConfig) => {\n if (tool.allowed_domains && tool.blocked_domains) {\n throw new Error(\n 'allowed_domains and blocked_domains cannot be used together.',\n )\n }\n}\n\nconst validateUserLocation = (tool: WebSearchToolConfig) => {\n const userLocation = tool.user_location\n if (userLocation) {\n if (\n userLocation.city &&\n (userLocation.city.length < 1 || userLocation.city.length > 255)\n ) {\n throw new Error(\n 'user_location.city must be between 1 and 255 characters.',\n )\n }\n if (userLocation.country && userLocation.country.length !== 2) {\n throw new Error('user_location.country must be exactly 2 characters.')\n }\n if (\n userLocation.region &&\n (userLocation.region.length < 1 || userLocation.region.length > 255)\n ) {\n throw new Error(\n 'user_location.region must be between 1 and 255 characters.',\n )\n }\n if (\n userLocation.timezone &&\n (userLocation.timezone.length < 1 || userLocation.timezone.length > 255)\n ) {\n throw new Error(\n 'user_location.timezone must be between 1 and 255 characters.',\n )\n }\n }\n}\n\nexport function convertWebSearchToolToAdapterFormat(\n tool: Tool,\n): WebSearchToolConfig {\n const metadata = tool.metadata as {\n allowedDomains?: Array<string> | null\n blockedDomains?: Array<string> | null\n maxUses?: number | null\n userLocation?: {\n type: 'approximate'\n city?: string | null\n country?: string | null\n region?: string | null\n timezone?: string | null\n } | null\n cacheControl?: CacheControl | null\n }\n return {\n name: 'web_search',\n type: 'web_search_20250305',\n allowed_domains: metadata.allowedDomains,\n blocked_domains: metadata.blockedDomains,\n max_uses: metadata.maxUses,\n user_location: metadata.userLocation,\n cache_control: metadata.cacheControl || null,\n }\n}\n\nexport function webSearchTool(\n config: WebSearchToolConfig,\n): AnthropicWebSearchTool {\n validateDomains(config)\n validateUserLocation(config)\n // Phantom-brand cast: '~provider'/'~toolKind' are type-only and never assigned at runtime.\n return {\n name: 'web_search',\n description: '',\n metadata: config,\n } as unknown as AnthropicWebSearchTool\n}\n"],"names":[],"mappings":"AAWA,MAAM,kBAAkB,CAAC,SAA8B;AACrD,MAAI,KAAK,mBAAmB,KAAK,iBAAiB;AAChD,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AACF;AAEA,MAAM,uBAAuB,CAAC,SAA8B;AAC1D,QAAM,eAAe,KAAK;AAC1B,MAAI,cAAc;AAChB,QACE,aAAa,SACZ,aAAa,KAAK,SAAS,KAAK,aAAa,KAAK,SAAS,MAC5D;AACA,YAAM,IAAI;AAAA,QACR;AAAA,MAAA;AAAA,IAEJ;AACA,QAAI,aAAa,WAAW,aAAa,QAAQ,WAAW,GAAG;AAC7D,YAAM,IAAI,MAAM,qDAAqD;AAAA,IACvE;AACA,QACE,aAAa,WACZ,aAAa,OAAO,SAAS,KAAK,aAAa,OAAO,SAAS,MAChE;AACA,YAAM,IAAI;AAAA,QACR;AAAA,MAAA;AAAA,IAEJ;AACA,QACE,aAAa,aACZ,aAAa,SAAS,SAAS,KAAK,aAAa,SAAS,SAAS,MACpE;AACA,YAAM,IAAI;AAAA,QACR;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;AACF;AAEO,SAAS,oCACd,MACqB;AACrB,QAAM,WAAW,KAAK;AAatB,SAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,IACN,iBAAiB,SAAS;AAAA,IAC1B,iBAAiB,SAAS;AAAA,IAC1B,UAAU,SAAS;AAAA,IACnB,eAAe,SAAS;AAAA,IACxB,eAAe,SAAS,gBAAgB;AAAA,EAAA;AAE5C;AAEO,SAAS,cACd,QACwB;AACxB,kBAAgB,MAAM;AACtB,uBAAqB,MAAM;AAE3B,SAAO;AAAA,IACL,MAAM;AAAA,IACN,aAAa;AAAA,IACb,UAAU;AAAA,EAAA;AAEd;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/ai-anthropic",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "Anthropic Claude adapter for TanStack AI",
|
|
5
5
|
"author": "",
|
|
6
6
|
"license": "MIT",
|
|
@@ -23,6 +23,10 @@
|
|
|
23
23
|
".": {
|
|
24
24
|
"types": "./dist/esm/index.d.ts",
|
|
25
25
|
"import": "./dist/esm/index.js"
|
|
26
|
+
},
|
|
27
|
+
"./tools": {
|
|
28
|
+
"types": "./dist/esm/tools/index.d.ts",
|
|
29
|
+
"import": "./dist/esm/tools/index.js"
|
|
26
30
|
}
|
|
27
31
|
},
|
|
28
32
|
"files": [
|
|
@@ -34,12 +38,12 @@
|
|
|
34
38
|
},
|
|
35
39
|
"peerDependencies": {
|
|
36
40
|
"zod": "^4.0.0",
|
|
37
|
-
"@tanstack/ai": "^0.
|
|
41
|
+
"@tanstack/ai": "^0.13.0"
|
|
38
42
|
},
|
|
39
43
|
"devDependencies": {
|
|
40
44
|
"@vitest/coverage-v8": "4.0.14",
|
|
41
45
|
"zod": "^4.2.0",
|
|
42
|
-
"@tanstack/ai": "0.
|
|
46
|
+
"@tanstack/ai": "0.13.0"
|
|
43
47
|
},
|
|
44
48
|
"scripts": {
|
|
45
49
|
"build": "vite build",
|
|
@@ -54,36 +54,52 @@ export class AnthropicSummarizeAdapter<
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
async summarize(options: SummarizationOptions): Promise<SummarizationResult> {
|
|
57
|
+
const { logger } = options
|
|
57
58
|
const systemPrompt = this.buildSummarizationPrompt(options)
|
|
58
59
|
|
|
59
|
-
|
|
60
|
+
logger.request(`activity=summarize provider=anthropic`, {
|
|
61
|
+
provider: 'anthropic',
|
|
60
62
|
model: options.model,
|
|
61
|
-
messages: [{ role: 'user', content: options.text }],
|
|
62
|
-
system: systemPrompt,
|
|
63
|
-
max_tokens: options.maxLength || 500,
|
|
64
|
-
temperature: 0.3,
|
|
65
|
-
stream: false,
|
|
66
63
|
})
|
|
67
64
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
65
|
+
try {
|
|
66
|
+
const response = await this.client.messages.create({
|
|
67
|
+
model: options.model,
|
|
68
|
+
messages: [{ role: 'user', content: options.text }],
|
|
69
|
+
system: systemPrompt,
|
|
70
|
+
max_tokens: options.maxLength || 500,
|
|
71
|
+
temperature: 0.3,
|
|
72
|
+
stream: false,
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
const content = response.content
|
|
76
|
+
.map((c) => (c.type === 'text' ? c.text : ''))
|
|
77
|
+
.join('')
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
id: response.id,
|
|
81
|
+
model: response.model,
|
|
82
|
+
summary: content,
|
|
83
|
+
usage: {
|
|
84
|
+
promptTokens: response.usage.input_tokens,
|
|
85
|
+
completionTokens: response.usage.output_tokens,
|
|
86
|
+
totalTokens:
|
|
87
|
+
response.usage.input_tokens + response.usage.output_tokens,
|
|
88
|
+
},
|
|
89
|
+
}
|
|
90
|
+
} catch (error) {
|
|
91
|
+
logger.errors('anthropic.summarize fatal', {
|
|
92
|
+
error,
|
|
93
|
+
source: 'anthropic.summarize',
|
|
94
|
+
})
|
|
95
|
+
throw error
|
|
81
96
|
}
|
|
82
97
|
}
|
|
83
98
|
|
|
84
99
|
async *summarizeStream(
|
|
85
100
|
options: SummarizationOptions,
|
|
86
101
|
): AsyncIterable<StreamChunk> {
|
|
102
|
+
const { logger } = options
|
|
87
103
|
const systemPrompt = this.buildSummarizationPrompt(options)
|
|
88
104
|
const id = generateId(this.name)
|
|
89
105
|
const model = options.model
|
|
@@ -91,50 +107,68 @@ export class AnthropicSummarizeAdapter<
|
|
|
91
107
|
let inputTokens = 0
|
|
92
108
|
let outputTokens = 0
|
|
93
109
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
system: systemPrompt,
|
|
98
|
-
max_tokens: options.maxLength || 500,
|
|
99
|
-
temperature: 0.3,
|
|
110
|
+
logger.request(`activity=summarize provider=anthropic`, {
|
|
111
|
+
provider: 'anthropic',
|
|
112
|
+
model,
|
|
100
113
|
stream: true,
|
|
101
114
|
})
|
|
102
115
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
116
|
+
try {
|
|
117
|
+
const stream = await this.client.messages.create({
|
|
118
|
+
model: options.model,
|
|
119
|
+
messages: [{ role: 'user', content: options.text }],
|
|
120
|
+
system: systemPrompt,
|
|
121
|
+
max_tokens: options.maxLength || 500,
|
|
122
|
+
temperature: 0.3,
|
|
123
|
+
stream: true,
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
for await (const event of stream) {
|
|
127
|
+
logger.provider(`provider=anthropic type=${event.type}`, {
|
|
128
|
+
chunk: event,
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
if (event.type === 'message_start') {
|
|
132
|
+
inputTokens = event.message.usage.input_tokens
|
|
133
|
+
} else if (event.type === 'content_block_delta') {
|
|
134
|
+
if (event.delta.type === 'text_delta') {
|
|
135
|
+
const delta = event.delta.text
|
|
136
|
+
accumulatedContent += delta
|
|
137
|
+
yield asChunk({
|
|
138
|
+
type: 'TEXT_MESSAGE_CONTENT',
|
|
139
|
+
messageId: id,
|
|
140
|
+
model,
|
|
141
|
+
timestamp: Date.now(),
|
|
142
|
+
delta,
|
|
143
|
+
content: accumulatedContent,
|
|
144
|
+
})
|
|
145
|
+
}
|
|
146
|
+
} else if (event.type === 'message_delta') {
|
|
147
|
+
outputTokens = event.usage.output_tokens
|
|
110
148
|
yield asChunk({
|
|
111
|
-
type: '
|
|
112
|
-
|
|
149
|
+
type: 'RUN_FINISHED',
|
|
150
|
+
runId: id,
|
|
113
151
|
model,
|
|
114
152
|
timestamp: Date.now(),
|
|
115
|
-
delta
|
|
116
|
-
|
|
153
|
+
finishReason: event.delta.stop_reason as
|
|
154
|
+
| 'stop'
|
|
155
|
+
| 'length'
|
|
156
|
+
| 'content_filter'
|
|
157
|
+
| null,
|
|
158
|
+
usage: {
|
|
159
|
+
promptTokens: inputTokens,
|
|
160
|
+
completionTokens: outputTokens,
|
|
161
|
+
totalTokens: inputTokens + outputTokens,
|
|
162
|
+
},
|
|
117
163
|
})
|
|
118
164
|
}
|
|
119
|
-
} else if (event.type === 'message_delta') {
|
|
120
|
-
outputTokens = event.usage.output_tokens
|
|
121
|
-
yield asChunk({
|
|
122
|
-
type: 'RUN_FINISHED',
|
|
123
|
-
runId: id,
|
|
124
|
-
model,
|
|
125
|
-
timestamp: Date.now(),
|
|
126
|
-
finishReason: event.delta.stop_reason as
|
|
127
|
-
| 'stop'
|
|
128
|
-
| 'length'
|
|
129
|
-
| 'content_filter'
|
|
130
|
-
| null,
|
|
131
|
-
usage: {
|
|
132
|
-
promptTokens: inputTokens,
|
|
133
|
-
completionTokens: outputTokens,
|
|
134
|
-
totalTokens: inputTokens + outputTokens,
|
|
135
|
-
},
|
|
136
|
-
})
|
|
137
165
|
}
|
|
166
|
+
} catch (error) {
|
|
167
|
+
logger.errors('anthropic.summarize fatal', {
|
|
168
|
+
error,
|
|
169
|
+
source: 'anthropic.summarize',
|
|
170
|
+
})
|
|
171
|
+
throw error
|
|
138
172
|
}
|
|
139
173
|
}
|
|
140
174
|
|
package/src/adapters/text.ts
CHANGED
|
@@ -9,12 +9,14 @@ import {
|
|
|
9
9
|
import type {
|
|
10
10
|
ANTHROPIC_MODELS,
|
|
11
11
|
AnthropicChatModelProviderOptionsByName,
|
|
12
|
+
AnthropicChatModelToolCapabilitiesByName,
|
|
12
13
|
AnthropicModelInputModalitiesByName,
|
|
13
14
|
} from '../model-meta'
|
|
14
15
|
import type {
|
|
15
16
|
StructuredOutputOptions,
|
|
16
17
|
StructuredOutputResult,
|
|
17
18
|
} from '@tanstack/ai/adapters'
|
|
19
|
+
import type { InternalLogger } from '@tanstack/ai/adapter-internals'
|
|
18
20
|
import type {
|
|
19
21
|
Base64ImageSource,
|
|
20
22
|
Base64PDFSource,
|
|
@@ -89,6 +91,11 @@ type ResolveInputModalities<TModel extends string> =
|
|
|
89
91
|
? AnthropicModelInputModalitiesByName[TModel]
|
|
90
92
|
: readonly ['text', 'image', 'document']
|
|
91
93
|
|
|
94
|
+
type ResolveToolCapabilities<TModel extends string> =
|
|
95
|
+
TModel extends keyof AnthropicChatModelToolCapabilitiesByName
|
|
96
|
+
? NonNullable<AnthropicChatModelToolCapabilitiesByName[TModel]>
|
|
97
|
+
: readonly []
|
|
98
|
+
|
|
92
99
|
// ===========================
|
|
93
100
|
// Adapter Implementation
|
|
94
101
|
// ===========================
|
|
@@ -101,14 +108,17 @@ type ResolveInputModalities<TModel extends string> =
|
|
|
101
108
|
*/
|
|
102
109
|
export class AnthropicTextAdapter<
|
|
103
110
|
TModel extends (typeof ANTHROPIC_MODELS)[number],
|
|
104
|
-
TProviderOptions extends
|
|
111
|
+
TProviderOptions extends Record<string, any> = ResolveProviderOptions<TModel>,
|
|
105
112
|
TInputModalities extends ReadonlyArray<Modality> =
|
|
106
113
|
ResolveInputModalities<TModel>,
|
|
114
|
+
TToolCapabilities extends ReadonlyArray<string> =
|
|
115
|
+
ResolveToolCapabilities<TModel>,
|
|
107
116
|
> extends BaseTextAdapter<
|
|
108
117
|
TModel,
|
|
109
118
|
TProviderOptions,
|
|
110
119
|
TInputModalities,
|
|
111
|
-
AnthropicMessageMetadataByModality
|
|
120
|
+
AnthropicMessageMetadataByModality,
|
|
121
|
+
TToolCapabilities
|
|
112
122
|
> {
|
|
113
123
|
readonly kind = 'text' as const
|
|
114
124
|
readonly name = 'anthropic' as const
|
|
@@ -121,11 +131,16 @@ export class AnthropicTextAdapter<
|
|
|
121
131
|
}
|
|
122
132
|
|
|
123
133
|
async *chatStream(
|
|
124
|
-
options: TextOptions<
|
|
134
|
+
options: TextOptions<TProviderOptions>,
|
|
125
135
|
): AsyncIterable<StreamChunk> {
|
|
136
|
+
const { logger } = options
|
|
126
137
|
try {
|
|
127
138
|
const requestParams = this.mapCommonOptionsToAnthropic(options)
|
|
128
139
|
|
|
140
|
+
logger.request(
|
|
141
|
+
`activity=chat provider=anthropic model=${this.model} messages=${options.messages.length} tools=${options.tools?.length ?? 0} stream=true`,
|
|
142
|
+
{ provider: 'anthropic', model: this.model },
|
|
143
|
+
)
|
|
129
144
|
const stream = await this.client.beta.messages.create(
|
|
130
145
|
{ ...requestParams, stream: true },
|
|
131
146
|
{
|
|
@@ -134,11 +149,18 @@ export class AnthropicTextAdapter<
|
|
|
134
149
|
},
|
|
135
150
|
)
|
|
136
151
|
|
|
137
|
-
yield* this.processAnthropicStream(
|
|
138
|
-
|
|
152
|
+
yield* this.processAnthropicStream(
|
|
153
|
+
stream,
|
|
154
|
+
options,
|
|
155
|
+
() => generateId(this.name),
|
|
156
|
+
logger,
|
|
139
157
|
)
|
|
140
158
|
} catch (error: unknown) {
|
|
141
159
|
const err = error as Error & { status?: number; code?: string }
|
|
160
|
+
logger.errors('anthropic.chatStream fatal', {
|
|
161
|
+
error,
|
|
162
|
+
source: 'anthropic.chatStream',
|
|
163
|
+
})
|
|
142
164
|
yield asChunk({
|
|
143
165
|
type: 'RUN_ERROR',
|
|
144
166
|
model: options.model,
|
|
@@ -160,9 +182,10 @@ export class AnthropicTextAdapter<
|
|
|
160
182
|
* The outputSchema is already JSON Schema (converted in the ai layer).
|
|
161
183
|
*/
|
|
162
184
|
async structuredOutput(
|
|
163
|
-
options: StructuredOutputOptions<
|
|
185
|
+
options: StructuredOutputOptions<TProviderOptions>,
|
|
164
186
|
): Promise<StructuredOutputResult<unknown>> {
|
|
165
187
|
const { chatOptions, outputSchema } = options
|
|
188
|
+
const { logger } = chatOptions
|
|
166
189
|
|
|
167
190
|
const requestParams = this.mapCommonOptionsToAnthropic(chatOptions)
|
|
168
191
|
|
|
@@ -180,6 +203,10 @@ export class AnthropicTextAdapter<
|
|
|
180
203
|
}
|
|
181
204
|
|
|
182
205
|
try {
|
|
206
|
+
logger.request(
|
|
207
|
+
`activity=chat provider=anthropic model=${this.model} messages=${chatOptions.messages.length} tools=${chatOptions.tools?.length ?? 0} stream=false`,
|
|
208
|
+
{ provider: 'anthropic', model: this.model },
|
|
209
|
+
)
|
|
183
210
|
// Make non-streaming request with tool_choice forced to our structured output tool
|
|
184
211
|
const response = await this.client.messages.create(
|
|
185
212
|
{
|
|
@@ -231,6 +258,10 @@ export class AnthropicTextAdapter<
|
|
|
231
258
|
}
|
|
232
259
|
} catch (error: unknown) {
|
|
233
260
|
const err = error as Error
|
|
261
|
+
logger.errors('anthropic.structuredOutput fatal', {
|
|
262
|
+
error,
|
|
263
|
+
source: 'anthropic.structuredOutput',
|
|
264
|
+
})
|
|
234
265
|
throw new Error(
|
|
235
266
|
`Structured output generation failed: ${err.message || 'Unknown error occurred'}`,
|
|
236
267
|
)
|
|
@@ -532,6 +563,7 @@ export class AnthropicTextAdapter<
|
|
|
532
563
|
stream: AsyncIterable<Anthropic_SDK.Beta.BetaRawMessageStreamEvent>,
|
|
533
564
|
options: TextOptions<AnthropicTextProviderOptions>,
|
|
534
565
|
genId: () => string,
|
|
566
|
+
logger: InternalLogger,
|
|
535
567
|
): AsyncIterable<StreamChunk> {
|
|
536
568
|
const model = options.model
|
|
537
569
|
let accumulatedContent = ''
|
|
@@ -558,6 +590,9 @@ export class AnthropicTextAdapter<
|
|
|
558
590
|
|
|
559
591
|
try {
|
|
560
592
|
for await (const event of stream) {
|
|
593
|
+
logger.provider(`provider=anthropic type=${event.type}`, {
|
|
594
|
+
chunk: event,
|
|
595
|
+
})
|
|
561
596
|
// Emit RUN_STARTED on first event
|
|
562
597
|
if (!hasEmittedRunStarted) {
|
|
563
598
|
hasEmittedRunStarted = true
|
|
@@ -868,6 +903,10 @@ export class AnthropicTextAdapter<
|
|
|
868
903
|
} catch (error: unknown) {
|
|
869
904
|
const err = error as Error & { status?: number; code?: string }
|
|
870
905
|
|
|
906
|
+
logger.errors('anthropic.processAnthropicStream fatal', {
|
|
907
|
+
error,
|
|
908
|
+
source: 'anthropic.processAnthropicStream',
|
|
909
|
+
})
|
|
871
910
|
yield asChunk({
|
|
872
911
|
type: 'RUN_ERROR',
|
|
873
912
|
runId,
|
package/src/index.ts
CHANGED
|
@@ -24,9 +24,10 @@ export {
|
|
|
24
24
|
// ============================================================================
|
|
25
25
|
|
|
26
26
|
export type {
|
|
27
|
+
AnthropicChatModel,
|
|
27
28
|
AnthropicChatModelProviderOptionsByName,
|
|
29
|
+
AnthropicChatModelToolCapabilitiesByName,
|
|
28
30
|
AnthropicModelInputModalitiesByName,
|
|
29
|
-
AnthropicChatModel,
|
|
30
31
|
} from './model-meta'
|
|
31
32
|
export { ANTHROPIC_MODELS } from './model-meta'
|
|
32
33
|
export type {
|
package/src/model-meta.ts
CHANGED
|
@@ -21,6 +21,15 @@ interface ModelMeta<
|
|
|
21
21
|
extended_thinking?: boolean
|
|
22
22
|
adaptive_thinking?: boolean
|
|
23
23
|
priority_tier?: boolean
|
|
24
|
+
tools?: Array<
|
|
25
|
+
| 'web_search'
|
|
26
|
+
| 'web_fetch'
|
|
27
|
+
| 'code_execution'
|
|
28
|
+
| 'computer_use'
|
|
29
|
+
| 'bash'
|
|
30
|
+
| 'text_editor'
|
|
31
|
+
| 'memory'
|
|
32
|
+
>
|
|
24
33
|
}
|
|
25
34
|
context_window?: number
|
|
26
35
|
max_output_tokens?: number
|
|
@@ -66,6 +75,15 @@ const CLAUDE_OPUS_4_6 = {
|
|
|
66
75
|
input: ['text', 'image', 'document'],
|
|
67
76
|
extended_thinking: true,
|
|
68
77
|
priority_tier: true,
|
|
78
|
+
tools: [
|
|
79
|
+
'web_search',
|
|
80
|
+
'web_fetch',
|
|
81
|
+
'code_execution',
|
|
82
|
+
'computer_use',
|
|
83
|
+
'bash',
|
|
84
|
+
'text_editor',
|
|
85
|
+
'memory',
|
|
86
|
+
],
|
|
69
87
|
},
|
|
70
88
|
} as const satisfies ModelMeta<
|
|
71
89
|
AnthropicContainerOptions &
|
|
@@ -96,6 +114,15 @@ const CLAUDE_OPUS_4_5 = {
|
|
|
96
114
|
input: ['text', 'image', 'document'],
|
|
97
115
|
extended_thinking: true,
|
|
98
116
|
priority_tier: true,
|
|
117
|
+
tools: [
|
|
118
|
+
'web_search',
|
|
119
|
+
'web_fetch',
|
|
120
|
+
'code_execution',
|
|
121
|
+
'computer_use',
|
|
122
|
+
'bash',
|
|
123
|
+
'text_editor',
|
|
124
|
+
'memory',
|
|
125
|
+
],
|
|
99
126
|
},
|
|
100
127
|
} as const satisfies ModelMeta<
|
|
101
128
|
AnthropicContainerOptions &
|
|
@@ -127,6 +154,15 @@ const CLAUDE_SONNET_4_6 = {
|
|
|
127
154
|
extended_thinking: true,
|
|
128
155
|
adaptive_thinking: true,
|
|
129
156
|
priority_tier: true,
|
|
157
|
+
tools: [
|
|
158
|
+
'web_search',
|
|
159
|
+
'web_fetch',
|
|
160
|
+
'code_execution',
|
|
161
|
+
'computer_use',
|
|
162
|
+
'bash',
|
|
163
|
+
'text_editor',
|
|
164
|
+
'memory',
|
|
165
|
+
],
|
|
130
166
|
},
|
|
131
167
|
} as const satisfies ModelMeta<
|
|
132
168
|
AnthropicContainerOptions &
|
|
@@ -157,6 +193,15 @@ const CLAUDE_SONNET_4_5 = {
|
|
|
157
193
|
input: ['text', 'image', 'document'],
|
|
158
194
|
extended_thinking: true,
|
|
159
195
|
priority_tier: true,
|
|
196
|
+
tools: [
|
|
197
|
+
'web_search',
|
|
198
|
+
'web_fetch',
|
|
199
|
+
'code_execution',
|
|
200
|
+
'computer_use',
|
|
201
|
+
'bash',
|
|
202
|
+
'text_editor',
|
|
203
|
+
'memory',
|
|
204
|
+
],
|
|
160
205
|
},
|
|
161
206
|
} as const satisfies ModelMeta<
|
|
162
207
|
AnthropicContainerOptions &
|
|
@@ -187,6 +232,15 @@ const CLAUDE_HAIKU_4_5 = {
|
|
|
187
232
|
input: ['text', 'image', 'document'],
|
|
188
233
|
extended_thinking: true,
|
|
189
234
|
priority_tier: true,
|
|
235
|
+
tools: [
|
|
236
|
+
'web_search',
|
|
237
|
+
'web_fetch',
|
|
238
|
+
'code_execution',
|
|
239
|
+
'computer_use',
|
|
240
|
+
'bash',
|
|
241
|
+
'text_editor',
|
|
242
|
+
'memory',
|
|
243
|
+
],
|
|
190
244
|
},
|
|
191
245
|
} as const satisfies ModelMeta<
|
|
192
246
|
AnthropicContainerOptions &
|
|
@@ -217,6 +271,15 @@ const CLAUDE_OPUS_4_1 = {
|
|
|
217
271
|
input: ['text', 'image', 'document'],
|
|
218
272
|
extended_thinking: true,
|
|
219
273
|
priority_tier: true,
|
|
274
|
+
tools: [
|
|
275
|
+
'web_search',
|
|
276
|
+
'web_fetch',
|
|
277
|
+
'code_execution',
|
|
278
|
+
'computer_use',
|
|
279
|
+
'bash',
|
|
280
|
+
'text_editor',
|
|
281
|
+
'memory',
|
|
282
|
+
],
|
|
220
283
|
},
|
|
221
284
|
} as const satisfies ModelMeta<
|
|
222
285
|
AnthropicContainerOptions &
|
|
@@ -247,6 +310,15 @@ const CLAUDE_SONNET_4 = {
|
|
|
247
310
|
input: ['text', 'image', 'document'],
|
|
248
311
|
extended_thinking: true,
|
|
249
312
|
priority_tier: true,
|
|
313
|
+
tools: [
|
|
314
|
+
'web_search',
|
|
315
|
+
'web_fetch',
|
|
316
|
+
'code_execution',
|
|
317
|
+
'computer_use',
|
|
318
|
+
'bash',
|
|
319
|
+
'text_editor',
|
|
320
|
+
'memory',
|
|
321
|
+
],
|
|
250
322
|
},
|
|
251
323
|
} as const satisfies ModelMeta<
|
|
252
324
|
AnthropicContainerOptions &
|
|
@@ -276,6 +348,15 @@ const CLAUDE_SONNET_3_7 = {
|
|
|
276
348
|
input: ['text', 'image', 'document'],
|
|
277
349
|
extended_thinking: true,
|
|
278
350
|
priority_tier: true,
|
|
351
|
+
tools: [
|
|
352
|
+
'web_search',
|
|
353
|
+
'web_fetch',
|
|
354
|
+
'code_execution',
|
|
355
|
+
'computer_use',
|
|
356
|
+
'bash',
|
|
357
|
+
'text_editor',
|
|
358
|
+
'memory',
|
|
359
|
+
],
|
|
279
360
|
},
|
|
280
361
|
} as const satisfies ModelMeta<
|
|
281
362
|
AnthropicContainerOptions &
|
|
@@ -306,6 +387,15 @@ const CLAUDE_OPUS_4 = {
|
|
|
306
387
|
input: ['text', 'image', 'document'],
|
|
307
388
|
extended_thinking: true,
|
|
308
389
|
priority_tier: true,
|
|
390
|
+
tools: [
|
|
391
|
+
'web_search',
|
|
392
|
+
'web_fetch',
|
|
393
|
+
'code_execution',
|
|
394
|
+
'computer_use',
|
|
395
|
+
'bash',
|
|
396
|
+
'text_editor',
|
|
397
|
+
'memory',
|
|
398
|
+
],
|
|
309
399
|
},
|
|
310
400
|
} as const satisfies ModelMeta<
|
|
311
401
|
AnthropicContainerOptions &
|
|
@@ -336,6 +426,7 @@ const CLAUDE_HAIKU_3_5 = {
|
|
|
336
426
|
input: ['text', 'image', 'document'],
|
|
337
427
|
extended_thinking: false,
|
|
338
428
|
priority_tier: true,
|
|
429
|
+
tools: ['web_search', 'web_fetch'],
|
|
339
430
|
},
|
|
340
431
|
} as const satisfies ModelMeta<
|
|
341
432
|
AnthropicContainerOptions &
|
|
@@ -366,6 +457,7 @@ const CLAUDE_HAIKU_3 = {
|
|
|
366
457
|
input: ['text', 'image', 'document'],
|
|
367
458
|
extended_thinking: false,
|
|
368
459
|
priority_tier: false,
|
|
460
|
+
tools: ['web_search'],
|
|
369
461
|
},
|
|
370
462
|
} as const satisfies ModelMeta<
|
|
371
463
|
AnthropicContainerOptions &
|
|
@@ -432,6 +524,15 @@ const CLAUDE_OPUS_4_6_FAST = {
|
|
|
432
524
|
input: ['text', 'image'],
|
|
433
525
|
extended_thinking: true,
|
|
434
526
|
priority_tier: true,
|
|
527
|
+
tools: [
|
|
528
|
+
'web_search',
|
|
529
|
+
'web_fetch',
|
|
530
|
+
'code_execution',
|
|
531
|
+
'computer_use',
|
|
532
|
+
'bash',
|
|
533
|
+
'text_editor',
|
|
534
|
+
'memory',
|
|
535
|
+
],
|
|
435
536
|
},
|
|
436
537
|
pricing: {
|
|
437
538
|
input: {
|
|
@@ -462,6 +563,15 @@ const CLAUDE_OPUS_4_7 = {
|
|
|
462
563
|
input: ['text', 'image'],
|
|
463
564
|
extended_thinking: true,
|
|
464
565
|
priority_tier: true,
|
|
566
|
+
tools: [
|
|
567
|
+
'web_search',
|
|
568
|
+
'web_fetch',
|
|
569
|
+
'code_execution',
|
|
570
|
+
'computer_use',
|
|
571
|
+
'bash',
|
|
572
|
+
'text_editor',
|
|
573
|
+
'memory',
|
|
574
|
+
],
|
|
465
575
|
},
|
|
466
576
|
pricing: {
|
|
467
577
|
input: {
|
|
@@ -619,6 +729,22 @@ export type AnthropicChatModelProviderOptionsByName = {
|
|
|
619
729
|
AnthropicSamplingOptions
|
|
620
730
|
}
|
|
621
731
|
|
|
732
|
+
export type AnthropicChatModelToolCapabilitiesByName = {
|
|
733
|
+
[CLAUDE_OPUS_4_6.id]: typeof CLAUDE_OPUS_4_6.supports.tools
|
|
734
|
+
[CLAUDE_OPUS_4_5.id]: typeof CLAUDE_OPUS_4_5.supports.tools
|
|
735
|
+
[CLAUDE_SONNET_4_6.id]: typeof CLAUDE_SONNET_4_6.supports.tools
|
|
736
|
+
[CLAUDE_SONNET_4_5.id]: typeof CLAUDE_SONNET_4_5.supports.tools
|
|
737
|
+
[CLAUDE_HAIKU_4_5.id]: typeof CLAUDE_HAIKU_4_5.supports.tools
|
|
738
|
+
[CLAUDE_OPUS_4_1.id]: typeof CLAUDE_OPUS_4_1.supports.tools
|
|
739
|
+
[CLAUDE_SONNET_4.id]: typeof CLAUDE_SONNET_4.supports.tools
|
|
740
|
+
[CLAUDE_SONNET_3_7.id]: typeof CLAUDE_SONNET_3_7.supports.tools
|
|
741
|
+
[CLAUDE_OPUS_4.id]: typeof CLAUDE_OPUS_4.supports.tools
|
|
742
|
+
[CLAUDE_HAIKU_3_5.id]: typeof CLAUDE_HAIKU_3_5.supports.tools
|
|
743
|
+
[CLAUDE_HAIKU_3.id]: typeof CLAUDE_HAIKU_3.supports.tools
|
|
744
|
+
[CLAUDE_OPUS_4_6_FAST.id]: typeof CLAUDE_OPUS_4_6_FAST.supports.tools
|
|
745
|
+
[CLAUDE_OPUS_4_7.id]: typeof CLAUDE_OPUS_4_7.supports.tools
|
|
746
|
+
}
|
|
747
|
+
|
|
622
748
|
/**
|
|
623
749
|
* Type-only map from chat model name to its supported input modalities.
|
|
624
750
|
* All Anthropic Claude models support text, image, and document (PDF) input.
|