@agentionai/agents 1.8.0 → 1.9.0
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/agents/AgentConfig.d.ts +19 -7
- package/dist/agents/openai/OpenAiAgent.d.ts +16 -0
- package/dist/agents/openai/OpenAiAgent.js +19 -3
- package/dist/agents/openai-compatible/OpenAICompatibleAgent.d.ts +22 -0
- package/dist/agents/openai-compatible/OpenAICompatibleAgent.js +49 -8
- package/dist/agents/openrouter/OpenRouterAgent.d.ts +6 -0
- package/dist/agents/openrouter/OpenRouterAgent.js +14 -1
- package/dist/history/transformers.d.ts +10 -1
- package/dist/history/transformers.js +10 -2
- package/dist/tools/BuiltInTool.d.ts +72 -6
- package/dist/tools/BuiltInTool.js +75 -0
- package/package.json +1 -1
|
@@ -131,6 +131,12 @@ export interface OpenAISpecificConfig {
|
|
|
131
131
|
reasoningEffort?: ReasoningEffort;
|
|
132
132
|
seed?: number;
|
|
133
133
|
user?: string;
|
|
134
|
+
/**
|
|
135
|
+
* Provider-defined / server-side tools (e.g. web search, file search, code
|
|
136
|
+
* interpreter). These run on OpenAI's infrastructure rather than locally —
|
|
137
|
+
* see `lib/tools/BuiltInTool.ts`.
|
|
138
|
+
*/
|
|
139
|
+
builtInTools?: BuiltInTool[];
|
|
134
140
|
}
|
|
135
141
|
/**
|
|
136
142
|
* Vendor-specific configuration for Mistral
|
|
@@ -164,11 +170,6 @@ export interface LlamaCppSpecificConfig {
|
|
|
164
170
|
/** Base URL of the llama.cpp server's OpenAI-compatible API (default: `http://localhost:8080/v1`) */
|
|
165
171
|
baseURL?: string;
|
|
166
172
|
}
|
|
167
|
-
/** Vendor-specific configuration for Cerebras */
|
|
168
|
-
export interface CerebrasSpecificConfig {
|
|
169
|
-
/** Cerebras OpenAI-compatible API base URL. */
|
|
170
|
-
baseURL?: string;
|
|
171
|
-
}
|
|
172
173
|
/**
|
|
173
174
|
* Vendor-specific configuration for OpenRouter
|
|
174
175
|
*
|
|
@@ -212,9 +213,13 @@ export interface OpenRouterSpecificConfig {
|
|
|
212
213
|
/** Reasoning configuration for models that support it. */
|
|
213
214
|
reasoning?: OpenRouterReasoningConfig;
|
|
214
215
|
/**
|
|
215
|
-
* OpenRouter plugins to enable —
|
|
216
|
-
*
|
|
216
|
+
* OpenRouter plugins to enable — file parsing, context compression,
|
|
217
|
+
* moderation. Passed through untouched; see
|
|
217
218
|
* https://openrouter.ai/docs/guides/features/plugins for the shapes.
|
|
219
|
+
*
|
|
220
|
+
* The `{ id: "web" }` web search plugin is deprecated in favour of the
|
|
221
|
+
* `openrouter:web_search` server tool — use {@link builtInTools} /
|
|
222
|
+
* `openRouterWebSearchTool()` instead.
|
|
218
223
|
*/
|
|
219
224
|
plugins?: unknown[];
|
|
220
225
|
/**
|
|
@@ -233,6 +238,13 @@ export interface OpenRouterSpecificConfig {
|
|
|
233
238
|
appTitle?: string;
|
|
234
239
|
/** Disable parallel tool calling (sends `parallel_tool_calls: false`). */
|
|
235
240
|
disableParallelToolUse?: boolean;
|
|
241
|
+
/**
|
|
242
|
+
* Provider-defined / server-side tools (e.g. `openrouter:web_search`,
|
|
243
|
+
* `openrouter:web_fetch`). These run on OpenRouter's infrastructure rather
|
|
244
|
+
* than locally — see `lib/tools/BuiltInTool.ts`. Prefer these over the
|
|
245
|
+
* deprecated {@link OpenRouterSpecificConfig.plugins} web search plugin.
|
|
246
|
+
*/
|
|
247
|
+
builtInTools?: BuiltInTool[];
|
|
236
248
|
}
|
|
237
249
|
/**
|
|
238
250
|
* Generic vendor-specific configuration container
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BaseAgent, BaseAgentConfig, ModelInfo, TokenUsage } from "../BaseAgent";
|
|
2
2
|
import { ExecuteOptions } from "../cancellation";
|
|
3
3
|
import { History, MessageContent } from "../../history/History";
|
|
4
|
+
import { type BuiltInTool } from "../../tools/BuiltInTool";
|
|
4
5
|
import { Tool, Response, ResponseUsage } from "openai/resources/responses/responses";
|
|
5
6
|
import type { Model as OpenAIModelCard } from "openai/resources/models";
|
|
6
7
|
import { OpenAIModel, ReasoningEffort, ReasoningEffortFor } from "../model-types";
|
|
@@ -23,6 +24,12 @@ type AgentConfig<M extends OpenAIModel = OpenAIModel> = BaseAgentConfig & {
|
|
|
23
24
|
*/
|
|
24
25
|
reasoningEffort?: ReasoningEffortFor<M>;
|
|
25
26
|
user?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Provider-defined / server-side tools (e.g. web search, file search, code
|
|
29
|
+
* interpreter). These run on OpenAI's infrastructure rather than locally.
|
|
30
|
+
* @see lib/tools/BuiltInTool.ts
|
|
31
|
+
*/
|
|
32
|
+
builtInTools?: BuiltInTool[];
|
|
26
33
|
};
|
|
27
34
|
/**
|
|
28
35
|
* Lowest `reasoning.effort` the given model accepts, used to resolve
|
|
@@ -78,6 +85,15 @@ export declare class OpenAiAgent<M extends OpenAIModel = OpenAIModel> extends Ba
|
|
|
78
85
|
*/
|
|
79
86
|
listModels(): Promise<ModelInfo<OpenAIModelCard>[]>;
|
|
80
87
|
protected getToolDefinitions(): Tool[];
|
|
88
|
+
/**
|
|
89
|
+
* Combine locally-executed tool definitions with provider-defined
|
|
90
|
+
* (server-side) built-in tools, in the shape the Responses API expects.
|
|
91
|
+
* Cast to `Tool[]`: built-in tool objects (e.g. `{ type: "web_search" }`)
|
|
92
|
+
* don't fit the SDK's `Tool` union, which only names `function` tools plus
|
|
93
|
+
* the specific built-ins it has typed — the same passthrough `ClaudeAgent`
|
|
94
|
+
* uses for its own `ToolUnion[]`.
|
|
95
|
+
*/
|
|
96
|
+
protected getAllToolDefinitions(): Tool[];
|
|
81
97
|
/**
|
|
82
98
|
* Build the `reasoning` field for a Responses API request, as an object to
|
|
83
99
|
* spread into the request params.
|
|
@@ -71,6 +71,7 @@ class OpenAiAgent extends BaseAgent_1.BaseAgent {
|
|
|
71
71
|
const disableReasoning = config.disableReasoning ?? vendorConfig.disableReasoning ?? false;
|
|
72
72
|
const reasoningEffort = config.reasoningEffort ?? vendorConfig.reasoningEffort;
|
|
73
73
|
const user = config.user ?? vendorConfig.user;
|
|
74
|
+
const builtInTools = config.builtInTools ?? vendorConfig.builtInTools;
|
|
74
75
|
this.config = {
|
|
75
76
|
model: config.model || "gpt-4.1-mini",
|
|
76
77
|
// No default. `max_output_tokens` is optional on the Responses API, and
|
|
@@ -84,6 +85,7 @@ class OpenAiAgent extends BaseAgent_1.BaseAgent {
|
|
|
84
85
|
disableReasoning,
|
|
85
86
|
reasoningEffort,
|
|
86
87
|
user,
|
|
88
|
+
builtInTools,
|
|
87
89
|
apiKey: config.apiKey,
|
|
88
90
|
temperature: config.temperature,
|
|
89
91
|
topP: config.topP,
|
|
@@ -136,6 +138,20 @@ class OpenAiAgent extends BaseAgent_1.BaseAgent {
|
|
|
136
138
|
};
|
|
137
139
|
});
|
|
138
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* Combine locally-executed tool definitions with provider-defined
|
|
143
|
+
* (server-side) built-in tools, in the shape the Responses API expects.
|
|
144
|
+
* Cast to `Tool[]`: built-in tool objects (e.g. `{ type: "web_search" }`)
|
|
145
|
+
* don't fit the SDK's `Tool` union, which only names `function` tools plus
|
|
146
|
+
* the specific built-ins it has typed — the same passthrough `ClaudeAgent`
|
|
147
|
+
* uses for its own `ToolUnion[]`.
|
|
148
|
+
*/
|
|
149
|
+
getAllToolDefinitions() {
|
|
150
|
+
return [
|
|
151
|
+
...this.getToolDefinitions(),
|
|
152
|
+
...(this.config.builtInTools ?? []),
|
|
153
|
+
];
|
|
154
|
+
}
|
|
139
155
|
/**
|
|
140
156
|
* Build the `reasoning` field for a Responses API request, as an object to
|
|
141
157
|
* spread into the request params.
|
|
@@ -204,7 +220,7 @@ class OpenAiAgent extends BaseAgent_1.BaseAgent {
|
|
|
204
220
|
model: this.config.model,
|
|
205
221
|
max_output_tokens: this.config.maxTokens,
|
|
206
222
|
input: inputMessages,
|
|
207
|
-
tools: this.
|
|
223
|
+
tools: this.getAllToolDefinitions(),
|
|
208
224
|
store: false,
|
|
209
225
|
temperature: this.config.temperature,
|
|
210
226
|
top_p: this.config.topP,
|
|
@@ -331,7 +347,7 @@ class OpenAiAgent extends BaseAgent_1.BaseAgent {
|
|
|
331
347
|
model: this.config.model,
|
|
332
348
|
max_output_tokens: this.config.maxTokens,
|
|
333
349
|
input: inputMessages,
|
|
334
|
-
tools: this.
|
|
350
|
+
tools: this.getAllToolDefinitions(),
|
|
335
351
|
store: false,
|
|
336
352
|
temperature: this.config.temperature,
|
|
337
353
|
top_p: this.config.topP,
|
|
@@ -511,7 +527,7 @@ class OpenAiAgent extends BaseAgent_1.BaseAgent {
|
|
|
511
527
|
model: this.config.model,
|
|
512
528
|
max_output_tokens: this.config.maxTokens,
|
|
513
529
|
input: inputMessages,
|
|
514
|
-
tools: this.
|
|
530
|
+
tools: this.getAllToolDefinitions(),
|
|
515
531
|
store: false,
|
|
516
532
|
stream: true,
|
|
517
533
|
temperature: this.config.temperature,
|
|
@@ -35,6 +35,12 @@ export declare abstract class OpenAICompatibleAgent extends BaseAgent {
|
|
|
35
35
|
protected config: Partial<OpenAICompatibleConfig>;
|
|
36
36
|
private vizEventId?;
|
|
37
37
|
private currentToolCallCount;
|
|
38
|
+
/**
|
|
39
|
+
* Whether this server accepts a replayed `reasoning_content` field on an
|
|
40
|
+
* assistant message. `undefined` until proven otherwise — see
|
|
41
|
+
* {@link withReasoningReplayFallback}.
|
|
42
|
+
*/
|
|
43
|
+
private reasoningReplaySupported?;
|
|
38
44
|
constructor(config: OpenAICompatibleConfig & {
|
|
39
45
|
vendor: AgentVendor;
|
|
40
46
|
}, history?: History);
|
|
@@ -53,6 +59,22 @@ export declare abstract class OpenAICompatibleAgent extends BaseAgent {
|
|
|
53
59
|
protected process(_input: string): Promise<string>;
|
|
54
60
|
execute(input: string | MessageContent[], options?: ExecuteOptions): Promise<string>;
|
|
55
61
|
private callProvider;
|
|
62
|
+
/**
|
|
63
|
+
* Some OpenAI-compatible servers (Cerebras, at least as of 2026-08) reject
|
|
64
|
+
* any message carrying `reasoning_content` with a plain 400 — no per-field
|
|
65
|
+
* detail worth parsing, and other servers *require* the field (DeepSeek's
|
|
66
|
+
* thinking mode), so it can't just be dropped unconditionally either.
|
|
67
|
+
*
|
|
68
|
+
* Runs `request` normally first. On a 400 that could plausibly be caused by
|
|
69
|
+
* a replayed reasoning field, retries once with it stripped; if that
|
|
70
|
+
* succeeds, remembers the result so every later call in this agent's
|
|
71
|
+
* lifetime skips straight to the working shape instead of paying for the
|
|
72
|
+
* failed attempt again. If the retry also fails, the original error is
|
|
73
|
+
* what surfaces — it's more likely to point at the real problem.
|
|
74
|
+
*/
|
|
75
|
+
private withReasoningReplayFallback;
|
|
76
|
+
/** Whether any assistant turn in history carries reasoning that would be replayed. */
|
|
77
|
+
private hasReplayableReasoning;
|
|
56
78
|
protected handleResponse(response: ChatCompletion, options?: ExecuteOptions): Promise<string>;
|
|
57
79
|
private handleToolCalls;
|
|
58
80
|
/**
|
|
@@ -9,6 +9,7 @@ const BaseAgent_1 = require("../BaseAgent");
|
|
|
9
9
|
const AgentEvent_1 = require("../AgentEvent");
|
|
10
10
|
const cancellation_1 = require("../cancellation");
|
|
11
11
|
const AgentError_1 = require("../errors/AgentError");
|
|
12
|
+
const types_1 = require("../../history/types");
|
|
12
13
|
const transformers_1 = require("../../history/transformers");
|
|
13
14
|
const VizReporter_1 = require("../../viz/VizReporter");
|
|
14
15
|
const VizConfig_1 = require("../../viz/VizConfig");
|
|
@@ -149,12 +150,11 @@ class OpenAICompatibleAgent extends BaseAgent_1.BaseAgent {
|
|
|
149
150
|
}
|
|
150
151
|
}
|
|
151
152
|
async callProvider(options) {
|
|
152
|
-
const messages = transformers_1.chatCompletionsTransformer.toProvider(this.history.getEntries());
|
|
153
153
|
const tools = this.tools.size > 0 ? this.getToolDefinitions() : undefined;
|
|
154
154
|
this.startTurnTimer();
|
|
155
|
-
return this.client.chat.completions.create({
|
|
155
|
+
return this.withReasoningReplayFallback((includeReasoning) => this.client.chat.completions.create({
|
|
156
156
|
model: this.config.model,
|
|
157
|
-
messages,
|
|
157
|
+
messages: transformers_1.chatCompletionsTransformer.toProvider(this.history.getEntries(), { includeReasoning }),
|
|
158
158
|
tools,
|
|
159
159
|
stream: false,
|
|
160
160
|
max_tokens: this.config.maxTokens,
|
|
@@ -165,7 +165,49 @@ class OpenAICompatibleAgent extends BaseAgent_1.BaseAgent {
|
|
|
165
165
|
presence_penalty: this.config.presencePenalty,
|
|
166
166
|
frequency_penalty: this.config.frequencyPenalty,
|
|
167
167
|
...this.buildExtraRequestParams(),
|
|
168
|
-
}, { signal: options?.signal });
|
|
168
|
+
}, { signal: options?.signal }));
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Some OpenAI-compatible servers (Cerebras, at least as of 2026-08) reject
|
|
172
|
+
* any message carrying `reasoning_content` with a plain 400 — no per-field
|
|
173
|
+
* detail worth parsing, and other servers *require* the field (DeepSeek's
|
|
174
|
+
* thinking mode), so it can't just be dropped unconditionally either.
|
|
175
|
+
*
|
|
176
|
+
* Runs `request` normally first. On a 400 that could plausibly be caused by
|
|
177
|
+
* a replayed reasoning field, retries once with it stripped; if that
|
|
178
|
+
* succeeds, remembers the result so every later call in this agent's
|
|
179
|
+
* lifetime skips straight to the working shape instead of paying for the
|
|
180
|
+
* failed attempt again. If the retry also fails, the original error is
|
|
181
|
+
* what surfaces — it's more likely to point at the real problem.
|
|
182
|
+
*/
|
|
183
|
+
async withReasoningReplayFallback(request) {
|
|
184
|
+
const includeReasoning = this.reasoningReplaySupported !== false;
|
|
185
|
+
try {
|
|
186
|
+
return await request(includeReasoning);
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
const worthRetrying = includeReasoning &&
|
|
190
|
+
this.hasReplayableReasoning() &&
|
|
191
|
+
error instanceof openai_1.default.APIError &&
|
|
192
|
+
error.status === 400;
|
|
193
|
+
if (!worthRetrying)
|
|
194
|
+
throw error;
|
|
195
|
+
try {
|
|
196
|
+
const result = await request(false);
|
|
197
|
+
this.reasoningReplaySupported = false;
|
|
198
|
+
return result;
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
throw error;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/** Whether any assistant turn in history carries reasoning that would be replayed. */
|
|
206
|
+
hasReplayableReasoning() {
|
|
207
|
+
return this.history
|
|
208
|
+
.getEntries()
|
|
209
|
+
.some((entry) => entry.role === "assistant" &&
|
|
210
|
+
entry.content.some((block) => (0, types_1.isThinkingContent)(block) && block.thinking.length > 0));
|
|
169
211
|
}
|
|
170
212
|
async handleResponse(response, options) {
|
|
171
213
|
const usage = this.accumulateUsage(this.parseUsage(response));
|
|
@@ -329,12 +371,11 @@ class OpenAICompatibleAgent extends BaseAgent_1.BaseAgent {
|
|
|
329
371
|
}
|
|
330
372
|
}
|
|
331
373
|
async *streamTurn(options) {
|
|
332
|
-
const messages = transformers_1.chatCompletionsTransformer.toProvider(this.history.getEntries());
|
|
333
374
|
const tools = this.tools.size > 0 ? this.getToolDefinitions() : undefined;
|
|
334
375
|
this.startTurnTimer();
|
|
335
|
-
const stream = await this.client.chat.completions.create({
|
|
376
|
+
const stream = await this.withReasoningReplayFallback((includeReasoning) => this.client.chat.completions.create({
|
|
336
377
|
model: this.config.model,
|
|
337
|
-
messages,
|
|
378
|
+
messages: transformers_1.chatCompletionsTransformer.toProvider(this.history.getEntries(), { includeReasoning }),
|
|
338
379
|
tools,
|
|
339
380
|
stream: true,
|
|
340
381
|
stream_options: { include_usage: true },
|
|
@@ -346,7 +387,7 @@ class OpenAICompatibleAgent extends BaseAgent_1.BaseAgent {
|
|
|
346
387
|
presence_penalty: this.config.presencePenalty,
|
|
347
388
|
frequency_penalty: this.config.frequencyPenalty,
|
|
348
389
|
...this.buildExtraRequestParams(),
|
|
349
|
-
}, { signal: options?.signal });
|
|
390
|
+
}, { signal: options?.signal }));
|
|
350
391
|
let textContent = "";
|
|
351
392
|
let reasoningContent = "";
|
|
352
393
|
const toolCallAcc = new Map();
|
|
@@ -129,6 +129,12 @@ export declare class OpenRouterAgent extends BaseAgent {
|
|
|
129
129
|
private getClient;
|
|
130
130
|
private createClient;
|
|
131
131
|
protected getToolDefinitions(): Array<Record<string, unknown>>;
|
|
132
|
+
/**
|
|
133
|
+
* Combine locally-executed tool definitions with provider-defined
|
|
134
|
+
* (server-side) built-in tools (e.g. `openrouter:web_search`). Both sit in
|
|
135
|
+
* the same flat `tools` array OpenRouter's OpenAI-compatible endpoint takes.
|
|
136
|
+
*/
|
|
137
|
+
protected getAllToolDefinitions(): Array<Record<string, unknown>>;
|
|
132
138
|
protected process(_input: string): Promise<string>;
|
|
133
139
|
/**
|
|
134
140
|
* List the models OpenRouter offers, following pagination to the end.
|
|
@@ -138,6 +138,7 @@ class OpenRouterAgent extends BaseAgent_1.BaseAgent {
|
|
|
138
138
|
retryCodes: config.retryCodes ?? nested.retryCodes,
|
|
139
139
|
reasoning: config.reasoning ?? nested.reasoning,
|
|
140
140
|
plugins: config.plugins ?? nested.plugins,
|
|
141
|
+
builtInTools: config.builtInTools ?? nested.builtInTools,
|
|
141
142
|
sessionId: config.sessionId ?? nested.sessionId,
|
|
142
143
|
user: config.user ?? nested.user,
|
|
143
144
|
serviceTier: config.serviceTier ?? nested.serviceTier,
|
|
@@ -202,6 +203,17 @@ class OpenRouterAgent extends BaseAgent_1.BaseAgent {
|
|
|
202
203
|
};
|
|
203
204
|
});
|
|
204
205
|
}
|
|
206
|
+
/**
|
|
207
|
+
* Combine locally-executed tool definitions with provider-defined
|
|
208
|
+
* (server-side) built-in tools (e.g. `openrouter:web_search`). Both sit in
|
|
209
|
+
* the same flat `tools` array OpenRouter's OpenAI-compatible endpoint takes.
|
|
210
|
+
*/
|
|
211
|
+
getAllToolDefinitions() {
|
|
212
|
+
return [
|
|
213
|
+
...this.getToolDefinitions(),
|
|
214
|
+
...(this.config.builtInTools ?? []),
|
|
215
|
+
];
|
|
216
|
+
}
|
|
205
217
|
async process(_input) {
|
|
206
218
|
return "";
|
|
207
219
|
}
|
|
@@ -381,7 +393,8 @@ class OpenRouterAgent extends BaseAgent_1.BaseAgent {
|
|
|
381
393
|
/** The `ChatRequest` body, identical for the streaming and buffered paths. */
|
|
382
394
|
buildRequest(stream) {
|
|
383
395
|
const messages = transformers_1.openRouterTransformer.toProvider(this.history.getEntries());
|
|
384
|
-
const
|
|
396
|
+
const allTools = this.getAllToolDefinitions();
|
|
397
|
+
const tools = allTools.length > 0 ? allTools : undefined;
|
|
385
398
|
return {
|
|
386
399
|
model: this.config.model,
|
|
387
400
|
messages,
|
|
@@ -143,8 +143,17 @@ export declare const chatCompletionsTransformer: {
|
|
|
143
143
|
/**
|
|
144
144
|
* Convert normalized entries to Chat Completions message format.
|
|
145
145
|
* Tool results become role:"tool" messages; tool calls are embedded in assistant messages.
|
|
146
|
+
*
|
|
147
|
+
* `includeReasoning` (default `true`) controls whether a prior assistant
|
|
148
|
+
* turn's reasoning is replayed as `reasoning_content`. DeepSeek's thinking
|
|
149
|
+
* mode requires it; some OpenAI-compatible servers (Cerebras) reject the
|
|
150
|
+
* field outright with a 400 on any message that carries it. Callers that
|
|
151
|
+
* have detected the latter pass `false` to fall back to the OpenAI-standard
|
|
152
|
+
* message shape.
|
|
146
153
|
*/
|
|
147
|
-
toProvider(entries: HistoryEntry[]
|
|
154
|
+
toProvider(entries: HistoryEntry[], options?: {
|
|
155
|
+
includeReasoning?: boolean;
|
|
156
|
+
}): ChatCompletionMessage[];
|
|
148
157
|
/**
|
|
149
158
|
* Convert a Chat Completions response message to a normalized HistoryEntry.
|
|
150
159
|
*/
|
|
@@ -630,8 +630,16 @@ exports.chatCompletionsTransformer = {
|
|
|
630
630
|
/**
|
|
631
631
|
* Convert normalized entries to Chat Completions message format.
|
|
632
632
|
* Tool results become role:"tool" messages; tool calls are embedded in assistant messages.
|
|
633
|
+
*
|
|
634
|
+
* `includeReasoning` (default `true`) controls whether a prior assistant
|
|
635
|
+
* turn's reasoning is replayed as `reasoning_content`. DeepSeek's thinking
|
|
636
|
+
* mode requires it; some OpenAI-compatible servers (Cerebras) reject the
|
|
637
|
+
* field outright with a 400 on any message that carries it. Callers that
|
|
638
|
+
* have detected the latter pass `false` to fall back to the OpenAI-standard
|
|
639
|
+
* message shape.
|
|
633
640
|
*/
|
|
634
|
-
toProvider(entries) {
|
|
641
|
+
toProvider(entries, options) {
|
|
642
|
+
const includeReasoning = options?.includeReasoning ?? true;
|
|
635
643
|
const messages = [];
|
|
636
644
|
for (const entry of entries) {
|
|
637
645
|
const textBlocks = entry.content.filter(types_1.isTextContent);
|
|
@@ -661,7 +669,7 @@ exports.chatCompletionsTransformer = {
|
|
|
661
669
|
.map((block) => block.thinking)
|
|
662
670
|
.filter((thought) => thought.length > 0)
|
|
663
671
|
.join("\n");
|
|
664
|
-
if (reasoning) {
|
|
672
|
+
if (reasoning && includeReasoning) {
|
|
665
673
|
msg.reasoning_content = reasoning;
|
|
666
674
|
}
|
|
667
675
|
if (toolUseBlocks.length > 0) {
|
|
@@ -3,11 +3,14 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Unlike `Tool`, these are not executed locally — the provider runs them as
|
|
5
5
|
* part of generating its response (e.g. Anthropic's web search, bash, and
|
|
6
|
-
* text editor tools
|
|
7
|
-
*
|
|
6
|
+
* text editor tools; OpenAI's web search, file search, and code interpreter;
|
|
7
|
+
* OpenRouter's web search/fetch server tools). They carry no `execute`
|
|
8
|
+
* function or input schema; the agent simply forwards their definition to
|
|
9
|
+
* the provider's API.
|
|
8
10
|
*
|
|
9
11
|
* Pass arbitrary built-in tool definitions straight through — only `type`
|
|
10
|
-
*
|
|
12
|
+
* is required. Anthropic also expects a `name` (the model's label for the
|
|
13
|
+
* tool); OpenAI and OpenRouter's built-in tool objects generally omit it.
|
|
11
14
|
*
|
|
12
15
|
* @example
|
|
13
16
|
* ```typescript
|
|
@@ -19,13 +22,13 @@
|
|
|
19
22
|
* });
|
|
20
23
|
* ```
|
|
21
24
|
*
|
|
22
|
-
* Or use one of the helpers below for the well-known
|
|
25
|
+
* Or use one of the helpers below for the well-known tools of each provider.
|
|
23
26
|
*/
|
|
24
27
|
export interface BuiltInTool {
|
|
25
28
|
/** Provider-specific tool type identifier, e.g. `"web_search_20250305"` */
|
|
26
29
|
type: string;
|
|
27
|
-
/** Name the model will use to refer to the tool, e.g. `"web_search"` */
|
|
28
|
-
name
|
|
30
|
+
/** Name the model will use to refer to the tool, e.g. `"web_search"` (Anthropic only) */
|
|
31
|
+
name?: string;
|
|
29
32
|
/** Any additional provider-specific configuration for this tool */
|
|
30
33
|
[key: string]: unknown;
|
|
31
34
|
}
|
|
@@ -63,6 +66,69 @@ export declare function bashTool(): BuiltInTool;
|
|
|
63
66
|
* Anthropic's server-side text editor tool — lets Claude view and edit text files.
|
|
64
67
|
*/
|
|
65
68
|
export declare function textEditorTool(version?: "20250124" | "20250429" | "20250728"): BuiltInTool;
|
|
69
|
+
/**
|
|
70
|
+
* Options for OpenAI's web search tool (`web_search`), used on the Responses API.
|
|
71
|
+
* @see https://developers.openai.com/api/docs/guides/tools-web-search
|
|
72
|
+
*/
|
|
73
|
+
export interface OpenAiWebSearchToolOptions {
|
|
74
|
+
/** Only include results from these domains (max 100) */
|
|
75
|
+
allowedDomains?: string[];
|
|
76
|
+
/** Never include results from these domains (max 100) */
|
|
77
|
+
blockedDomains?: string[];
|
|
78
|
+
/** Approximate user location, used to localize search results */
|
|
79
|
+
userLocation?: {
|
|
80
|
+
type?: "approximate";
|
|
81
|
+
city?: string;
|
|
82
|
+
region?: string;
|
|
83
|
+
country?: string;
|
|
84
|
+
timezone?: string;
|
|
85
|
+
};
|
|
86
|
+
/** How much of the web page to feed back into context (higher = more thorough, more tokens) */
|
|
87
|
+
searchContextSize?: "low" | "medium" | "high";
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* OpenAI's server-side web search tool for the Responses API.
|
|
91
|
+
* The model decides when to search; results are fetched and processed by OpenAI.
|
|
92
|
+
*/
|
|
93
|
+
export declare function openAiWebSearchTool(options?: OpenAiWebSearchToolOptions): BuiltInTool;
|
|
94
|
+
/**
|
|
95
|
+
* OpenAI's server-side file search tool — retrieves from vector stores you've
|
|
96
|
+
* already uploaded files to.
|
|
97
|
+
* @see https://developers.openai.com/api/docs/guides/tools-file-search
|
|
98
|
+
*/
|
|
99
|
+
export declare function openAiFileSearchTool(vectorStoreIds: string[], options?: {
|
|
100
|
+
maxNumResults?: number;
|
|
101
|
+
}): BuiltInTool;
|
|
102
|
+
/**
|
|
103
|
+
* OpenAI's server-side code interpreter tool — runs Python in a sandboxed container.
|
|
104
|
+
* Defaults to `container: { type: "auto" }`, which OpenAI provisions automatically
|
|
105
|
+
* and reuses across a conversation's follow-up requests.
|
|
106
|
+
* @see https://developers.openai.com/api/docs/guides/tools-code-interpreter
|
|
107
|
+
*/
|
|
108
|
+
export declare function openAiCodeInterpreterTool(containerId?: string): BuiltInTool;
|
|
109
|
+
/**
|
|
110
|
+
* Options for OpenRouter's web search server tool (`openrouter:web_search`).
|
|
111
|
+
* @see https://openrouter.ai/docs/guides/features/server-tools/web-search
|
|
112
|
+
*/
|
|
113
|
+
export interface OpenRouterWebSearchToolOptions {
|
|
114
|
+
maxResults?: number;
|
|
115
|
+
maxTotalResults?: number;
|
|
116
|
+
searchContextSize?: "low" | "medium" | "high";
|
|
117
|
+
allowedDomains?: string[];
|
|
118
|
+
excludedDomains?: string[];
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* OpenRouter's server-side web search tool — works identically across every
|
|
122
|
+
* tool-calling model OpenRouter fronts, unlike each upstream provider's own
|
|
123
|
+
* (differently-shaped) web search tool.
|
|
124
|
+
*/
|
|
125
|
+
export declare function openRouterWebSearchTool(options?: OpenRouterWebSearchToolOptions): BuiltInTool;
|
|
126
|
+
/**
|
|
127
|
+
* OpenRouter's server-side web fetch tool (`openrouter:web_fetch`) — retrieves
|
|
128
|
+
* and renders a specific URL, as opposed to searching.
|
|
129
|
+
* @see https://openrouter.ai/docs/guides/features/server-tools/overview
|
|
130
|
+
*/
|
|
131
|
+
export declare function openRouterWebFetchTool(): BuiltInTool;
|
|
66
132
|
/**
|
|
67
133
|
* Define an arbitrary provider-defined / built-in tool by its raw definition.
|
|
68
134
|
* Use this to pass through tools not covered by the helpers above (or for
|
|
@@ -3,6 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.webSearchTool = webSearchTool;
|
|
4
4
|
exports.bashTool = bashTool;
|
|
5
5
|
exports.textEditorTool = textEditorTool;
|
|
6
|
+
exports.openAiWebSearchTool = openAiWebSearchTool;
|
|
7
|
+
exports.openAiFileSearchTool = openAiFileSearchTool;
|
|
8
|
+
exports.openAiCodeInterpreterTool = openAiCodeInterpreterTool;
|
|
9
|
+
exports.openRouterWebSearchTool = openRouterWebSearchTool;
|
|
10
|
+
exports.openRouterWebFetchTool = openRouterWebFetchTool;
|
|
6
11
|
exports.builtInTool = builtInTool;
|
|
7
12
|
/**
|
|
8
13
|
* Anthropic's server-side web search tool.
|
|
@@ -42,6 +47,76 @@ function textEditorTool(version = "20250728") {
|
|
|
42
47
|
};
|
|
43
48
|
return { type: `text_editor_${version}`, name: names[version] };
|
|
44
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* OpenAI's server-side web search tool for the Responses API.
|
|
52
|
+
* The model decides when to search; results are fetched and processed by OpenAI.
|
|
53
|
+
*/
|
|
54
|
+
function openAiWebSearchTool(options = {}) {
|
|
55
|
+
const tool = { type: "web_search" };
|
|
56
|
+
if (options.allowedDomains || options.blockedDomains) {
|
|
57
|
+
tool.filters = {
|
|
58
|
+
...(options.allowedDomains ? { allowed_domains: options.allowedDomains } : {}),
|
|
59
|
+
...(options.blockedDomains ? { blocked_domains: options.blockedDomains } : {}),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if (options.userLocation) {
|
|
63
|
+
tool.user_location = { type: "approximate", ...options.userLocation };
|
|
64
|
+
}
|
|
65
|
+
if (options.searchContextSize) {
|
|
66
|
+
tool.search_context_size = options.searchContextSize;
|
|
67
|
+
}
|
|
68
|
+
return tool;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* OpenAI's server-side file search tool — retrieves from vector stores you've
|
|
72
|
+
* already uploaded files to.
|
|
73
|
+
* @see https://developers.openai.com/api/docs/guides/tools-file-search
|
|
74
|
+
*/
|
|
75
|
+
function openAiFileSearchTool(vectorStoreIds, options = {}) {
|
|
76
|
+
const tool = { type: "file_search", vector_store_ids: vectorStoreIds };
|
|
77
|
+
if (options.maxNumResults !== undefined)
|
|
78
|
+
tool.max_num_results = options.maxNumResults;
|
|
79
|
+
return tool;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* OpenAI's server-side code interpreter tool — runs Python in a sandboxed container.
|
|
83
|
+
* Defaults to `container: { type: "auto" }`, which OpenAI provisions automatically
|
|
84
|
+
* and reuses across a conversation's follow-up requests.
|
|
85
|
+
* @see https://developers.openai.com/api/docs/guides/tools-code-interpreter
|
|
86
|
+
*/
|
|
87
|
+
function openAiCodeInterpreterTool(containerId) {
|
|
88
|
+
return {
|
|
89
|
+
type: "code_interpreter",
|
|
90
|
+
container: containerId ?? { type: "auto" },
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* OpenRouter's server-side web search tool — works identically across every
|
|
95
|
+
* tool-calling model OpenRouter fronts, unlike each upstream provider's own
|
|
96
|
+
* (differently-shaped) web search tool.
|
|
97
|
+
*/
|
|
98
|
+
function openRouterWebSearchTool(options = {}) {
|
|
99
|
+
const tool = { type: "openrouter:web_search" };
|
|
100
|
+
if (options.maxResults !== undefined)
|
|
101
|
+
tool.max_results = options.maxResults;
|
|
102
|
+
if (options.maxTotalResults !== undefined)
|
|
103
|
+
tool.max_total_results = options.maxTotalResults;
|
|
104
|
+
if (options.searchContextSize)
|
|
105
|
+
tool.search_context_size = options.searchContextSize;
|
|
106
|
+
if (options.allowedDomains)
|
|
107
|
+
tool.allowed_domains = options.allowedDomains;
|
|
108
|
+
if (options.excludedDomains)
|
|
109
|
+
tool.excluded_domains = options.excludedDomains;
|
|
110
|
+
return tool;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* OpenRouter's server-side web fetch tool (`openrouter:web_fetch`) — retrieves
|
|
114
|
+
* and renders a specific URL, as opposed to searching.
|
|
115
|
+
* @see https://openrouter.ai/docs/guides/features/server-tools/overview
|
|
116
|
+
*/
|
|
117
|
+
function openRouterWebFetchTool() {
|
|
118
|
+
return { type: "openrouter:web_fetch" };
|
|
119
|
+
}
|
|
45
120
|
/**
|
|
46
121
|
* Define an arbitrary provider-defined / built-in tool by its raw definition.
|
|
47
122
|
* Use this to pass through tools not covered by the helpers above (or for
|