zidane 3.0.1 → 3.1.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
@@ -12,25 +12,17 @@ Built to be embedded.
12
12
 
13
13
  ## Features
14
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`, `read_file`, `write_file`, `edit`, `multi_edit`, `glob`, `grep`, `spawn`, human-in-the-loop, plus any [MCP](https://modelcontextprotocol.io) server. Sequential or parallel execution, per-call gates, typed hooks. Built-in tools ship with sensible truncation and idempotency defaults so consumers don't have to polyfill them.
18
- - ✂️ **Token-aware tool ergonomics** — `read_file` line-paginates with a footer that documents how to read the rest, `shell` tail-truncates combined output at 8 KB, `write_file` returns `No change needed` on idempotent writes. `outputBytes` surfaced on every tool/mcp hook.
19
- - 🧰 **Self-healing tool args** — `validateToolArgs` auto-coerces small/OSS-model mistakes (`"true"` `true`, `"42"` → `42`, JSON-encoded arrays) before reaching `execute`. `validation:reject` fires only on irrecoverable mismatches.
20
- - 🪤 **Hallucinated tool names** handled — `tool:unknown` fires before the default error so consumers can substitute a friendly response.
21
- - 📉 **Per-turn output budget** — `behavior.toolOutputBudget` injects a "summarize before continuing" message when a turn's tool outputs exceed the cap. Off by default.
22
- - 🧩 **[Agent Skills](https://agentskills.io/specification) spec-aligned** — discover, activate, and run skills with `allowed-tools` enforcement and session-resume rehydration.
23
- - 💾 **Pluggable sessions** — in-memory, SQLite, remote HTTP, or a file-map adapter. Turns persist incrementally a crash leaves valid partial history.
24
- - 🖼 **Multimodal** — images + documents via `PromptPart[]`; tools can return image blocks (screenshots, diagrams) routed natively on vision providers and via companion messages elsewhere.
25
- - 🧠 **Extended thinking** — named levels (`off` / `minimal` / `low` / `medium` / `high`) or exact token budgets; traces streamed + persisted.
26
- - ⚡ **Prompt caching** — auto-injected `cache_control` breakpoints on Anthropic + OpenRouter routes; cache-read / cache-write surfaced on `TurnUsage`.
27
- - 🚀 **Parallel MCP bootstrap** — every server connects concurrently with per-server timeouts; `agent.warmup()` + `eager: true` hide cold-start latency.
28
- - 🎯 **Structured output** — force the final answer to match a JSON Schema (Zod v4 interop), no brittle parsing.
29
- - 🧵 **Sub-agent spawning** — delegate to child agents with inherited or overridden preset; child stream/tool events bubble to the parent.
30
- - 🧭 **Typed errors** — `AgentContextExceededError` / `AgentProviderError` / `AgentAbortedError` instead of sniffing error strings.
31
- - 🔌 **Execution contexts** — run tools in-process, in Docker, or in a remote sandbox (E2B / Rivet / any `SandboxProvider`).
32
- - 🪝 **Hookable everything** — typed hook events covering turn, stream, tool, MCP, session, skills, spawn, OAuth refresh, bootstrap timing, validation rejection / coercion, and budget overflow.
33
- - 🧪 **1000+ tests, zero API keys** — mock providers + mock execution contexts; suite runs in under 2 seconds.
15
+ A small, hookable core with sensible defaults so most consumers don't write a single hook. Built around three principles: **token discipline by default** (cache, dedup, compaction, byte-accounting), **self-healing on the fault paths** (auto-coerce args, hallucinated-tool fallback, error rewriting), and **provider parity** (server-side features on Anthropic, client-side equivalents everywhere else).
16
+
17
+ - 🧠 **Multi-provider, multi-auth** — Anthropic, OpenAI Codex, OpenRouter, Cerebras, plus a generic `openaiCompat` factory (Baseten, Fireworks, Groq, local servers). OAuth + API key, auto-refreshing tokens. Anthropic accepts opt-in `extraBetas` and `contextManagement` for first-party features.
18
+ - 🪝 **Streaming, hookable turn loop** — text/thinking deltas, tool calls, MCP, sessions, skills, spawn, OAuth, validation, budgets all observable (and most mutatable) via typed hook events.
19
+ - 🛠 **Tools first-class** — `shell`, `read_file`, `write_file`, `edit`, `multi_edit`, `glob`, `grep`, `spawn`, human-in-the-loop, plus any [MCP](https://modelcontextprotocol.io) server. Sequential or parallel, per-call gates (`tool:gate`), validation auto-coerce (`"true"` → `true`), hallucinated-tool fallback (`tool:unknown`), error rewriting (`tool:error` `result`).
20
+ - ✂️ **Token-aware ergonomics** — paginated reads with a "how to page" footer, 8 KB tail-truncated `shell`, idempotent `write_file`; `outputBytes` surfaced on every tool/MCP hook. `behavior.toolOutputBudget` injects a "summarize" nudge when a turn's outputs exceed the cap.
21
+ - 🗜 **Context discipline** — auto-injected `cache_control` breakpoints (Anthropic + OpenRouter); server-side compaction via `context-management-2025-06-27` on Anthropic, `behavior.compactStrategy: 'tail'` on everyone else. Per-session `read_file` dedup + opt-in `requireReadBeforeEdit` guard kill stale-content edits.
22
+ - 🎯 **Reasoning + structured output** — thinking levels (`off` / `minimal` / `low` / `medium` / `high` / `adaptive`) with optional exact budgets; force the final answer to a JSON Schema (Zod v4 interop), no brittle parsing.
23
+ - 💾 **Sessions, skills, multimodal** — pluggable session stores (memory / SQLite / remote / file-map), incremental persistence; [Agent Skills](https://agentskills.io/specification) spec-aligned with `allowed-tools` enforcement + resume rehydration; images + documents via `PromptPart[]`, tools can return image blocks routed natively on vision providers or via companion messages elsewhere.
24
+ - 🧵 **Sub-agents + execution contexts** — delegate to child agents with inherited or overridden preset (child events bubble to the parent); run tools in-process, Docker, or any `SandboxProvider` (E2B / Rivet / custom). Parallel MCP bootstrap with `agent.warmup()` + `eager: true` to hide cold starts.
25
+ - 🧭 **Typed errors + 1000+ tests** — `AgentContextExceededError` / `AgentProviderError` / `AgentAbortedError` instead of sniffing strings. Suite runs in under 2s with mock providers + mock execution contexts, zero API keys.
34
26
 
35
27
  > Upgrading from 2.x? See [`docs/migrate-from-v2.md`](./docs/migrate-from-v2.md) for the full list of behavior changes.
36
28
 
@@ -77,6 +69,11 @@ createAgent({
77
69
  thinkingBudget: 10240, // exact thinking token budget
78
70
  cache: true, // prompt-cache breakpoints on supported providers (default: true)
79
71
  toolOutputBudget: 32768, // soft per-turn cap on tool-output bytes (off by default)
72
+ dedupReads: true, // dedup identical re-reads of the same file in `read_file` (default: true)
73
+ requireReadBeforeEdit: false, // refuse `edit` / `multi_edit` against unread or stale files (default: false)
74
+ compactStrategy: 'off', // client-side tail compaction for non-Anthropic providers — 'off' | 'tail' (default: 'off')
75
+ compactThreshold: 131_072, // bytes threshold that triggers tail compaction (default: 128 KiB)
76
+ compactKeepTurns: 4, // trailing turns left intact during compaction (default: 4)
80
77
  },
81
78
  execution: createProcessContext(), // where tools run
82
79
  mcpServers: [], // MCP tool servers
@@ -141,10 +138,30 @@ anthropic({ apiKey: 'sk-ant-...' })
141
138
  anthropic({ access: 'sk-ant-oat-...' }) // OAuth
142
139
  anthropic({ access: 'sk-ant-oat-...', refresh: '...', expires: Date.now() + 3600_000 }) // auto-refresh
143
140
  anthropic({ apiKey: '...', defaultModel: 'claude-sonnet-4-6' })
141
+
142
+ // Opt into first-party Anthropic betas + server-side context compaction:
143
+ anthropic({
144
+ apiKey: '...',
145
+ extraBetas: [
146
+ 'context-management-2025-06-27', // server-side, token-accurate compaction
147
+ 'token-efficient-tools-2026-03-28', // ~4.5% output token reduction
148
+ 'interleaved-thinking-2025-05-14', // think between tool calls in one turn
149
+ ],
150
+ contextManagement: {
151
+ edits: [{
152
+ type: 'clear_tool_uses_20250919',
153
+ trigger: { type: 'input_tokens', value: 180_000 },
154
+ clear_at_least: { type: 'input_tokens', value: 140_000 },
155
+ clear_tool_inputs: ['Read', 'Bash', 'Grep', 'Glob'],
156
+ }],
157
+ },
158
+ })
144
159
  ```
