@tanstack/ai-anthropic 0.0.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.
Files changed (58) hide show
  1. package/LICENSE +21 -0
  2. package/dist/esm/anthropic-adapter.d.ts +69 -0
  3. package/dist/esm/anthropic-adapter.js +473 -0
  4. package/dist/esm/anthropic-adapter.js.map +1 -0
  5. package/dist/esm/index.d.ts +5 -0
  6. package/dist/esm/index.js +9 -0
  7. package/dist/esm/index.js.map +1 -0
  8. package/dist/esm/message-types.d.ts +69 -0
  9. package/dist/esm/model-meta.d.ts +215 -0
  10. package/dist/esm/model-meta.js +42 -0
  11. package/dist/esm/model-meta.js.map +1 -0
  12. package/dist/esm/text/text-provider-options.d.ts +139 -0
  13. package/dist/esm/text/text-provider-options.js +30 -0
  14. package/dist/esm/text/text-provider-options.js.map +1 -0
  15. package/dist/esm/tools/bash-tool.d.ts +5 -0
  16. package/dist/esm/tools/bash-tool.js +8 -0
  17. package/dist/esm/tools/bash-tool.js.map +1 -0
  18. package/dist/esm/tools/code-execution-tool.d.ts +5 -0
  19. package/dist/esm/tools/code-execution-tool.js +8 -0
  20. package/dist/esm/tools/code-execution-tool.js.map +1 -0
  21. package/dist/esm/tools/computer-use-tool.d.ts +5 -0
  22. package/dist/esm/tools/computer-use-tool.js +8 -0
  23. package/dist/esm/tools/computer-use-tool.js.map +1 -0
  24. package/dist/esm/tools/custom-tool.d.ts +25 -0
  25. package/dist/esm/tools/custom-tool.js +21 -0
  26. package/dist/esm/tools/custom-tool.js.map +1 -0
  27. package/dist/esm/tools/index.d.ts +10 -0
  28. package/dist/esm/tools/memory-tool.d.ts +5 -0
  29. package/dist/esm/tools/memory-tool.js +11 -0
  30. package/dist/esm/tools/memory-tool.js.map +1 -0
  31. package/dist/esm/tools/text-editor-tool.d.ts +5 -0
  32. package/dist/esm/tools/text-editor-tool.js +10 -0
  33. package/dist/esm/tools/text-editor-tool.js.map +1 -0
  34. package/dist/esm/tools/tool-converter.d.ts +27 -0
  35. package/dist/esm/tools/tool-converter.js +35 -0
  36. package/dist/esm/tools/tool-converter.js.map +1 -0
  37. package/dist/esm/tools/web-fetch-tool.d.ts +5 -0
  38. package/dist/esm/tools/web-fetch-tool.js +12 -0
  39. package/dist/esm/tools/web-fetch-tool.js.map +1 -0
  40. package/dist/esm/tools/web-search-tool.d.ts +5 -0
  41. package/dist/esm/tools/web-search-tool.js +16 -0
  42. package/dist/esm/tools/web-search-tool.js.map +1 -0
  43. package/package.json +53 -0
  44. package/src/anthropic-adapter.ts +680 -0
  45. package/src/index.ts +25 -0
  46. package/src/message-types.ts +85 -0
  47. package/src/model-meta.ts +482 -0
  48. package/src/text/text-provider-options.ts +205 -0
  49. package/src/tools/bash-tool.ts +19 -0
  50. package/src/tools/code-execution-tool.ts +24 -0
  51. package/src/tools/computer-use-tool.ts +24 -0
  52. package/src/tools/custom-tool.ts +64 -0
  53. package/src/tools/index.ts +30 -0
  54. package/src/tools/memory-tool.ts +20 -0
  55. package/src/tools/text-editor-tool.ts +28 -0
  56. package/src/tools/tool-converter.ts +61 -0
  57. package/src/tools/web-fetch-tool.ts +23 -0
  58. package/src/tools/web-search-tool.ts +81 -0
