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