145
160
 
146
161
  Fallback: `params.apiKey` > `params.access` > `ANTHROPIC_API_KEY` env > `.credentials.json`
147
162
 
163
+ `extraBetas` are merged with the OAuth defaults (`claude-code-20250219`, `oauth-2025-04-20`) and de-duped. `contextManagement` is sent on the request body as `context_management`; pair it with the `context-management-2025-06-27` beta. For non-Anthropic providers, see `behavior.compactStrategy: 'tail'` for the client-side fallback.
164
+
148
165
  ### OpenRouter
149
166
 
150
167
  ```ts
@@ -270,6 +287,7 @@ Extended reasoning with named levels or exact token budgets.
270
287
  | `low` | 4,096 tokens |
271
288
  | `medium` | 10,240 tokens |
272
289
  | `high` | 32,768 tokens |
290
+ | `adaptive` | model self-budgets per turn |
273
291
 
274
292
  ```ts
275
293
  // Named level
@@ -278,12 +296,18 @@ await agent.run({ prompt: 'solve this', thinking: 'high' })
278
296
  // Exact budget (overrides level default)
279
297
  await agent.run({ prompt: 'solve this', thinking: 'high', behavior: { thinkingBudget: 50000 } })
280
298
 
299
+ // Adaptive — model self-budgets, but `thinkingBudget` caps the response envelope
300
+ // (max_tokens) to soft-bound runaway thinking on Anthropic.
301
+ await agent.run({ prompt: 'solve this', thinking: 'adaptive', behavior: { thinkingBudget: 32000 } })
302
+
281
303
  // Agent-level default
282
304
  const agent = createAgent({ ...basic, provider, behavior: { thinkingBudget: 16384 } })
283
305
  ```
284
306
 
285
307
  Thinking traces are stored in session turns as `{ type: 'thinking', text }` content blocks and streamed live via the `stream:thinking` hook. Supported by Anthropic (native) and OpenRouter/Cerebras (`reasoning_content`/`reasoning` SSE fields).
286
308
 
309
+ `adaptive` is Anthropic-specific (`thinking.type='adaptive'`) and avoids the `thinking.type='enabled'` deprecation warning on opus 4.6+. It has no native budget knob — when `thinkingBudget` is paired with `adaptive`, zidane caps `max_tokens = min(maxTokens, thinkingBudget)` so unbounded reasoning can't run away. Other providers fall back to no reasoning when `adaptive` is selected.
310
+
287
311
  ## Hooks
288
312
 
289
313
  Every hook receives a mutable context object.
@@ -352,7 +376,11 @@ agent.hooks.hook('tool:gate', (ctx) => {
352
376
 
353
377
  agent.hooks.hook('tool:before', (ctx) => { /* ctx.turnId, ctx.callId, ctx.name, ctx.input, ctx.coercions? */ })
354
378
  agent.hooks.hook('tool:after', (ctx) => { /* + ctx.result, ctx.outputBytes, ctx.coercions? */ })
355
- agent.hooks.hook('tool:error', (ctx) => { /* + ctx.error */ })
379
+ agent.hooks.hook('tool:error', (ctx) => {
380
+ // + ctx.error. Mutate ctx.result to substitute the payload sent back to the
381
+ // model in place of the default `Tool error: <msg>` — useful for OSS-model
382
+ // error rewriting (collapse stack traces, prepend recovery hints).
383
+ })
356
384
  agent.hooks.hook('tool:transform', (ctx) => {
357
385
  // + ctx.result, ctx.isError, ctx.outputBytes (pre-mutation), ctx.coercions? — mutate result/isError to modify.
358
386
  // Built-in tools already truncate; use this hook for consumer concerns the framework can't infer,
@@ -458,6 +486,30 @@ agent.hooks.hook('budget:exceeded', (ctx) => {
458
486
  })
459
487
  ```
460
488
 
489
+ ### Client-side context compaction (non-Anthropic)
490
+
491
+ For non-Anthropic providers (cerebras / openai-compat / openrouter on OSS models), `behavior.compactStrategy: 'tail'` elides older `tool_result` blocks from the wire-level message list once their combined size exceeds `compactThreshold`. The newest `compactKeepTurns` messages stay intact so the model retains the freshest tool context.
492
+
493
+ ```ts
494
+ const agent = createAgent({
495
+ ...basic,
496
+ provider: cerebras({ apiKey: '...' }),
497
+ behavior: {
498
+ compactStrategy: 'tail',
499
+ compactThreshold: 131_072, // 128 KiB; default
500
+ compactKeepTurns: 4, // default
501
+ },
502
+ })
503
+ ```
504
+
505
+ Anthropic users should prefer the server-side `context-management-2025-06-27` beta (token-accurate, configured via `anthropic({ extraBetas, contextManagement })`) — `'tail'` is a client-side approximation that exists because OSS-model providers have no server-side equivalent.
506
+
507
+ ### Read dedup + read-before-edit guard
508
+
509
+ `behavior.dedupReads` (on by default) — `read_file` returns a short `"unchanged since the previous read"` stub instead of re-emitting bytes when the model re-reads the same file with the same slice. Per-session content-hash; requires a session.
510
+
511
+ `behavior.requireReadBeforeEdit` (off by default) — `edit` and `multi_edit` reject when the file hasn't been read in the session, or when its on-disk content has drifted since the last read. Eliminates the silent-corruption case where a model edits against bytes it "remembers" but no longer reflect reality. Recommended on for stricter eval-grade runs.
512
+
461
513
  ## Steering and Follow-up