@@ -0,0 +1,205 @@
1
+ import type {
2
+ BetaContextManagementConfig,
3
+ BetaToolChoiceAny,
4
+ BetaToolChoiceAuto,
5
+ BetaToolChoiceTool,
6
+ } from '@anthropic-ai/sdk/resources/beta/messages/messages'
7
+ import type { AnthropicTool } from '../tools'
8
+ import type {
9
+ MessageParam,
10
+ TextBlockParam,
11
+ } from '@anthropic-ai/sdk/resources/messages'
12
+
13
+ export interface AnthropicContainerOptions {
14
+ /**
15
+ * Container identifier for reuse across requests.
16
+ * Container parameters with skills to be loaded.
17
+ */
18
+ container?: {
19
+ id: string | null
20
+ /**
21
+ * List of skills to load into the container
22
+ */
23
+ skills: Array<{
24
+ /**
25
+ * Between 1-64 characters
26
+ */
27
+ skill_id: string
28
+
29
+ type: 'anthropic' | 'custom'
30
+ /**
31
+ * Skill version or latest by default
32
+ */
33
+ version?: string
34
+ }> | null
35
+ } | null
36
+ }
37
+
38
+ export interface AnthropicContextManagementOptions {
39
+ /**
40
+ * Context management configuration.
41
+
42
+ This allows you to control how Claude manages context across multiple requests, such as whether to clear function results or not.
43
+ */
44
+ context_management?: BetaContextManagementConfig | null
45
+ }
46
+
47
+ export interface AnthropicMCPOptions {
48
+ /**
49
+ * MCP servers to be utilized in this request
50
+ * Maximum of 20 servers
51
+ */
52
+ mcp_servers?: Array<MCPServer>
53
+ }
54
+
55
+ export interface AnthropicServiceTierOptions {
56
+ /**
57
+ * Determines whether to use priority capacity (if available) or standard capacity for this request.
58
+ */
59
+ service_tier?: 'auto' | 'standard_only'
60
+ }
61
+
62
+ export interface AnthropicStopSequencesOptions {
63
+ /**
64
+ * Custom text sequences that will cause the model to stop generating.
65
+
66
+ Anthropic models will normally stop when they have naturally completed their turn, which will result in a response stop_reason of "end_turn".
67
+
68
+ If you want the model to stop generating when it encounters custom strings of text, you can use the stop_sequences parameter. If the model encounters one of the custom sequences, the response stop_reason value will be "stop_sequence" and the response stop_sequence value will contain the matched stop sequence.
69
+ */
70
+ stop_sequences?: Array<string>
71
+ }
72
+
73
+ export interface AnthropicThinkingOptions {
74
+ /**
75
+ * Configuration for enabling Claude's extended thinking.
76
+
77
+ When enabled, responses include thinking content blocks showing Claude's thinking process before the final answer. Requires a minimum budget of 1,024 tokens and counts towards your max_tokens limit.
78
+ */
79
+ thinking?:
80
+ | {
81
+ /**
82
+ * Determines how many tokens Claude can use for its internal reasoning process. Larger budgets can enable more thorough analysis for complex problems, improving response quality.
83
+
84
+ Must be ≥1024 and less than max_tokens
85
+ */
86
+ budget_tokens: number
87
+
88
+ type: 'enabled'
89
+ }
90
+ | {
91
+ type: 'disabled'
92
+ }
93
+ }
94
+
95
+ export interface AnthropicToolChoiceOptions {
96
+ tool_choice?: BetaToolChoiceAny | BetaToolChoiceTool | BetaToolChoiceAuto
97
+ }
98
+
99
+ export interface AnthropicSamplingOptions {
100
+ /**
101
+ * Only sample from the top K options for each subsequent token.
102
+
103
+ Used to remove "long tail" low probability responses.
104
+ Recommended for advanced use cases only. You usually only need to use temperature.
105
+
106
+ Required range: x >= 0
107
+ */
108
+ top_k?: number
109
+ }
110
+
111
+ export type ExternalTextProviderOptions = AnthropicContainerOptions &
112
+ AnthropicContextManagementOptions &
113
+ AnthropicMCPOptions &
114
+ AnthropicServiceTierOptions &
115
+ AnthropicStopSequencesOptions &
116
+ AnthropicThinkingOptions &
117
+ AnthropicToolChoiceOptions &
118
+ AnthropicSamplingOptions
119
+
120
+ export interface InternalTextProviderOptions
121
+ extends ExternalTextProviderOptions {
122
+ model: string
123
+
124
+ messages: Array<MessageParam>
125
+
126
+ /**
127
+ * The maximum number of tokens to generate before stopping. This parameter only specifies the absolute maximum number of tokens to generate.
128
+ * Range x >= 1.
129
+ */
130
+ max_tokens: number
131
+ /**
132
+ * Whether to incrementally stream the response using server-sent events.
133
+ */
134
+ stream?: boolean
135
+ /**
136
+ * stem prompt.
137
+
138
+ A system prompt is a way of providing context and instructions to Claude, such as specifying a particular goal or role.
139
+ */
140
+ system?: string | Array<TextBlockParam>
141
+ /**
142
+ * Amount of randomness injected into the response.
143
+ * Either use this or top_p, but not both.
144
+ * Defaults to 1.0. Ranges from 0.0 to 1.0. Use temperature closer to 0.0 for analytical / multiple choice, and closer to 1.0 for creative and generative tasks.
145
+ * @default 1.0
146
+ */
147
+ temperature?: number
148
+
149
+ tools?: Array<AnthropicTool>
150
+
151
+ /**
152
+ * Use nucleus sampling.
153
+
154
+ In nucleus sampling, we compute the cumulative distribution over all the options for each subsequent token in decreasing probability order and cut it off once it reaches a particular probability specified by top_p. You should either alter temperature or top_p, but not both.
155
+ */
156
+ top_p?: number
157
+ }
158
+
159
+ const validateTopPandTemperature = (options: InternalTextProviderOptions) => {
160
+ if (options.top_p !== undefined && options.temperature !== undefined) {
161
+ throw new Error('You should either set top_p or temperature, but not both.')
162
+ }
163
+ }
164
+
165
+ export interface CacheControl {
166
+ type: 'ephemeral'
167
+ ttl: '5m' | '1h'
168
+ }
169
+
170
+ const validateThinking = (options: InternalTextProviderOptions) => {
171
+ const thinking = options.thinking
172
+ if (thinking && thinking.type === 'enabled') {
173
+ if (thinking.budget_tokens < 1024) {
174
+ throw new Error('thinking.budget_tokens must be at least 1024.')
175
+ }
176
+ if (thinking.budget_tokens >= options.max_tokens) {
177
+ throw new Error('thinking.budget_tokens must be less than max_tokens.')
178
+ }
179
+ }
180
+ }
181
+
182
+ interface MCPServer {
183
+ name: string
184
+ url: string
185
+ type: 'url'
186
+ authorization_token?: string | null
187
+ tool_configuration: {
188
+ allowed_tools?: Array<string> | null
189
+ enabled?: boolean | null
190
+ } | null
191
+ }
192
+
193
+ const validateMaxTokens = (options: InternalTextProviderOptions) => {
194
+ if (options.max_tokens < 1) {
195
+ throw new Error('max_tokens must be at least 1.')
196
+ }
197
+ }
198
+
199
+ export const validateTextProviderOptions = (
200
+ options: InternalTextProviderOptions,
201
+ ) => {
202
+ validateTopPandTemperature(options)
203
+ validateThinking(options)
204
+ validateMaxTokens(options)
205
+ }
@@ -0,0 +1,19 @@
1
+ import type {
2
+ BetaToolBash20241022,
3
+ BetaToolBash20250124,
4
+ } from '@anthropic-ai/sdk/resources/beta'
5
+ import type { Tool } from '@tanstack/ai'
6
+
7
+ export type BashTool = BetaToolBash20241022 | BetaToolBash20250124
8
+
9
+ export function convertBashToolToAdapterFormat(tool: Tool): BashTool {
10
+ const metadata = tool.metadata as BashTool
11
+ return metadata
12
+ }
13
+ export function bashTool(config: BashTool): Tool {
14
+ return {
15
+ name: 'bash',
16
+ description: '',
17
+ metadata: config,
18
+ }
19
+ }
@@ -0,0 +1,24 @@
1
+ import type {
2
+ BetaCodeExecutionTool20250522,
3
+ BetaCodeExecutionTool20250825,
4
+ } from '@anthropic-ai/sdk/resources/beta'
5
+ import type { Tool } from '@tanstack/ai'
6
+
7
+ export type CodeExecutionTool =
8
+ | BetaCodeExecutionTool20250522
9
+ | BetaCodeExecutionTool20250825
10
+
11
+ export function convertCodeExecutionToolToAdapterFormat(
12
+ tool: Tool,
13
+ ): CodeExecutionTool {
14
+ const metadata = tool.metadata as CodeExecutionTool
15
+ return metadata
16
+ }
17
+
18
+ export function codeExecutionTool(config: CodeExecutionTool): Tool {
19
+ return {
20
+ name: 'code_execution',
21
+ description: '',
22
+ metadata: config,
23
+ }
24
+ }
@@ -0,0 +1,24 @@
1
+ import type {
2
+ BetaToolComputerUse20241022,
3
+ BetaToolComputerUse20250124,
4
+ } from '@anthropic-ai/sdk/resources/beta'
5
+ import type { Tool } from '@tanstack/ai'
6
+
7
+ export type ComputerUseTool =
8
+ | BetaToolComputerUse20241022
9
+ | BetaToolComputerUse20250124
10
+
11
+ export function convertComputerUseToolToAdapterFormat(
12
+ tool: Tool,
13
+ ): ComputerUseTool {
14
+ const metadata = tool.metadata as ComputerUseTool
15
+ return metadata
16
+ }
17
+
18
+ export function computerUseTool(config: ComputerUseTool): Tool {
19
+ return {
20
+ name: 'computer',
21
+ description: '',
22
+ metadata: config,
23
+ }
24
+ }
@@ -0,0 +1,64 @@
1
+ import { convertZodToJsonSchema } from '@tanstack/ai'
2
+ import type { Tool } from '@tanstack/ai'
3
+ import type { z } from 'zod'
4
+ import type { CacheControl } from '../text/text-provider-options'
5
+
6
+ export interface CustomTool {
7
+ /**
8
+ * The name of the tool.
9
+ */
10
+ name: string
11
+ type: 'custom'
12
+ /**
13
+ * A brief description of what the tool does. Tool descriptions should be as detailed as possible. The more information that the model has about what the tool is and how to use it, the better it will perform. You can use natural language descriptions to reinforce important aspects of the tool input JSON schema.
14
+ */
15
+ description: string
16
+ /**
17
+ * This defines the shape of the input that your tool accepts and that the model will produce.
18
+ */
19
+ input_schema: {
20
+ type: 'object'
21
+ properties: Record<string, any> | null
22
+ required?: Array<string> | null
23
+ }
24
+
25
+ cache_control?: CacheControl | null
26
+ }
27
+
28
+ export function convertCustomToolToAdapterFormat(tool: Tool): CustomTool {
29
+ const metadata =
30
+ (tool.metadata as { cacheControl?: CacheControl | null } | undefined) || {}
31
+
32
+ // Convert Zod schema to JSON Schema
33
+ const jsonSchema = convertZodToJsonSchema(tool.inputSchema)
34
+
35
+ const inputSchema = {
36
+ type: 'object' as const,
37
+ properties: jsonSchema?.properties || null,
38
+ required: jsonSchema?.required || null,
39
+ }
40
+
41
+ return {
42
+ name: tool.name,
43
+ type: 'custom',
44
+ description: tool.description,
45
+ input_schema: inputSchema,
46
+ cache_control: metadata.cacheControl || null,
47
+ }
48
+ }
49
+
50
+ export function customTool(
51
+ name: string,
52
+ description: string,
53
+ inputSchema: z.ZodType,
54
+ cacheControl?: CacheControl | null,
55
+ ): Tool {
56
+ return {
57
+ name,
58
+ description,
59
+ inputSchema,
60
+ metadata: {
61
+ cacheControl,
62
+ },
63
+ }
64
+ }
@@ -0,0 +1,30 @@
1
+ import type { BashTool } from './bash-tool'
2
+ import type { CodeExecutionTool } from './code-execution-tool'
3
+ import type { ComputerUseTool } from './computer-use-tool'
4
+ import type { CustomTool } from './custom-tool'
5
+ import type { MemoryTool } from './memory-tool'
6
+ import type { TextEditorTool } from './text-editor-tool'
7
+ import type { WebFetchTool } from './web-fetch-tool'
8
+ import type { WebSearchTool } from './web-search-tool'
9
+
10
+ export type AnthropicTool =
11
+ | BashTool
12
+ | CodeExecutionTool
13
+ | ComputerUseTool
14
+ | CustomTool
15
+ | MemoryTool
16
+ | TextEditorTool
17
+ | WebFetchTool
18
+ | WebSearchTool
19
+
20
+ // Export individual tool types
21
+ export type {
22
+ // BashTool,
23
+ // CodeExecutionTool,
24
+ // ComputerUseTool,
25
+ CustomTool,
26
+ // MemoryTool,
27
+ // TextEditorTool,
28
+ // WebFetchTool,
29
+ // WebSearchTool,
30
+ }
@@ -0,0 +1,20 @@
1
+ import type { BetaMemoryTool20250818 } from '@anthropic-ai/sdk/resources/beta'
2
+ import type { Tool } from '@tanstack/ai'
3
+
4
+ export type MemoryTool = BetaMemoryTool20250818
5
+
6
+ export function convertMemoryToolToAdapterFormat(tool: Tool): MemoryTool {
7
+ const metadata = tool.metadata as Omit<MemoryTool, 'type'>
8
+ return {
9
+ type: 'memory_20250818',
10
+ ...metadata,
11
+ }
12
+ }
13
+
14
+ export function memoryTool(config?: MemoryTool): Tool {
15
+ return {
16
+ name: 'memory',
17
+ description: '',
18
+ metadata: config,
19
+ }
20
+ }
@@ -0,0 +1,28 @@
1
+ import type {
2
+ ToolTextEditor20250124,
3
+ ToolTextEditor20250429,
4
+ ToolTextEditor20250728,
5
+ } from '@anthropic-ai/sdk/resources/messages'
6
+ import type { Tool } from '@tanstack/ai'
7
+
8
+ export type TextEditorTool =
9
+ | ToolTextEditor20250124
10
+ | ToolTextEditor20250429
11
+ | ToolTextEditor20250728
12
+
13
+ export function convertTextEditorToolToAdapterFormat(
14
+ tool: Tool,
15
+ ): TextEditorTool {
16
+ const metadata = tool.metadata as TextEditorTool
17
+ return {
18
+ ...metadata,
19
+ }
20
+ }
21
+
22
+ export function textEditorTool<T extends TextEditorTool>(config: T): Tool {
23
+ return {
24
+ name: 'str_replace_editor',
25
+ description: '',
26
+ metadata: config,
27
+ }
28
+ }
@@ -0,0 +1,61 @@
1
+ import { convertBashToolToAdapterFormat } from './bash-tool'
2
+ import { convertCodeExecutionToolToAdapterFormat } from './code-execution-tool'
3
+ import { convertComputerUseToolToAdapterFormat } from './computer-use-tool'
4
+ import { convertCustomToolToAdapterFormat } from './custom-tool'
5
+ import { convertMemoryToolToAdapterFormat } from './memory-tool'
6
+ import { convertTextEditorToolToAdapterFormat } from './text-editor-tool'
7
+ import { convertWebFetchToolToAdapterFormat } from './web-fetch-tool'
8
+ import { convertWebSearchToolToAdapterFormat } from './web-search-tool'
9
+ import type { AnthropicTool } from '.'
10
+ import type { Tool } from '@tanstack/ai'
11
+
12
+ /**
13
+ * Converts standard Tool format to Anthropic-specific tool format
14
+ *
15
+ * @param tools - Array of standard Tool objects
16
+ * @returns Array of Anthropic-specific tool definitions
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * const tools: Tool[] = [{
21
+ * type: "function",
22
+ * function: {
23
+ * name: "get_weather",
24
+ * description: "Get weather for a location",
25
+ * parameters: {
26
+ * type: "object",
27
+ * properties: { location: { type: "string" } },
28
+ * required: ["location"]
29
+ * }
30
+ * }
31
+ * }];
32
+ *
33
+ * const anthropicTools = convertToolsToProviderFormat(tools);
34
+ * ```
35
+ */
36
+ export function convertToolsToProviderFormat<TTool extends Tool>(
37
+ tools: Array<TTool>,
38
+ ): Array<AnthropicTool> {
39
+ return tools.map((tool) => {
40
+ const name = tool.name
41
+
42
+ switch (name) {
43
+ case 'bash':
44
+ return convertBashToolToAdapterFormat(tool)
45
+ case 'code_execution':
46
+ return convertCodeExecutionToolToAdapterFormat(tool)
47
+ case 'computer':
48
+ return convertComputerUseToolToAdapterFormat(tool)
49
+ case 'memory':
50
+ return convertMemoryToolToAdapterFormat(tool)
51
+ case 'str_replace_editor':
52
+ return convertTextEditorToolToAdapterFormat(tool)
53
+ case 'web_fetch':
54
+ return convertWebFetchToolToAdapterFormat(tool)
55
+ case 'web_search':
56
+ return convertWebSearchToolToAdapterFormat(tool)
57
+ default:
58
+ return convertCustomToolToAdapterFormat(tool)
59
+ }
60
+ })
61
+ }
@@ -0,0 +1,23 @@
1
+ import type { BetaWebFetchTool20250910 } from '@anthropic-ai/sdk/resources/beta'
2
+ import type { Tool } from '@tanstack/ai'
3
+
4
+ export type WebFetchTool = BetaWebFetchTool20250910
5
+
6
+ export function convertWebFetchToolToAdapterFormat(tool: Tool): WebFetchTool {
7
+ const metadata = tool.metadata as Omit<WebFetchTool, 'type' | 'name'>
8
+ return {
9
+ name: 'web_fetch',
10
+ type: 'web_fetch_20250910',
11
+ ...metadata,
12
+ }
13
+ }
14
+
15
+ export function webFetchTool(
16
+ config?: Omit<WebFetchTool, 'type' | 'name'>,
17
+ ): Tool {
18
+ return {
19
+ name: 'web_fetch',
20
+ description: '',
21
+ metadata: config,
22
+ }
23
+ }
@@ -0,0 +1,81 @@
1
+ import type { WebSearchTool20250305 } from '@anthropic-ai/sdk/resources/messages'
2
+ import type { CacheControl } from '../text/text-provider-options'
3
+ import type { Tool } from '@tanstack/ai'
4
+
5
+ export type WebSearchTool = WebSearchTool20250305
6
+
7
+ const validateDomains = (tool: WebSearchTool) => {
8
+ if (tool.allowed_domains && tool.blocked_domains) {
9
+ throw new Error(
10
+ 'allowed_domains and blocked_domains cannot be used together.',
11
+ )
12
+ }
13
+ }
14
+
15
+ const validateUserLocation = (tool: WebSearchTool) => {
16
+ const userLocation = tool.user_location
17
+ if (userLocation) {
18
+ if (
19
+ userLocation.city &&
20
+ (userLocation.city.length < 1 || userLocation.city.length > 255)
21
+ ) {
22
+ throw new Error(
23
+ 'user_location.city must be between 1 and 255 characters.',
24
+ )
25
+ }
26
+ if (userLocation.country && userLocation.country.length !== 2) {
27
+ throw new Error('user_location.country must be exactly 2 characters.')
28
+ }
29
+ if (
30
+ userLocation.region &&
31
+ (userLocation.region.length < 1 || userLocation.region.length > 255)
32
+ ) {
33
+ throw new Error(
34
+ 'user_location.region must be between 1 and 255 characters.',
35
+ )
36
+ }
37
+ if (
38
+ userLocation.timezone &&
39
+ (userLocation.timezone.length < 1 || userLocation.timezone.length > 255)
40
+ ) {
41
+ throw new Error(
42
+ 'user_location.timezone must be between 1 and 255 characters.',
43
+ )
44
+ }
45
+ }
46
+ }
47
+
48
+ export function convertWebSearchToolToAdapterFormat(tool: Tool): WebSearchTool {
49
+ const metadata = tool.metadata as {
50
+ allowedDomains?: Array<string> | null
51
+ blockedDomains?: Array<string> | null
52
+ maxUses?: number | null
53
+ userLocation?: {
54
+ type: 'approximate'
55
+ city?: string | null
56
+ country?: string | null
57
+ region?: string | null
58
+ timezone?: string | null
59
+ } | null
60
+ cacheControl?: CacheControl | null
61
+ }
62
+ return {
63
+ name: 'web_search',
64
+ type: 'web_search_20250305',
65
+ allowed_domains: metadata.allowedDomains,
66
+ blocked_domains: metadata.blockedDomains,
67
+ max_uses: metadata.maxUses,
68
+ user_location: metadata.userLocation,
69
+ cache_control: metadata.cacheControl || null,
70
+ }
71
+ }
72
+
73
+ export function webSearchTool(config: WebSearchTool): Tool {
74
+ validateDomains(config)
75
+ validateUserLocation(config)
76
+ return {
77
+ name: 'web_search',
78
+ description: '',
79
+ metadata: config,
80
+ }
81
+ }