toolpack-sdk 3.4.0 → 3.6.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Toolpack SDK
2
2
 
3
- The TypeScript SDK for building production AI agents — 100+ built-in tools, 8 channel integrations, a persistent cognitive layer, and full Knowledge/RAG, all in one package.
3
+ The TypeScript SDK for building production AI agents — 100+ built-in tools, 9 channel integrations, a persistent cognitive layer, and full Knowledge/RAG, all in one package.
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/toolpack-sdk.svg)](https://www.npmjs.com/package/toolpack-sdk)
6
6
  [![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
@@ -206,7 +206,7 @@ const sdk = await Toolpack.init({
206
206
  ```
207
207
 
208
208
  See `docs/MCP_INTEGRATION.md` and `docs/examples/mcp-integration-example.ts` for full instructions and best practices.
209
- - **Gemini**: Uses synthetic tool call IDs (`gemini_<timestamp>_<random>`) since the Gemini API doesn't return tool call IDs natively. Tool results are converted to `functionResponse` parts in chat history automatically. API key read from `GOOGLE_GENERATIVE_AI_KEY` or `TOOLPACK_GEMINI_KEY`.
209
+ - **Gemini**: Uses synthetic tool call IDs (`gemini_<timestamp>_<random>`) since the Gemini API doesn't return tool call IDs natively. Tool results are converted to `functionResponse` parts in chat history automatically. API key read from `GEMINI_API_KEY` or `TOOLPACK_GEMINI_KEY`.
210
210
  - **Ollama**: Auto-discovers all locally pulled models when registered as `{ ollama: {} }`. Uses `/api/show` and tool probing to detect capabilities (tool calling, vision, embeddings) per model. Models without tool support are automatically stripped of tools and given a system instruction to prevent hallucinated tool usage. Uses synthetic tool call IDs (`ollama_<timestamp>_<random>`). Embeddings use the modern `/api/embed` batch endpoint. Legacy per-model registration (`{ 'ollama-llama3': {} }`) is also supported.
211
211
  - **OpenRouter**: Routes requests to any of the 300+ models available on [openrouter.ai](https://openrouter.ai) via an OpenAI-compatible API. Models are discovered dynamically from the `/models` endpoint. Tool calling is fully supported; models that reject `tool_choice: 'none'` have tools stripped gracefully instead. No embeddings support. Optional `siteUrl` and `siteName` config for OpenRouter's attribution leaderboard. API key read from `OPENROUTER_API_KEY` or `TOOLPACK_OPENROUTER_KEY`.
212
212
 
@@ -594,6 +594,44 @@ execute: async (args, ctx) => {
594
594
 
595
595
  When one instance serves several people, pass a function (read on every tool call), for example `actor: () => requestStore.getStore() ?? null`.
596
596
 
597
+ ### Stopping a request
598
+
599
+ Pass an `AbortSignal` as `signal` on a request. A stop takes effect at once, also in the middle of a provider call, a rate limit wait, or a tool.
600
+
601
+ ```typescript
602
+ const controller = new AbortController();
603
+ stopButton.onclick = () => controller.abort(); // or a timeout, a newer message
604
+
605
+ for await (const chunk of sdk.stream({ model, messages, signal: controller.signal })) {
606
+ if (chunk.finish_reason === 'aborted') break; // stopped: what arrived before is kept
607
+ process.stdout.write(chunk.delta);
608
+ }
609
+ ```
610
+
611
+ - `stream()` ends without throwing; its last chunk has `finish_reason: 'aborted'`
612
+ - `generate()` rejects with an `AbortedError` (`name` is `'AbortError'`, exported from the package root)
613
+ - Tools that have not started are not run. A tool can read `ctx.signal` to end its own long work early, for example `fetch(url, { signal: ctx.signal })`
614
+
615
+ ### Stopping or changing a tool call
616
+
617
+ Pass `interceptTool` on a request to wrap every tool call of that request (request, mode and registry tools, and `tool.search`). Call `run()` to run the tool and use or change its result, or return text without calling it to stop the call: the model then sees that text as the tool's result.
618
+
619
+ ```typescript
620
+ import type { ToolInterceptor } from 'toolpack-sdk';
621
+
622
+ const interceptTool: ToolInterceptor = async (call, run) => {
623
+ // call: { toolName, args, round }
624
+ if (call.toolName === 'fs.delete_file') return 'Deleting files is not allowed here.'; // not run
625
+ return run();
626
+ };
627
+
628
+ const response = await sdk.generate({ model, messages, interceptTool });
629
+ ```
630
+
631
+ - The tool's `tool:started`, `tool:completed` and log events are sent only when `run()` is called
632
+ - After a stop (`signal`), the interceptor is not asked and no tool is started
633
+ - `interceptTool` is never sent to the provider
634
+
597
635
  ### Returning files from tools
598
636
 
599
637
  A tool can return a file by URL with `{ "type": "file", "mimeType": "application/pdf", "url": "https://..." }`. Anthropic and Vertex AI receive it as a native file part, and OpenAI receives images (other files get a placeholder). `data:` URIs keep working as before.
@@ -1132,7 +1170,7 @@ A data URI (`data:<mime>;base64,<data>`) is also accepted in `file.url` for inli
1132
1170
  # Provider API keys (at least one required)
1133
1171
  export OPENAI_API_KEY="sk-..."
1134
1172
  export ANTHROPIC_API_KEY="sk-ant-..."
1135
- export GOOGLE_GENERATIVE_AI_KEY="AIza..."
1173
+ export GEMINI_API_KEY="AIza..."
1136
1174
  export OPENROUTER_API_KEY="sk-or-..."
1137
1175
 
1138
1176
  # SDK logging (override programmatic config)
@@ -1327,7 +1365,9 @@ interface CompletionRequest {
1327
1365
  max_tokens?: number;
1328
1366
  tools?: ToolCallRequest[];
1329
1367
  requestTools?: RequestToolDefinition[]; // Request-scoped tools
1368
+ interceptTool?: ToolInterceptor; // Wraps every tool call: stop it or change its result
1330
1369
  tool_choice?: 'auto' | 'none' | 'required';
1370
+ signal?: AbortSignal; // Stops the request
1331
1371
  }
1332
1372
 
1333
1373
  interface CompletionResponse {
@@ -1340,7 +1380,7 @@ interface CompletionResponse {
1340
1380
  interface CompletionChunk {
1341
1381
  delta: string;
1342
1382
  usage?: Usage;
1343
- finish_reason?: 'stop' | 'length' | 'tool_calls' | 'content_filter' | 'error';
1383
+ finish_reason?: 'stop' | 'length' | 'tool_calls' | 'content_filter' | 'error' | 'aborted'; // 'aborted': stopped by the request's signal
1344
1384
  tool_calls?: ToolCallResult[];
1345
1385
  }
1346
1386