462
514
 
463
515
  ### Steering
@@ -216,6 +216,62 @@ interface AgentBehavior {
216
216
  * starting value for OSS-model integrations is `32768`.
217
217
  */
218
218
  toolOutputBudget?: number;
219
+ /**
220
+ * Deduplicate identical re-reads of the same file in `read_file`. When the
221
+ * model re-reads a file with the same slice and the bytes haven't changed
222
+ * since the last read in this session, the tool returns a short stub
223
+ * instead of re-emitting the full content. Pairs with the read-before-edit
224
+ * guard in `edit` / `multi_edit`.
225
+ *
226
+ * Requires a session (set via `createSession()`); without one, the flag is
227
+ * a no-op since per-session state has nowhere to live.
228
+ *
229
+ * Default: `true`.
230
+ */
231
+ dedupReads?: boolean;
232
+ /**
233
+ * Require `read_file` before `edit` / `multi_edit` on the same path, and
234
+ * reject edits when the file has changed on disk since the last read in
235
+ * this session. Eliminates the silent-corruption failure mode where a
236
+ * model "remembers" stale content and applies a substring edit against
237
+ * bytes that have moved.
238
+ *
239
+ * Requires a session. Off by default to preserve back-compat — turn it on
240
+ * for stricter eval-grade runs.
241
+ *
242
+ * Default: `false`.
243
+ */
244
+ requireReadBeforeEdit?: boolean;
245
+ /**
246
+ * Client-side context compaction strategy. Use this for non-Anthropic
247
+ * providers (OSS via cerebras / openai-compat / openrouter) that don't
248
+ * have a server-side equivalent. Anthropic users should prefer the
249
+ * server-side `context-management-2025-06-27` beta — see
250
+ * `AnthropicParams.contextManagement`.
251
+ *
252
+ * - `'off'` (default) — no client-side compaction.
253
+ * - `'tail'` — when total tool-output bytes in the persisted history
254
+ * exceed `compactThreshold`, replace older `tool_result` outputs with a
255
+ * short stub, keeping the newest `compactKeepTurns` turns intact. The
256
+ * compaction is applied to the wire-level message list only; the
257
+ * underlying session turns are not modified.
258
+ *
259
+ * Default: `'off'`.
260
+ */
261
+ compactStrategy?: 'off' | 'tail';
262
+ /**
263
+ * Soft byte threshold that triggers tail compaction when
264
+ * `compactStrategy === 'tail'`. Counts the post-`context:transform` bytes
265
+ * of `tool_result` outputs across all messages. Default: `131_072` (128
266
+ * KiB). Ignored when compaction is off.
267
+ */
268
+ compactThreshold?: number;
269
+ /**
270
+ * Number of trailing turns to leave untouched during tail compaction. The
271
+ * most-recent `compactKeepTurns` user/assistant messages are not eligible
272
+ * for elision so the model keeps the freshest tool context. Default: `4`.
273
+ */
274
+ compactKeepTurns?: number;
219
275
  }
220
276
  interface ImageContent {
221
277
  type: 'image';
@@ -541,6 +597,18 @@ interface OAuthRefreshHookContext {
541
597
  }
542
598
  type SessionEndStatus = 'completed' | 'aborted' | 'error';
543
599
 
600
+ /**
601
+ * Server-side context-management config — the body of `context_management` on
602
+ * the Messages API. Typed loosely (Record-of-unknown) so we don't pin a specific
603
+ * SDK schema version: the v0.90 SDK does not yet type this field, but the wire
604
+ * format is stable behind the `context-management-2025-06-27` beta.
605
+ *
606
+ * See: https://docs.anthropic.com/en/docs/build-with-claude/context-management
607
+ */
608
+ interface AnthropicContextManagement {
609
+ edits?: Array<Record<string, unknown>>;
610
+ [key: string]: unknown;
611
+ }
544
612
  interface AnthropicParams {
545
613
  apiKey?: string;
546
614
  access?: string;
@@ -553,6 +621,43 @@ interface AnthropicParams {
553
621
  * gateways, internal router).
554
622
  */
555
623
  baseURL?: string;
624
+ /**
625
+ * Additional `anthropic-beta` flags to opt into. Merged with the OAuth-path
626
+ * defaults (`claude-code-20250219`, `oauth-2025-04-20`); duplicates are
627
+ * de-duped. Examples:
628
+ *
629
+ * - `'context-management-2025-06-27'` — server-side context compaction
630
+ * (token-accurate; pair with {@link AnthropicParams.contextManagement}).
631
+ * - `'token-efficient-tools-2026-03-28'` — terser tool_use wire format.
632
+ * - `'interleaved-thinking-2025-05-14'` — think between tool calls within
633
+ * one turn.
634
+ * - `'redact-thinking-2026-02-12'` — replace large thinking blocks with
635
+ * stubs server-side.
636
+ * - `'prompt-caching-scope-2026-01-05'` — extended prompt-cache scope.
637
+ *
638
+ * Honored on both the OAuth and API-key paths.
639
+ */
640
+ extraBetas?: readonly string[];
641
+ /**
642
+ * Server-side context-management directive. Sent on the request body as
643
+ * `context_management`. Requires the `context-management-2025-06-27` beta —
644
+ * add it to {@link AnthropicParams.extraBetas}.
645
+ *
646
+ * Typed loosely so future Anthropic schema additions land without an SDK
647
+ * bump. A typical compaction edit:
648
+ *
649
+ * ```ts
650
+ * contextManagement: {
651
+ * edits: [{
652
+ * type: 'clear_tool_uses_20250919',
653
+ * trigger: { type: 'input_tokens', value: 180_000 },
654
+ * clear_at_least: { type: 'input_tokens', value: 140_000 },
655
+ * clear_tool_inputs: ['Read', 'Bash', 'Grep'],
656
+ * }],
657
+ * }
658
+ * ```
659
+ */
660
+ contextManagement?: AnthropicContextManagement;
556
661
  }
557
662
  declare function anthropic(anthropicParams?: AnthropicParams): Provider;
558
663
 
@@ -1466,8 +1571,18 @@ interface AgentHooks {
1466
1571
  outputBytes: number;
1467
1572
  coercions?: readonly string[];
1468
1573
  }) => void;
1574
+ /**
1575
+ * Fires when a tool throws during execution. Mutate `result` to substitute a
1576
+ * tool-output payload that gets sent back to the model in place of the
1577
+ * default `Tool error: <msg>` string — useful for OSS-model error rewriting
1578
+ * (collapse stack traces, hide internal paths, prepend recovery hints).
1579
+ *
1580
+ * The post-hook value flows through `tool:transform` like a normal output, so
1581
+ * downstream byte-budgeting and image-stripping still apply.
1582
+ */
1469
1583
  'tool:error': (ctx: ToolHookContext & {
1470
1584
  error: Error;
1585
+ result?: string | ToolResultContent[];
1471
1586
  }) => void;
