zidane 5.13.26 → 5.14.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.
Files changed (145) hide show
  1. package/dist/{acp-CjAoILwj.js → acp-DgKEJH3P.js} +7 -7
  2. package/dist/{acp-CjAoILwj.js.map → acp-DgKEJH3P.js.map} +1 -1
  3. package/dist/acp-cli.js +11 -6
  4. package/dist/acp-cli.js.map +1 -1
  5. package/dist/acp.d.ts +2 -2
  6. package/dist/acp.js +1 -1
  7. package/dist/{tools-B32lZXLE.js → agent-B-cKanSC.js} +8035 -9459
  8. package/dist/agent-B-cKanSC.js.map +1 -0
  9. package/dist/{agent-DQIL5BFk.d.ts → agent-BAgOgS37.d.ts} +367 -208
  10. package/dist/agent-BAgOgS37.d.ts.map +1 -0
  11. package/dist/agent.d.ts +3 -0
  12. package/dist/agent.js +5 -0
  13. package/dist/anthropic-RGqsJlC8.js +807 -0
  14. package/dist/anthropic-RGqsJlC8.js.map +1 -0
  15. package/dist/{atomic-write-Bgtr5JPu.js → atomic-write-B7zr1ddF.js} +2 -2
  16. package/dist/{atomic-write-Bgtr5JPu.js.map → atomic-write-B7zr1ddF.js.map} +1 -1
  17. package/dist/{auth-DPrSP1YV.js → auth-C-ms5N2x.js} +33 -5
  18. package/dist/{auth-DPrSP1YV.js.map → auth-C-ms5N2x.js.map} +1 -1
  19. package/dist/cache-telemetry-BKAwsNxm.js +169 -0
  20. package/dist/cache-telemetry-BKAwsNxm.js.map +1 -0
  21. package/dist/chat/pure.d.ts +3 -3
  22. package/dist/chat/pure.js +1 -1
  23. package/dist/chat.d.ts +21 -7
  24. package/dist/chat.d.ts.map +1 -1
  25. package/dist/chat.js +30 -5
  26. package/dist/chat.js.map +1 -1
  27. package/dist/contexts/daytona.d.ts +1 -1
  28. package/dist/contexts/docker.js +0 -1
  29. package/dist/contexts/docker.js.map +1 -1
  30. package/dist/contexts/e2b.d.ts +1 -1
  31. package/dist/errors-CkTvg97v.d.ts +203 -0
  32. package/dist/errors-CkTvg97v.d.ts.map +1 -0
  33. package/dist/errors.d.ts +3 -0
  34. package/dist/errors.js +3 -0
  35. package/dist/eval.d.ts +1 -1
  36. package/dist/eval.js +2 -2
  37. package/dist/headless.d.ts +1 -1
  38. package/dist/headless.js +406 -1
  39. package/dist/headless.js.map +1 -0
  40. package/dist/{index-YY3vp2F2.d.ts → index-CLuLFFLa.d.ts} +88 -418
  41. package/dist/index-CLuLFFLa.d.ts.map +1 -0
  42. package/dist/{index-C5qw3pj7.d.ts → index-CgBIl2mX.d.ts} +2 -2
  43. package/dist/{index-C5qw3pj7.d.ts.map → index-CgBIl2mX.d.ts.map} +1 -1
  44. package/dist/index.d.ts +9 -5
  45. package/dist/index.js +113 -167
  46. package/dist/index.js.map +1 -1
  47. package/dist/{logger-C2ngE8CY.d.ts → logger-CJ-lpKPy.d.ts} +2 -2
  48. package/dist/{logger-C2ngE8CY.d.ts.map → logger-CJ-lpKPy.d.ts.map} +1 -1
  49. package/dist/mcp.d.ts +1 -1
  50. package/dist/messages-YZQLKaz2.js +1157 -0
  51. package/dist/messages-YZQLKaz2.js.map +1 -0
  52. package/dist/oauth-8LqbeI_Q.js +292 -0
  53. package/dist/oauth-8LqbeI_Q.js.map +1 -0
  54. package/dist/{messages-Iy_vEycX.js → openai-compat-0Y7jcncn.js} +27 -1379
  55. package/dist/openai-compat-0Y7jcncn.js.map +1 -0
  56. package/dist/output/stream-json.d.ts +2 -2
  57. package/dist/output/stream-json.js +1 -1
  58. package/dist/output/terminal.d.ts +2 -2
  59. package/dist/{presets-B9nDwmaz.js → presets-Pr02ZNcy.js} +3 -2
  60. package/dist/{presets-B9nDwmaz.js.map → presets-Pr02ZNcy.js.map} +1 -1
  61. package/dist/presets.d.ts +2 -2
  62. package/dist/presets.js +1 -1
  63. package/dist/prompt.d.ts +2 -0
  64. package/dist/prompt.js +210 -0
  65. package/dist/prompt.js.map +1 -0
  66. package/dist/providers/anthropic.d.ts +2 -0
  67. package/dist/providers/anthropic.js +2 -0
  68. package/dist/providers/arcee.d.ts +2 -0
  69. package/dist/providers/arcee.js +42 -0
  70. package/dist/providers/arcee.js.map +1 -0
  71. package/dist/providers/baseten.d.ts +2 -0
  72. package/dist/providers/baseten.js +66 -0
  73. package/dist/providers/baseten.js.map +1 -0
  74. package/dist/providers/cerebras.d.ts +2 -0
  75. package/dist/providers/cerebras.js +31 -0
  76. package/dist/providers/cerebras.js.map +1 -0
  77. package/dist/providers/local.d.ts +2 -0
  78. package/dist/providers/local.js +44 -0
  79. package/dist/providers/local.js.map +1 -0
  80. package/dist/providers/openai-compat.d.ts +2 -0
  81. package/dist/providers/openai-compat.js +2 -0
  82. package/dist/providers/openai.d.ts +2 -0
  83. package/dist/providers/openai.js +504 -0
  84. package/dist/providers/openai.js.map +1 -0
  85. package/dist/providers/openrouter.d.ts +2 -0
  86. package/dist/providers/openrouter.js +52 -0
  87. package/dist/providers/openrouter.js.map +1 -0
  88. package/dist/providers/xai.d.ts +2 -0
  89. package/dist/providers/xai.js +2 -0
  90. package/dist/providers-DgmdYGKm.js +168 -0
  91. package/dist/providers-DgmdYGKm.js.map +1 -0
  92. package/dist/providers.d.ts +1 -1
  93. package/dist/providers.js +10 -2
  94. package/dist/restate.d.ts +1 -1
  95. package/dist/run-summary-DAnBZnrt.d.ts +249 -0
  96. package/dist/run-summary-DAnBZnrt.d.ts.map +1 -0
  97. package/dist/run-summary-nD3IQ4ZQ.js +253 -0
  98. package/dist/run-summary-nD3IQ4ZQ.js.map +1 -0
  99. package/dist/session/sqlite.d.ts +1 -1
  100. package/dist/{session-CiA1_8SB.js → session-CqrAFAKJ.js} +2 -2
  101. package/dist/{session-CiA1_8SB.js.map → session-CqrAFAKJ.js.map} +1 -1
  102. package/dist/session.d.ts +1 -1
  103. package/dist/session.js +2 -2
  104. package/dist/skills.d.ts +2 -2
  105. package/dist/system-prompt-BlsdjcUi.d.ts +139 -0
  106. package/dist/system-prompt-BlsdjcUi.d.ts.map +1 -0
  107. package/dist/timeout-CpFm0jJ6.d.ts +10 -0
  108. package/dist/timeout-CpFm0jJ6.d.ts.map +1 -0
  109. package/dist/timeout-kGGSXagK.js +84 -0
  110. package/dist/timeout-kGGSXagK.js.map +1 -0
  111. package/dist/{tool-formatters-w5oaoCS4.d.ts → tool-formatters-Ch8oRpYR.d.ts} +2 -2
  112. package/dist/{tool-formatters-w5oaoCS4.d.ts.map → tool-formatters-Ch8oRpYR.d.ts.map} +1 -1
  113. package/dist/tools/fetch-url.d.ts +1 -1
  114. package/dist/tools/web-search.d.ts +1 -1
  115. package/dist/tools-00_Nqazv.js +1689 -0
  116. package/dist/tools-00_Nqazv.js.map +1 -0
  117. package/dist/tools.d.ts +2 -2
  118. package/dist/tools.js +2 -1
  119. package/dist/{transcript-anchors-BUtOd-qa.js → transcript-anchors-BUmvPnis.js} +10 -9
  120. package/dist/{transcript-anchors-BUtOd-qa.js.map → transcript-anchors-BUmvPnis.js.map} +1 -1
  121. package/dist/{transcript-anchors-BJ-ESWnm.d.ts → transcript-anchors-CL9UM_M4.d.ts} +4 -4
  122. package/dist/{transcript-anchors-BJ-ESWnm.d.ts.map → transcript-anchors-CL9UM_M4.d.ts.map} +1 -1
  123. package/dist/tui.d.ts +3 -3
  124. package/dist/tui.js +38 -13
  125. package/dist/tui.js.map +1 -1
  126. package/dist/{turn-operations-BSSQHNq1.d.ts → turn-operations-Cj6v_ypW.d.ts} +3 -3
  127. package/dist/{turn-operations-BSSQHNq1.d.ts.map → turn-operations-Cj6v_ypW.d.ts.map} +1 -1
  128. package/dist/{turn-operations-B_XeuNp-.js → turn-operations-tG0vuBNc.js} +2 -2
  129. package/dist/{turn-operations-B_XeuNp-.js.map → turn-operations-tG0vuBNc.js.map} +1 -1
  130. package/dist/types-CyVGdbia.js.map +1 -1
  131. package/dist/types.d.ts +4 -3
  132. package/dist/xai-tPdbAGkq.js +379 -0
  133. package/dist/xai-tPdbAGkq.js.map +1 -0
  134. package/docs/ARCHITECTURE.md +4 -2
  135. package/docs/CHAT.md +4 -0
  136. package/docs/SKILL.md +31 -5
  137. package/package.json +63 -1
  138. package/dist/agent-DQIL5BFk.d.ts.map +0 -1
  139. package/dist/headless-2SH7dvoW.js +0 -656
  140. package/dist/headless-2SH7dvoW.js.map +0 -1
  141. package/dist/index-YY3vp2F2.d.ts.map +0 -1
  142. package/dist/messages-Iy_vEycX.js.map +0 -1
  143. package/dist/providers-BMw1D_lj.js +0 -2332
  144. package/dist/providers-BMw1D_lj.js.map +0 -1
  145. package/dist/tools-B32lZXLE.js.map +0 -1
