zidane 2.2.0 → 2.2.2
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 +146 -12
- package/dist/{agent-vPBFXnu-.d.ts → agent-C0hLXofc.d.ts} +100 -4
- package/dist/{chunk-S3FCOMRI.js → chunk-CYWF2U62.js} +45 -3
- package/dist/{chunk-37GD7NL3.js → chunk-DRAYZZ23.js} +168 -106
- package/dist/{chunk-SP5NA6WF.js → chunk-MDVZX6GM.js} +1 -1
- package/dist/{chunk-F5UBXERT.js → chunk-O2XZLJMG.js} +51 -9
- package/dist/{chunk-CDRXC7A7.js → chunk-ZSEMKVHP.js} +55 -2
- package/dist/index.d.ts +4 -4
- package/dist/index.js +5 -5
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +1 -1
- package/dist/presets.d.ts +2 -2
- package/dist/presets.js +3 -3
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +2 -2
- package/dist/session/sqlite.d.ts +1 -1
- package/dist/session.d.ts +1 -1
- package/dist/session.js +1 -1
- package/dist/{skills-use-39cCsA7_.d.ts → skills-use-CvRJ1Qe3.d.ts} +1 -1
- package/dist/skills.d.ts +2 -2
- package/dist/{spawn-Czx3owjX.d.ts → spawn-CT0ivxxH.d.ts} +1 -1
- package/dist/tools.d.ts +4 -4
- package/dist/tools.js +2 -2
- package/dist/types.d.ts +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,7 +4,29 @@
|
|
|
4
4
|
|
|
5
5
|
An agent that goes straight to the goal.
|
|
6
6
|
|
|
7
|
-
Minimal TypeScript agent loop built with [Bun](https://bun.sh).
|
|
7
|
+
Minimal TypeScript agent loop built with [Bun](https://bun.sh).
|
|
8
|
+
|
|
9
|
+
Hook into every step using [hookable](https://github.com/unjs/hookable).
|
|
10
|
+
|
|
11
|
+
Built to be embedded.
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- 🧠 **Multi-provider** — Anthropic, OpenAI Codex, OpenRouter, Cerebras, plus a generic `openaiCompat` factory (Baseten, Fireworks, Groq, local servers). OAuth + API-key auth, auto-refreshing tokens.
|
|
16
|
+
- 🔁 **Streaming turn loop** — stream text + thinking deltas, tool calls, and tool results with hookable events at every step.
|
|
17
|
+
- 🛠 **Tools first-class** — shell, file IO, glob, spawn, human-in-the-loop, plus any [MCP](https://modelcontextprotocol.io) server. Sequential or parallel execution, per-call gates, typed hooks.
|
|
18
|
+
- 🧩 **[Agent Skills](https://agentskills.io/specification) spec-aligned** — discover, activate, and run skills with `allowed-tools` enforcement and session-resume rehydration.
|
|
19
|
+
- 💾 **Pluggable sessions** — in-memory, SQLite, remote HTTP, or a file-map adapter. Turns persist incrementally — a crash leaves valid partial history.
|
|
20
|
+
- 🖼 **Multimodal** — images + documents via `PromptPart[]`; tools can return image blocks (screenshots, diagrams) routed natively on vision providers and via companion messages elsewhere.
|
|
21
|
+
- 🧠 **Extended thinking** — named levels (`off` / `minimal` / `low` / `medium` / `high`) or exact token budgets; traces streamed + persisted.
|
|
22
|
+
- ⚡ **Prompt caching** — auto-injected `cache_control` breakpoints on Anthropic + OpenRouter routes; cache-read / cache-write surfaced on `TurnUsage`.
|
|
23
|
+
- 🚀 **Parallel MCP bootstrap** — every server connects concurrently with per-server timeouts; `agent.warmup()` + `eager: true` hide cold-start latency.
|
|
24
|
+
- 🎯 **Structured output** — force the final answer to match a JSON Schema (Zod v4 interop), no brittle parsing.
|
|
25
|
+
- 🧵 **Sub-agent spawning** — delegate to child agents with inherited or overridden preset; child stream/tool events bubble to the parent.
|
|
26
|
+
- 🧭 **Typed errors** — `AgentContextExceededError` / `AgentProviderError` / `AgentAbortedError` instead of sniffing error strings.
|
|
27
|
+
- 🔌 **Execution contexts** — run tools in-process, in Docker, or in a remote sandbox (E2B / Rivet / any `SandboxProvider`).
|
|
28
|
+
- 🪝 **Hookable everything** — ~40 typed hook events covering turn, stream, tool, MCP, session, skills, spawn, OAuth refresh, and bootstrap timing.
|
|
29
|
+
- 🧪 **915+ tests, zero API keys** — mock providers + mock execution contexts; suite runs in under 2 seconds.
|
|
8
30
|
|
|
9
31
|
## Quickstart
|
|
10
32
|
|
|
@@ -47,9 +69,11 @@ createAgent({
|
|
|
47
69
|
maxTurns: 50, // max loop iterations
|
|
48
70
|
maxTokens: 16384, // max tokens per LLM response
|
|
49
71
|
thinkingBudget: 10240, // exact thinking token budget
|
|
72
|
+
cache: true, // prompt-cache breakpoints on supported providers (default: true)
|
|
50
73
|
},
|
|
51
74
|
execution: createProcessContext(), // where tools run
|
|
52
75
|
mcpServers: [], // MCP tool servers
|
|
76
|
+
eager: true, // pre-warm MCP bootstrap in the background (default: false)
|
|
53
77
|
skills: {}, // skills configuration
|
|
54
78
|
})
|
|
55
79
|
```
|
|
@@ -148,6 +172,39 @@ cerebras({ apiKey: 'csk-...', defaultModel: 'zai-glm-4.7' })
|
|
|
148
172
|
|
|
149
173
|
Fallback: `params.apiKey` > `CEREBRAS_API_KEY` env
|
|
150
174
|
|
|
175
|
+
### OpenAI-compatible (custom endpoints)
|
|
176
|
+
|
|
177
|
+
Any OpenAI Chat Completions endpoint — Baseten, Fireworks, Groq, local LM servers, corporate proxies:
|
|
178
|
+
|
|
179
|
+
```ts
|
|
180
|
+
import { openaiCompat } from 'zidane/providers'
|
|
181
|
+
|
|
182
|
+
openaiCompat({
|
|
183
|
+
name: 'baseten',
|
|
184
|
+
apiKey: process.env.BASETEN_API_KEY!,
|
|
185
|
+
baseURL: process.env.BASETEN_PROXY_URL!,
|
|
186
|
+
authHeader: { name: 'Authorization', scheme: 'Api-Key' }, // vendor-specific scheme
|
|
187
|
+
capabilities: { vision: false, imageInToolResult: false },
|
|
188
|
+
cacheBreakpoints: false, // set true only for endpoints that honor `cache_control`
|
|
189
|
+
})
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
`openrouter` and `cerebras` are thin wrappers around this factory with vendor defaults pinned. Reach for `openaiCompat` directly when adding a new backend instead of forking a bespoke provider.
|
|
193
|
+
|
|
194
|
+
### Prompt caching
|
|
195
|
+
|
|
196
|
+
Enabled by default via `behavior.cache`. The provider inserts `cache_control: { type: 'ephemeral' }` markers on the three largest stable prefixes — system prompt, tool definitions, and the last message's final content block — so the shared prefix is served from cache across turns.
|
|
197
|
+
|
|
198
|
+
| Provider | Behavior |
|
|
199
|
+
|---|---|
|
|
200
|
+
| `anthropic` | Breakpoints honored natively. |
|
|
201
|
+
| `openrouter` | Breakpoints forwarded; Anthropic + Gemini routes honor them, OpenAI / DeepSeek / Grok / Groq / Moonshot routes cache automatically and ignore the markers. |
|
|
202
|
+
| `openaiCompat` | Opt-in via `cacheBreakpoints: true`. Default off so strict-schema endpoints (OpenAI direct, most OSS servers) don't reject unknown fields. |
|
|
203
|
+
| `cerebras` | Off (factory doesn't enable breakpoints). |
|
|
204
|
+
| `openai` (Codex) | Not affected — separate wire format (pi-ai). |
|
|
205
|
+
|
|
206
|
+
Cache hits + writes land on `TurnUsage.cacheRead` / `TurnUsage.cacheCreation` and are surfaced via the `usage` hook.
|
|
207
|
+
|
|
151
208
|
## Presets
|
|
152
209
|
|
|
153
210
|
Reusable slices of `AgentOptions` — spread them into `createAgent()`.
|
|
@@ -157,11 +214,13 @@ The `basic` preset bundles:
|
|
|
157
214
|
| Tool | Description |
|
|
158
215
|
|---|---|
|
|
159
216
|
| `shell` | Execute shell commands |
|
|
160
|
-
| `
|
|
161
|
-
| `
|
|
162
|
-
| `
|
|
217
|
+
| `readFile` | Read file contents |
|
|
218
|
+
| `writeFile` | Write/create files |
|
|
219
|
+
| `listFiles` | List directory contents |
|
|
163
220
|
| `spawn` | Spawn a sub-agent |
|
|
164
221
|
|
|
222
|
+
Extra tools live alongside: `glob` (pattern-based file matching), `createInteractionTool` (human-in-the-loop factory), and the three `skills_use` / `skills_read` / `skills_run_script` tools that auto-inject when the skills catalog is non-empty.
|
|
223
|
+
|
|
165
224
|
Define a custom preset:
|
|
166
225
|
|
|
167
226
|
```ts
|
|
@@ -395,13 +454,17 @@ Turns are persisted incrementally after each turn — not as a full save. If the
|
|
|
395
454
|
### Storage backends
|
|
396
455
|
|
|
397
456
|
```ts
|
|
398
|
-
import { createMemoryStore,
|
|
457
|
+
import { createMemoryStore, createRemoteStore, createFileMapStore } from 'zidane/session'
|
|
458
|
+
import { createSqliteStore } from 'zidane/session/sqlite' // separate subpath (Bun-only)
|
|
399
459
|
|
|
400
460
|
createMemoryStore() // in-memory, no persistence
|
|
401
|
-
createSqliteStore({ path: './sessions.db' }) // SQLite
|
|
461
|
+
createSqliteStore({ path: './sessions.db' }) // SQLite via bun:sqlite — WAL mode, per-turn flush
|
|
402
462
|
createRemoteStore({ url: 'https://api.example.com' }) // HTTP REST API
|
|
463
|
+
createFileMapStore(hostAdapter) // bridge to any { get, save, delete } file-map backend
|
|
403
464
|
```
|
|
404
465
|
|
|
466
|
+
`createSqliteStore` lives on its own subpath because it depends on `bun:sqlite`. Non-Bun consumers importing from `zidane` or `zidane/session` never evaluate that module.
|
|
467
|
+
|
|
405
468
|
### Restoring a session
|
|
406
469
|
|
|
407
470
|
```ts
|
|
@@ -431,13 +494,47 @@ const agent = createAgent({
|
|
|
431
494
|
...basic,
|
|
432
495
|
provider,
|
|
433
496
|
mcpServers: [
|
|
434
|
-
{ name: 'fs', transport: 'stdio', command: 'npx', args: ['-y', '@modelcontextprotocol/server-filesystem', '.'] },
|
|
497
|
+
{ name: 'fs', transport: 'stdio', command: 'npx', args: ['-y', '@modelcontextprotocol/server-filesystem', '.'], bootstrapTimeout: 10_000 },
|
|
435
498
|
{ name: 'api', transport: 'streamable-http', url: 'http://localhost:3002/mcp' },
|
|
436
499
|
],
|
|
437
500
|
})
|
|
438
501
|
```
|
|
439
502
|
|
|
440
503
|
MCP servers can live on a preset too (they're just `AgentOptions` fields). Connections are lazy (first `run()`) and reused.
|
|
504
|
+
Set `bootstrapTimeout` to cap how long a slow `connect + listTools` phase can delay the first model request.
|
|
505
|
+
|
|
506
|
+
### Hiding bootstrap latency
|
|
507
|
+
|
|
508
|
+
Every server is bootstrapped in parallel, but the first `run()` still waits for the slowest one. Two knobs to hide the cost:
|
|
509
|
+
|
|
510
|
+
```ts
|
|
511
|
+
// Option 1 — pre-warm manually behind other setup work.
|
|
512
|
+
const agent = createAgent({ provider, mcpServers })
|
|
513
|
+
await Promise.all([agent.warmup(), authenticate(), loadConfig()])
|
|
514
|
+
await agent.run({ prompt: 'go' }) // no MCP wait here
|
|
515
|
+
|
|
516
|
+
// Option 2 — let createAgent kick the warmup off for you.
|
|
517
|
+
const agent = createAgent({ provider, mcpServers, eager: true })
|
|
518
|
+
// ... unrelated startup work ...
|
|
519
|
+
await agent.run({ prompt: 'go' }) // awaits the in-flight warmup
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
`warmup()` is idempotent and safe to call from multiple callers concurrently. Failures are surfaced on the next `warmup()` / `run()` rather than crashing the eager kickoff.
|
|
523
|
+
|
|
524
|
+
### Observability
|
|
525
|
+
|
|
526
|
+
Two hooks fire around each per-server bootstrap, regardless of success:
|
|
527
|
+
|
|
528
|
+
```ts
|
|
529
|
+
agent.hooks.hook('mcp:bootstrap:start', ({ name, transport }) => { /* ... */ })
|
|
530
|
+
agent.hooks.hook('mcp:bootstrap:end', (ctx) => {
|
|
531
|
+
// ctx.name, ctx.transport, ctx.durationMs
|
|
532
|
+
// ctx.ok === true → ctx.toolCount
|
|
533
|
+
// ctx.ok === false → ctx.error
|
|
534
|
+
})
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
Use these to attribute cold-start latency per server — the only way to know if a specific MCP (e.g. a remote GitHub MCP) is the one stretching your first `run()`.
|
|
441
538
|
|
|
442
539
|
## Skills
|
|
443
540
|
|
|
@@ -541,6 +638,7 @@ agent.isRunning // is a run in progress?
|
|
|
541
638
|
agent.turns // conversation history (SessionTurn[])
|
|
542
639
|
agent.abort() // cancel the current run
|
|
543
640
|
agent.reset() // clear messages and queues
|
|
641
|
+
await agent.warmup() // pre-connect MCP (idempotent, safe to call concurrently)
|
|
544
642
|
await agent.destroy() // clean up context + MCP connections
|
|
545
643
|
await agent.waitForIdle() // wait for current run to complete
|
|
546
644
|
```
|
|
@@ -554,8 +652,12 @@ type SessionContentBlock =
|
|
|
554
652
|
| { type: 'text', text: string }
|
|
555
653
|
| { type: 'image', mediaType: string, data: string }
|
|
556
654
|
| { type: 'tool_call', id: string, name: string, input: Record<string, unknown> }
|
|
557
|
-
| { type: 'tool_result', callId: string, output: string, isError?: boolean }
|
|
558
|
-
| { type: 'thinking', text: string }
|
|
655
|
+
| { type: 'tool_result', callId: string, output: string | ToolResultContent[], isError?: boolean }
|
|
656
|
+
| { type: 'thinking', text: string, signature?: string }
|
|
657
|
+
|
|
658
|
+
type ToolResultContent =
|
|
659
|
+
| { type: 'text', text: string }
|
|
660
|
+
| { type: 'image', mediaType: string, data: string }
|
|
559
661
|
|
|
560
662
|
interface SessionMessage {
|
|
561
663
|
role: 'user' | 'assistant'
|
|
@@ -563,12 +665,39 @@ interface SessionMessage {
|
|
|
563
665
|
}
|
|
564
666
|
```
|
|
565
667
|
|
|
668
|
+
Tool results can carry structured content — pure-text tools keep returning a `string`, tools that produce images (MCP browser servers, screenshot tools) return a `ToolResultContent[]` that the loop routes natively on providers with `imageInToolResult: true` and via a companion user message elsewhere. Use `toolResultToText(output)` to flatten when a consumer only handles strings.
|
|
669
|
+
|
|
566
670
|
Converters for external interop:
|
|
567
671
|
|
|
568
672
|
```ts
|
|
569
673
|
import { fromAnthropic, toAnthropic, fromOpenAI, toOpenAI, autoDetectAndConvert } from 'zidane'
|
|
570
674
|
```
|
|
571
675
|
|
|
676
|
+
## Typed Errors
|
|
677
|
+
|
|
678
|
+
Provider failures are wrapped into typed error classes before leaving `agent.run()` — match on `instanceof` instead of sniffing strings.
|
|
679
|
+
|
|
680
|
+
```ts
|
|
681
|
+
import { AgentAbortedError, AgentContextExceededError, AgentProviderError } from 'zidane'
|
|
682
|
+
|
|
683
|
+
try {
|
|
684
|
+
await agent.run({ prompt })
|
|
685
|
+
}
|
|
686
|
+
catch (err) {
|
|
687
|
+
if (err instanceof AgentContextExceededError) {
|
|
688
|
+
// prune history, retry
|
|
689
|
+
}
|
|
690
|
+
else if (err instanceof AgentAbortedError) {
|
|
691
|
+
// user cancelled
|
|
692
|
+
}
|
|
693
|
+
else if (err instanceof AgentProviderError) {
|
|
694
|
+
console.error(`${err.provider}: ${err.message} (${err.providerCode})`)
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
```
|
|
698
|
+
|
|
699
|
+
Every provider ships a `classifyError(err)` that maps native errors into a `ClassifiedError` union — unrecognized errors fall through as `AgentProviderError`. Abort paths (`agent.abort()` or a triggered `AbortSignal`) always produce `AgentAbortedError` regardless of classification.
|
|
700
|
+
|
|
572
701
|
## Structured Output
|
|
573
702
|
|
|
574
703
|
Force the agent's final response to match a JSON Schema via provider-level tool forcing.
|
|
@@ -612,8 +741,9 @@ const schema = zodToJsonSchema(z.toJsonSchema(z.object({ name: z.string() })))
|
|
|
612
741
|
|
|
613
742
|
```ts
|
|
614
743
|
const stats = await agent.run({ prompt: 'hello' })
|
|
615
|
-
stats.turnUsage
|
|
616
|
-
stats.cost
|
|
744
|
+
stats.turnUsage // TurnUsage[] — per-turn { input, output, cacheCreation?, cacheRead?, thinking?, cost?, finishReason?, modelId? }
|
|
745
|
+
stats.cost // total USD cost (if reported by provider)
|
|
746
|
+
stats.timeTillFirstTokenMs // ms from run() start to the first stream/tool event
|
|
617
747
|
```
|
|
618
748
|
|
|
619
749
|
## Types
|
|
@@ -633,7 +763,11 @@ import type { ToolHookContext, McpToolHookContext, SessionHookContext, StreamHoo
|
|
|
633
763
|
bun test
|
|
634
764
|
```
|
|
635
765
|
|
|
636
|
-
|
|
766
|
+
915+ tests with mock provider and execution context. No API keys or Docker needed; the suite runs in under 2 seconds.
|
|
767
|
+
|
|
768
|
+
## Benchmarks
|
|
769
|
+
|
|
770
|
+
Harness integrations for running zidane against public agent benchmarks live in [`benchmarks/`](./benchmarks). First integration: [Terminal-Bench](./benchmarks/terminal-bench).
|
|
637
771
|
|
|
638
772
|
## License
|
|
639
773
|
|
|
@@ -153,6 +153,16 @@ interface McpServerConfig {
|
|
|
153
153
|
url?: string;
|
|
154
154
|
/** Optional headers for HTTP transports */
|
|
155
155
|
headers?: Record<string, string>;
|
|
156
|
+
/**
|
|
157
|
+
* Timeout in milliseconds for MCP server bootstrap (connect + tool discovery).
|
|
158
|
+
*
|
|
159
|
+
* Zidane connects MCP servers lazily on the first `run()`. Without a
|
|
160
|
+
* bootstrap timeout, a slow or hung server can delay the first provider call
|
|
161
|
+
* for an arbitrarily long time even when that MCP server is never used.
|
|
162
|
+
*
|
|
163
|
+
* Default: `10000`.
|
|
164
|
+
*/
|
|
165
|
+
bootstrapTimeout?: number;
|
|
156
166
|
/** Timeout in milliseconds for MCP tool calls (default: 30000) */
|
|
157
167
|
toolTimeout?: number;
|
|
158
168
|
}
|
|
@@ -166,8 +176,24 @@ interface AgentBehavior {
|
|
|
166
176
|
maxTokens?: number;
|
|
167
177
|
/** Thinking token budget — overrides the level-based default when set */
|
|
168
178
|
thinkingBudget?: number;
|
|
169
|
-
/** JSON Schema for structured output
|
|
179
|
+
/** JSON Schema for structured output enforcement */
|
|
170
180
|
schema?: Record<string, unknown>;
|
|
181
|
+
/**
|
|
182
|
+
* Enable provider prompt caching. When on (default), the provider marks the
|
|
183
|
+
* system prompt, tools, and the last stable message with cache breakpoints so
|
|
184
|
+
* the shared prefix is served from cache across turns.
|
|
185
|
+
*
|
|
186
|
+
* - Anthropic: `cache_control: { type: 'ephemeral' }` on the last `system`
|
|
187
|
+
* content part, the last tool, and the last message content part.
|
|
188
|
+
* - OpenAI-compatible / OpenRouter: same shape — honored by Anthropic-backed
|
|
189
|
+
* OpenRouter routes and by Gemini; ignored (no-op) by providers that cache
|
|
190
|
+
* automatically (OpenAI, DeepSeek, Grok, Groq, Moonshot).
|
|
191
|
+
*
|
|
192
|
+
* Usage is surfaced via `TurnUsage.cacheRead` / `TurnUsage.cacheCreation`.
|
|
193
|
+
*
|
|
194
|
+
* Default: `true`.
|
|
195
|
+
*/
|
|
196
|
+
cache?: boolean;
|
|
171
197
|
}
|
|
172
198
|
interface ImageContent {
|
|
173
199
|
type: 'image';
|
|
@@ -600,6 +626,20 @@ interface OpenAICompatParams {
|
|
|
600
626
|
* (e.g. OpenRouter vision models, Baseten image-capable deployments).
|
|
601
627
|
*/
|
|
602
628
|
capabilities?: ProviderCapabilities;
|
|
629
|
+
/**
|
|
630
|
+
* Whether this endpoint honors `cache_control: { type: 'ephemeral' }` markers
|
|
631
|
+
* on message content parts and tool definitions.
|
|
632
|
+
*
|
|
633
|
+
* - `true` — inject markers when the caller asks for caching. OpenRouter routes
|
|
634
|
+
* to Anthropic/Gemini forward the markers; routes to OpenAI/DeepSeek/
|
|
635
|
+
* Grok/Groq/Moonshot ignore them (those backends cache automatically).
|
|
636
|
+
* - `false` — never inject markers. Safe default for endpoints that strictly
|
|
637
|
+
* validate the request schema (OpenAI direct, most OSS inference
|
|
638
|
+
* servers) and would reject unknown fields.
|
|
639
|
+
*
|
|
640
|
+
* Default: `false`. The `openrouter` wrapper sets this to `true`.
|
|
641
|
+
*/
|
|
642
|
+
cacheBreakpoints?: boolean;
|
|
603
643
|
}
|
|
604
644
|
/**
|
|
605
645
|
* Factory for any OpenAI-compatible HTTP endpoint.
|
|
@@ -723,6 +763,14 @@ interface StreamOptions {
|
|
|
723
763
|
type: 'auto' | 'required' | 'tool';
|
|
724
764
|
name?: string;
|
|
725
765
|
};
|
|
766
|
+
/**
|
|
767
|
+
* Enable prompt caching on this call. When `true`, providers that support it
|
|
768
|
+
* insert `cache_control` breakpoints on the system prompt, last tool, and
|
|
769
|
+
* last stable message so the shared prefix is cached across turns.
|
|
770
|
+
*
|
|
771
|
+
* Default: `false` (providers opt callers in — the agent loop passes `true`).
|
|
772
|
+
*/
|
|
773
|
+
cache?: boolean;
|
|
726
774
|
/** Abort signal for cancellation */
|
|
727
775
|
signal?: AbortSignal;
|
|
728
776
|
}
|
|
@@ -1448,6 +1496,30 @@ interface AgentHooks {
|
|
|
1448
1496
|
'mcp:close': (ctx: {
|
|
1449
1497
|
name: string;
|
|
1450
1498
|
}) => void;
|
|
1499
|
+
/**
|
|
1500
|
+
* Fires at the start of a per-server bootstrap attempt, before any network I/O.
|
|
1501
|
+
* Pairs with `mcp:bootstrap:end` and is always emitted, regardless of outcome.
|
|
1502
|
+
*/
|
|
1503
|
+
'mcp:bootstrap:start': (ctx: {
|
|
1504
|
+
name: string;
|
|
1505
|
+
transport: string;
|
|
1506
|
+
}) => void;
|
|
1507
|
+
/**
|
|
1508
|
+
* Fires at the end of a per-server bootstrap attempt. `durationMs` spans from
|
|
1509
|
+
* the matching `mcp:bootstrap:start`. On `ok: false` carries the originating
|
|
1510
|
+
* error so consumers can log / trace without relying on a separate `mcp:error`.
|
|
1511
|
+
*/
|
|
1512
|
+
'mcp:bootstrap:end': (ctx: {
|
|
1513
|
+
name: string;
|
|
1514
|
+
transport: string;
|
|
1515
|
+
durationMs: number;
|
|
1516
|
+
} & ({
|
|
1517
|
+
ok: true;
|
|
1518
|
+
toolCount: number;
|
|
1519
|
+
} | {
|
|
1520
|
+
ok: false;
|
|
1521
|
+
error: Error;
|
|
1522
|
+
})) => void;
|
|
1451
1523
|
'mcp:tool:gate': (ctx: McpToolHookContext & {
|
|
1452
1524
|
block: boolean;
|
|
1453
1525
|
reason: string;
|
|
@@ -1535,8 +1607,21 @@ interface AgentOptions {
|
|
|
1535
1607
|
session?: Session;
|
|
1536
1608
|
/** Skills configuration */
|
|
1537
1609
|
skills?: SkillsConfig;
|
|
1538
|
-
/** @internal */
|
|
1539
|
-
|
|
1610
|
+
/** @internal Test-only override for the MCP connector. Public consumers should not rely on this. */
|
|
1611
|
+
mcpConnector?: (configs: McpServerConfig[]) => Promise<McpConnection>;
|
|
1612
|
+
/**
|
|
1613
|
+
* Pre-connect MCP servers in the background as soon as `createAgent` returns,
|
|
1614
|
+
* instead of deferring the bootstrap to the first `agent.run()`.
|
|
1615
|
+
*
|
|
1616
|
+
* Useful when MCP latency is the dominant cost of a cold start: callers that
|
|
1617
|
+
* construct the agent early (e.g. at process init) can hide the bootstrap
|
|
1618
|
+
* behind other setup work. If bootstrap fails, the error is stored and
|
|
1619
|
+
* surfaced on the first `agent.run()` / `agent.warmup()`; the in-flight
|
|
1620
|
+
* promise is `await`ed by both paths so the error is never silently lost.
|
|
1621
|
+
*
|
|
1622
|
+
* No-op when `mcpServers` is empty. Default: `false`.
|
|
1623
|
+
*/
|
|
1624
|
+
eager?: boolean;
|
|
1540
1625
|
}
|
|
1541
1626
|
interface Agent {
|
|
1542
1627
|
hooks: Hookable<AgentHooks>;
|
|
@@ -1568,6 +1653,17 @@ interface Agent {
|
|
|
1568
1653
|
* No-op when the skill wasn't active.
|
|
1569
1654
|
*/
|
|
1570
1655
|
deactivateSkill: (name: string) => Promise<void>;
|
|
1656
|
+
/**
|
|
1657
|
+
* Pre-connect MCP servers without running a turn. Idempotent and concurrency-safe:
|
|
1658
|
+
* - No MCP servers configured → resolves immediately.
|
|
1659
|
+
* - Connection already established → resolves immediately.
|
|
1660
|
+
* - Another `warmup()` / `run()` is bootstrapping → awaits the in-flight promise.
|
|
1661
|
+
*
|
|
1662
|
+
* Use from host code that wants to hide MCP bootstrap latency behind other
|
|
1663
|
+
* startup work (UI init, auth, etc.). Safe to call multiple times and from
|
|
1664
|
+
* multiple callers concurrently.
|
|
1665
|
+
*/
|
|
1666
|
+
warmup: () => Promise<void>;
|
|
1571
1667
|
readonly isRunning: boolean;
|
|
1572
1668
|
readonly turns: SessionTurn[];
|
|
1573
1669
|
readonly execution: ExecutionContext;
|
|
@@ -1577,6 +1673,6 @@ interface Agent {
|
|
|
1577
1673
|
readonly activeSkills: readonly ActiveSkill[];
|
|
1578
1674
|
meta: Record<string, unknown>;
|
|
1579
1675
|
}
|
|
1580
|
-
declare function createAgent({ provider, name: agentName, system: agentSystem, tools: agentTools, toolAliases, behavior: agentBehavior, execution, mcpServers, session, skills: agentSkills,
|
|
1676
|
+
declare function createAgent({ provider, name: agentName, system: agentSystem, tools: agentTools, toolAliases, behavior: agentBehavior, execution, mcpServers, session, skills: agentSkills, mcpConnector, eager }: AgentOptions): Agent;
|
|
1581
1677
|
|
|
1582
1678
|
export { type ToolHookContext as $, type Agent as A, type SessionData as B, CONTEXT_EXCEEDED_MESSAGE_PATTERNS as C, type SessionEndStatus as D, type SessionHookContext as E, type SessionMessage as F, type SessionRun as G, type SessionStore as H, type ImageContent as I, type SessionTurn as J, type SkillConfig as K, type SkillResource as L, type McpConnection as M, type SkillsConfig as N, type OAuthRefreshHookContext as O, type PromptDocumentPart as P, type SpawnHookContext as Q, type RemoteStoreOptions as R, type Session as S, type StreamCallbacks as T, type StreamHookContext as U, type StreamOptions as V, type ThinkingLevel as W, type ToolCall as X, type ToolContext as Y, type ToolDef as Z, type ToolExecutionMode as _, AgentAbortedError as a, type ToolMap as a0, type ToolResult as a1, type ToolResultContent as a2, type ToolResultImageContent as a3, type ToolResultTextContent as a4, type ToolSpec as a5, type TurnFinishReason as a6, type TurnResult as a7, type TurnUsage as a8, matchesContextExceeded as a9, loadSession as aA, mapOAIFinishReason as aB, normalizeMcpBlocks as aC, normalizeMcpServers as aD, openai as aE, openaiCompat as aF, openrouter as aG, resultToString as aH, toAnthropic as aI, toOpenAI as aJ, toTypedError as aK, toolResultToText as aa, type ActivationVia as ab, type ActiveSkill as ac, type DeactivationReason as ad, type FileMapAdapter as ae, type FileMapStoreOptions as af, type OpenAICompatAuthHeader as ag, OpenAICompatHttpError as ah, type OpenAICompatParams as ai, type SkillActivationState as aj, type SkillActivationStateOptions as ak, type SkillDiagnostic as al, type SkillSource as am, anthropic as an, autoDetectAndConvert as ao, cerebras as ap, classifyOpenAICompatError as aq, connectMcpServers as ar, createAgent as as, createFileMapStore as at, createMemoryStore as au, createRemoteStore as av, createSession as aw, createSkillActivationState as ax, fromAnthropic as ay, fromOpenAI as az, type AgentBehavior as b, AgentContextExceededError as c, type AgentHooks as d, type AgentOptions as e, AgentProviderError as f, type AgentRunOptions as g, type AgentStats as h, AgentToolNotAllowedError as i, type AnthropicParams as j, type CerebrasParams as k, type ChildRunStats as l, type ClassifiedError as m, type ClassifiedErrorKind as n, type CreateSessionOptions as o, type McpServerConfig as p, type McpToolHookContext as q, type OpenAIParams as r, type OpenRouterParams as s, type PromptImagePart as t, type PromptPart as u, type PromptTextPart as v, type Provider as w, type ProviderCapabilities as x, type RunHookMap as y, type SessionContentBlock as z };
|
|
@@ -84,10 +84,14 @@ async function consumeSSE(response, callbacks, signal) {
|
|
|
84
84
|
}
|
|
85
85
|
const chunkUsage = chunk.usage;
|
|
86
86
|
if (chunkUsage) {
|
|
87
|
+
const cachedRead = chunkUsage.prompt_tokens_details?.cached_tokens;
|
|
88
|
+
const cachedWrite = chunkUsage.prompt_tokens_details?.cache_creation_input_tokens ?? chunkUsage.prompt_tokens_details?.cache_write_tokens ?? chunkUsage.cache_creation_input_tokens;
|
|
87
89
|
usage = {
|
|
88
90
|
input: chunkUsage.prompt_tokens ?? 0,
|
|
89
91
|
output: chunkUsage.completion_tokens ?? 0,
|
|
90
|
-
cost: chunkUsage.total_cost ?? void 0
|
|
92
|
+
cost: chunkUsage.total_cost ?? void 0,
|
|
93
|
+
...typeof cachedRead === "number" && cachedRead > 0 ? { cacheRead: cachedRead } : {},
|
|
94
|
+
...typeof cachedWrite === "number" && cachedWrite > 0 ? { cacheCreation: cachedWrite } : {}
|
|
91
95
|
};
|
|
92
96
|
}
|
|
93
97
|
}
|
|
@@ -204,6 +208,38 @@ ${attachedMarker}` : attachedMarker;
|
|
|
204
208
|
}
|
|
205
209
|
return out;
|
|
206
210
|
}
|
|
211
|
+
var EPHEMERAL = { type: "ephemeral" };
|
|
212
|
+
function applyOAICacheBreakpoints(messages) {
|
|
213
|
+
if (messages.length === 0)
|
|
214
|
+
return;
|
|
215
|
+
const first = messages[0];
|
|
216
|
+
if (first.role === "system")
|
|
217
|
+
markLastContentPart(first);
|
|
218
|
+
const lastIdx = messages.length - 1;
|
|
219
|
+
if (lastIdx > 0)
|
|
220
|
+
markLastContentPart(messages[lastIdx]);
|
|
221
|
+
}
|
|
222
|
+
function markLastContentPart(msg) {
|
|
223
|
+
if (typeof msg.content === "string") {
|
|
224
|
+
if (msg.content.length === 0)
|
|
225
|
+
return;
|
|
226
|
+
msg.content = [{ type: "text", text: msg.content, cache_control: EPHEMERAL }];
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
if (!Array.isArray(msg.content) || msg.content.length === 0)
|
|
230
|
+
return;
|
|
231
|
+
const parts = msg.content;
|
|
232
|
+
const lastBlockIdx = parts.length - 1;
|
|
233
|
+
parts[lastBlockIdx] = { ...parts[lastBlockIdx], cache_control: EPHEMERAL };
|
|
234
|
+
}
|
|
235
|
+
function applyOAIToolCacheBreakpoint(tools) {
|
|
236
|
+
if (tools.length === 0)
|
|
237
|
+
return tools;
|
|
238
|
+
const lastIdx = tools.length - 1;
|
|
239
|
+
return tools.map(
|
|
240
|
+
(tool, i) => i === lastIdx ? { ...tool, cache_control: EPHEMERAL } : tool
|
|
241
|
+
);
|
|
242
|
+
}
|
|
207
243
|
function formatTools(tools) {
|
|
208
244
|
return tools.map((t) => ({
|
|
209
245
|
type: "function",
|
|
@@ -337,6 +373,7 @@ function openaiCompat(params) {
|
|
|
337
373
|
vision: params.capabilities?.vision ?? false,
|
|
338
374
|
imageInToolResult: params.capabilities?.imageInToolResult ?? false
|
|
339
375
|
};
|
|
376
|
+
const cacheBreakpointsEnabled = params.cacheBreakpoints === true;
|
|
340
377
|
return {
|
|
341
378
|
name,
|
|
342
379
|
meta: { defaultModel, capabilities },
|
|
@@ -350,6 +387,10 @@ function openaiCompat(params) {
|
|
|
350
387
|
const messages = toOAIMessages(options.system, options.messages, {
|
|
351
388
|
imageInToolResult: capabilities.imageInToolResult === true
|
|
352
389
|
});
|
|
390
|
+
const shouldCache = cacheBreakpointsEnabled && options.cache !== false;
|
|
391
|
+
if (shouldCache) {
|
|
392
|
+
applyOAICacheBreakpoints(messages);
|
|
393
|
+
}
|
|
353
394
|
const maxTokens = options.thinkingBudget ? options.thinkingBudget + options.maxTokens : options.maxTokens;
|
|
354
395
|
const body = {
|
|
355
396
|
model: modelId,
|
|
@@ -357,8 +398,9 @@ function openaiCompat(params) {
|
|
|
357
398
|
max_tokens: maxTokens,
|
|
358
399
|
stream: true
|
|
359
400
|
};
|
|
360
|
-
if (options.tools && options.tools.length > 0)
|
|
361
|
-
body.tools = options.tools;
|
|
401
|
+
if (options.tools && options.tools.length > 0) {
|
|
402
|
+
body.tools = shouldCache ? applyOAIToolCacheBreakpoint(options.tools) : options.tools;
|
|
403
|
+
}
|
|
362
404
|
if (options.toolChoice) {
|
|
363
405
|
if (options.toolChoice.type === "tool" && options.toolChoice.name)
|
|
364
406
|
body.tool_choice = { type: "function", function: { name: options.toolChoice.name } };
|
|
@@ -3,6 +3,7 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
|
3
3
|
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
|
|
4
4
|
import { getDefaultEnvironment, StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
5
5
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
6
|
+
var DEFAULT_MCP_BOOTSTRAP_TIMEOUT_MS = 1e4;
|
|
6
7
|
function inferTransport(raw) {
|
|
7
8
|
if (raw.transport === "stdio" || raw.transport === "sse" || raw.transport === "streamable-http")
|
|
8
9
|
return raw.transport;
|
|
@@ -34,6 +35,8 @@ function normalizeOne(name, raw) {
|
|
|
34
35
|
config.url = url;
|
|
35
36
|
if (raw.headers)
|
|
36
37
|
config.headers = raw.headers;
|
|
38
|
+
if (typeof raw.bootstrapTimeout === "number")
|
|
39
|
+
config.bootstrapTimeout = raw.bootstrapTimeout;
|
|
37
40
|
if (typeof raw.toolTimeout === "number")
|
|
38
41
|
config.toolTimeout = raw.toolTimeout;
|
|
39
42
|
return config;
|
|
@@ -148,113 +151,25 @@ async function connectMcpServers(configs, _clientFactory, hooks) {
|
|
|
148
151
|
const tools = {};
|
|
149
152
|
const errors = [];
|
|
150
153
|
let closed = false;
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
await
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
name: namespacedName,
|
|
165
|
-
description: tool.description || "",
|
|
166
|
-
inputSchema: tool.inputSchema ?? { type: "object", properties: {} }
|
|
167
|
-
},
|
|
168
|
-
execute: async (input, ctx) => {
|
|
169
|
-
const { turnId, callId, signal } = ctx;
|
|
170
|
-
const displayName = ctx.toolAliases?.[namespacedName] ?? namespacedName;
|
|
171
|
-
const gateCtx = {
|
|
172
|
-
turnId,
|
|
173
|
-
callId,
|
|
174
|
-
server: config.name,
|
|
175
|
-
tool: tool.name,
|
|
176
|
-
displayName,
|
|
177
|
-
input,
|
|
178
|
-
block: false,
|
|
179
|
-
reason: "MCP tool execution was blocked"
|
|
180
|
-
};
|
|
181
|
-
await hooks?.callHook("mcp:tool:gate", gateCtx);
|
|
182
|
-
if (gateCtx.block)
|
|
183
|
-
return `Blocked: ${gateCtx.reason}`;
|
|
184
|
-
const effectiveInput = gateCtx.input;
|
|
185
|
-
await hooks?.callHook("mcp:tool:before", {
|
|
186
|
-
turnId,
|
|
187
|
-
callId,
|
|
188
|
-
server: config.name,
|
|
189
|
-
tool: tool.name,
|
|
190
|
-
displayName,
|
|
191
|
-
input: effectiveInput
|
|
192
|
-
});
|
|
193
|
-
const timeout = config.toolTimeout ?? 3e4;
|
|
194
|
-
try {
|
|
195
|
-
const result = await raceWithTimeoutAndSignal(
|
|
196
|
-
() => client.callTool({ name: tool.name, arguments: effectiveInput }),
|
|
197
|
-
timeout,
|
|
198
|
-
`MCP tool "${tool.name}" on server "${config.name}" timed out after ${timeout}ms`,
|
|
199
|
-
signal
|
|
200
|
-
);
|
|
201
|
-
let output = packMcpResult(result.content);
|
|
202
|
-
const transformCtx = {
|
|
203
|
-
turnId,
|
|
204
|
-
callId,
|
|
205
|
-
server: config.name,
|
|
206
|
-
tool: tool.name,
|
|
207
|
-
displayName,
|
|
208
|
-
input: effectiveInput,
|
|
209
|
-
result: output
|
|
210
|
-
};
|
|
211
|
-
await hooks?.callHook("mcp:tool:transform", transformCtx);
|
|
212
|
-
output = transformCtx.result;
|
|
213
|
-
await hooks?.callHook("mcp:tool:after", {
|
|
214
|
-
turnId,
|
|
215
|
-
callId,
|
|
216
|
-
server: config.name,
|
|
217
|
-
tool: tool.name,
|
|
218
|
-
displayName,
|
|
219
|
-
input: effectiveInput,
|
|
220
|
-
result: output
|
|
221
|
-
});
|
|
222
|
-
return output;
|
|
223
|
-
} catch (err) {
|
|
224
|
-
const error = err instanceof Error ? err : new Error(String(err));
|
|
225
|
-
await hooks?.callHook("mcp:tool:error", {
|
|
226
|
-
turnId,
|
|
227
|
-
callId,
|
|
228
|
-
server: config.name,
|
|
229
|
-
tool: tool.name,
|
|
230
|
-
displayName,
|
|
231
|
-
input: effectiveInput,
|
|
232
|
-
error
|
|
233
|
-
});
|
|
234
|
-
await hooks?.callHook("mcp:tool:after", {
|
|
235
|
-
turnId,
|
|
236
|
-
callId,
|
|
237
|
-
server: config.name,
|
|
238
|
-
tool: tool.name,
|
|
239
|
-
displayName,
|
|
240
|
-
input: effectiveInput,
|
|
241
|
-
result: error.message
|
|
242
|
-
});
|
|
243
|
-
throw error;
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
};
|
|
247
|
-
}
|
|
248
|
-
await hooks?.callHook("mcp:connect", {
|
|
249
|
-
name: config.name,
|
|
250
|
-
transport: config.transport,
|
|
251
|
-
tools: toolNames
|
|
252
|
-
});
|
|
253
|
-
} catch (err) {
|
|
254
|
-
const error = err instanceof Error ? err : new Error(String(err));
|
|
255
|
-
errors.push({ name: config.name, error });
|
|
256
|
-
await hooks?.callHook("mcp:error", { name: config.name, error });
|
|
154
|
+
const bootstrapResults = await Promise.all(configs.map((config) => bootstrapServer(config, _clientFactory, hooks)));
|
|
155
|
+
for (const result of bootstrapResults) {
|
|
156
|
+
if (!result.ok) {
|
|
157
|
+
errors.push({ name: result.name, error: result.error });
|
|
158
|
+
await hooks?.callHook("mcp:error", { name: result.name, error: result.error });
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
connections.push({ name: result.name, client: result.client });
|
|
162
|
+
const toolNames = [];
|
|
163
|
+
for (const tool of result.tools) {
|
|
164
|
+
const namespacedName = `mcp_${result.config.name}_${tool.name}`;
|
|
165
|
+
toolNames.push(namespacedName);
|
|
166
|
+
tools[namespacedName] = buildMcpToolDef(result.config, result.client, tool, namespacedName, hooks);
|
|
257
167
|
}
|
|
168
|
+
await hooks?.callHook("mcp:connect", {
|
|
169
|
+
name: result.name,
|
|
170
|
+
transport: result.config.transport,
|
|
171
|
+
tools: toolNames
|
|
172
|
+
});
|
|
258
173
|
}
|
|
259
174
|
if (errors.length > 0 && connections.length === 0) {
|
|
260
175
|
const messages = errors.map((e) => `${e.name}: ${e.error.message}`).join(", ");
|
|
@@ -275,6 +190,153 @@ async function connectMcpServers(configs, _clientFactory, hooks) {
|
|
|
275
190
|
}
|
|
276
191
|
};
|
|
277
192
|
}
|
|
193
|
+
async function bootstrapServer(config, _clientFactory, hooks) {
|
|
194
|
+
const start = Date.now();
|
|
195
|
+
await hooks?.callHook("mcp:bootstrap:start", { name: config.name, transport: config.transport });
|
|
196
|
+
let client = null;
|
|
197
|
+
try {
|
|
198
|
+
client = _clientFactory ? _clientFactory() : new Client({ name: "zidane", version: "1.0.0" });
|
|
199
|
+
const currentClient = client;
|
|
200
|
+
const transport = createTransport(config);
|
|
201
|
+
const bootstrapTimeout = config.bootstrapTimeout ?? DEFAULT_MCP_BOOTSTRAP_TIMEOUT_MS;
|
|
202
|
+
const { tools: mcpTools } = await raceWithTimeout(
|
|
203
|
+
async () => {
|
|
204
|
+
await currentClient.connect(transport);
|
|
205
|
+
return await currentClient.listTools();
|
|
206
|
+
},
|
|
207
|
+
bootstrapTimeout,
|
|
208
|
+
`MCP server "${config.name}" bootstrap timed out after ${bootstrapTimeout}ms`
|
|
209
|
+
);
|
|
210
|
+
const durationMs = Date.now() - start;
|
|
211
|
+
await hooks?.callHook("mcp:bootstrap:end", {
|
|
212
|
+
name: config.name,
|
|
213
|
+
transport: config.transport,
|
|
214
|
+
durationMs,
|
|
215
|
+
ok: true,
|
|
216
|
+
toolCount: mcpTools.length
|
|
217
|
+
});
|
|
218
|
+
return { ok: true, name: config.name, config, client: currentClient, tools: mcpTools };
|
|
219
|
+
} catch (err) {
|
|
220
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
221
|
+
await closeClientQuietly(client);
|
|
222
|
+
const durationMs = Date.now() - start;
|
|
223
|
+
await hooks?.callHook("mcp:bootstrap:end", {
|
|
224
|
+
name: config.name,
|
|
225
|
+
transport: config.transport,
|
|
226
|
+
durationMs,
|
|
227
|
+
ok: false,
|
|
228
|
+
error
|
|
229
|
+
});
|
|
230
|
+
return { ok: false, name: config.name, error };
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
function buildMcpToolDef(config, client, tool, namespacedName, hooks) {
|
|
234
|
+
return {
|
|
235
|
+
spec: {
|
|
236
|
+
name: namespacedName,
|
|
237
|
+
description: tool.description || "",
|
|
238
|
+
inputSchema: tool.inputSchema ?? { type: "object", properties: {} }
|
|
239
|
+
},
|
|
240
|
+
execute: async (input, ctx) => {
|
|
241
|
+
const { turnId, callId, signal } = ctx;
|
|
242
|
+
const displayName = ctx.toolAliases?.[namespacedName] ?? namespacedName;
|
|
243
|
+
const gateCtx = {
|
|
244
|
+
turnId,
|
|
245
|
+
callId,
|
|
246
|
+
server: config.name,
|
|
247
|
+
tool: tool.name,
|
|
248
|
+
displayName,
|
|
249
|
+
input,
|
|
250
|
+
block: false,
|
|
251
|
+
reason: "MCP tool execution was blocked"
|
|
252
|
+
};
|
|
253
|
+
await hooks?.callHook("mcp:tool:gate", gateCtx);
|
|
254
|
+
if (gateCtx.block)
|
|
255
|
+
return `Blocked: ${gateCtx.reason}`;
|
|
256
|
+
const effectiveInput = gateCtx.input;
|
|
257
|
+
await hooks?.callHook("mcp:tool:before", {
|
|
258
|
+
turnId,
|
|
259
|
+
callId,
|
|
260
|
+
server: config.name,
|
|
261
|
+
tool: tool.name,
|
|
262
|
+
displayName,
|
|
263
|
+
input: effectiveInput
|
|
264
|
+
});
|
|
265
|
+
const timeout = config.toolTimeout ?? 3e4;
|
|
266
|
+
try {
|
|
267
|
+
const result = await raceWithTimeoutAndSignal(
|
|
268
|
+
() => client.callTool({ name: tool.name, arguments: effectiveInput }),
|
|
269
|
+
timeout,
|
|
270
|
+
`MCP tool "${tool.name}" on server "${config.name}" timed out after ${timeout}ms`,
|
|
271
|
+
signal
|
|
272
|
+
);
|
|
273
|
+
let output = packMcpResult(result.content);
|
|
274
|
+
const transformCtx = {
|
|
275
|
+
turnId,
|
|
276
|
+
callId,
|
|
277
|
+
server: config.name,
|
|
278
|
+
tool: tool.name,
|
|
279
|
+
displayName,
|
|
280
|
+
input: effectiveInput,
|
|
281
|
+
result: output
|
|
282
|
+
};
|
|
283
|
+
await hooks?.callHook("mcp:tool:transform", transformCtx);
|
|
284
|
+
output = transformCtx.result;
|
|
285
|
+
await hooks?.callHook("mcp:tool:after", {
|
|
286
|
+
turnId,
|
|
287
|
+
callId,
|
|
288
|
+
server: config.name,
|
|
289
|
+
tool: tool.name,
|
|
290
|
+
displayName,
|
|
291
|
+
input: effectiveInput,
|
|
292
|
+
result: output
|
|
293
|
+
});
|
|
294
|
+
return output;
|
|
295
|
+
} catch (err) {
|
|
296
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
297
|
+
await hooks?.callHook("mcp:tool:error", {
|
|
298
|
+
turnId,
|
|
299
|
+
callId,
|
|
300
|
+
server: config.name,
|
|
301
|
+
tool: tool.name,
|
|
302
|
+
displayName,
|
|
303
|
+
input: effectiveInput,
|
|
304
|
+
error
|
|
305
|
+
});
|
|
306
|
+
await hooks?.callHook("mcp:tool:after", {
|
|
307
|
+
turnId,
|
|
308
|
+
callId,
|
|
309
|
+
server: config.name,
|
|
310
|
+
tool: tool.name,
|
|
311
|
+
displayName,
|
|
312
|
+
input: effectiveInput,
|
|
313
|
+
result: error.message
|
|
314
|
+
});
|
|
315
|
+
throw error;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
async function closeClientQuietly(client) {
|
|
321
|
+
if (!client)
|
|
322
|
+
return;
|
|
323
|
+
try {
|
|
324
|
+
await client.close();
|
|
325
|
+
} catch {
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
async function raceWithTimeout(task, timeoutMs, timeoutMessage) {
|
|
329
|
+
let timer;
|
|
330
|
+
try {
|
|
331
|
+
return await new Promise((resolvePromise, rejectPromise) => {
|
|
332
|
+
timer = setTimeout(() => rejectPromise(new Error(timeoutMessage)), timeoutMs);
|
|
333
|
+
task().then(resolvePromise, rejectPromise);
|
|
334
|
+
});
|
|
335
|
+
} finally {
|
|
336
|
+
if (timer)
|
|
337
|
+
clearTimeout(timer);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
278
340
|
async function raceWithTimeoutAndSignal(task, timeoutMs, timeoutMessage, signal) {
|
|
279
341
|
if (signal?.aborted)
|
|
280
342
|
throw new Error("MCP tool call aborted");
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from "./chunk-2EQT4EHD.js";
|
|
12
12
|
import {
|
|
13
13
|
connectMcpServers
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-DRAYZZ23.js";
|
|
15
15
|
import {
|
|
16
16
|
AgentAbortedError,
|
|
17
17
|
AgentProviderError,
|
|
@@ -589,6 +589,7 @@ async function executeTurn(ctx, turn) {
|
|
|
589
589
|
maxTokens: ctx.maxTokens ?? 16384,
|
|
590
590
|
thinking: ctx.thinking,
|
|
591
591
|
thinkingBudget: ctx.thinkingBudget,
|
|
592
|
+
cache: ctx.cache ?? true,
|
|
592
593
|
signal: ctx.signal
|
|
593
594
|
};
|
|
594
595
|
const transformCtx = { messages: streamOptions.messages };
|
|
@@ -960,6 +961,8 @@ var HOOK_EVENT_NAMES = [
|
|
|
960
961
|
"mcp:connect",
|
|
961
962
|
"mcp:error",
|
|
962
963
|
"mcp:close",
|
|
964
|
+
"mcp:bootstrap:start",
|
|
965
|
+
"mcp:bootstrap:end",
|
|
963
966
|
"mcp:tool:gate",
|
|
964
967
|
"mcp:tool:before",
|
|
965
968
|
"mcp:tool:after",
|
|
@@ -989,10 +992,11 @@ function resolveBehavior(agentBehavior, runBehavior) {
|
|
|
989
992
|
maxTurns: runBehavior?.maxTurns ?? agentBehavior?.maxTurns,
|
|
990
993
|
maxTokens: runBehavior?.maxTokens ?? agentBehavior?.maxTokens,
|
|
991
994
|
thinkingBudget: runBehavior?.thinkingBudget ?? agentBehavior?.thinkingBudget,
|
|
992
|
-
schema: runBehavior?.schema ?? agentBehavior?.schema
|
|
995
|
+
schema: runBehavior?.schema ?? agentBehavior?.schema,
|
|
996
|
+
cache: runBehavior?.cache ?? agentBehavior?.cache ?? true
|
|
993
997
|
};
|
|
994
998
|
}
|
|
995
|
-
function createAgent({ provider, name: agentName, system: agentSystem, tools: agentTools, toolAliases, behavior: agentBehavior, execution, mcpServers, session, skills: agentSkills,
|
|
999
|
+
function createAgent({ provider, name: agentName, system: agentSystem, tools: agentTools, toolAliases, behavior: agentBehavior, execution, mcpServers, session, skills: agentSkills, mcpConnector, eager }) {
|
|
996
1000
|
const hooks = createHooks();
|
|
997
1001
|
const executionContext = execution ?? createProcessContext();
|
|
998
1002
|
const sourceTools = agentTools ?? {};
|
|
@@ -1002,6 +1006,7 @@ function createAgent({ provider, name: agentName, system: agentSystem, tools: ag
|
|
|
1002
1006
|
let idlePromise;
|
|
1003
1007
|
let executionHandle = null;
|
|
1004
1008
|
let mcpConnection = null;
|
|
1009
|
+
let mcpWarmupPromise = null;
|
|
1005
1010
|
const allMcpServers = mcpServers ?? [];
|
|
1006
1011
|
const steeringQueue = [];
|
|
1007
1012
|
const followUpQueue = [];
|
|
@@ -1076,11 +1081,7 @@ function createAgent({ provider, name: agentName, system: agentSystem, tools: ag
|
|
|
1076
1081
|
executionHandle = await executionContext.spawn();
|
|
1077
1082
|
}
|
|
1078
1083
|
if (allMcpServers.length > 0 && !mcpConnection) {
|
|
1079
|
-
|
|
1080
|
-
mcpConnection = await _mcpConnector(allMcpServers);
|
|
1081
|
-
} else {
|
|
1082
|
-
mcpConnection = await connectMcpServers(allMcpServers, void 0, hooks);
|
|
1083
|
-
}
|
|
1084
|
+
await warmup();
|
|
1084
1085
|
}
|
|
1085
1086
|
if (!skillsDisabled && skillsConfig && !resolvedSkills) {
|
|
1086
1087
|
resolvedSkills = await resolveSkills(skillsConfig);
|
|
@@ -1115,7 +1116,7 @@ function createAgent({ provider, name: agentName, system: agentSystem, tools: ag
|
|
|
1115
1116
|
}
|
|
1116
1117
|
const thinking = options.thinking ?? "off";
|
|
1117
1118
|
const model = options.model ?? provider.meta.defaultModel;
|
|
1118
|
-
const { toolExecution, maxTurns, maxTokens, thinkingBudget, schema } = resolveBehavior(agentBehavior, options.behavior);
|
|
1119
|
+
const { toolExecution, maxTurns, maxTokens, thinkingBudget, schema, cache } = resolveBehavior(agentBehavior, options.behavior);
|
|
1119
1120
|
let system = options.system || agentSystem || "You are a helpful assistant.";
|
|
1120
1121
|
if (skillsCatalog) {
|
|
1121
1122
|
system = `${system}
|
|
@@ -1177,6 +1178,12 @@ ${skillsCatalog}`;
|
|
|
1177
1178
|
}
|
|
1178
1179
|
conversationTurns = turns;
|
|
1179
1180
|
let lastPersistedTurnCount = isResume ? session.turns.length : 0;
|
|
1181
|
+
if (session && turns.length > lastPersistedTurnCount) {
|
|
1182
|
+
const seededTurns = turns.slice(lastPersistedTurnCount);
|
|
1183
|
+
await session.appendTurns(seededTurns);
|
|
1184
|
+
lastPersistedTurnCount = turns.length;
|
|
1185
|
+
await hooks.callHook("session:turns", { sessionId: session.id, turns: seededTurns, count: turns.length });
|
|
1186
|
+
}
|
|
1180
1187
|
const unregisterSessionSync = session ? hooks.hook("turn:after", async () => {
|
|
1181
1188
|
const newTurns = turns.slice(lastPersistedTurnCount);
|
|
1182
1189
|
if (newTurns.length > 0) {
|
|
@@ -1243,6 +1250,7 @@ ${skillsCatalog}`;
|
|
|
1243
1250
|
depth: runDepth,
|
|
1244
1251
|
thinkingBudget,
|
|
1245
1252
|
schema,
|
|
1253
|
+
cache,
|
|
1246
1254
|
runStartMs
|
|
1247
1255
|
});
|
|
1248
1256
|
const finalStats = {
|
|
@@ -1358,10 +1366,39 @@ ${skillsCatalog}`;
|
|
|
1358
1366
|
};
|
|
1359
1367
|
}
|
|
1360
1368
|
let destroyed = false;
|
|
1369
|
+
async function warmup() {
|
|
1370
|
+
if (destroyed)
|
|
1371
|
+
return;
|
|
1372
|
+
if (mcpConnection || allMcpServers.length === 0)
|
|
1373
|
+
return;
|
|
1374
|
+
if (mcpWarmupPromise)
|
|
1375
|
+
return mcpWarmupPromise;
|
|
1376
|
+
mcpWarmupPromise = (async () => {
|
|
1377
|
+
const connection = mcpConnector ? await mcpConnector(allMcpServers) : await connectMcpServers(allMcpServers, void 0, hooks);
|
|
1378
|
+
if (destroyed) {
|
|
1379
|
+
await connection.close().catch(() => {
|
|
1380
|
+
});
|
|
1381
|
+
return;
|
|
1382
|
+
}
|
|
1383
|
+
mcpConnection = connection;
|
|
1384
|
+
})();
|
|
1385
|
+
try {
|
|
1386
|
+
await mcpWarmupPromise;
|
|
1387
|
+
} catch (err) {
|
|
1388
|
+
mcpWarmupPromise = null;
|
|
1389
|
+
throw err;
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1361
1392
|
async function destroy() {
|
|
1362
1393
|
if (destroyed)
|
|
1363
1394
|
return;
|
|
1364
1395
|
destroyed = true;
|
|
1396
|
+
if (mcpWarmupPromise) {
|
|
1397
|
+
try {
|
|
1398
|
+
await mcpWarmupPromise;
|
|
1399
|
+
} catch {
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1365
1402
|
if (mcpConnection) {
|
|
1366
1403
|
await mcpConnection.close();
|
|
1367
1404
|
mcpConnection = null;
|
|
@@ -1371,6 +1408,10 @@ ${skillsCatalog}`;
|
|
|
1371
1408
|
executionHandle = null;
|
|
1372
1409
|
}
|
|
1373
1410
|
}
|
|
1411
|
+
if (eager && allMcpServers.length > 0) {
|
|
1412
|
+
void warmup().catch(() => {
|
|
1413
|
+
});
|
|
1414
|
+
}
|
|
1374
1415
|
return {
|
|
1375
1416
|
hooks,
|
|
1376
1417
|
run,
|
|
@@ -1380,6 +1421,7 @@ ${skillsCatalog}`;
|
|
|
1380
1421
|
waitForIdle,
|
|
1381
1422
|
reset,
|
|
1382
1423
|
destroy,
|
|
1424
|
+
warmup,
|
|
1383
1425
|
activateSkill,
|
|
1384
1426
|
deactivateSkill,
|
|
1385
1427
|
get isRunning() {
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
toAnthropic,
|
|
6
6
|
toolResultsMessage,
|
|
7
7
|
userMessage
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-CYWF2U62.js";
|
|
9
9
|
import {
|
|
10
10
|
matchesContextExceeded
|
|
11
11
|
} from "./chunk-LNN5UTS2.js";
|
|
@@ -186,6 +186,52 @@ function mapStopReason(stopReason) {
|
|
|
186
186
|
return "other";
|
|
187
187
|
}
|
|
188
188
|
}
|
|
189
|
+
var EPHEMERAL = { type: "ephemeral" };
|
|
190
|
+
function applyAnthropicCacheBreakpoints(params) {
|
|
191
|
+
if (typeof params.system === "string") {
|
|
192
|
+
if (params.system.length > 0) {
|
|
193
|
+
params.system = [{ type: "text", text: params.system, cache_control: EPHEMERAL }];
|
|
194
|
+
}
|
|
195
|
+
} else if (Array.isArray(params.system) && params.system.length > 0) {
|
|
196
|
+
const lastIdx = params.system.length - 1;
|
|
197
|
+
params.system = params.system.map(
|
|
198
|
+
(block, i) => i === lastIdx ? { ...block, cache_control: EPHEMERAL } : block
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
if (params.tools && params.tools.length > 0) {
|
|
202
|
+
const lastIdx = params.tools.length - 1;
|
|
203
|
+
params.tools = params.tools.map(
|
|
204
|
+
(tool, i) => i === lastIdx ? { ...tool, cache_control: EPHEMERAL } : tool
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
if (params.messages.length === 0)
|
|
208
|
+
return;
|
|
209
|
+
const lastMsgIdx = params.messages.length - 1;
|
|
210
|
+
const lastMsg = params.messages[lastMsgIdx];
|
|
211
|
+
if (typeof lastMsg.content === "string") {
|
|
212
|
+
if (lastMsg.content.length === 0)
|
|
213
|
+
return;
|
|
214
|
+
params.messages[lastMsgIdx] = {
|
|
215
|
+
...lastMsg,
|
|
216
|
+
content: [{ type: "text", text: lastMsg.content, cache_control: EPHEMERAL }]
|
|
217
|
+
};
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
if (!Array.isArray(lastMsg.content) || lastMsg.content.length === 0)
|
|
221
|
+
return;
|
|
222
|
+
const blocks = lastMsg.content;
|
|
223
|
+
let targetIdx = blocks.length - 1;
|
|
224
|
+
while (targetIdx >= 0 && isThinkingBlock(blocks[targetIdx]))
|
|
225
|
+
targetIdx -= 1;
|
|
226
|
+
if (targetIdx < 0)
|
|
227
|
+
return;
|
|
228
|
+
const nextBlocks = blocks.slice();
|
|
229
|
+
nextBlocks[targetIdx] = { ...nextBlocks[targetIdx], cache_control: EPHEMERAL };
|
|
230
|
+
params.messages[lastMsgIdx] = { ...lastMsg, content: nextBlocks };
|
|
231
|
+
}
|
|
232
|
+
function isThinkingBlock(block) {
|
|
233
|
+
return block.type === "thinking" || block.type === "redacted_thinking";
|
|
234
|
+
}
|
|
189
235
|
function looksLikeAnthropicApiError(err) {
|
|
190
236
|
if (!err || typeof err !== "object")
|
|
191
237
|
return false;
|
|
@@ -345,6 +391,8 @@ function anthropic(anthropicParams) {
|
|
|
345
391
|
messages: messages.map((m) => toAnthropic(m)),
|
|
346
392
|
stream: true
|
|
347
393
|
};
|
|
394
|
+
if (options.cache !== false)
|
|
395
|
+
applyAnthropicCacheBreakpoints(params);
|
|
348
396
|
if (thinking !== "off") {
|
|
349
397
|
const budgetTokens = options.thinkingBudget ?? THINKING_BUDGETS[thinking];
|
|
350
398
|
params.thinking = {
|
|
@@ -698,7 +746,12 @@ function openrouter(params) {
|
|
|
698
746
|
"HTTP-Referer": "https://github.com/Tahul/zidane",
|
|
699
747
|
"X-Title": "zidane"
|
|
700
748
|
},
|
|
701
|
-
capabilities: params?.capabilities ?? { vision: true, imageInToolResult: false }
|
|
749
|
+
capabilities: params?.capabilities ?? { vision: true, imageInToolResult: false },
|
|
750
|
+
// OpenRouter honors `cache_control` markers for Anthropic + Gemini routes and
|
|
751
|
+
// silently ignores them for routes that cache automatically. Safe to turn on
|
|
752
|
+
// by default — the caller can still flip `behavior.cache = false` to opt out
|
|
753
|
+
// without needing to re-instantiate the provider.
|
|
754
|
+
cacheBreakpoints: true
|
|
702
755
|
});
|
|
703
756
|
}
|
|
704
757
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { d as AgentHooks } from './agent-
|
|
2
|
-
export { ab as ActivationVia, ac as ActiveSkill, A as Agent, a as AgentAbortedError, b as AgentBehavior, c as AgentContextExceededError, e as AgentOptions, f as AgentProviderError, g as AgentRunOptions, h as AgentStats, i as AgentToolNotAllowedError, j as AnthropicParams, C as CONTEXT_EXCEEDED_MESSAGE_PATTERNS, k as CerebrasParams, m as ClassifiedError, n as ClassifiedErrorKind, o as CreateSessionOptions, ad as DeactivationReason, ae as FileMapAdapter, af as FileMapStoreOptions, I as ImageContent, M as McpConnection, p as McpServerConfig, q as McpToolHookContext, O as OAuthRefreshHookContext, ag as OpenAICompatAuthHeader, ah as OpenAICompatHttpError, ai as OpenAICompatParams, r as OpenAIParams, s as OpenRouterParams, P as PromptDocumentPart, t as PromptImagePart, u as PromptPart, v as PromptTextPart, w as Provider, x as ProviderCapabilities, R as RemoteStoreOptions, y as RunHookMap, S as Session, z as SessionContentBlock, B as SessionData, D as SessionEndStatus, E as SessionHookContext, F as SessionMessage, G as SessionRun, H as SessionStore, J as SessionTurn, aj as SkillActivationState, ak as SkillActivationStateOptions, K as SkillConfig, al as SkillDiagnostic, L as SkillResource, am as SkillSource, N as SkillsConfig, Q as SpawnHookContext, T as StreamCallbacks, U as StreamHookContext, V as StreamOptions, W as ThinkingLevel, X as ToolCall, Y as ToolContext, Z as ToolDef, _ as ToolExecutionMode, $ as ToolHookContext, a0 as ToolMap, a1 as ToolResult, a2 as ToolResultContent, a3 as ToolResultImageContent, a4 as ToolResultTextContent, a5 as ToolSpec, a6 as TurnFinishReason, a7 as TurnResult, a8 as TurnUsage, an as anthropic, ao as autoDetectAndConvert, ap as cerebras, aq as classifyOpenAICompatError, ar as connectMcpServers, as as createAgent, at as createFileMapStore, au as createMemoryStore, av as createRemoteStore, aw as createSession, ax as createSkillActivationState, ay as fromAnthropic, az as fromOpenAI, aA as loadSession, aB as mapOAIFinishReason, a9 as matchesContextExceeded, aC as normalizeMcpBlocks, aD as normalizeMcpServers, aE as openai, aF as openaiCompat, aG as openrouter, aH as resultToString, aI as toAnthropic, aJ as toOpenAI, aK as toTypedError, aa as toolResultToText } from './agent-
|
|
1
|
+
import { d as AgentHooks } from './agent-C0hLXofc.js';
|
|
2
|
+
export { ab as ActivationVia, ac as ActiveSkill, A as Agent, a as AgentAbortedError, b as AgentBehavior, c as AgentContextExceededError, e as AgentOptions, f as AgentProviderError, g as AgentRunOptions, h as AgentStats, i as AgentToolNotAllowedError, j as AnthropicParams, C as CONTEXT_EXCEEDED_MESSAGE_PATTERNS, k as CerebrasParams, m as ClassifiedError, n as ClassifiedErrorKind, o as CreateSessionOptions, ad as DeactivationReason, ae as FileMapAdapter, af as FileMapStoreOptions, I as ImageContent, M as McpConnection, p as McpServerConfig, q as McpToolHookContext, O as OAuthRefreshHookContext, ag as OpenAICompatAuthHeader, ah as OpenAICompatHttpError, ai as OpenAICompatParams, r as OpenAIParams, s as OpenRouterParams, P as PromptDocumentPart, t as PromptImagePart, u as PromptPart, v as PromptTextPart, w as Provider, x as ProviderCapabilities, R as RemoteStoreOptions, y as RunHookMap, S as Session, z as SessionContentBlock, B as SessionData, D as SessionEndStatus, E as SessionHookContext, F as SessionMessage, G as SessionRun, H as SessionStore, J as SessionTurn, aj as SkillActivationState, ak as SkillActivationStateOptions, K as SkillConfig, al as SkillDiagnostic, L as SkillResource, am as SkillSource, N as SkillsConfig, Q as SpawnHookContext, T as StreamCallbacks, U as StreamHookContext, V as StreamOptions, W as ThinkingLevel, X as ToolCall, Y as ToolContext, Z as ToolDef, _ as ToolExecutionMode, $ as ToolHookContext, a0 as ToolMap, a1 as ToolResult, a2 as ToolResultContent, a3 as ToolResultImageContent, a4 as ToolResultTextContent, a5 as ToolSpec, a6 as TurnFinishReason, a7 as TurnResult, a8 as TurnUsage, an as anthropic, ao as autoDetectAndConvert, ap as cerebras, aq as classifyOpenAICompatError, ar as connectMcpServers, as as createAgent, at as createFileMapStore, au as createMemoryStore, av as createRemoteStore, aw as createSession, ax as createSkillActivationState, ay as fromAnthropic, az as fromOpenAI, aA as loadSession, aB as mapOAIFinishReason, a9 as matchesContextExceeded, aC as normalizeMcpBlocks, aD as normalizeMcpServers, aE as openai, aF as openaiCompat, aG as openrouter, aH as resultToString, aI as toAnthropic, aJ as toOpenAI, aK as toTypedError, aa as toolResultToText } from './agent-C0hLXofc.js';
|
|
3
3
|
export { createDockerContext, createProcessContext } from './contexts.js';
|
|
4
4
|
export { S as SandboxProvider, c as createSandboxContext } from './sandbox-CW72eLDP.js';
|
|
5
5
|
export { C as ContextCapabilities, a as ContextType, E as ExecResult, b as ExecutionContext, c as ExecutionHandle, S as SpawnConfig } from './types-BpvTmawk.js';
|
|
6
6
|
export { Preset, basic, basicTools, definePreset } from './presets.js';
|
|
7
7
|
export { IMPLICITLY_ALLOWED_SKILL_TOOLS, SkillValidationIssue, SkillValidationResult, SourcedScanPath, buildCatalog, defineSkill, discoverSkills, installAllowedToolsGate, interpolateShellCommands, isToolAllowedByUnion, matchesAllowedTool, parseAllowedToolPattern, parseSkillFile, resolveSkills, validateResourcePath, validateSkillForWrite, validateSkillName, writeSkillToDisk, writeSkillsToDisk } from './skills.js';
|
|
8
|
-
export { S as SkillsReadToolOptions, a as SkillsRunScriptToolOptions, b as SkillsUseToolOptions, c as createSkillsReadTool, d as createSkillsRunScriptTool, e as createSkillsUseTool, g as glob } from './skills-use-
|
|
9
|
-
export { C as ChildAgent, I as InteractionToolOptions, S as SpawnToolOptions, a as SpawnToolState, c as createInteractionTool, b as createSpawnTool, s as spawn } from './spawn-
|
|
8
|
+
export { S as SkillsReadToolOptions, a as SkillsRunScriptToolOptions, b as SkillsUseToolOptions, c as createSkillsReadTool, d as createSkillsRunScriptTool, e as createSkillsUseTool, g as glob } from './skills-use-CvRJ1Qe3.js';
|
|
9
|
+
export { C as ChildAgent, I as InteractionToolOptions, S as SpawnToolOptions, a as SpawnToolState, c as createInteractionTool, b as createSpawnTool, s as spawn } from './spawn-CT0ivxxH.js';
|
|
10
10
|
import { Hookable } from 'hookable';
|
|
11
11
|
import '@modelcontextprotocol/sdk/client/index.js';
|
|
12
12
|
|
package/dist/index.js
CHANGED
|
@@ -9,12 +9,12 @@ import {
|
|
|
9
9
|
cerebras,
|
|
10
10
|
openai,
|
|
11
11
|
openrouter
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-ZSEMKVHP.js";
|
|
13
13
|
import {
|
|
14
14
|
basicTools,
|
|
15
15
|
basic_default,
|
|
16
16
|
definePreset
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-MDVZX6GM.js";
|
|
18
18
|
import {
|
|
19
19
|
createAgent,
|
|
20
20
|
createInteractionTool,
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
createSpawnTool,
|
|
25
25
|
glob,
|
|
26
26
|
spawn
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-O2XZLJMG.js";
|
|
28
28
|
import {
|
|
29
29
|
IMPLICITLY_ALLOWED_SKILL_TOOLS,
|
|
30
30
|
buildCatalog,
|
|
@@ -53,7 +53,7 @@ import {
|
|
|
53
53
|
normalizeMcpBlocks,
|
|
54
54
|
normalizeMcpServers,
|
|
55
55
|
resultToString
|
|
56
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-DRAYZZ23.js";
|
|
57
57
|
import {
|
|
58
58
|
createFileMapStore,
|
|
59
59
|
createMemoryStore,
|
|
@@ -71,7 +71,7 @@ import {
|
|
|
71
71
|
openaiCompat,
|
|
72
72
|
toAnthropic,
|
|
73
73
|
toOpenAI
|
|
74
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-CYWF2U62.js";
|
|
75
75
|
import {
|
|
76
76
|
AgentAbortedError,
|
|
77
77
|
AgentContextExceededError,
|
package/dist/mcp.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import 'hookable';
|
|
2
|
-
export { M as McpConnection, p as McpServerConfig, ar as connectMcpServers, aC as normalizeMcpBlocks, aD as normalizeMcpServers, aH as resultToString } from './agent-
|
|
2
|
+
export { M as McpConnection, p as McpServerConfig, ar as connectMcpServers, aC as normalizeMcpBlocks, aD as normalizeMcpServers, aH as resultToString } from './agent-C0hLXofc.js';
|
|
3
3
|
import '@modelcontextprotocol/sdk/client/index.js';
|
|
4
4
|
import './types-BpvTmawk.js';
|
package/dist/mcp.js
CHANGED
package/dist/presets.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Z as ToolDef, e as AgentOptions } from './agent-
|
|
1
|
+
import { Z as ToolDef, e as AgentOptions } from './agent-C0hLXofc.js';
|
|
2
2
|
import 'hookable';
|
|
3
3
|
import './types-BpvTmawk.js';
|
|
4
4
|
import '@modelcontextprotocol/sdk/client/index.js';
|
|
@@ -24,7 +24,7 @@ declare const _default: Preset;
|
|
|
24
24
|
* createAgent({ ...basic, provider })
|
|
25
25
|
* ```
|
|
26
26
|
*/
|
|
27
|
-
type Preset = Omit<Partial<AgentOptions>, 'provider' | 'execution' | 'session' | '
|
|
27
|
+
type Preset = Omit<Partial<AgentOptions>, 'provider' | 'execution' | 'session' | 'mcpConnector'>;
|
|
28
28
|
/**
|
|
29
29
|
* Identity helper for type inference when defining a preset.
|
|
30
30
|
*/
|
package/dist/presets.js
CHANGED
|
@@ -2,11 +2,11 @@ import {
|
|
|
2
2
|
basicTools,
|
|
3
3
|
basic_default,
|
|
4
4
|
definePreset
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-MDVZX6GM.js";
|
|
6
|
+
import "./chunk-O2XZLJMG.js";
|
|
7
7
|
import "./chunk-TPXPVEH6.js";
|
|
8
8
|
import "./chunk-2EQT4EHD.js";
|
|
9
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-DRAYZZ23.js";
|
|
10
10
|
import "./chunk-LNN5UTS2.js";
|
|
11
11
|
export {
|
|
12
12
|
basic_default as basic,
|
package/dist/providers.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { j as AnthropicParams, k as CerebrasParams, ag as OpenAICompatAuthHeader, ah as OpenAICompatHttpError, ai as OpenAICompatParams, r as OpenAIParams, s as OpenRouterParams, w as Provider, x as ProviderCapabilities, T as StreamCallbacks, V as StreamOptions, X as ToolCall, a1 as ToolResult, a5 as ToolSpec, a7 as TurnResult, an as anthropic, ap as cerebras, aq as classifyOpenAICompatError, aB as mapOAIFinishReason, aE as openai, aF as openaiCompat, aG as openrouter } from './agent-
|
|
1
|
+
export { j as AnthropicParams, k as CerebrasParams, ag as OpenAICompatAuthHeader, ah as OpenAICompatHttpError, ai as OpenAICompatParams, r as OpenAIParams, s as OpenRouterParams, w as Provider, x as ProviderCapabilities, T as StreamCallbacks, V as StreamOptions, X as ToolCall, a1 as ToolResult, a5 as ToolSpec, a7 as TurnResult, an as anthropic, ap as cerebras, aq as classifyOpenAICompatError, aB as mapOAIFinishReason, aE as openai, aF as openaiCompat, aG as openrouter } from './agent-C0hLXofc.js';
|
|
2
2
|
import 'hookable';
|
|
3
3
|
import './types-BpvTmawk.js';
|
|
4
4
|
import '@modelcontextprotocol/sdk/client/index.js';
|
package/dist/providers.js
CHANGED
|
@@ -3,13 +3,13 @@ import {
|
|
|
3
3
|
cerebras,
|
|
4
4
|
openai,
|
|
5
5
|
openrouter
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-ZSEMKVHP.js";
|
|
7
7
|
import {
|
|
8
8
|
OpenAICompatHttpError,
|
|
9
9
|
classifyOpenAICompatError,
|
|
10
10
|
mapOAIFinishReason,
|
|
11
11
|
openaiCompat
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-CYWF2U62.js";
|
|
13
13
|
import "./chunk-LNN5UTS2.js";
|
|
14
14
|
export {
|
|
15
15
|
OpenAICompatHttpError,
|
package/dist/session/sqlite.d.ts
CHANGED
package/dist/session.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { o as CreateSessionOptions, ae as FileMapAdapter, af as FileMapStoreOptions, R as RemoteStoreOptions, S as Session, z as SessionContentBlock, B as SessionData, F as SessionMessage, G as SessionRun, H as SessionStore, J as SessionTurn, ao as autoDetectAndConvert, at as createFileMapStore, au as createMemoryStore, av as createRemoteStore, aw as createSession, ay as fromAnthropic, az as fromOpenAI, aA as loadSession, aI as toAnthropic, aJ as toOpenAI } from './agent-
|
|
1
|
+
export { o as CreateSessionOptions, ae as FileMapAdapter, af as FileMapStoreOptions, R as RemoteStoreOptions, S as Session, z as SessionContentBlock, B as SessionData, F as SessionMessage, G as SessionRun, H as SessionStore, J as SessionTurn, ao as autoDetectAndConvert, at as createFileMapStore, au as createMemoryStore, av as createRemoteStore, aw as createSession, ay as fromAnthropic, az as fromOpenAI, aA as loadSession, aI as toAnthropic, aJ as toOpenAI } from './agent-C0hLXofc.js';
|
|
2
2
|
import 'hookable';
|
|
3
3
|
import './types-BpvTmawk.js';
|
|
4
4
|
import '@modelcontextprotocol/sdk/client/index.js';
|
package/dist/session.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Z as ToolDef, K as SkillConfig, aj as SkillActivationState, d as AgentHooks } from './agent-
|
|
1
|
+
import { Z as ToolDef, K as SkillConfig, aj as SkillActivationState, d as AgentHooks } from './agent-C0hLXofc.js';
|
|
2
2
|
import { Hookable } from 'hookable';
|
|
3
3
|
|
|
4
4
|
declare const glob: ToolDef;
|
package/dist/skills.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { d as AgentHooks, aj as SkillActivationState, K as SkillConfig, am as SkillSource, al as SkillDiagnostic, N as SkillsConfig } from './agent-
|
|
2
|
-
export { ab as ActivationVia, ac as ActiveSkill, ad as DeactivationReason, ak as SkillActivationStateOptions, L as SkillResource, ax as createSkillActivationState } from './agent-
|
|
1
|
+
import { d as AgentHooks, aj as SkillActivationState, K as SkillConfig, am as SkillSource, al as SkillDiagnostic, N as SkillsConfig } from './agent-C0hLXofc.js';
|
|
2
|
+
export { ab as ActivationVia, ac as ActiveSkill, ad as DeactivationReason, ak as SkillActivationStateOptions, L as SkillResource, ax as createSkillActivationState } from './agent-C0hLXofc.js';
|
|
3
3
|
import { Hookable } from 'hookable';
|
|
4
4
|
import { b as ExecutionContext, c as ExecutionHandle } from './types-BpvTmawk.js';
|
|
5
5
|
import '@modelcontextprotocol/sdk/client/index.js';
|
package/dist/tools.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { S as SkillsReadToolOptions, a as SkillsRunScriptToolOptions, b as SkillsUseToolOptions, c as createSkillsReadTool, d as createSkillsRunScriptTool, e as createSkillsUseTool, g as glob } from './skills-use-
|
|
2
|
-
export { C as ChildAgent, I as InteractionToolOptions, S as SpawnToolOptions, a as SpawnToolState, c as createInteractionTool, b as createSpawnTool, s as spawn } from './spawn-
|
|
3
|
-
import { Z as ToolDef } from './agent-
|
|
4
|
-
export { Y as ToolContext, a0 as ToolMap } from './agent-
|
|
1
|
+
export { S as SkillsReadToolOptions, a as SkillsRunScriptToolOptions, b as SkillsUseToolOptions, c as createSkillsReadTool, d as createSkillsRunScriptTool, e as createSkillsUseTool, g as glob } from './skills-use-CvRJ1Qe3.js';
|
|
2
|
+
export { C as ChildAgent, I as InteractionToolOptions, S as SpawnToolOptions, a as SpawnToolState, c as createInteractionTool, b as createSpawnTool, s as spawn } from './spawn-CT0ivxxH.js';
|
|
3
|
+
import { Z as ToolDef } from './agent-C0hLXofc.js';
|
|
4
|
+
export { Y as ToolContext, a0 as ToolMap } from './agent-C0hLXofc.js';
|
|
5
5
|
export { V as ValidationResult, v as validateToolArgs } from './validation-DOY_k7lW.js';
|
|
6
6
|
import 'hookable';
|
|
7
7
|
import './presets.js';
|
package/dist/tools.js
CHANGED
|
@@ -11,10 +11,10 @@ import {
|
|
|
11
11
|
spawn,
|
|
12
12
|
validateToolArgs,
|
|
13
13
|
writeFile
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-O2XZLJMG.js";
|
|
15
15
|
import "./chunk-TPXPVEH6.js";
|
|
16
16
|
import "./chunk-2EQT4EHD.js";
|
|
17
|
-
import "./chunk-
|
|
17
|
+
import "./chunk-DRAYZZ23.js";
|
|
18
18
|
import "./chunk-LNN5UTS2.js";
|
|
19
19
|
export {
|
|
20
20
|
createInteractionTool,
|
package/dist/types.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export { A as Agent, a as AgentAbortedError, b as AgentBehavior, c as AgentContextExceededError, d as AgentHooks, e as AgentOptions, f as AgentProviderError, g as AgentRunOptions, h as AgentStats, i as AgentToolNotAllowedError, j as AnthropicParams, C as CONTEXT_EXCEEDED_MESSAGE_PATTERNS, k as CerebrasParams, l as ChildRunStats, m as ClassifiedError, n as ClassifiedErrorKind, o as CreateSessionOptions, I as ImageContent, M as McpConnection, p as McpServerConfig, q as McpToolHookContext, O as OAuthRefreshHookContext, r as OpenAIParams, s as OpenRouterParams, P as PromptDocumentPart, t as PromptImagePart, u as PromptPart, v as PromptTextPart, w as Provider, x as ProviderCapabilities, R as RemoteStoreOptions, y as RunHookMap, S as Session, z as SessionContentBlock, B as SessionData, D as SessionEndStatus, E as SessionHookContext, F as SessionMessage, G as SessionRun, H as SessionStore, J as SessionTurn, K as SkillConfig, L as SkillResource, N as SkillsConfig, Q as SpawnHookContext, T as StreamCallbacks, U as StreamHookContext, V as StreamOptions, W as ThinkingLevel, X as ToolCall, Y as ToolContext, Z as ToolDef, _ as ToolExecutionMode, $ as ToolHookContext, a0 as ToolMap, a1 as ToolResult, a2 as ToolResultContent, a3 as ToolResultImageContent, a4 as ToolResultTextContent, a5 as ToolSpec, a6 as TurnFinishReason, a7 as TurnResult, a8 as TurnUsage, a9 as matchesContextExceeded, aa as toolResultToText } from './agent-
|
|
1
|
+
export { A as Agent, a as AgentAbortedError, b as AgentBehavior, c as AgentContextExceededError, d as AgentHooks, e as AgentOptions, f as AgentProviderError, g as AgentRunOptions, h as AgentStats, i as AgentToolNotAllowedError, j as AnthropicParams, C as CONTEXT_EXCEEDED_MESSAGE_PATTERNS, k as CerebrasParams, l as ChildRunStats, m as ClassifiedError, n as ClassifiedErrorKind, o as CreateSessionOptions, I as ImageContent, M as McpConnection, p as McpServerConfig, q as McpToolHookContext, O as OAuthRefreshHookContext, r as OpenAIParams, s as OpenRouterParams, P as PromptDocumentPart, t as PromptImagePart, u as PromptPart, v as PromptTextPart, w as Provider, x as ProviderCapabilities, R as RemoteStoreOptions, y as RunHookMap, S as Session, z as SessionContentBlock, B as SessionData, D as SessionEndStatus, E as SessionHookContext, F as SessionMessage, G as SessionRun, H as SessionStore, J as SessionTurn, K as SkillConfig, L as SkillResource, N as SkillsConfig, Q as SpawnHookContext, T as StreamCallbacks, U as StreamHookContext, V as StreamOptions, W as ThinkingLevel, X as ToolCall, Y as ToolContext, Z as ToolDef, _ as ToolExecutionMode, $ as ToolHookContext, a0 as ToolMap, a1 as ToolResult, a2 as ToolResultContent, a3 as ToolResultImageContent, a4 as ToolResultTextContent, a5 as ToolSpec, a6 as TurnFinishReason, a7 as TurnResult, a8 as TurnUsage, a9 as matchesContextExceeded, aa as toolResultToText } from './agent-C0hLXofc.js';
|
|
2
2
|
export { C as ContextCapabilities, a as ContextType, E as ExecResult, b as ExecutionContext, c as ExecutionHandle, S as SpawnConfig } from './types-BpvTmawk.js';
|
|
3
3
|
export { S as SandboxProvider } from './sandbox-CW72eLDP.js';
|
|
4
4
|
export { Preset } from './presets.js';
|
|
5
|
-
export { C as ChildAgent, I as InteractionToolOptions, S as SpawnToolOptions, a as SpawnToolState } from './spawn-
|
|
5
|
+
export { C as ChildAgent, I as InteractionToolOptions, S as SpawnToolOptions, a as SpawnToolState } from './spawn-CT0ivxxH.js';
|
|
6
6
|
export { V as ValidationResult } from './validation-DOY_k7lW.js';
|
|
7
7
|
import 'hookable';
|
|
8
8
|
import '@modelcontextprotocol/sdk/client/index.js';
|