1472
1587
  'tool:transform': (ctx: ToolHookContext & {
1473
1588
  result: string | ToolResultContent[];
@@ -5,7 +5,7 @@ import {
5
5
  toAnthropic,
6
6
  toolResultsMessage,
7
7
  userMessage
8
- } from "./chunk-CYWF2U62.js";
8
+ } from "./chunk-VF4A7HAC.js";
9
9
  import {
10
10
  matchesContextExceeded
11
11
  } from "./chunk-LNN5UTS2.js";
@@ -132,6 +132,28 @@ async function loadAnthropicSdk() {
132
132
  );
133
133
  }
134
134
  }
135
+ var OAUTH_DEFAULT_BETAS = ["claude-code-20250219", "oauth-2025-04-20"];
136
+ function resolveAnthropicBetas(isOAuth, extraBetas) {
137
+ const seen = /* @__PURE__ */ new Set();
138
+ const out = [];
139
+ if (isOAuth) {
140
+ for (const b of OAUTH_DEFAULT_BETAS) {
141
+ if (!seen.has(b)) {
142
+ seen.add(b);
143
+ out.push(b);
144
+ }
145
+ }
146
+ }
147
+ if (extraBetas) {
148
+ for (const b of extraBetas) {
149
+ if (typeof b === "string" && b.length > 0 && !seen.has(b)) {
150
+ seen.add(b);
151
+ out.push(b);
152
+ }
153
+ }
154
+ }
155
+ return out.length > 0 ? out.join(",") : void 0;
156
+ }
135
157
  function getConfiguredApiKey(anthropicParams) {
136
158
  if (anthropicParams?.apiKey)
137
159
  return anthropicParams.apiKey;
@@ -144,22 +166,31 @@ function getConfiguredApiKey(anthropicParams) {
144
166
  return access;
145
167
  throw new Error("No API key found. Run `bun run auth` first.");
146
168
  }
147
- function createClient(SDK, apiKey, isOAuth, baseURL) {
169
+ function createClient(SDK, apiKey, isOAuth, baseURL, extraBetas) {
148
170
  const base = baseURL ? { baseURL } : {};
149
- return new SDK(
150
- isOAuth ? {
171
+ const betaHeader = resolveAnthropicBetas(isOAuth, extraBetas);
172
+ if (isOAuth) {
173
+ const defaultHeaders2 = {
174
+ "anthropic-dangerous-direct-browser-access": "true",
175
+ "user-agent": "zidane/2.0.0",
176
+ "x-app": "cli"
177
+ };
178
+ if (betaHeader)
179
+ defaultHeaders2["anthropic-beta"] = betaHeader;
180
+ return new SDK({
151
181
  apiKey: null,
152
182
  authToken: apiKey,
153
183
  dangerouslyAllowBrowser: true,
154
- defaultHeaders: {
155
- "anthropic-beta": "claude-code-20250219,oauth-2025-04-20",
156
- "anthropic-dangerous-direct-browser-access": "true",
157
- "user-agent": "zidane/2.0.0",
158
- "x-app": "cli"
159
- },
184
+ defaultHeaders: defaultHeaders2,
160
185
  ...base
161
- } : { apiKey, ...base }
162
- );
186
+ });
187
+ }
188
+ const defaultHeaders = betaHeader ? { "anthropic-beta": betaHeader } : void 0;
189
+ return new SDK({
190
+ apiKey,
191
+ ...defaultHeaders ? { defaultHeaders } : {},
192
+ ...base
193
+ });
163
194
  }
164
195
  var EFFORT_FOR_LEVEL = {
165
196
  minimal: "low",
@@ -170,8 +201,11 @@ var EFFORT_FOR_LEVEL = {
170
201
  function planAnthropicThinking(level, customBudget) {
171
202
  if (level === "off")
172
203
  return null;
173
- if (level === "adaptive")
204
+ if (level === "adaptive") {
205
+ if (typeof customBudget === "number" && customBudget > 0)
206
+ return { kind: "adaptive", maxTokensCap: customBudget };
174
207
  return { kind: "adaptive" };
208
+ }
175
209
  if (customBudget !== void 0) {
176
210
  return { kind: "enabled", budgetTokens: customBudget, maxTokensBump: customBudget };
177
211
  }
@@ -384,7 +418,13 @@ function anthropic(anthropicParams) {
384
418
  }
385
419
  }
386
420
  );
387
- const client = createClient(SDK, apiKey, apiKey.includes("sk-ant-oat"), anthropicParams?.baseURL);
421
+ const client = createClient(
422
+ SDK,
423
+ apiKey,
424
+ apiKey.includes("sk-ant-oat"),
425
+ anthropicParams?.baseURL,
426
+ anthropicParams?.extraBetas
427
+ );
388
428
  const system = isOAuth ? `You are Claude Code, Anthropic's official CLI for Claude.` : options.system;
389
429
  const messages = isOAuth && options.system ? [
390
430
  { role: "user", content: [{ type: "text", text: options.system }] },
@@ -401,6 +441,10 @@ function anthropic(anthropicParams) {
401
441
  messages: messages.map((m) => toAnthropic(m)),
402
442
  stream: true
403
443
  };
444
+ if (anthropicParams?.contextManagement) {
445
+ ;
446
+ params.context_management = anthropicParams.contextManagement;
447
+ }
404
448
  if (options.cache !== false)
405
449
  applyAnthropicCacheBreakpoints(params);
406
450
  const plan = planAnthropicThinking(thinking, options.thinkingBudget);
@@ -412,6 +456,8 @@ function anthropic(anthropicParams) {
412
456
  params.thinking = { type: "adaptive" };
413
457
  if (plan.effort)
414
458
  params.output_config = { effort: plan.effort };
459
+ if (typeof plan.maxTokensCap === "number" && plan.maxTokensCap > 0)
460
+ params.max_tokens = Math.min(params.max_tokens, plan.maxTokensCap);
415
461
  }
416
462
  params.temperature = 1;
417
463
  }
@@ -37,6 +37,27 @@ function countExactMatches(haystack, needle) {
37
37
  return count;
38
38
  }
39
39
 
40
+ // src/tools/read-state.ts
41
+ var STATE = /* @__PURE__ */ new WeakMap();
42
+ function getReadState(session) {
43
+ if (!session)
44
+ return void 0;
45
+ let map = STATE.get(session);
46
+ if (!map) {
47
+ map = /* @__PURE__ */ new Map();
48
+ STATE.set(session, map);
49
+ }
50
+ return map;
51
+ }
52
+ function hashContent(text) {
53
+ let h = 2166136261;
54
+ for (let i = 0; i < text.length; i++) {
55
+ h ^= text.charCodeAt(i);
56
+ h = h + ((h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24)) >>> 0;
57
+ }
58
+ return h.toString(16).padStart(8, "0");
59
+ }
60
+
40
61
  // src/tools/edit.ts
41
62
  var edit = {
42
63
  spec: {
@@ -68,6 +89,15 @@ var edit = {
68
89
  } catch {
69
90
  return `Edit error: file not found: ${target}`;
70
91
  }
92
+ if (ctx.behavior?.requireReadBeforeEdit && ctx.session) {
93
+ const readState = getReadState(ctx.session);
94
+ const absKey = `${ctx.handle.cwd}::${target}`;
95
+ const prior = readState?.get(absKey);
96
+ if (!prior)
97
+ return `Edit error: ${target} has not been read in this session. Call read_file first so the edit applies against the current contents.`;
98
+ if (prior.contentHash !== hashContent(original))
99
+ return `Edit error: ${target} has changed on disk since the last read. Re-read the file before editing.`;
100
+ }
71
101
  const occurrences = countExactMatches(original, find);
72
102
  if (occurrences === 0) {
73
103
  const preview = nearestMatchPreview(original, find);
@@ -79,6 +109,14 @@ var edit = {
79
109
  if (updated === original)
80
110
  return `Edit error: replacement produced no change in ${target}.`;
81
111
  await ctx.execution.writeFile(ctx.handle, target, updated);
112
+ if (ctx.session) {
113
+ const readState = getReadState(ctx.session);
114
+ const absKey = `${ctx.handle.cwd}::${target}`;
115
+ const prior = readState?.get(absKey);
116
+ if (readState && prior) {
117
+ readState.set(absKey, { ...prior, contentHash: hashContent(updated), mtimeMs: Date.now() });
118
+ }
119
+ }
82
120
  return `Edited ${target}: replaced ${occurrences} occurrence${occurrences === 1 ? "" : "s"}.`;
83
121
  }
84
122
  };
@@ -443,6 +481,15 @@ var multiEdit = {
443
481
  } catch {
444
482
  return `multi_edit error: file not found: ${target}`;
445
483
  }
484
+ if (ctx.behavior?.requireReadBeforeEdit && ctx.session) {
485
+ const readState = getReadState(ctx.session);
486
+ const absKey = `${ctx.handle.cwd}::${target}`;
487
+ const prior = readState?.get(absKey);
488
+ if (!prior)
489
+ return `multi_edit error: ${target} has not been read in this session. Call read_file first so the edits apply against the current contents.`;
490
+ if (prior.contentHash !== hashContent(current))
491
+ return `multi_edit error: ${target} has changed on disk since the last read. Re-read the file before editing.`;
492
+ }
446
493
  let applied = 0;
447
494
  for (let i = 0; i < steps.length; i++) {
448
495
  const step = steps[i];
@@ -464,6 +511,14 @@ var multiEdit = {
464
511
  applied += occurrences;
465
512
  }
466
513
  await ctx.execution.writeFile(ctx.handle, target, current);
514
+ if (ctx.session) {
515
+ const readState = getReadState(ctx.session);
516
+ const absKey = `${ctx.handle.cwd}::${target}`;
517
+ const prior = readState?.get(absKey);
518
+ if (readState && prior) {
519
+ readState.set(absKey, { ...prior, contentHash: hashContent(current), mtimeMs: Date.now() });
520
+ }
521
+ }
467
522
  return `Edited ${target}: applied ${steps.length} edit${steps.length === 1 ? "" : "s"} (${applied} replacement${applied === 1 ? "" : "s"}).`;
468
523
  }
469
524
  };
@@ -496,12 +551,25 @@ var readFile = {
496
551
  return `File not found: ${path}`;
497
552
  }
498
553
  const totalBytes = Buffer.byteLength(raw);
554
+ const dedupEnabled = ctx.behavior?.dedupReads !== false;
555
+ const readState = dedupEnabled ? getReadState(ctx.session) : void 0;
556
+ const absKey = `${ctx.handle.cwd}::${path}`;
557
+ const offsetForKey = normalizeInteger(offset, 1);
558
+ const limitForKey = normalizeInteger(limit, DEFAULT_LINE_LIMIT);
559
+ const maxBytesForKey = normalizeInteger(maxBytes, DEFAULT_BYTE_CAP);
560
+ const currentHash = readState ? hashContent(raw) : "";
561
+ if (readState) {
562
+ const prior = readState.get(absKey);
563
+ if (prior && prior.contentHash === currentHash && prior.offset === offsetForKey && prior.limit === limitForKey && prior.maxBytes === maxBytesForKey) {
564
+ return `File ${path} unchanged since the previous read in this session \u2014 the prior result is still current.`;
565
+ }
566
+ }
499
567
  if (looksBinary(raw)) {
500
568
  return `[binary file: ${path}, ${totalBytes} bytes; use shell with hexdump | xxd | od to inspect]`;
501
569
  }
502
- const offsetN = normalizeInteger(offset, 1);
503
- const limitN = normalizeInteger(limit, DEFAULT_LINE_LIMIT);
504
- const maxBytesN = normalizeInteger(maxBytes, DEFAULT_BYTE_CAP);
570
+ const offsetN = offsetForKey;
571
+ const limitN = limitForKey;
572
+ const maxBytesN = maxBytesForKey;
505
573
  const lines = raw.split("\n");
506
574
  const totalLines = lines.length;
507
575
  const startIdx = Math.max(0, offsetN - 1);
@@ -546,6 +614,15 @@ var readFile = {
546
614
  const body = slice.join("\n");
547
615
  const linesReturned = slice.length;
548
616
  const lastLineRead = startIdx + linesReturned;
617
+ if (readState) {
618
+ readState.set(absKey, {
619
+ contentHash: currentHash,
620
+ offset: offsetN,
621
+ limit: limitN,
622
+ maxBytes: maxBytesN,
623
+ mtimeMs: Date.now()
624
+ });
625
+ }
549
626
  const linesTruncated = endIdx < totalLines || bytesCut;
550
627
  if (!linesTruncated && offsetN === 1)
551
628
  return body;
@@ -1101,6 +1178,43 @@ var IMAGE_OMITTED_MARKER = "[image omitted \u2014 model does not support vision]
1101
1178
  function turnsToMessages(turns) {
1102
1179
  return turns.filter((t) => t.role !== "system").map((t) => ({ role: t.role, content: t.content }));
1103
1180
  }
1181
+ var COMPACTION_STUB = "[\u2026elided by client-side tail compaction; ask the user or re-run the tool to retrieve.]";
1182
+ function applyTailCompaction(messages, threshold, keepTurns) {
1183
+ if (messages.length === 0)
1184
+ return messages;
1185
+ let totalBytes = 0;
1186
+ for (const msg of messages) {
1187
+ for (const block of msg.content) {
1188
+ if (block.type === "tool_result")
1189
+ totalBytes += toolOutputByteLength(block.output);
1190
+ }
1191
+ }
1192
+ if (totalBytes <= threshold)
1193
+ return messages;
1194
+ const keep = Math.max(0, keepTurns);
1195
+ const cutoff = messages.length - keep;
1196
+ if (cutoff <= 0)
1197
+ return messages;
1198
+ let changed = false;
1199
+ const out = messages.slice();
1200
+ for (let i = 0; i < cutoff; i++) {
1201
+ const msg = out[i];
1202
+ let msgChanged = false;
1203
+ const newContent = msg.content.map((block) => {
1204
+ if (block.type !== "tool_result")
1205
+ return block;
1206
+ const existingBytes = toolOutputByteLength(block.output);
1207
+ if (existingBytes <= COMPACTION_STUB.length)
1208
+ return block;
1209
+ msgChanged = true;
1210
+ changed = true;
1211
+ return { ...block, output: COMPACTION_STUB };
1212
+ });
1213
+ if (msgChanged)
1214
+ out[i] = { ...msg, content: newContent };
1215
+ }
1216
+ return changed ? out : messages;
1217
+ }
1104
1218
  function sanitizeStoredToolResults(provider, messages) {
1105
1219
  if (provider.meta.capabilities?.vision !== false)
1106
1220
  return messages;
@@ -1210,7 +1324,12 @@ async function executeTurn(ctx, turn) {
1210
1324
  const turnId = await ctx.generateTurnId();
1211
1325
  const canonicalMessages = turnsToMessages(ctx.turns);
1212
1326
  const wireMessages = rewriteMessagesToWire(canonicalMessages, ctx.aliasMaps);
1213
- const sanitizedMessages = sanitizeStoredToolResults(ctx.provider, wireMessages);
1327
+ let sanitizedMessages = sanitizeStoredToolResults(ctx.provider, wireMessages);
1328
+ if (ctx.compactStrategy === "tail") {
1329
+ const threshold = typeof ctx.compactThreshold === "number" && ctx.compactThreshold > 0 ? ctx.compactThreshold : 131072;
1330
+ const keep = typeof ctx.compactKeepTurns === "number" && ctx.compactKeepTurns >= 0 ? ctx.compactKeepTurns : 4;
1331
+ sanitizedMessages = applyTailCompaction(sanitizedMessages, threshold, keep);
1332
+ }
1214
1333
  const streamOptions = {
1215
1334
  model: ctx.model,
1216
1335
  system: ctx.system,
@@ -1479,15 +1598,16 @@ async function executeSingleTool(ctx, call, turnId) {
1479
1598
  output = await toolDef.execute(effectiveInput, toolCtx);
1480
1599
  } catch (err) {
1481
1600
  const error = err instanceof Error ? err : new Error(String(err));
1482
- await ctx.hooks.callHook("tool:error", {
1601
+ const errorCtx = {
1483
1602
  turnId,
1484
1603
  callId,
1485
1604
  name: call.name,
1486
1605
  displayName,
1487
1606
  input: effectiveInput,
1488
1607
  error
1489
- });
1490
- output = `Tool error: ${error.message}`;
1608
+ };
1609
+ await ctx.hooks.callHook("tool:error", errorCtx);
1610
+ output = errorCtx.result ?? `Tool error: ${error.message}`;
1491
1611
  isError = true;
1492
1612
  }
1493
1613
  const transformCtx = {
@@ -1690,7 +1810,10 @@ function resolveBehavior(agentBehavior, runBehavior) {
1690
1810
  thinkingBudget: runBehavior?.thinkingBudget ?? agentBehavior?.thinkingBudget,
1691
1811
  schema: runBehavior?.schema ?? agentBehavior?.schema,
1692
1812
  cache: runBehavior?.cache ?? agentBehavior?.cache ?? true,
1693
- toolOutputBudget: runBehavior?.toolOutputBudget ?? agentBehavior?.toolOutputBudget
1813
+ toolOutputBudget: runBehavior?.toolOutputBudget ?? agentBehavior?.toolOutputBudget,
1814
+ compactStrategy: runBehavior?.compactStrategy ?? agentBehavior?.compactStrategy ?? "off",
1815
+ compactThreshold: runBehavior?.compactThreshold ?? agentBehavior?.compactThreshold,
1816
+ compactKeepTurns: runBehavior?.compactKeepTurns ?? agentBehavior?.compactKeepTurns
1694
1817
  };
1695
1818
  }
1696
1819
  function createAgent({ provider, name: agentName, system: agentSystem, tools: agentTools, toolAliases, behavior: agentBehavior, execution, mcpServers, session, skills: agentSkills, mcpConnector, eager }) {
@@ -1813,7 +1936,7 @@ function createAgent({ provider, name: agentName, system: agentSystem, tools: ag
1813
1936
  }
1814
1937
  const thinking = options.thinking ?? "off";
1815
1938
  const model = options.model ?? provider.meta.defaultModel;
1816
- const { toolExecution, maxTurns, maxTokens, thinkingBudget, schema, cache, toolOutputBudget } = resolveBehavior(agentBehavior, options.behavior);
1939
+ const { toolExecution, maxTurns, maxTokens, thinkingBudget, schema, cache, toolOutputBudget, compactStrategy, compactThreshold, compactKeepTurns } = resolveBehavior(agentBehavior, options.behavior);
1817
1940
  let system = options.system || agentSystem || "You are a helpful assistant.";
1818
1941
  if (skillsCatalog) {
1819
1942
  system = `${system}
@@ -1949,6 +2072,9 @@ ${skillsCatalog}`;
1949
2072
  schema,
1950
2073
  cache,
1951
2074
  toolOutputBudget,
2075
+ compactStrategy,
2076
+ compactThreshold,
2077
+ compactKeepTurns,
1952
2078
  runStartMs
1953
2079
  });
1954
2080
  const finalStats = {
@@ -6,7 +6,7 @@ import {
6
6
  shell,
7
7
  spawn,
8
8
  writeFile
9
- } from "./chunk-QFHGWKK3.js";
9
+ } from "./chunk-PYLYK3K7.js";
10
10
 
11
11
  // src/presets/basic.ts
12
12
  var basicTools = { shell, readFile, writeFile, listFiles, edit, multiEdit };
@@ -433,6 +433,8 @@ function openaiCompat(params) {
433
433
  usage: {
434
434
  input: result.usage.input,
435
435
  output: result.usage.output,
436
+ ...result.usage.cacheRead !== void 0 ? { cacheRead: result.usage.cacheRead } : {},
437
+ ...result.usage.cacheCreation !== void 0 ? { cacheCreation: result.usage.cacheCreation } : {},
436
438
  ...result.usage.cost !== void 0 ? { cost: result.usage.cost } : {},
437
439
  ...finishReason ? { finishReason } : {},
438
440
  modelId
package/dist/index.d.ts CHANGED
@@ -1,12 +1,12 @@
1
- import { d as AgentHooks } from './agent-4zeSbdXy.js';
2
- export { ac as ActivationVia, ad 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, ae as DeactivationReason, af as FileMapAdapter, ag as FileMapStoreOptions, I as ImageContent, M as McpConnection, p as McpServerConfig, q as McpToolHookContext, O as OAuthRefreshHookContext, ah as OpenAICompatAuthHeader, ai as OpenAICompatHttpError, aj 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, ak as SkillActivationState, al as SkillActivationStateOptions, K as SkillConfig, am as SkillDiagnostic, L as SkillResource, an 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, ao as anthropic, ap as autoDetectAndConvert, aq as cerebras, ar as classifyOpenAICompatError, as as connectMcpServers, at as createAgent, au as createFileMapStore, av as createMemoryStore, aw as createRemoteStore, ax as createSession, ay as createSkillActivationState, az as fromAnthropic, aA as fromOpenAI, aB as loadSession, aC as mapOAIFinishReason, a9 as matchesContextExceeded, aD as normalizeMcpBlocks, aE as normalizeMcpServers, aF as openai, aG as openaiCompat, aH as openrouter, aI as resultToString, aJ as toAnthropic, aK as toOpenAI, aL as toTypedError, aa as toolOutputByteLength, ab as toolResultToText } from './agent-4zeSbdXy.js';
1
+ import { d as AgentHooks } from './agent-O5SmWixc.js';
2
+ export { ac as ActivationVia, ad 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, ae as DeactivationReason, af as FileMapAdapter, ag as FileMapStoreOptions, I as ImageContent, M as McpConnection, p as McpServerConfig, q as McpToolHookContext, O as OAuthRefreshHookContext, ah as OpenAICompatAuthHeader, ai as OpenAICompatHttpError, aj 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, ak as SkillActivationState, al as SkillActivationStateOptions, K as SkillConfig, am as SkillDiagnostic, L as SkillResource, an 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, ao as anthropic, ap as autoDetectAndConvert, aq as cerebras, ar as classifyOpenAICompatError, as as connectMcpServers, at as createAgent, au as createFileMapStore, av as createMemoryStore, aw as createRemoteStore, ax as createSession, ay as createSkillActivationState, az as fromAnthropic, aA as fromOpenAI, aB as loadSession, aC as mapOAIFinishReason, a9 as matchesContextExceeded, aD as normalizeMcpBlocks, aE as normalizeMcpServers, aF as openai, aG as openaiCompat, aH as openrouter, aI as resultToString, aJ as toAnthropic, aK as toOpenAI, aL as toTypedError, aa as toolOutputByteLength, ab as toolResultToText } from './agent-O5SmWixc.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, f as edit, g as glob, h as grep, m as multiEdit } from './skills-use-DhxQaluD.js';
9
- export { C as ChildAgent, I as InteractionToolOptions, S as SpawnToolOptions, a as SpawnToolState, V as ValidationResult, c as createInteractionTool, b as createSpawnTool, s as spawn, v as validateToolArgs } from './validation-CYISGVTn.js';
8
+ export { S as SkillsReadToolOptions, a as SkillsRunScriptToolOptions, b as SkillsUseToolOptions, c as createSkillsReadTool, d as createSkillsRunScriptTool, e as createSkillsUseTool, f as edit, g as glob, h as grep, m as multiEdit } from './skills-use-DJKUctM5.js';
9
+ export { C as ChildAgent, I as InteractionToolOptions, S as SpawnToolOptions, a as SpawnToolState, V as ValidationResult, c as createInteractionTool, b as createSpawnTool, s as spawn, v as validateToolArgs } from './validation-DE4g5Cez.js';
10
10
  import { Hookable } from 'hookable';
11
11
  import '@modelcontextprotocol/sdk/client/index.js';
12
12
 
package/dist/index.js CHANGED
@@ -6,12 +6,12 @@ import {
6
6
  cerebras,
7
7
  openai,
8
8
  openrouter
9
- } from "./chunk-HQD5ICI6.js";
9
+ } from "./chunk-FEAOZ5DB.js";
10
10
  import {
11
11
  basicTools,
12
12
  basic_default,
13
13
  definePreset
14
- } from "./chunk-2VM47IBI.js";
14
+ } from "./chunk-SARMZCEL.js";
15
15
  import {
16
16
  createAgent,
17
17
  createInteractionTool,
@@ -25,7 +25,7 @@ import {
25
25
  multiEdit,
26
26
  spawn,
27
27
  validateToolArgs
28
- } from "./chunk-QFHGWKK3.js";
28
+ } from "./chunk-PYLYK3K7.js";
29
29
  import {
30
30
  IMPLICITLY_ALLOWED_SKILL_TOOLS,
31
31
  buildCatalog,
@@ -76,7 +76,7 @@ import {
76
76
  openaiCompat,
77
77
  toAnthropic,
78
78
  toOpenAI
79
- } from "./chunk-CYWF2U62.js";
79
+ } from "./chunk-VF4A7HAC.js";
80
80
  import {
81
81
  AgentAbortedError,
82
82
  AgentContextExceededError,
package/dist/mcp.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import 'hookable';
2
- export { M as McpConnection, p as McpServerConfig, as as connectMcpServers, aD as normalizeMcpBlocks, aE as normalizeMcpServers, aI as resultToString } from './agent-4zeSbdXy.js';
2
+ export { M as McpConnection, p as McpServerConfig, as as connectMcpServers, aD as normalizeMcpBlocks, aE as normalizeMcpServers, aI as resultToString } from './agent-O5SmWixc.js';
3
3
  import '@modelcontextprotocol/sdk/client/index.js';
4
4
  import './types-BpvTmawk.js';
package/dist/presets.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Z as ToolDef, e as AgentOptions } from './agent-4zeSbdXy.js';
1
+ import { Z as ToolDef, e as AgentOptions } from './agent-O5SmWixc.js';
2
2
  import 'hookable';
3
3
  import './types-BpvTmawk.js';
4
4
  import '@modelcontextprotocol/sdk/client/index.js';
package/dist/presets.js CHANGED
@@ -2,8 +2,8 @@ import {
2
2
  basicTools,
3
3
  basic_default,
4
4
  definePreset
5
- } from "./chunk-2VM47IBI.js";
6
- import "./chunk-QFHGWKK3.js";
5
+ } from "./chunk-SARMZCEL.js";
6
+ import "./chunk-PYLYK3K7.js";
7
7
  import "./chunk-TPXPVEH6.js";
8
8
  import "./chunk-2EQT4EHD.js";
9
9
  import "./chunk-R74LQKAM.js";
@@ -1,4 +1,4 @@
1
- export { j as AnthropicParams, k as CerebrasParams, ah as OpenAICompatAuthHeader, ai as OpenAICompatHttpError, aj 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, ao as anthropic, aq as cerebras, ar as classifyOpenAICompatError, aC as mapOAIFinishReason, aF as openai, aG as openaiCompat, aH as openrouter } from './agent-4zeSbdXy.js';
1
+ export { j as AnthropicParams, k as CerebrasParams, ah as OpenAICompatAuthHeader, ai as OpenAICompatHttpError, aj 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, ao as anthropic, aq as cerebras, ar as classifyOpenAICompatError, aC as mapOAIFinishReason, aF as openai, aG as openaiCompat, aH as openrouter } from './agent-O5SmWixc.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-HQD5ICI6.js";
6
+ } from "./chunk-FEAOZ5DB.js";
7
7
  import {
8
8
  OpenAICompatHttpError,
9
9
  classifyOpenAICompatError,
10
10
  mapOAIFinishReason,
11
11
  openaiCompat
12
- } from "./chunk-CYWF2U62.js";
12
+ } from "./chunk-VF4A7HAC.js";
13
13
  import "./chunk-LNN5UTS2.js";
14
14
  export {
15
15
  OpenAICompatHttpError,
@@ -1,4 +1,4 @@
1
- import { H as SessionStore } from '../agent-4zeSbdXy.js';
1
+ import { H as SessionStore } from '../agent-O5SmWixc.js';
2
2
  import 'hookable';
3
3
  import '../types-BpvTmawk.js';
4
4
  import '@modelcontextprotocol/sdk/client/index.js';
package/dist/session.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { o as CreateSessionOptions, af as FileMapAdapter, ag 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, ap as autoDetectAndConvert, au as createFileMapStore, av as createMemoryStore, aw as createRemoteStore, ax as createSession, az as fromAnthropic, aA as fromOpenAI, aB as loadSession, aJ as toAnthropic, aK as toOpenAI } from './agent-4zeSbdXy.js';
1
+ export { o as CreateSessionOptions, af as FileMapAdapter, ag 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, ap as autoDetectAndConvert, au as createFileMapStore, av as createMemoryStore, aw as createRemoteStore, ax as createSession, az as fromAnthropic, aA as fromOpenAI, aB as loadSession, aJ as toAnthropic, aK as toOpenAI } from './agent-O5SmWixc.js';
2
2
  import 'hookable';
3
3
  import './types-BpvTmawk.js';
4
4
  import '@modelcontextprotocol/sdk/client/index.js';
package/dist/session.js CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  fromOpenAI,
12
12
  toAnthropic,
13
13
  toOpenAI
14
- } from "./chunk-CYWF2U62.js";
14
+ } from "./chunk-VF4A7HAC.js";
15
15
  import "./chunk-LNN5UTS2.js";
16
16
  export {
17
17
  autoDetectAndConvert,
@@ -1,4 +1,4 @@
1
- import { Z as ToolDef, K as SkillConfig, ak as SkillActivationState, d as AgentHooks } from './agent-4zeSbdXy.js';
1
+ import { Z as ToolDef, K as SkillConfig, ak as SkillActivationState, d as AgentHooks } from './agent-O5SmWixc.js';
2
2
  import { Hookable } from 'hookable';
3
3
 
4
4
  /**
package/dist/skills.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { d as AgentHooks, ak as SkillActivationState, K as SkillConfig, an as SkillSource, am as SkillDiagnostic, N as SkillsConfig } from './agent-4zeSbdXy.js';
2
- export { ac as ActivationVia, ad as ActiveSkill, ae as DeactivationReason, al as SkillActivationStateOptions, L as SkillResource, ay as createSkillActivationState } from './agent-4zeSbdXy.js';
1
+ import { d as AgentHooks, ak as SkillActivationState, K as SkillConfig, an as SkillSource, am as SkillDiagnostic, N as SkillsConfig } from './agent-O5SmWixc.js';
2
+ export { ac as ActivationVia, ad as ActiveSkill, ae as DeactivationReason, al as SkillActivationStateOptions, L as SkillResource, ay as createSkillActivationState } from './agent-O5SmWixc.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, f as edit, g as glob, h as grep, m as multiEdit } from './skills-use-DhxQaluD.js';
2
- export { C as ChildAgent, I as InteractionToolOptions, S as SpawnToolOptions, a as SpawnToolState, V as ValidationResult, c as createInteractionTool, b as createSpawnTool, s as spawn, v as validateToolArgs } from './validation-CYISGVTn.js';
3
- import { Z as ToolDef } from './agent-4zeSbdXy.js';
4
- export { Y as ToolContext, a0 as ToolMap } from './agent-4zeSbdXy.js';
1
+ export { S as SkillsReadToolOptions, a as SkillsRunScriptToolOptions, b as SkillsUseToolOptions, c as createSkillsReadTool, d as createSkillsRunScriptTool, e as createSkillsUseTool, f as edit, g as glob, h as grep, m as multiEdit } from './skills-use-DJKUctM5.js';
2
+ export { C as ChildAgent, I as InteractionToolOptions, S as SpawnToolOptions, a as SpawnToolState, V as ValidationResult, c as createInteractionTool, b as createSpawnTool, s as spawn, v as validateToolArgs } from './validation-DE4g5Cez.js';
3
+ import { Z as ToolDef } from './agent-O5SmWixc.js';
4
+ export { Y as ToolContext, a0 as ToolMap } from './agent-O5SmWixc.js';
5
5
  import 'hookable';
6
6
  import './presets.js';
7
7
  import './types-BpvTmawk.js';
package/dist/tools.js CHANGED
@@ -14,7 +14,7 @@ import {
14
14
  spawn,
15
15
  validateToolArgs,
16
16
  writeFile
17
- } from "./chunk-QFHGWKK3.js";
17
+ } from "./chunk-PYLYK3K7.js";
18
18
  import "./chunk-TPXPVEH6.js";
19
19
  import "./chunk-2EQT4EHD.js";
20
20
  import "./chunk-R74LQKAM.js";
package/dist/types.d.ts CHANGED
@@ -1,7 +1,7 @@
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 toolOutputByteLength, ab as toolResultToText } from './agent-4zeSbdXy.js';
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 toolOutputByteLength, ab as toolResultToText } from './agent-O5SmWixc.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, V as ValidationResult } from './validation-CYISGVTn.js';
5
+ export { C as ChildAgent, I as InteractionToolOptions, S as SpawnToolOptions, a as SpawnToolState, V as ValidationResult } from './validation-DE4g5Cez.js';
6
6
  import 'hookable';
7
7
  import '@modelcontextprotocol/sdk/client/index.js';
@@ -1,4 +1,4 @@
1
- import { Y as ToolContext, Z as ToolDef, h as AgentStats, l as ChildRunStats } from './agent-4zeSbdXy.js';
1
+ import { Y as ToolContext, Z as ToolDef, h as AgentStats, l as ChildRunStats } from './agent-O5SmWixc.js';
2
2
  import { Preset } from './presets.js';
3
3
 
4
4
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zidane",
3
- "version": "3.0.1",
3
+ "version": "3.1.0",
4
4
  "description": "an agent that goes straight to the goal",
5
5
  "type": "module",
6
6
  "private": false,
@@ -77,7 +77,7 @@
77
77
  "md4x": "^0.0.25"
78
78
  },
79
79
  "peerDependencies": {
80
- "@anthropic-ai/sdk": "^0.88.0",
80
+ "@anthropic-ai/sdk": "^0.90.0",
81
81
  "@modelcontextprotocol/sdk": ">=1.11.0",
82
82
  "zod": ">=4.0.0"
83
83
  },