@gullabs/claude-cli 0.6.1 → 0.16.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/dist/index.cjs CHANGED
@@ -5,9 +5,107 @@ var os = require('os');
5
5
  var path = require('path');
6
6
  var core = require('@gullabs/core');
7
7
  var child_process = require('child_process');
8
+ var string_decoder = require('string_decoder');
8
9
  var zod = require('zod');
9
10
 
10
11
  // src/adapter.ts
12
+ var INHERITED_NAMES = /* @__PURE__ */ new Set([
13
+ // Process basics.
14
+ "PATH",
15
+ "HOME",
16
+ "USER",
17
+ "LOGNAME",
18
+ "LANG",
19
+ "LANGUAGE",
20
+ "TERM",
21
+ "TMPDIR",
22
+ "TEMP",
23
+ "TMP",
24
+ "SHELL",
25
+ "TZ",
26
+ // Windows equivalents of the above.
27
+ "SYSTEMROOT",
28
+ "SYSTEMDRIVE",
29
+ "WINDIR",
30
+ "COMSPEC",
31
+ "PATHEXT",
32
+ "USERPROFILE",
33
+ "APPDATA",
34
+ "LOCALAPPDATA",
35
+ "PROGRAMDATA",
36
+ "HOMEDRIVE",
37
+ "HOMEPATH",
38
+ // Network: proxies and trust roots.
39
+ "HTTPS_PROXY",
40
+ "HTTP_PROXY",
41
+ "ALL_PROXY",
42
+ "NO_PROXY",
43
+ "https_proxy",
44
+ "http_proxy",
45
+ "all_proxy",
46
+ "no_proxy",
47
+ "NODE_EXTRA_CA_CERTS",
48
+ "SSL_CERT_FILE",
49
+ "SSL_CERT_DIR",
50
+ // The CLI's own documented settings that keep the subscription login usable:
51
+ // where its login lives, the long-lived subscription token from
52
+ // `claude setup-token`, and client certificates for an mTLS proxy.
53
+ "CLAUDE_CONFIG_DIR",
54
+ "CLAUDE_CODE_OAUTH_TOKEN",
55
+ "CLAUDE_CODE_CLIENT_CERT",
56
+ "CLAUDE_CODE_CLIENT_KEY",
57
+ "CLAUDE_CODE_CLIENT_KEY_PASSPHRASE",
58
+ "CLAUDE_CODE_PROXY_RESOLVES_HOSTS"
59
+ ]);
60
+ var INHERITED_PREFIXES = ["LC_", "XDG_"];
61
+ function isInherited(name, windows) {
62
+ const key = windows ? name.toUpperCase() : name;
63
+ if (INHERITED_NAMES.has(key)) return true;
64
+ return INHERITED_PREFIXES.some((prefix) => key.startsWith(prefix));
65
+ }
66
+ function buildChildEnv(parent, extra, windows) {
67
+ const env = {};
68
+ for (const [name, value] of Object.entries(parent)) {
69
+ if (value !== void 0 && isInherited(name, windows)) env[name] = value;
70
+ }
71
+ if (extra !== void 0) {
72
+ if (windows) {
73
+ const overridden = new Set(Object.keys(extra).map((name) => name.toUpperCase()));
74
+ for (const name of Object.keys(env)) {
75
+ if (overridden.has(name.toUpperCase())) delete env[name];
76
+ }
77
+ }
78
+ Object.assign(env, extra);
79
+ }
80
+ return env;
81
+ }
82
+ function badEnv(message) {
83
+ return new core.LlmError(message, {
84
+ kind: "bad_request",
85
+ retryable: false,
86
+ provider: "claude-cli"
87
+ });
88
+ }
89
+ function parseExtraEnv(env) {
90
+ if (env === void 0) return void 0;
91
+ if (env === null || typeof env !== "object" || Array.isArray(env)) {
92
+ throw badEnv("claudeCliAdapter: `env` must be an object of string values");
93
+ }
94
+ const copy = {};
95
+ for (const [name, value] of Object.entries(env)) {
96
+ if (name === "" || name.includes("=") || name.includes("\0")) {
97
+ throw badEnv(`claudeCliAdapter: \`env\` has an invalid name "${name}"`);
98
+ }
99
+ if (typeof value !== "string" || value.includes("\0")) {
100
+ throw badEnv(
101
+ `claudeCliAdapter: \`env.${name}\` must be a string without NUL characters`
102
+ );
103
+ }
104
+ copy[name] = value;
105
+ }
106
+ return Object.freeze(copy);
107
+ }
108
+ var MAX_STDOUT_BYTES = 32 * 1024 * 1024;
11
109
  function buildClaudeCliRunner(claudePath = "claude") {
12
110
  return {
13
111
  run(args, input, opts) {
@@ -20,9 +118,14 @@ function buildClaudeCliRunner(claudePath = "claude") {
20
118
  }
21
119
  const child = child_process.spawn(claudePath, args, {
22
120
  cwd: opts.cwd,
23
- stdio: ["pipe", "pipe", "pipe"]
121
+ stdio: ["pipe", "pipe", "pipe"],
122
+ detached: process.platform !== "win32",
123
+ env: buildChildEnv(process.env, opts.env, process.platform === "win32")
24
124
  });
125
+ const stdoutDecoder = new string_decoder.StringDecoder("utf8");
126
+ const stderrDecoder = new string_decoder.StringDecoder("utf8");
25
127
  let stdout = "";
128
+ let stdoutBytes = 0;
26
129
  let stderr = "";
27
130
  let settled = false;
28
131
  let pendingError;
@@ -38,12 +141,31 @@ function buildClaudeCliRunner(claudePath = "claude") {
38
141
  opts.signal.removeEventListener("abort", onAbort);
39
142
  }
40
143
  };
144
+ const signalTree = (signal) => {
145
+ if (process.platform !== "win32" && child.pid !== void 0) {
146
+ try {
147
+ process.kill(-child.pid, signal);
148
+ return;
149
+ } catch {
150
+ }
151
+ }
152
+ child.kill(signal);
153
+ };
41
154
  const killChild = () => {
42
- child.kill("SIGTERM");
155
+ signalTree("SIGTERM");
43
156
  killTimeoutHandle = setTimeout(() => {
44
- child.kill("SIGKILL");
157
+ signalTree("SIGKILL");
158
+ child.stdout.destroy();
159
+ child.stderr.destroy();
45
160
  }, 5e3);
46
161
  };
162
+ const sweepGroup = () => {
163
+ if (process.platform === "win32" || child.pid === void 0) return;
164
+ try {
165
+ process.kill(-child.pid, "SIGKILL");
166
+ } catch {
167
+ }
168
+ };
47
169
  const beginReject = (err) => {
48
170
  if (settled || pendingError !== void 0) return;
49
171
  pendingError = err;
@@ -66,10 +188,22 @@ function buildClaudeCliRunner(claudePath = "claude") {
66
188
  }, opts.timeoutMs);
67
189
  }
68
190
  child.stdout.on("data", (chunk) => {
69
- stdout += chunk.toString("utf8");
191
+ if (pendingError !== void 0) return;
192
+ stdoutBytes += chunk.length;
193
+ if (stdoutBytes > MAX_STDOUT_BYTES) {
194
+ const err = new Error(
195
+ `claude-cli stdout exceeded ${MAX_STDOUT_BYTES} bytes; the process was killed`
196
+ );
197
+ err.name = "OutputLimitError";
198
+ beginReject(err);
199
+ return;
200
+ }
201
+ stdout += stdoutDecoder.write(chunk);
70
202
  });
71
203
  child.stderr.on("data", (chunk) => {
72
- stderr += chunk.toString("utf8");
204
+ stderr = (stderr + stderrDecoder.write(chunk)).slice(-1048576);
205
+ });
206
+ child.stdin.on("error", () => {
73
207
  });
74
208
  child.once("error", (err) => {
75
209
  if (settled) return;
@@ -82,8 +216,11 @@ function buildClaudeCliRunner(claudePath = "claude") {
82
216
  settled = true;
83
217
  cleanup();
84
218
  if (pendingError !== void 0) {
219
+ sweepGroup();
85
220
  reject(pendingError);
86
221
  } else {
222
+ stdout += stdoutDecoder.end();
223
+ stderr = (stderr + stderrDecoder.end()).slice(-1048576);
87
224
  resolve({ stdout, stderr, exitCode });
88
225
  }
89
226
  });
@@ -94,31 +231,52 @@ function buildClaudeCliRunner(claudePath = "claude") {
94
231
  }
95
232
 
96
233
  // src/adapter.ts
234
+ function abortError() {
235
+ const err = new Error("claude-cli call aborted");
236
+ err.name = "AbortError";
237
+ return err;
238
+ }
97
239
  var Semaphore = class {
98
240
  available;
99
- queue = [];
241
+ waiters = [];
100
242
  constructor(max) {
101
243
  this.available = max;
102
244
  }
103
- async acquire() {
245
+ /**
246
+ * Take a slot. A caller that has to wait leaves the queue, and rejects with an
247
+ * `AbortError`, as soon as `signal` fires: a call the engine already gave up
248
+ * on must not hold a place in line.
249
+ */
250
+ acquire(signal) {
251
+ if (signal?.aborted === true) return Promise.reject(abortError());
104
252
  if (this.available > 0) {
105
253
  this.available -= 1;
106
- return () => {
254
+ return Promise.resolve(() => {
107
255
  this.release();
108
- };
256
+ });
109
257
  }
110
- await new Promise((resolve) => {
111
- this.queue.push(resolve);
258
+ return new Promise((resolve, reject) => {
259
+ const grant = () => {
260
+ signal?.removeEventListener("abort", onAbort);
261
+ resolve(() => {
262
+ this.release();
263
+ });
264
+ };
265
+ const onAbort = () => {
266
+ const at = this.waiters.indexOf(grant);
267
+ if (at >= 0) this.waiters.splice(at, 1);
268
+ reject(abortError());
269
+ };
270
+ signal?.addEventListener("abort", onAbort, { once: true });
271
+ this.waiters.push(grant);
112
272
  });
113
- this.available -= 1;
114
- return () => {
115
- this.release();
116
- };
117
273
  }
274
+ // A freed slot goes straight to the next waiter, so a new caller cannot
275
+ // overtake it between the release and the waiter's wake-up.
118
276
  release() {
119
- this.available += 1;
120
- const next = this.queue.shift();
277
+ const next = this.waiters.shift();
121
278
  if (next !== void 0) next();
279
+ else this.available += 1;
122
280
  }
123
281
  };
124
282
  function mapFinishReason(stopReason) {
@@ -126,6 +284,8 @@ function mapFinishReason(stopReason) {
126
284
  switch (stopReason) {
127
285
  case "end_turn":
128
286
  return "stop";
287
+ case "refusal":
288
+ return "content_filter";
129
289
  case "tool_use":
130
290
  return "stop";
131
291
  default:
@@ -133,14 +293,19 @@ function mapFinishReason(stopReason) {
133
293
  }
134
294
  }
135
295
  function mapUsage(usage) {
136
- const inputTokens = usage?.input_tokens ?? 0;
296
+ const cacheRead = usage?.cache_read_input_tokens;
297
+ const cacheWrite = usage?.cache_creation_input_tokens;
298
+ const inputTokens = (usage?.input_tokens ?? 0) + (cacheRead ?? 0) + (cacheWrite ?? 0);
137
299
  const outputTokens = usage?.output_tokens ?? 0;
138
- const cachedInputTokens = usage?.cache_read_input_tokens;
300
+ const cachedInputTokens = cacheRead;
301
+ const thinkingTokens = usage?.output_tokens_details?.thinking_tokens;
139
302
  const totalTokens = usage !== void 0 ? inputTokens + outputTokens : void 0;
140
303
  const details = {
141
304
  input: inputTokens,
142
305
  output: outputTokens,
143
306
  ...cachedInputTokens !== void 0 ? { cached: cachedInputTokens } : {},
307
+ ...cacheWrite !== void 0 ? { cacheWrite } : {},
308
+ ...thinkingTokens !== void 0 ? { thinking: thinkingTokens } : {},
144
309
  ...totalTokens !== void 0 ? { total: totalTokens } : {}
145
310
  };
146
311
  const raw = usage !== void 0 ? usage : null;
@@ -150,6 +315,7 @@ function mapUsage(usage) {
150
315
  details,
151
316
  raw,
152
317
  ...cachedInputTokens !== void 0 ? { cachedInputTokens } : {},
318
+ ...thinkingTokens !== void 0 ? { thinkingTokens } : {},
153
319
  ...totalTokens !== void 0 ? { totalTokens } : {}
154
320
  };
155
321
  }
@@ -179,20 +345,47 @@ function buildPrompt(messages) {
179
345
  ${messageText(msg)}`;
180
346
  }).join("\n\n");
181
347
  }
348
+ var AUTH_FAILURE = /\b(?:log ?in|auth|oauth|authentication|unauthori[sz]ed|401)\b/i;
349
+ var RATE_LIMITED = /\brate[ -]?limit(?:ed|s|ing)?\b|\btoo many requests\b|(?<![\w.:/-])429(?![\w-]|\.\d)/i;
182
350
  function looksAuthy(text) {
183
- return /login|auth|unauthorized/i.test(text);
351
+ return AUTH_FAILURE.test(text);
184
352
  }
185
353
  function looksRateLimited(text) {
186
- return /rate limit|429/i.test(text);
354
+ return RATE_LIMITED.test(text);
187
355
  }
188
- function classifyRunFailure(envelope, result) {
189
- const combinedText = `${envelope?.subtype ?? ""} ${result.stderr}`;
190
- if (looksAuthy(combinedText)) {
191
- return new core.LlmError(
192
- `claude CLI reported an authentication failure: ${result.stderr.slice(-500)}`,
193
- { kind: "invalid_auth", retryable: false, provider: "claude-cli" }
356
+ function assertServedModel(envelope, requestedModel) {
357
+ const modelUsage = envelope.modelUsage;
358
+ if (modelUsage === null || typeof modelUsage !== "object" || Array.isArray(modelUsage)) {
359
+ throw new core.LlmError("claude CLI did not report a valid modelUsage object.", {
360
+ kind: "server",
361
+ retryable: false,
362
+ provider: "claude-cli"
363
+ });
364
+ }
365
+ for (const served of Object.keys(modelUsage)) {
366
+ if (served !== requestedModel) {
367
+ throw new core.LlmError(
368
+ `claude CLI served model "${served}" but the request asked for "${requestedModel}".`,
369
+ { kind: "server", retryable: false, provider: "claude-cli" }
370
+ );
371
+ }
372
+ }
373
+ if (!Object.hasOwn(modelUsage, requestedModel)) {
374
+ throw new core.LlmError(
375
+ `claude CLI did not report the requested model "${requestedModel}" in modelUsage.`,
376
+ { kind: "server", retryable: false, provider: "claude-cli" }
194
377
  );
195
378
  }
379
+ }
380
+ function classifyRunFailure(envelope, result) {
381
+ if (envelope?.stop_reason === "refusal") {
382
+ return new core.LlmError("claude CLI refused the prompt (stop_reason: refusal).", {
383
+ kind: "content_filter",
384
+ retryable: false,
385
+ provider: "claude-cli"
386
+ });
387
+ }
388
+ const combinedText = `${envelope?.subtype ?? ""} ${result.stderr}`;
196
389
  if (looksRateLimited(combinedText)) {
197
390
  return new core.LlmError(
198
391
  `claude CLI reported rate limiting: ${result.stderr.slice(-500)}`,
@@ -203,6 +396,12 @@ function classifyRunFailure(envelope, result) {
203
396
  }
204
397
  );
205
398
  }
399
+ if (looksAuthy(combinedText)) {
400
+ return new core.LlmError(
401
+ `claude CLI reported an authentication failure: ${result.stderr.slice(-500)}`,
402
+ { kind: "invalid_auth", retryable: false, provider: "claude-cli" }
403
+ );
404
+ }
206
405
  if (envelope?.is_error === true) {
207
406
  return new core.LlmError(
208
407
  `claude CLI reported an error (subtype: ${envelope.subtype ?? "unknown"}): ${result.stderr.slice(-500)}`,
@@ -218,6 +417,7 @@ function classifyRunFailure(envelope, result) {
218
417
  function claudeCliAdapter(opts) {
219
418
  const runner = opts?.runner ?? buildClaudeCliRunner(opts?.claudePath);
220
419
  const semaphore = new Semaphore(opts?.maxConcurrency ?? 2);
420
+ const env = parseExtraEnv(opts?.env);
221
421
  return {
222
422
  id: "claude-cli",
223
423
  async run(req, ctx) {
@@ -243,6 +443,27 @@ function claudeCliAdapter(opts) {
243
443
  const warnings = [];
244
444
  const model = req.model;
245
445
  const config = req.config;
446
+ if (req.modelDescriptor?.model !== model || req.modelDescriptor.provider !== "claude-cli") {
447
+ throw new core.LlmError(`No matching Claude model descriptor for "${model}".`, {
448
+ kind: "bad_request",
449
+ retryable: false,
450
+ provider: "claude-cli"
451
+ });
452
+ }
453
+ if (req.transientProviderState !== void 0) {
454
+ throw new core.LlmError(`Model "${model}" does not admit transientProviderState.`, {
455
+ kind: "bad_request",
456
+ retryable: false,
457
+ provider: "claude-cli"
458
+ });
459
+ }
460
+ if (config.reasoning !== void 0 && req.modelDescriptor.capabilities?.reasoningApi === void 0) {
461
+ throw new core.LlmError(`Model "${model}" does not admit reasoning.`, {
462
+ kind: "bad_request",
463
+ retryable: false,
464
+ provider: "claude-cli"
465
+ });
466
+ }
246
467
  const prompt = buildPrompt(req.messages);
247
468
  const args = [
248
469
  "-p",
@@ -252,7 +473,9 @@ function claudeCliAdapter(opts) {
252
473
  "--tools",
253
474
  "",
254
475
  "--disable-slash-commands",
255
- "--no-session-persistence"
476
+ "--no-session-persistence",
477
+ "--settings",
478
+ '{"switchModelsOnFlag":false}'
256
479
  ];
257
480
  args.push("--model", model);
258
481
  const effort = config.reasoning?.effort;
@@ -266,14 +489,29 @@ function claudeCliAdapter(opts) {
266
489
  args.push("--json-schema", JSON.stringify(req.outputJsonSchema));
267
490
  }
268
491
  const timeoutMs = req.attemptTimeoutMs ?? config.timeoutMs;
269
- const cwd = await promises.mkdtemp(path.join(os.tmpdir(), "claude-cli-"));
270
- const release = await semaphore.acquire();
492
+ let release;
493
+ try {
494
+ release = await semaphore.acquire(ctx.signal);
495
+ } catch (waitErr) {
496
+ throw new core.LlmError(
497
+ waitErr instanceof Error ? waitErr.message : "claude-cli call aborted",
498
+ { kind: "aborted", retryable: false, provider: "claude-cli" }
499
+ );
500
+ }
501
+ let cwd;
502
+ try {
503
+ cwd = await promises.mkdtemp(path.join(os.tmpdir(), "claude-cli-"));
504
+ } catch (mkdirErr) {
505
+ release();
506
+ throw mkdirErr;
507
+ }
271
508
  let result;
272
509
  try {
273
510
  result = await runner.run(args, prompt, {
274
511
  cwd,
275
512
  ...timeoutMs !== void 0 ? { timeoutMs } : {},
276
- ...ctx.signal !== void 0 ? { signal: ctx.signal } : {}
513
+ ...ctx.signal !== void 0 ? { signal: ctx.signal } : {},
514
+ ...env !== void 0 ? { env } : {}
277
515
  });
278
516
  } catch (rawErr) {
279
517
  release();
@@ -315,6 +553,7 @@ function claudeCliAdapter(opts) {
315
553
  if (result.exitCode !== 0 || envelope?.is_error === true || envelope === void 0) {
316
554
  throw classifyRunFailure(envelope, result);
317
555
  }
556
+ assertServedModel(envelope, model);
318
557
  const text = envelope.result ?? "";
319
558
  let rawStructured;
320
559
  if (req.outputJsonSchema !== void 0) {
@@ -337,6 +576,10 @@ function claudeCliAdapter(opts) {
337
576
  };
338
577
  const adapterResult = {
339
578
  model,
579
+ message: {
580
+ role: "assistant",
581
+ parts: text.length > 0 ? [{ kind: "text", text }] : []
582
+ },
340
583
  usage,
341
584
  warnings,
342
585
  ...text.length > 0 ? { text } : {},
@@ -349,13 +592,13 @@ function claudeCliAdapter(opts) {
349
592
  };
350
593
  }
351
594
  var CLAUDE_CLI_MODEL_IDS = [
352
- "claude-fable-5",
353
- "claude-opus-4-8",
595
+ "claude-fable-5-1",
596
+ "claude-opus-5-5",
354
597
  "claude-sonnet-5",
355
598
  "claude-haiku-4-5-20251001"
356
599
  ];
357
600
  var CLAUDE_CLI_EFFORTS = ["low", "medium", "high", "xhigh", "max"];
358
- function buildClaudeCliConfigSchema(modelName) {
601
+ function buildEffortConfigSchema(modelName) {
359
602
  return zod.z.strictObject({
360
603
  reasoning: zod.z.strictObject({
361
604
  effort: zod.z.enum(CLAUDE_CLI_EFFORTS).meta({
@@ -375,32 +618,51 @@ function buildClaudeCliConfigSchema(modelName) {
375
618
  description: `Strict claude-cli config for model ${modelName}. Text-only, no sampling knobs, effort-based reasoning.`
376
619
  });
377
620
  }
378
- var ClaudeFable5ConfigSchema = buildClaudeCliConfigSchema("claude-fable-5");
379
- var ClaudeOpus48ConfigSchema = buildClaudeCliConfigSchema("claude-opus-4-8");
380
- var ClaudeSonnet5ConfigSchema = buildClaudeCliConfigSchema("claude-sonnet-5");
381
- var ClaudeHaiku45ConfigSchema = buildClaudeCliConfigSchema(
382
- "claude-haiku-4-5-20251001"
383
- );
621
+ function buildHaikuConfigSchema() {
622
+ return zod.z.strictObject({
623
+ timeoutMs: zod.z.number().int().positive().max(18e5).optional().meta({
624
+ title: "Timeout",
625
+ description: "Logical request timeout in milliseconds; forwarded to the CLI runner."
626
+ })
627
+ }).meta({
628
+ title: "claude-haiku-4-5-20251001Config",
629
+ description: "Strict claude-cli config for claude-haiku-4-5-20251001. No reasoning key: the CLI drops --effort."
630
+ });
631
+ }
632
+ var ClaudeFable51ConfigSchema = buildEffortConfigSchema("claude-fable-5-1");
633
+ var ClaudeOpus55ConfigSchema = buildEffortConfigSchema("claude-opus-5-5");
634
+ var ClaudeSonnet5ConfigSchema = buildEffortConfigSchema("claude-sonnet-5");
635
+ var ClaudeHaiku45ConfigSchema = buildHaikuConfigSchema();
384
636
  var CONFIG_SCHEMAS = {
385
- "claude-fable-5": ClaudeFable5ConfigSchema,
386
- "claude-opus-4-8": ClaudeOpus48ConfigSchema,
637
+ "claude-fable-5-1": ClaudeFable51ConfigSchema,
638
+ "claude-opus-5-5": ClaudeOpus55ConfigSchema,
387
639
  "claude-sonnet-5": ClaudeSonnet5ConfigSchema,
388
640
  "claude-haiku-4-5-20251001": ClaudeHaiku45ConfigSchema
389
641
  };
642
+ var CLAUDE_CLI_LIMITS = {
643
+ "claude-fable-5-1": { contextWindow: 1e6, maxOutputTokens: 64e3 },
644
+ "claude-opus-5-5": { contextWindow: 1e6, maxOutputTokens: 128e3 },
645
+ "claude-sonnet-5": { contextWindow: 1e6, maxOutputTokens: 128e3 },
646
+ "claude-haiku-4-5-20251001": { contextWindow: 2e5, maxOutputTokens: 32e3 }
647
+ };
390
648
  var claudeCliModelDescriptors = CLAUDE_CLI_MODEL_IDS.map(
391
649
  (id) => {
392
650
  const configSchema = CONFIG_SCHEMAS[id];
393
651
  return {
394
652
  model: id,
395
653
  provider: "claude-cli",
654
+ limits: CLAUDE_CLI_LIMITS[id],
396
655
  capabilities: {
656
+ // The CLI runs text-only: the adapter rejects every non-text part.
657
+ inputMimeTypes: [],
397
658
  structuredOutput: true,
398
659
  nativeStructuredOutput: true,
399
- reasoningApi: "level",
400
- sampling: "fixed",
401
- vision: false
660
+ ...id !== "claude-haiku-4-5-20251001" ? { reasoningApi: "level" } : {},
661
+ admittedReasoningEfforts: id === "claude-haiku-4-5-20251001" ? [] : CLAUDE_CLI_EFFORTS,
662
+ sampling: "fixed"
402
663
  },
403
664
  configSchema,
665
+ configKeys: core.toConfigKeys(configSchema),
404
666
  configJsonSchema: core.toConfigJsonSchema(configSchema),
405
667
  validateConfig: core.zodToStandardSchema(configSchema)
406
668
  };
@@ -418,9 +680,11 @@ function claudeCliProvider(opts) {
418
680
  };
419
681
  }
420
682
 
421
- exports.ClaudeFable5ConfigSchema = ClaudeFable5ConfigSchema;
683
+ exports.CLAUDE_CLI_EFFORTS = CLAUDE_CLI_EFFORTS;
684
+ exports.CLAUDE_CLI_MODEL_IDS = CLAUDE_CLI_MODEL_IDS;
685
+ exports.ClaudeFable51ConfigSchema = ClaudeFable51ConfigSchema;
422
686
  exports.ClaudeHaiku45ConfigSchema = ClaudeHaiku45ConfigSchema;
423
- exports.ClaudeOpus48ConfigSchema = ClaudeOpus48ConfigSchema;
687
+ exports.ClaudeOpus55ConfigSchema = ClaudeOpus55ConfigSchema;
424
688
  exports.ClaudeSonnet5ConfigSchema = ClaudeSonnet5ConfigSchema;
425
689
  exports.buildClaudeCliRunner = buildClaudeCliRunner;
426
690
  exports.claudeCliAdapter = claudeCliAdapter;