@agentionai/agents 1.8.0 → 1.10.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.
@@ -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 — web search, file parsing, context
216
- * compression, moderation. Passed through untouched; see
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
@@ -99,6 +99,18 @@ export declare class LlamaCppAgent extends OpenAICompatibleAgent {
99
99
  * included, is on `raw`.
100
100
  */
101
101
  listModels(): Promise<ModelInfo<LlamaCppModelCard>[]>;
102
+ /**
103
+ * Tells the server to end the model's reasoning phase early, mid-stream,
104
+ * via llama.cpp's proprietary `/chat/completions/control` endpoint. Useful
105
+ * for cutting off a model that is thinking for too long without waiting
106
+ * for it to decide to stop on its own.
107
+ *
108
+ * A no-op if no streamed completion is in flight yet (`lastChunkId` unset).
109
+ * Best-effort: a failed request is logged (when `debug` is on) rather than
110
+ * thrown, since this is a side channel to a turn that should otherwise
111
+ * proceed normally.
112
+ */
113
+ skipReasoning(): Promise<void>;
102
114
  }
103
115
  export {};
104
116
  //# sourceMappingURL=LlamaCppAgent.d.ts.map
@@ -68,6 +68,36 @@ class LlamaCppAgent extends OpenAICompatibleAgent_1.OpenAICompatibleAgent {
68
68
  },
69
69
  }));
70
70
  }
71
+ /**
72
+ * Tells the server to end the model's reasoning phase early, mid-stream,
73
+ * via llama.cpp's proprietary `/chat/completions/control` endpoint. Useful
74
+ * for cutting off a model that is thinking for too long without waiting
75
+ * for it to decide to stop on its own.
76
+ *
77
+ * A no-op if no streamed completion is in flight yet (`lastChunkId` unset).
78
+ * Best-effort: a failed request is logged (when `debug` is on) rather than
79
+ * thrown, since this is a side channel to a turn that should otherwise
80
+ * proceed normally.
81
+ */
82
+ async skipReasoning() {
83
+ if (!this.lastChunkId)
84
+ return;
85
+ try {
86
+ await fetch(`${this.config.baseURL}/chat/completions/control`, {
87
+ method: "POST",
88
+ headers: { "Content-Type": "application/json" },
89
+ body: JSON.stringify({
90
+ action: "reasoning_end",
91
+ id: this.lastChunkId,
92
+ }),
93
+ });
94
+ }
95
+ catch (error) {
96
+ if (this.debug) {
97
+ console.error(`Failed to signal reasoning_end to ${this.getVendorName()}: ${error instanceof Error ? error.message : "Unknown error"}`);
98
+ }
99
+ }
100
+ }
71
101
  }
72
102
  exports.LlamaCppAgent = LlamaCppAgent;
73
103
  //# sourceMappingURL=LlamaCppAgent.js.map
@@ -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.getToolDefinitions(),
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.getToolDefinitions(),
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.getToolDefinitions(),
530
+ tools: this.getAllToolDefinitions(),
515
531
  store: false,
516
532
  stream: true,
517
533
  temperature: this.config.temperature,
@@ -35,6 +35,20 @@ export declare abstract class OpenAICompatibleAgent extends BaseAgent {
35
35
  protected config: Partial<OpenAICompatibleConfig>;
36
36
  private vizEventId?;
37
37
  private currentToolCallCount;
38
+ /**
39
+ * The `id` of the most recently seen streamed `ChatCompletionChunk`
40
+ * (`chatcmpl-...`). Internal only — some servers key control-plane calls
41
+ * (e.g. llama.cpp's `/chat/completions/control`) off the in-flight
42
+ * completion's id, so it needs to be captured somewhere subclasses can
43
+ * reach it, but it isn't part of the public `StreamChunk` shape.
44
+ */
45
+ protected lastChunkId?: string;
46
+ /**
47
+ * Whether this server accepts a replayed `reasoning_content` field on an
48
+ * assistant message. `undefined` until proven otherwise — see
49
+ * {@link withReasoningReplayFallback}.
50
+ */
51
+ private reasoningReplaySupported?;
38
52
  constructor(config: OpenAICompatibleConfig & {
39
53
  vendor: AgentVendor;
40
54
  }, history?: History);
@@ -53,6 +67,22 @@ export declare abstract class OpenAICompatibleAgent extends BaseAgent {
53
67
  protected process(_input: string): Promise<string>;
54
68
  execute(input: string | MessageContent[], options?: ExecuteOptions): Promise<string>;
55
69
  private callProvider;
70
+ /**
71
+ * Some OpenAI-compatible servers (Cerebras, at least as of 2026-08) reject
72
+ * any message carrying `reasoning_content` with a plain 400 — no per-field
73
+ * detail worth parsing, and other servers *require* the field (DeepSeek's
74
+ * thinking mode), so it can't just be dropped unconditionally either.
75
+ *
76
+ * Runs `request` normally first. On a 400 that could plausibly be caused by
77
+ * a replayed reasoning field, retries once with it stripped; if that
78
+ * succeeds, remembers the result so every later call in this agent's
79
+ * lifetime skips straight to the working shape instead of paying for the
80
+ * failed attempt again. If the retry also fails, the original error is
81
+ * what surfaces — it's more likely to point at the real problem.
82
+ */
83
+ private withReasoningReplayFallback;
84
+ /** Whether any assistant turn in history carries reasoning that would be replayed. */
85
+ private hasReplayableReasoning;
56
86
  protected handleResponse(response: ChatCompletion, options?: ExecuteOptions): Promise<string>;
57
87
  private handleToolCalls;
58
88
  /**
@@ -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();
@@ -360,6 +401,8 @@ class OpenAICompatibleAgent extends BaseAgent_1.BaseAgent {
360
401
  // taking the last one covers both layouts without double-counting.
361
402
  if (chunk.usage)
362
403
  streamUsage = chunk.usage;
404
+ if (chunk.id)
405
+ this.lastChunkId = chunk.id;
363
406
  if (chunk.choices.length === 0)
364
407
  continue;
365
408
  const choice = chunk.choices[0];
@@ -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 tools = this.tools.size > 0 ? this.getToolDefinitions() : undefined;
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[]): ChatCompletionMessage[];
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). They carry no `execute` function or input schema; the
7
- * agent simply forwards their definition to the provider's API.
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
- * and `name` are required, any other provider-specific fields are allowed:
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 Anthropic tools.
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: string;
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
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@agentionai/agents",
3
3
  "author": "Laurent Zuijdwijk",
4
- "version": "1.8.0",
4
+ "version": "1.10.0",
5
5
  "description": "Agent Library",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",