@@ -0,0 +1,807 @@
1
+ import { t as lazyAsync } from "./lazy-DLOurOC_.js";
2
+ import { c as classifyErrorPrelude, d as isRetryableHttpStatus, f as matchesContextExceeded, p as matchesToolPairingError } from "./errors-DJUxZg9b.js";
3
+ import { b as fillEstimatedCost, w as unsupportedMediaError, y as sanitizeToolSpecs } from "./openai-compat-0Y7jcncn.js";
4
+ import { renderSystemForWire, splitSystemPrompt } from "./prompt.js";
5
+ import { l as fromAnthropic, p as toAnthropic } from "./messages-YZQLKaz2.js";
6
+ import { i as resolveOAuthApiKey, r as readOAuthCredentials, t as extractRuntimeCredentials } from "./oauth-8LqbeI_Q.js";
7
+ //#region src/chat/anthropic-models.ts
8
+ /**
9
+ * Anthropic "fast mode" — `speed: "fast"` on the Messages API. ~2.5× output
10
+ * tokens/sec at a per-model price multiplier. Supported on Opus 4.6 / 4.7 / 4.8
11
+ * only; the API errors if sent on any other model, so it's attached just to
12
+ * those entries (see {@link FAST_MODE_OPTIONS}).
13
+ *
14
+ * The multiplier scales ALL rate components (input, output, and both cache
15
+ * rates) uniformly: per Anthropic, "prompt caching multipliers apply on top of
16
+ * fast mode pricing" across the full context window. Opus 4.8 is 2× ($5/$25 →
17
+ * $10/$50); Opus 4.6 / 4.7 are a steeper 6× ($5/$25 → $30/$150).
18
+ * See https://platform.claude.com/docs/en/build-with-claude/fast-mode.
19
+ */
20
+ const FAST_MODE_OPTION = {
21
+ id: "fast",
22
+ label: "Fast mode",
23
+ description: "~2.5× faster output at premium pricing",
24
+ costMultiplier: {
25
+ input: 2,
26
+ output: 2,
27
+ cacheRead: 2,
28
+ cacheWrite: 2
29
+ }
30
+ };
31
+ const FAST_MODE_OPTION_LEGACY = {
32
+ ...FAST_MODE_OPTION,
33
+ description: "~2.5× faster output at 6× pricing",
34
+ costMultiplier: {
35
+ input: 6,
36
+ output: 6,
37
+ cacheRead: 6,
38
+ cacheWrite: 6
39
+ }
40
+ };
41
+ /** Model ids that accept `speed: "fast"`, mapped to their fast-mode option. */
42
+ const FAST_MODE_OPTIONS = {
43
+ "claude-opus-4-8": FAST_MODE_OPTION,
44
+ "claude-opus-4-7": FAST_MODE_OPTION_LEGACY,
45
+ "claude-opus-4-6": FAST_MODE_OPTION_LEGACY
46
+ };
47
+ /**
48
+ * The price multiplier to apply to a model's base rates when fast mode is
49
+ * active, or `undefined` when the model has no fast-mode pricing (i.e. doesn't
50
+ * support it). Mirrors {@link FAST_MODE_OPTIONS} — kept as a separate accessor
51
+ * so the cost layer can stay decoupled from the picker-facing option objects.
52
+ */
53
+ function fastModeCostMultiplier(modelId) {
54
+ return FAST_MODE_OPTIONS[modelId]?.costMultiplier;
55
+ }
56
+ /**
57
+ * Claude Fable 5 — GA 2026-06-09. Anthropic's most capable widely released
58
+ * model: $10/$50 per MTok, 1M context, 128k output, adaptive thinking
59
+ * (always on), vision. No fast-mode support (Opus 4.6/4.7/4.8 only).
60
+ *
61
+ * Claude Opus 4.8 — shipped 2026-05-28. Same price/context/output as Opus 4.7
62
+ * ($5/$25 per MTok, 1M context, 128k output), adaptive thinking, vision.
63
+ * See https://www.anthropic.com/news/claude-opus-4-8.
64
+ *
65
+ * Claude Mythos 5 is deliberately absent: it's invitation-only (Project
66
+ * Glasswing), so it would be a dead picker entry for virtually all users.
67
+ *
68
+ * See https://platform.claude.com/docs/en/about-claude/models/overview.
69
+ */
70
+ const ANTHROPIC_EXTRA_MODELS = [{
71
+ id: "claude-fable-5",
72
+ name: "Claude Fable 5",
73
+ reasoning: true,
74
+ input: ["text", "image"],
75
+ cost: {
76
+ input: 10,
77
+ output: 50,
78
+ cacheRead: 1,
79
+ cacheWrite: 12.5
80
+ },
81
+ contextWindow: 1e6,
82
+ maxTokens: 128e3,
83
+ provider: "anthropic"
84
+ }, {
85
+ id: "claude-opus-4-8",
86
+ name: "Claude Opus 4.8",
87
+ reasoning: true,
88
+ input: ["text", "image"],
89
+ cost: {
90
+ input: 5,
91
+ output: 25,
92
+ cacheRead: .5,
93
+ cacheWrite: 6.25
94
+ },
95
+ contextWindow: 1e6,
96
+ maxTokens: 128e3,
97
+ provider: "anthropic",
98
+ options: [FAST_MODE_OPTION]
99
+ }];
100
+ //#endregion
101
+ //#region src/providers/anthropic.ts
102
+ const loadAnthropicSdk = lazyAsync(async () => {
103
+ try {
104
+ return (await import("@anthropic-ai/sdk")).default;
105
+ } catch (err) {
106
+ throw new Error("The `anthropic` provider requires the `@anthropic-ai/sdk` package, which is an optional peer dependency. Install it with your package manager (e.g. `bun add @anthropic-ai/sdk`).", err instanceof Error ? { cause: err } : void 0);
107
+ }
108
+ });
109
+ /** Beta flags sent unconditionally on the OAuth path (Claude Code parity). */
110
+ const OAUTH_DEFAULT_BETAS = ["claude-code-20250219", "oauth-2025-04-20"];
111
+ /**
112
+ * Beta flag that enables the `speed: "fast"` request field (fast mode — up to
113
+ * 2.5× output tokens/sec on Opus 4.6/4.7/4.8 at premium pricing). Sent as an
114
+ * `anthropic-beta` header only on requests that opt into fast mode; absent
115
+ * otherwise so standard requests keep a byte-stable header for prompt caching.
116
+ *
117
+ * See: https://platform.claude.com/docs/en/build-with-claude/fast-mode
118
+ */
119
+ const FAST_MODE_BETA = "fast-mode-2026-02-01";
120
+ const API_KEY_RESERVED_EXTRA_HEADER_NAMES = new Set(["anthropic-beta"]);
121
+ const OAUTH_RESERVED_EXTRA_HEADER_NAMES = new Set([
122
+ "anthropic-beta",
123
+ "anthropic-dangerous-direct-browser-access",
124
+ "user-agent",
125
+ "x-app"
126
+ ]);
127
+ function filterReservedExtraHeaders(extraHeaders, reservedNames) {
128
+ const out = {};
129
+ for (const [name, value] of Object.entries(extraHeaders ?? {})) if (!reservedNames.has(name.toLowerCase())) out[name] = value;
130
+ return out;
131
+ }
132
+ /**
133
+ * Build the `anthropic-beta` header value — OAuth defaults plus caller-supplied
134
+ * extras, de-duped while preserving order. Returns `undefined` when no betas
135
+ * apply (non-OAuth, no extras).
136
+ */
137
+ function resolveAnthropicBetas(isOAuth, extraBetas) {
138
+ const seen = /* @__PURE__ */ new Set();
139
+ const out = [];
140
+ if (isOAuth) {
141
+ for (const b of OAUTH_DEFAULT_BETAS) if (!seen.has(b)) {
142
+ seen.add(b);
143
+ out.push(b);
144
+ }
145
+ }
146
+ if (extraBetas) {
147
+ for (const b of extraBetas) if (typeof b === "string" && b.length > 0 && !seen.has(b)) {
148
+ seen.add(b);
149
+ out.push(b);
150
+ }
151
+ }
152
+ return out.length > 0 ? out.join(",") : void 0;
153
+ }
154
+ function getConfiguredApiKey(anthropicParams) {
155
+ if (anthropicParams?.apiKey) return anthropicParams.apiKey;
156
+ if (anthropicParams?.access) return anthropicParams.access;
157
+ if (process.env.ANTHROPIC_API_KEY) return process.env.ANTHROPIC_API_KEY;
158
+ const access = readOAuthCredentials().anthropic?.access;
159
+ if (typeof access === "string" && access.length > 0) return access;
160
+ throw new Error("No API key found. Run `bun run auth` first.");
161
+ }
162
+ /**
163
+ * Resolve {@link AnthropicParams.extraHeaders} to a concrete map. A function
164
+ * form is invoked (and awaited) per call so gateway auth tokens can refresh
165
+ * each turn; a static map passes through.
166
+ */
167
+ async function resolveExtraHeaders(value) {
168
+ return typeof value === "function" ? value() : value;
169
+ }
170
+ function createClient(SDK, apiKey, isOAuth, baseURL, extraBetas, extraHeaders) {
171
+ const base = baseURL ? { baseURL } : {};
172
+ const betaHeader = resolveAnthropicBetas(isOAuth, extraBetas);
173
+ if (isOAuth) {
174
+ const defaultHeaders = {
175
+ ...filterReservedExtraHeaders(extraHeaders, OAUTH_RESERVED_EXTRA_HEADER_NAMES),
176
+ "anthropic-dangerous-direct-browser-access": "true",
177
+ "user-agent": "zidane/2.0.0",
178
+ "x-app": "cli"
179
+ };
180
+ if (betaHeader) defaultHeaders["anthropic-beta"] = betaHeader;
181
+ return new SDK({
182
+ apiKey: null,
183
+ authToken: apiKey,
184
+ dangerouslyAllowBrowser: true,
185
+ defaultHeaders,
186
+ ...base
187
+ });
188
+ }
189
+ const defaultHeaders = filterReservedExtraHeaders(extraHeaders, API_KEY_RESERVED_EXTRA_HEADER_NAMES);
190
+ if (betaHeader) defaultHeaders["anthropic-beta"] = betaHeader;
191
+ return new SDK({
192
+ apiKey,
193
+ ...Object.keys(defaultHeaders).length > 0 ? { defaultHeaders } : {},
194
+ ...base
195
+ });
196
+ }
197
+ /**
198
+ * Map `ThinkingLevel` budgeted tiers to Anthropic's `output_config.effort`
199
+ * enum. `minimal` collapses to `low` (the closest equivalent — Anthropic does
200
+ * not have a sub-`low` tier).
201
+ */
202
+ const EFFORT_FOR_LEVEL = {
203
+ minimal: "low",
204
+ low: "low",
205
+ medium: "medium",
206
+ high: "high",
207
+ xhigh: "xhigh",
208
+ max: "max"
209
+ };
210
+ /**
211
+ * Decide how to translate a `ThinkingLevel` into Anthropic's request shape.
212
+ * Pure / synchronous — exported so tests can assert routing without standing
213
+ * up the SDK.
214
+ *
215
+ * Routing rules:
216
+ * - `'off'` → `null` (no thinking field, no effort hint).
217
+ * - `'adaptive'` → adaptive thinking with no effort hint (model decides
218
+ * everything). When `customBudget` is set, it is carried as `maxTokensCap`
219
+ * so the request builder caps `max_tokens` accordingly — adaptive has no
220
+ * native budget knob, but capping the response envelope soft-bounds the
221
+ * thinking that lives inside it.
222
+ * - Budgeted levels → adaptive thinking with an `effort` hint, unless
223
+ * `customBudget` is provided.
224
+ * - Any level + `customBudget` → explicit-budget `enabled` path. The caller
225
+ * has opted into precise budget control and accepts the Anthropic
226
+ * deprecation warning that comes with it on opus 4.6+. `'adaptive'` is the
227
+ * sole exception: it never falls back to enabled, since adaptive is the
228
+ * current Anthropic API surface for self-budgeted thinking.
229
+ */
230
+ function planAnthropicThinking(level, customBudget) {
231
+ if (level === "off") return null;
232
+ if (level === "adaptive") {
233
+ if (typeof customBudget === "number" && customBudget > 0) return {
234
+ kind: "adaptive",
235
+ maxTokensCap: customBudget
236
+ };
237
+ return { kind: "adaptive" };
238
+ }
239
+ if (customBudget !== void 0) return {
240
+ kind: "enabled",
241
+ budgetTokens: customBudget,
242
+ maxTokensBump: customBudget
243
+ };
244
+ return {
245
+ kind: "adaptive",
246
+ effort: EFFORT_FOR_LEVEL[level]
247
+ };
248
+ }
249
+ /**
250
+ * Map Anthropic's native `stop_reason` to the zidane `TurnFinishReason` union.
251
+ *
252
+ * `pause_turn` and `model_context_window_exceeded` are 4.6+ stop reasons that
253
+ * pre-Z21 collapsed to `'other'` and silently terminated the run. They now
254
+ * map to `'pause'` and `'length'` respectively, and the surrounding caller
255
+ * adjusts the `done` flag so the loop can recover.
256
+ */
257
+ function mapStopReason(stopReason) {
258
+ if (!stopReason) return void 0;
259
+ switch (stopReason) {
260
+ case "end_turn":
261
+ case "stop_sequence": return "stop";
262
+ case "tool_use": return "tool-calls";
263
+ case "max_tokens":
264
+ case "model_context_window_exceeded": return "length";
265
+ case "refusal": return "content-filter";
266
+ case "pause_turn": return "pause";
267
+ default: return "other";
268
+ }
269
+ }
270
+ const EPHEMERAL = { type: "ephemeral" };
271
+ /**
272
+ * Mutate an Anthropic request in place to add cache breakpoints on the three
273
+ * stable prefixes:
274
+ * 1. System prompt — `cache_control` on the static prefix only (see below).
275
+ * 2. Tool definitions — last tool.
276
+ * 3. Conversation — last content block of the last message.
277
+ *
278
+ * Each breakpoint tells Anthropic to cache the prefix ending at that block;
279
+ * subsequent turns reuse the cached prefix and pay only for the delta. Safe
280
+ * no-op when any prefix is empty (no tools, empty system, etc.).
281
+ *
282
+ * System-prompt boundary handling (`SYSTEM_PROMPT_BOUNDARY`):
283
+ *
284
+ * - When `originalSystem` is provided AND carries the marker, the system
285
+ * block is rewritten as a 2-block array: static (cached) then dynamic
286
+ * (uncached). The caller is expected to have already stripped the marker
287
+ * from `params.system` via {@link renderSystemForWire} — this helper
288
+ * only re-splits to apply `cache_control` cleanly.
289
+ * - When `originalSystem` is omitted or marker-free, the existing single-
290
+ * block treatment applies: `cache_control` on the whole system string.
291
+ * - Array system prompts: existing semantics — `cache_control` lands on the
292
+ * last block. Callers building their own multi-block layout own the
293
+ * breakpoint placement.
294
+ */
295
+ function applyAnthropicCacheBreakpoints(params, originalSystem) {
296
+ if (typeof params.system === "string") {
297
+ if (params.system.length > 0) {
298
+ const parts = splitSystemPrompt(originalSystem && originalSystem.length > 0 ? originalSystem : params.system);
299
+ if (parts.dynamic.length > 0) {
300
+ const blocks = [];
301
+ if (parts.static.length > 0) blocks.push({
302
+ type: "text",
303
+ text: parts.static,
304
+ cache_control: EPHEMERAL
305
+ });
306
+ blocks.push({
307
+ type: "text",
308
+ text: parts.dynamic
309
+ });
310
+ params.system = blocks;
311
+ } else params.system = [{
312
+ type: "text",
313
+ text: parts.static,
314
+ cache_control: EPHEMERAL
315
+ }];
316
+ }
317
+ } else if (Array.isArray(params.system) && params.system.length > 0) {
318
+ const lastIdx = params.system.length - 1;
319
+ params.system = params.system.map((block, i) => i === lastIdx ? {
320
+ ...block,
321
+ cache_control: EPHEMERAL
322
+ } : block);
323
+ }
324
+ if (params.tools && params.tools.length > 0) {
325
+ const lastIdx = params.tools.length - 1;
326
+ params.tools = params.tools.map((tool, i) => i === lastIdx ? {
327
+ ...tool,
328
+ cache_control: EPHEMERAL
329
+ } : tool);
330
+ }
331
+ if (params.messages.length === 0) return;
332
+ const lastMsgIdx = params.messages.length - 1;
333
+ const lastMsg = params.messages[lastMsgIdx];
334
+ if (typeof lastMsg.content === "string") {
335
+ if (lastMsg.content.length === 0) return;
336
+ params.messages[lastMsgIdx] = {
337
+ ...lastMsg,
338
+ content: [{
339
+ type: "text",
340
+ text: lastMsg.content,
341
+ cache_control: EPHEMERAL
342
+ }]
343
+ };
344
+ return;
345
+ }
346
+ if (!Array.isArray(lastMsg.content) || lastMsg.content.length === 0) return;
347
+ const blocks = lastMsg.content;
348
+ let targetIdx = blocks.length - 1;
349
+ while (targetIdx >= 0 && isThinkingBlock(blocks[targetIdx])) targetIdx -= 1;
350
+ if (targetIdx < 0) return;
351
+ const nextBlocks = blocks.slice();
352
+ nextBlocks[targetIdx] = {
353
+ ...nextBlocks[targetIdx],
354
+ cache_control: EPHEMERAL
355
+ };
356
+ params.messages[lastMsgIdx] = {
357
+ ...lastMsg,
358
+ content: nextBlocks
359
+ };
360
+ }
361
+ function isThinkingBlock(block) {
362
+ return block.type === "thinking" || block.type === "redacted_thinking";
363
+ }
364
+ /**
365
+ * Duck-type check for an Anthropic SDK `APIError` — avoids a runtime dependency
366
+ * on `@anthropic-ai/sdk` so `classifyError` stays usable even when the optional
367
+ * peer dep isn't loaded (e.g. host code calling it on an unrelated provider's
368
+ * error).
369
+ *
370
+ * Anthropic's APIError shape: `.status: number` + `.error` (parsed body, object
371
+ * or null). Plain `Error`s don't have `.status` + `.error`.
372
+ */
373
+ function looksLikeAnthropicApiError(err) {
374
+ if (!err || typeof err !== "object") return false;
375
+ const e = err;
376
+ return typeof e.status === "number" && "error" in e;
377
+ }
378
+ /**
379
+ * Anthropic SSE `error` event types that warrant a retry. `overloaded_error`
380
+ * is the headline case (capacity event mid-stream); `api_error` and
381
+ * `timeout_error` are both server-side transient failures. `invalid_request_error`,
382
+ * `authentication_error`, `permission_error`, `not_found_error`, `billing_error`
383
+ * are terminal — retrying them would just hammer a bad request.
384
+ *
385
+ * `rate_limit_error` here would be redundant: the SDK's pre-stream retry
386
+ * handles 429, and a mid-stream `rate_limit_error` is exceedingly rare. We
387
+ * include it anyway for symmetry with the HTTP-level retry policy.
388
+ */
389
+ const SSE_RETRYABLE_ERROR_TYPES = new Set([
390
+ "overloaded_error",
391
+ "api_error",
392
+ "timeout_error",
393
+ "rate_limit_error"
394
+ ]);
395
+ /**
396
+ * Try to parse an Anthropic SSE `error` event payload out of a thrown error's
397
+ * message. The SDK's `MessageStream` surfaces mid-stream error events by
398
+ * throwing an `AnthropicError` whose `.message` contains the raw JSON shape:
399
+ *
400
+ * {"type":"error","error":{"type":"overloaded_error","message":"Overloaded"},"request_id":"req_..."}
401
+ *
402
+ * Returns the inner `{ type, message }` or `null` when the message isn't
403
+ * the canonical SSE error shape. Tolerant: silently returns `null` for
404
+ * non-string input, non-JSON content, or any shape mismatch.
405
+ */
406
+ function matchSseErrorEvent(message) {
407
+ if (typeof message !== "string" || message.length === 0) return null;
408
+ if (!message.includes("\"type\":\"error\"") && !message.includes("\"type\": \"error\"")) return null;
409
+ const start = message.indexOf("{");
410
+ if (start < 0) return null;
411
+ try {
412
+ const parsed = JSON.parse(message.slice(start));
413
+ if (!parsed || typeof parsed !== "object") return null;
414
+ const outer = parsed;
415
+ if (outer.type !== "error" || !outer.error || typeof outer.error !== "object") return null;
416
+ const inner = outer.error;
417
+ if (typeof inner.type !== "string") return null;
418
+ return {
419
+ type: inner.type,
420
+ message: typeof inner.message === "string" ? inner.message : inner.type
421
+ };
422
+ } catch {
423
+ return null;
424
+ }
425
+ }
426
+ /**
427
+ * Classify an Anthropic SDK / HTTP error for typed-error wrapping.
428
+ *
429
+ * - `prompt is too long` (400 invalid_request_error) → `context_exceeded`.
430
+ * - `'tool_use' ids were found without 'tool_result' blocks` /
431
+ * `'tool_result must be preceded by a tool_call'` (400) →
432
+ * `tool_pairing_corruption`. The local repair pass should have caught
433
+ * this — the typed error tells consumers their pre-send pipeline is
434
+ * shipping orphaned blocks somehow (custom `context:transform` hook,
435
+ * bypassed loop, mid-stream session edit) so they can patch the root
436
+ * cause instead of chasing 400s.
437
+ * - Any other Anthropic `APIError`-shaped value → `provider_error` with the
438
+ * native status/type code.
439
+ * - Unknown errors → `null` (loop wraps in `AgentProviderError` generically).
440
+ *
441
+ * Anthropic's wire error shape is `{ type: 'error', error: { type, message } }` — the
442
+ * SDK stores the parsed body on `err.error`. We walk both levels so callers see the
443
+ * most specific `providerCode` we can find.
444
+ */
445
+ function classifyAnthropicError(err) {
446
+ const prelude = classifyErrorPrelude(err);
447
+ if (prelude === "not-object") return null;
448
+ if (prelude === "aborted") return { kind: "aborted" };
449
+ const anyErr = err;
450
+ if (!looksLikeAnthropicApiError(err)) {
451
+ const sseError = matchSseErrorEvent(anyErr.message);
452
+ if (sseError) return {
453
+ kind: "provider_error",
454
+ providerCode: sseError.type,
455
+ message: sseError.message,
456
+ retryable: SSE_RETRYABLE_ERROR_TYPES.has(sseError.type)
457
+ };
458
+ return null;
459
+ }
460
+ const innerType = anyErr.error?.error?.type;
461
+ const outerType = anyErr.error?.type;
462
+ const nativeType = innerType && innerType !== "error" ? innerType : outerType;
463
+ const message = anyErr.error?.error?.message ?? anyErr.error?.message ?? anyErr.message ?? "";
464
+ if (matchesContextExceeded(message)) return {
465
+ kind: "context_exceeded",
466
+ providerCode: nativeType ?? "invalid_request_error",
467
+ message
468
+ };
469
+ if (matchesToolPairingError(message)) return {
470
+ kind: "tool_pairing_corruption",
471
+ providerCode: nativeType ?? "invalid_request_error",
472
+ message
473
+ };
474
+ const status = anyErr.status;
475
+ const retryable = typeof status === "number" ? isRetryableHttpStatus(status) : void 0;
476
+ return {
477
+ kind: "provider_error",
478
+ providerCode: nativeType ?? (status ? String(status) : void 0),
479
+ message,
480
+ ...retryable !== void 0 ? { retryable } : {}
481
+ };
482
+ }
483
+ function shouldFallbackFromFastMode(err) {
484
+ const classified = classifyAnthropicError(err);
485
+ if (classified?.kind === "provider_error" && classified.retryable === true) return true;
486
+ const message = err instanceof Error ? err.message : String(err);
487
+ return /\b(?:fast|speed)\b/i.test(message) && /capacity|overload|rate|unavailable|unsupported|not supported|not permitted|extra inputs|invalid/i.test(message);
488
+ }
489
+ /**
490
+ * Build a user `SessionMessage` from multimodal prompt parts.
491
+ *
492
+ * - Text parts → text blocks.
493
+ * - Image parts → base64 image blocks.
494
+ * - Document parts → canonical document blocks. `toAnthropic` emits native
495
+ * document blocks only for base64 PDFs; text/non-PDF documents fall back to
496
+ * attachment-tagged text to avoid invalid Anthropic source media types.
497
+ *
498
+ * The format mirrors `defaultPromptMessage`'s output on shape — Anthropic-specific
499
+ * handling differs only in that `promptMessage` being present tells the agent loop
500
+ * to route PromptPart[] through this function rather than throwing on base64 docs.
501
+ */
502
+ function anthropicPromptMessage(parts) {
503
+ const content = [];
504
+ for (const part of parts) {
505
+ if (part.type === "text") {
506
+ if (part.text.length > 0) content.push({
507
+ type: "text",
508
+ text: part.text
509
+ });
510
+ continue;
511
+ }
512
+ if (part.type === "image") {
513
+ content.push({
514
+ type: "image",
515
+ mediaType: part.mediaType,
516
+ data: part.data
517
+ });
518
+ continue;
519
+ }
520
+ if (part.type === "audio") throw unsupportedMediaError("audio", "anthropic");
521
+ if (part.type === "video") throw unsupportedMediaError("video", "anthropic");
522
+ content.push({
523
+ type: "document",
524
+ mediaType: part.mediaType,
525
+ data: part.data,
526
+ encoding: part.encoding,
527
+ ...part.name ? { name: part.name } : {}
528
+ });
529
+ }
530
+ return {
531
+ role: "user",
532
+ content
533
+ };
534
+ }
535
+ function anthropic(anthropicParams) {
536
+ const isOAuth = getConfiguredApiKey(anthropicParams).includes("sk-ant-oat");
537
+ const defaultModel = anthropicParams?.defaultModel || "claude-opus-4-8";
538
+ let runtimeCredentials = extractRuntimeCredentials(anthropicParams);
539
+ return {
540
+ name: "anthropic",
541
+ meta: {
542
+ defaultModel,
543
+ isOAuth,
544
+ clearsContextServerSide: Boolean(anthropicParams?.contextManagement),
545
+ capabilities: {
546
+ vision: true,
547
+ imageInToolResult: true,
548
+ documents: true,
549
+ audio: false,
550
+ video: false,
551
+ nativeWebSearch: { maxUses: 5 }
552
+ }
553
+ },
554
+ formatTools(tools) {
555
+ const nativeWebSearch = this.meta.capabilities?.nativeWebSearch;
556
+ const hasWebSearch = !!nativeWebSearch && tools.some((t) => t.name === "web_search");
557
+ const out = sanitizeToolSpecs(hasWebSearch ? tools.filter((t) => t.name !== "web_search") : tools, { profile: "anthropic" }).map((t) => ({
558
+ name: t.name,
559
+ description: t.description,
560
+ input_schema: t.inputSchema
561
+ }));
562
+ if (hasWebSearch && nativeWebSearch) {
563
+ const block = {
564
+ type: "web_search_20250305",
565
+ name: "web_search"
566
+ };
567
+ if (typeof nativeWebSearch.maxUses === "number") block.max_uses = nativeWebSearch.maxUses;
568
+ out.push(block);
569
+ }
570
+ return out;
571
+ },
572
+ userMessage(content) {
573
+ return {
574
+ role: "user",
575
+ content: [{
576
+ type: "text",
577
+ text: content
578
+ }]
579
+ };
580
+ },
581
+ assistantMessage(content) {
582
+ return {
583
+ role: "assistant",
584
+ content: [{
585
+ type: "text",
586
+ text: content
587
+ }]
588
+ };
589
+ },
590
+ toolResultsMessage(results) {
591
+ return {
592
+ role: "user",
593
+ content: results.map((r) => ({
594
+ type: "tool_result",
595
+ callId: r.id,
596
+ output: r.content,
597
+ ...r.isError ? { isError: true } : {}
598
+ }))
599
+ };
600
+ },
601
+ promptMessage: anthropicPromptMessage,
602
+ classifyError: classifyAnthropicError,
603
+ async countTokens(payload, signal) {
604
+ try {
605
+ const SDK = await loadAnthropicSdk();
606
+ const apiKey = await resolveOAuthApiKey({
607
+ provider: "anthropic",
608
+ providerId: "anthropic",
609
+ params: runtimeCredentials ? {
610
+ ...anthropicParams,
611
+ ...runtimeCredentials
612
+ } : anthropicParams,
613
+ envKey: "ANTHROPIC_API_KEY",
614
+ missingError: "No API key found. Run `bun run auth` first.",
615
+ refreshError: (reason) => `Anthropic OAuth token refresh failed. ${reason}`
616
+ });
617
+ const callIsOAuth = apiKey.includes("sk-ant-oat");
618
+ const client = createClient(SDK, apiKey, callIsOAuth, anthropicParams?.baseURL, anthropicParams?.extraBetas, await resolveExtraHeaders(anthropicParams?.extraHeaders));
619
+ const wireSystem = renderSystemForWire(payload.system);
620
+ const system = callIsOAuth ? `You are Claude Code, Anthropic's official CLI for Claude.` : wireSystem;
621
+ const messages = callIsOAuth && payload.system ? [
622
+ {
623
+ role: "user",
624
+ content: [{
625
+ type: "text",
626
+ text: wireSystem
627
+ }]
628
+ },
629
+ {
630
+ role: "assistant",
631
+ content: [{
632
+ type: "text",
633
+ text: "Understood. I will proceed with these instructions above the rest of my system prompt."
634
+ }]
635
+ },
636
+ ...payload.messages
637
+ ] : [...payload.messages];
638
+ return (await client.messages.countTokens({
639
+ model: payload.model,
640
+ system,
641
+ tools: payload.tools,
642
+ messages: messages.map((m) => toAnthropic(m))
643
+ }, signal ? { signal } : void 0)).input_tokens;
644
+ } catch (err) {
645
+ if (process.env.ZIDANE_DEBUG_COUNT) console.error("[anthropic.countTokens] failed:", err);
646
+ return null;
647
+ }
648
+ },
649
+ async stream(options, callbacks) {
650
+ const SDK = await loadAnthropicSdk();
651
+ const apiKey = await resolveOAuthApiKey({
652
+ provider: "anthropic",
653
+ providerId: "anthropic",
654
+ params: runtimeCredentials ? {
655
+ ...anthropicParams,
656
+ ...runtimeCredentials
657
+ } : anthropicParams,
658
+ envKey: "ANTHROPIC_API_KEY",
659
+ missingError: "No API key found. Run `bun run auth` first.",
660
+ refreshError: (reason) => `Anthropic OAuth token refresh failed. Run \`bun run auth --anthropic\` again. ${reason}`
661
+ }, {
662
+ ...callbacks,
663
+ async onOAuthRefresh(ctx) {
664
+ if (ctx.source === "params") runtimeCredentials = {
665
+ access: ctx.credentials.access,
666
+ refresh: ctx.credentials.refresh,
667
+ expires: ctx.credentials.expires
668
+ };
669
+ await callbacks.onOAuthRefresh?.(ctx);
670
+ }
671
+ });
672
+ const requestBetas = options.modelOptions?.fast ? [...anthropicParams?.extraBetas ?? [], FAST_MODE_BETA] : anthropicParams?.extraBetas;
673
+ const callIsOAuth = apiKey.includes("sk-ant-oat");
674
+ const client = createClient(SDK, apiKey, callIsOAuth, anthropicParams?.baseURL, requestBetas, await resolveExtraHeaders(anthropicParams?.extraHeaders));
675
+ const wireSystem = renderSystemForWire(options.system);
676
+ const system = callIsOAuth ? `You are Claude Code, Anthropic's official CLI for Claude.` : wireSystem;
677
+ const messages = callIsOAuth && options.system ? [
678
+ {
679
+ role: "user",
680
+ content: [{
681
+ type: "text",
682
+ text: wireSystem
683
+ }]
684
+ },
685
+ {
686
+ role: "assistant",
687
+ content: [{
688
+ type: "text",
689
+ text: "Understood. I will proceed with these instructions above the rest of my system prompt."
690
+ }]
691
+ },
692
+ ...options.messages
693
+ ] : [...options.messages];
694
+ const thinking = options.thinking ?? "off";
695
+ const modelId = options.model;
696
+ const params = {
697
+ ...anthropicParams?.extraBodyParams ?? {},
698
+ model: modelId,
699
+ max_tokens: options.maxTokens,
700
+ system,
701
+ tools: options.tools,
702
+ messages: messages.map((m) => toAnthropic(m)),
703
+ stream: true
704
+ };
705
+ if (anthropicParams?.contextManagement) params.context_management = anthropicParams.contextManagement;
706
+ if (options.cache !== false) applyAnthropicCacheBreakpoints(params, callIsOAuth ? void 0 : options.system);
707
+ const plan = planAnthropicThinking(thinking, options.thinkingBudget);
708
+ if (plan) {
709
+ if (plan.kind === "enabled") {
710
+ params.thinking = {
711
+ type: "enabled",
712
+ budget_tokens: plan.budgetTokens,
713
+ display: "summarized"
714
+ };
715
+ params.max_tokens = plan.maxTokensBump + params.max_tokens;
716
+ } else {
717
+ params.thinking = {
718
+ type: "adaptive",
719
+ display: "summarized"
720
+ };
721
+ if (plan.effort) params.output_config = { effort: plan.effort };
722
+ if (typeof plan.maxTokensCap === "number" && plan.maxTokensCap > 0) params.max_tokens = Math.min(params.max_tokens, plan.maxTokensCap);
723
+ }
724
+ params.temperature = 1;
725
+ }
726
+ if (options.modelOptions?.fast) params.speed = "fast";
727
+ if (options.toolChoice) if (options.toolChoice.type === "tool" && options.toolChoice.name) params.tool_choice = {
728
+ type: "tool",
729
+ name: options.toolChoice.name
730
+ };
731
+ else if (options.toolChoice.type === "required") params.tool_choice = { type: "any" };
732
+ else params.tool_choice = { type: "auto" };
733
+ const runStream = async (requestParams, fastRequested) => {
734
+ const s = client.messages.stream(requestParams, { signal: options.signal });
735
+ let text = "";
736
+ let observedOutput = false;
737
+ s.on("text", (delta) => {
738
+ observedOutput = true;
739
+ text += delta;
740
+ callbacks.onText(delta);
741
+ });
742
+ if (callbacks.onThinking) s.on("thinking", (delta) => {
743
+ observedOutput = true;
744
+ callbacks.onThinking(delta);
745
+ });
746
+ if (callbacks.onToolCallDelta) s.on("inputJson", () => {
747
+ observedOutput = true;
748
+ callbacks.onToolCallDelta();
749
+ });
750
+ if (callbacks.onServerToolUse || callbacks.onServerToolResult) s.on("contentBlock", (block) => {
751
+ observedOutput = true;
752
+ if (block.type === "server_tool_use") callbacks.onServerToolUse?.({
753
+ id: block.id,
754
+ name: block.name,
755
+ input: block.input ?? {}
756
+ });
757
+ else if (block.type === "web_search_tool_result") callbacks.onServerToolResult?.({
758
+ toolUseId: block.tool_use_id,
759
+ toolName: "web_search",
760
+ content: block.content
761
+ });
762
+ });
763
+ let response;
764
+ try {
765
+ response = await s.finalMessage();
766
+ } catch (err) {
767
+ if (fastRequested && !observedOutput && shouldFallbackFromFastMode(err)) {
768
+ const standardParams = { ...requestParams };
769
+ delete standardParams.speed;
770
+ return await runStream(standardParams, false);
771
+ }
772
+ throw err;
773
+ }
774
+ const toolCalls = response.content.filter((b) => b.type === "tool_use").map((b) => ({
775
+ id: b.id,
776
+ name: b.name,
777
+ input: b.input
778
+ }));
779
+ const finishReason = mapStopReason(response.stop_reason);
780
+ const isPause = response.stop_reason === "pause_turn";
781
+ const usage = await fillEstimatedCost({
782
+ input: response.usage.input_tokens,
783
+ output: response.usage.output_tokens,
784
+ cacheCreation: response.usage.cache_creation_input_tokens ?? void 0,
785
+ cacheRead: response.usage.cache_read_input_tokens ?? void 0,
786
+ ...finishReason ? { finishReason } : {},
787
+ modelId: response.model ?? options.model
788
+ }, "anthropic", fastRequested ? fastModeCostMultiplier(response.model ?? options.model) : void 0);
789
+ return {
790
+ assistantMessage: fromAnthropic({
791
+ role: "assistant",
792
+ content: response.content
793
+ }),
794
+ text,
795
+ toolCalls,
796
+ done: !isPause && (response.stop_reason === "end_turn" || toolCalls.length === 0),
797
+ usage
798
+ };
799
+ };
800
+ return await runStream(params, options.modelOptions?.fast === true);
801
+ }
802
+ };
803
+ }
804
+ //#endregion
805
+ export { resolveAnthropicBetas as a, planAnthropicThinking as i, applyAnthropicCacheBreakpoints as n, ANTHROPIC_EXTRA_MODELS as o, classifyAnthropicError as r, FAST_MODE_OPTIONS as s, anthropic as t };
806
+
807
+ //# sourceMappingURL=anthropic-RGqsJlC8.js.map