claude-use 11.17.1 → 11.19.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
@@ -346,10 +346,10 @@ var init_schema = __esm({
346
346
  ANTIGRAVITY_EFFORTS = ["none", "low", "medium", "high", "xhigh", "max"];
347
347
  ANTIGRAVITY_DEFAULT_MODE = "cloud";
348
348
  ANTIGRAVITY_DEFAULT_TIER_MODELS = Object.freeze({
349
- fable: ["claude-opus-5-5-high", "gemini-4-argon-high", "gemini-3.8-flash-high"],
349
+ fable: ["gemini-4-argon-high", "claude-opus-5-5-high", "gemini-3.8-flash-high"],
350
350
  opus: ["claude-opus-5-5-high", "gemini-4-argon-high", "gemini-3.8-flash-high"],
351
351
  sonnet: ["claude-sonnet-5-5-medium", "gemini-4-argon-medium", "gemini-3.8-flash-medium"],
352
- haiku: ["gemini-3.8-flash-low", "gemini-4-argon-low", "gpt-oss-120b-medium"]
352
+ haiku: ["gemini-3.8-flash-low", "gemini-4-argon-low", "claude-sonnet-5-5-low"]
353
353
  });
354
354
  AntigravityModelTargetSchema = import_zod.z.union([import_zod.z.string().min(1), import_zod.z.array(import_zod.z.string().min(1)).min(1)]);
355
355
  AntigravityProviderConfigSchema = import_zod.z.strictObject({
@@ -359,6 +359,8 @@ var init_schema = __esm({
359
359
  defaultModel: import_zod.z.string().min(1).optional(),
360
360
  /** Model name mapping. A key naming a tier (`fable`, `opus`, `sonnet`, `haiku`) overrides that tier's shipped model and is matched by substring of the requested name in `ANTIGRAVITY_TIERS` order; any other key is an alias, matched against the whole requested name case-insensitively, so `/model <alias>` selects its backend model. An alias outranks every other rule, including the pass-through of backend names. A value is one model or an ordered list of candidates: the request goes to the first whose quota windows are not spent, and when every candidate is spent, to the one whose binding window lifts soonest. */
361
361
  models: import_zod.z.record(import_zod.z.string().min(1), AntigravityModelTargetSchema).optional(),
362
+ /** When every candidate of the tier a request names has no quota left, serve it from the next tier down, and onward through the lower tiers, instead of failing with the quota limit. Applies to a name that selects a tier (`/model fable`), not to an alias or a backend model name. Defaults to false. */
363
+ degradeDownTiers: import_zod.z.boolean().optional(),
362
364
  /** The reasoning effort used when the request's own effort is not one the backend accepts. */
363
365
  effort: import_zod.z.enum(ANTIGRAVITY_EFFORTS).optional(),
364
366
  /** Cloud-specific settings (for `mode: "cloud"`). */
@@ -581,25 +583,102 @@ var init_schema = __esm({
581
583
  }
582
584
  });
583
585
 
586
+ // src/config/unrecognisedKeys.ts
587
+ function isRecord(value) {
588
+ return typeof value === "object" && value !== null;
589
+ }
590
+ function parseIgnoringUnrecognisedKeys(schema, raw) {
591
+ const first = schema.safeParse(raw);
592
+ if (first.success) {
593
+ return { success: true, data: first.data, ignored: [] };
594
+ }
595
+ const unrecognised = first.error.issues.filter((issue) => issue.code === "unrecognized_keys");
596
+ const others = first.error.issues.filter((issue) => issue.code !== "unrecognized_keys");
597
+ if (others.length > 0) {
598
+ return { success: false, issues: others };
599
+ }
600
+ const stripped = structuredClone(raw);
601
+ const ignored = [];
602
+ for (const issue of unrecognised) {
603
+ let holder = stripped;
604
+ for (const step of issue.path) {
605
+ holder = isRecord(holder) ? holder[step] : void 0;
606
+ }
607
+ if (isRecord(holder)) {
608
+ const values = Object.fromEntries(issue.keys.map((key) => [key, holder[key]]));
609
+ for (const key of issue.keys) {
610
+ Reflect.deleteProperty(holder, key);
611
+ }
612
+ ignored.push({ path: issue.path, keys: issue.keys, values });
613
+ }
614
+ }
615
+ const second = schema.safeParse(stripped);
616
+ return second.success ? { success: true, data: second.data, ignored } : { success: false, issues: second.error.issues };
617
+ }
618
+ function describeIgnoredKeys(filePath, ignored) {
619
+ const places = ignored.map(({ path: path41, keys }) => `${path41.length === 0 ? "" : `${path41.map(String).join(".")}.`}${keys.join(", ")}`);
620
+ return `${filePath} has settings this version of agent-shim does not know and ignores: ${places.join("; ")}. A newer release may read them.`;
621
+ }
622
+ function noteIgnoredKeys(filePath, ignored) {
623
+ if (ignored.length === 0) {
624
+ ignoredByFile.delete(filePath);
625
+ return;
626
+ }
627
+ ignoredByFile.set(filePath, ignored);
628
+ const message = `agent-shim: warning: ${describeIgnoredKeys(filePath, ignored)}
629
+ `;
630
+ if (!warned.has(message)) {
631
+ warned.add(message);
632
+ process.stderr.write(message);
633
+ }
634
+ }
635
+ function restoreIgnoredKeys(filePath, value) {
636
+ const ignored = ignoredByFile.get(filePath);
637
+ if (ignored === void 0) {
638
+ return value;
639
+ }
640
+ const restored = structuredClone(value);
641
+ for (const { path: path41, values } of ignored) {
642
+ let holder = restored;
643
+ for (const step of path41) {
644
+ holder = isRecord(holder) ? holder[step] : void 0;
645
+ }
646
+ if (isRecord(holder)) {
647
+ for (const [key, held] of Object.entries(values)) {
648
+ holder[key] = held;
649
+ }
650
+ }
651
+ }
652
+ return restored;
653
+ }
654
+ var warned, ignoredByFile;
655
+ var init_unrecognisedKeys = __esm({
656
+ "src/config/unrecognisedKeys.ts"() {
657
+ "use strict";
658
+ warned = /* @__PURE__ */ new Set();
659
+ ignoredByFile = /* @__PURE__ */ new Map();
660
+ }
661
+ });
662
+
584
663
  // src/config/load.ts
585
664
  function createExplorer(moduleName = "agent-shim") {
586
665
  return (0, import_cosmiconfig.cosmiconfigSync)(moduleName, { searchPlaces: [] });
587
666
  }
588
- function isRecord(value) {
667
+ function isRecord2(value) {
589
668
  return typeof value === "object" && value !== null && !Array.isArray(value);
590
669
  }
591
670
  function captureEntryOrder(value) {
592
- if (!isRecord(value)) {
671
+ if (!isRecord2(value)) {
593
672
  return [];
594
673
  }
595
674
  const entries = value.entries;
596
- if (!isRecord(entries)) {
675
+ if (!isRecord2(entries)) {
597
676
  return [];
598
677
  }
599
678
  return Object.keys(entries);
600
679
  }
601
680
  function captureRuleEntryOrders(value) {
602
- if (!isRecord(value)) {
681
+ if (!isRecord2(value)) {
603
682
  return [];
604
683
  }
605
684
  const rules = value.rules;
@@ -614,7 +693,7 @@ function cosmiconfigReader(explorer = createExplorer()) {
614
693
  try {
615
694
  result = explorer.load(filepath);
616
695
  } catch (error) {
617
- const code = isRecord(error) ? error.code : void 0;
696
+ const code = isRecord2(error) ? error.code : void 0;
618
697
  if (code === "ENOENT") {
619
698
  return void 0;
620
699
  }
@@ -631,10 +710,11 @@ function loadConfigFile(filepath, schema, read = cosmiconfigReader()) {
631
710
  if (raw === void 0) {
632
711
  return void 0;
633
712
  }
634
- const parsed = schema.safeParse(raw);
713
+ const parsed = parseIgnoringUnrecognisedKeys(schema, raw);
635
714
  if (!parsed.success) {
636
- throw new ConfigValidationError(filepath, parsed.error.issues);
715
+ throw new ConfigValidationError(filepath, parsed.issues);
637
716
  }
717
+ noteIgnoredKeys(filepath, parsed.ignored);
638
718
  return {
639
719
  filepath,
640
720
  config: parsed.data,
@@ -648,6 +728,7 @@ var init_load = __esm({
648
728
  "use strict";
649
729
  import_cosmiconfig = require("cosmiconfig");
650
730
  init_cliError();
731
+ init_unrecognisedKeys();
651
732
  ConfigValidationError = class extends CliError {
652
733
  constructor(filepath, issues) {
653
734
  const detail = issues.map((issue) => ` ${issue.path.join(".") || "(root)"}: ${issue.message}`).join("\n");
@@ -673,10 +754,11 @@ function readJson(filePath, schema, storeFs = nodeStoreFs) {
673
754
  return void 0;
674
755
  }
675
756
  const parsed = JSON.parse(raw);
676
- const result = schema.safeParse(parsed);
757
+ const result = parseIgnoringUnrecognisedKeys(schema, parsed);
677
758
  if (!result.success) {
678
- throw new ConfigValidationError(filePath, result.error.issues);
759
+ throw new ConfigValidationError(filePath, result.issues);
679
760
  }
761
+ noteIgnoredKeys(filePath, result.ignored);
680
762
  return result.data;
681
763
  }
682
764
  function writeTextAtomic(filePath, contents, storeFs = nodeStoreFs) {
@@ -692,7 +774,7 @@ function writeTextAtomic(filePath, contents, storeFs = nodeStoreFs) {
692
774
  }
693
775
  }
694
776
  function writeJsonAtomic(filePath, data, storeFs = nodeStoreFs) {
695
- writeTextAtomic(filePath, `${JSON.stringify(data, null, 2)}
777
+ writeTextAtomic(filePath, `${JSON.stringify(restoreIgnoredKeys(filePath, data), null, 2)}
696
778
  `, storeFs);
697
779
  }
698
780
  function applyPatch(filePath, schema, patch, options = {}) {
@@ -718,6 +800,7 @@ var init_store = __esm({
718
800
  import_node_path3 = __toESM(require("node:path"), 1);
719
801
  import_node_crypto = require("node:crypto");
720
802
  init_load();
803
+ init_unrecognisedKeys();
721
804
  nodeStoreFs = {
722
805
  readFileUtf8(filePath) {
723
806
  try {
@@ -2837,7 +2920,7 @@ var init_package = __esm({
2837
2920
  "package.json"() {
2838
2921
  package_default = {
2839
2922
  name: "claude-use",
2840
- version: "11.17.1",
2923
+ version: "11.19.0",
2841
2924
  description: "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
2842
2925
  license: "MIT",
2843
2926
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -6201,7 +6284,7 @@ function formatCredentialSummary(summary) {
6201
6284
  function describeCredential(credential) {
6202
6285
  return formatCredentialSummary(summariseCredential(credential));
6203
6286
  }
6204
- function isRecord5(value) {
6287
+ function isRecord6(value) {
6205
6288
  return typeof value === "object" && value !== null && !Array.isArray(value);
6206
6289
  }
6207
6290
  function unpackKeyringToken(raw) {
@@ -6213,7 +6296,7 @@ function unpackKeyringToken(raw) {
6213
6296
  const base64Str = trimmed.slice(GO_KEYRING_BASE64_PREFIX.length);
6214
6297
  const decoded = Buffer.from(base64Str, "base64").toString("utf8");
6215
6298
  const parsed = JSON.parse(decoded);
6216
- if (isRecord5(parsed) && isRecord5(parsed.token)) {
6299
+ if (isRecord6(parsed) && isRecord6(parsed.token)) {
6217
6300
  const accessToken = parsed.token.access_token;
6218
6301
  if (typeof accessToken === "string" && accessToken.trim() !== "") {
6219
6302
  return accessToken.trim();
@@ -6327,14 +6410,14 @@ function providerJsonPath(paths, name) {
6327
6410
  function providerExists(paths, name) {
6328
6411
  return import_node_fs6.default.existsSync(providerJsonPath(paths, name));
6329
6412
  }
6330
- function isRecord6(value) {
6413
+ function isRecord7(value) {
6331
6414
  return typeof value === "object" && value !== null && !Array.isArray(value);
6332
6415
  }
6333
6416
  function legacyProviderConversion(raw) {
6334
- if (!isRecord6(raw) || "credential" in raw) {
6417
+ if (!isRecord7(raw) || "credential" in raw) {
6335
6418
  return void 0;
6336
6419
  }
6337
- const env = isRecord6(raw.env) ? raw.env : void 0;
6420
+ const env = isRecord7(raw.env) ? raw.env : void 0;
6338
6421
  const legacyEnvKeys = env === void 0 ? [] : Object.keys(env).filter((key) => LEGACY_ENV_CREDENTIAL_KEYS.includes(key));
6339
6422
  const fields = [...LEGACY_PROVIDER_FIELDS.filter((field) => field in raw), ...legacyEnvKeys.map((key) => `env.${key}`)];
6340
6423
  if (fields.length === 0) {
@@ -6367,10 +6450,11 @@ function parseProviderFile(filePath, raw) {
6367
6450
  if (conversion !== void 0) {
6368
6451
  throw new LegacyProviderFileError(filePath, conversion);
6369
6452
  }
6370
- const parsed = ProviderSchema.safeParse(raw);
6453
+ const parsed = parseIgnoringUnrecognisedKeys(ProviderSchema, raw);
6371
6454
  if (!parsed.success) {
6372
- throw new ConfigValidationError(filePath, parsed.error.issues);
6455
+ throw new ConfigValidationError(filePath, parsed.issues);
6373
6456
  }
6457
+ noteIgnoredKeys(filePath, parsed.ignored);
6374
6458
  return parsed.data;
6375
6459
  }
6376
6460
  function readProvider(paths, name) {
@@ -6431,7 +6515,7 @@ function isEmptyCodexConfig(config) {
6431
6515
  return config === void 0 || config.defaultModel === void 0 && config.effort === void 0 && config.login === void 0 && (config.models === void 0 || Object.keys(config.models).length === 0);
6432
6516
  }
6433
6517
  function isEmptyAntigravityConfig(config) {
6434
- return config === void 0 || config.mode === void 0 && config.defaultModel === void 0 && config.effort === void 0 && config.cloud === void 0 && config.local === void 0 && (config.models === void 0 || Object.keys(config.models).length === 0);
6518
+ return config === void 0 || config.mode === void 0 && config.defaultModel === void 0 && config.effort === void 0 && config.degradeDownTiers === void 0 && config.cloud === void 0 && config.local === void 0 && (config.models === void 0 || Object.keys(config.models).length === 0);
6435
6519
  }
6436
6520
  function addProvider(paths, name, input) {
6437
6521
  if (providerExists(paths, name)) {
@@ -6580,6 +6664,7 @@ var init_providersStore = __esm({
6580
6664
  import_node_path25 = __toESM(require("node:path"), 1);
6581
6665
  init_load();
6582
6666
  init_store();
6667
+ init_unrecognisedKeys();
6583
6668
  init_schema();
6584
6669
  init_cliError();
6585
6670
  init_credential();
@@ -7562,7 +7647,7 @@ function resolvePoolLaunch(params) {
7562
7647
  if (stickyRead.problem !== void 0) {
7563
7648
  log.warn(`agent-shim: ${stickyRead.problem}; ignoring the last-pick record`);
7564
7649
  }
7565
- const warned = /* @__PURE__ */ new Set();
7650
+ const warned2 = /* @__PURE__ */ new Set();
7566
7651
  for (; ; ) {
7567
7652
  const nowMs = params.now();
7568
7653
  let graph;
@@ -7586,8 +7671,8 @@ function resolvePoolLaunch(params) {
7586
7671
  }
7587
7672
  for (const gone of graph.missing) {
7588
7673
  const key = `${gone.pool}:${gone.identity}`;
7589
- if (!warned.has(key)) {
7590
- warned.add(key);
7674
+ if (!warned2.has(key)) {
7675
+ warned2.add(key);
7591
7676
  log.warn(`agent-shim: pool "${gone.pool}" names identity "${gone.identity}", which does not exist; skipping it`);
7592
7677
  }
7593
7678
  }
@@ -10302,7 +10387,7 @@ var LiveTaskSchema = import_zod5.z.strictObject({
10302
10387
  observedAt: import_zod5.z.number()
10303
10388
  });
10304
10389
  var SYSTEM_SUBTYPES = ["task_started", "task_progress", "task_updated", "task_notification", "background_tasks_changed"];
10305
- function isRecord2(value) {
10390
+ function isRecord3(value) {
10306
10391
  return typeof value === "object" && value !== null && !Array.isArray(value);
10307
10392
  }
10308
10393
  function stringField(record, field) {
@@ -10319,7 +10404,7 @@ function booleanField(record, field) {
10319
10404
  }
10320
10405
  function usageOf(record) {
10321
10406
  const raw = record.usage;
10322
- if (!isRecord2(raw)) {
10407
+ if (!isRecord3(raw)) {
10323
10408
  return void 0;
10324
10409
  }
10325
10410
  const totalTokens = numberField(raw, "total_tokens");
@@ -10351,7 +10436,7 @@ function bounded(book) {
10351
10436
  return book;
10352
10437
  }
10353
10438
  function applyAgentTaskEvent(book, sessionId, payload, observedAt2) {
10354
- if (!isRecord2(payload) || payload.type !== "system") {
10439
+ if (!isRecord3(payload) || payload.type !== "system") {
10355
10440
  return book;
10356
10441
  }
10357
10442
  const subtype = payload.subtype;
@@ -10367,8 +10452,8 @@ function applyAgentTaskEvent(book, sessionId, payload, observedAt2) {
10367
10452
  if (subtype === "background_tasks_changed") {
10368
10453
  const tasks = Array.isArray(payload.tasks) ? payload.tasks : [];
10369
10454
  for (const raw of tasks) {
10370
- const taskId2 = isRecord2(raw) ? stringField(raw, "task_id") : void 0;
10371
- if (isRecord2(raw) && taskId2 !== void 0) {
10455
+ const taskId2 = isRecord3(raw) ? stringField(raw, "task_id") : void 0;
10456
+ if (isRecord3(raw) && taskId2 !== void 0) {
10372
10457
  upsert(taskId2, { runId: stringField(raw, "run_id"), taskType: stringField(raw, "task_type"), description: stringField(raw, "description") });
10373
10458
  }
10374
10459
  }
@@ -10391,7 +10476,7 @@ function applyAgentTaskEvent(book, sessionId, payload, observedAt2) {
10391
10476
  } else if (subtype === "task_progress") {
10392
10477
  upsert(taskId, { ...common, subagentType: stringField(payload, "subagent_type"), lastToolName: stringField(payload, "last_tool_name"), usage: usageOf(payload) });
10393
10478
  } else if (subtype === "task_updated") {
10394
- const patch = isRecord2(payload.patch) ? payload.patch : {};
10479
+ const patch = isRecord3(payload.patch) ? payload.patch : {};
10395
10480
  upsert(taskId, { runId: stringField(payload, "run_id"), status: stringField(patch, "status") });
10396
10481
  } else {
10397
10482
  upsert(taskId, { ...common, status: stringField(payload, "status"), outputFile: stringField(payload, "output_file"), summary: stringField(payload, "summary"), usage: usageOf(payload) });
@@ -10473,7 +10558,7 @@ function sessionCreateId(body) {
10473
10558
  const id = session.id;
10474
10559
  return typeof id === "string" && id.startsWith(RC_SESSION_ID_PREFIX) ? id : void 0;
10475
10560
  }
10476
- function isRecord3(value) {
10561
+ function isRecord4(value) {
10477
10562
  return typeof value === "object" && value !== null && !Array.isArray(value);
10478
10563
  }
10479
10564
  function parseJsonObject(body) {
@@ -10483,7 +10568,7 @@ function parseJsonObject(body) {
10483
10568
  } catch {
10484
10569
  return void 0;
10485
10570
  }
10486
- return isRecord3(parsed) ? parsed : void 0;
10571
+ return isRecord4(parsed) ? parsed : void 0;
10487
10572
  }
10488
10573
  function nonEmptyString(record, field) {
10489
10574
  const value = record === void 0 ? void 0 : record[field];
@@ -10504,11 +10589,11 @@ function payloadEventsOf(body) {
10504
10589
  }
10505
10590
  const payloads = [];
10506
10591
  for (const event of events) {
10507
- if (!isRecord3(event)) {
10592
+ if (!isRecord4(event)) {
10508
10593
  continue;
10509
10594
  }
10510
10595
  const payload = event.payload;
10511
- if (!isRecord3(payload)) {
10596
+ if (!isRecord4(payload)) {
10512
10597
  continue;
10513
10598
  }
10514
10599
  payloads.push(payload);
@@ -10523,7 +10608,7 @@ function pendingOfControlRequestPayload(payload) {
10523
10608
  if (requestId === void 0) {
10524
10609
  return void 0;
10525
10610
  }
10526
- const request4 = isRecord3(payload.request) ? payload.request : void 0;
10611
+ const request4 = isRecord4(payload.request) ? payload.request : void 0;
10527
10612
  const subtype = nonEmptyString(request4, "subtype");
10528
10613
  const type = subtype ?? "control_request";
10529
10614
  let summary = "";
@@ -10540,7 +10625,7 @@ function answeredRequestIdsOfControlResponsePayload(payload) {
10540
10625
  if (payload.type !== "control_response") {
10541
10626
  return [];
10542
10627
  }
10543
- const response = isRecord3(payload.response) ? payload.response : void 0;
10628
+ const response = isRecord4(payload.response) ? payload.response : void 0;
10544
10629
  const id = nonEmptyString(response, "request_id") ?? nonEmptyString(payload, "request_id") ?? nonEmptyString(payload, "uuid");
10545
10630
  return id === void 0 ? [] : [id];
10546
10631
  }
@@ -10769,7 +10854,7 @@ function createRcSessionTracker(deps) {
10769
10854
  return;
10770
10855
  }
10771
10856
  entry.sequenceNum = entry.sequenceNum === void 0 || event.sequence_num > entry.sequenceNum ? event.sequence_num : entry.sequenceNum;
10772
- if (!isRecord3(event.payload)) {
10857
+ if (!isRecord4(event.payload)) {
10773
10858
  return;
10774
10859
  }
10775
10860
  entry.liveTasks = applyAgentTaskEvent(entry.liveTasks, sessionId, event.payload, deps.now());
@@ -12192,11 +12277,11 @@ var import_node_path10 = __toESM(require("node:path"), 1);
12192
12277
  function isSafeSessionId(sessionId) {
12193
12278
  return /^[A-Za-z0-9_-]+$/.test(sessionId);
12194
12279
  }
12195
- function isRecord4(value) {
12280
+ function isRecord5(value) {
12196
12281
  return typeof value === "object" && value !== null && !Array.isArray(value);
12197
12282
  }
12198
12283
  function credentialOfJson(parsed) {
12199
- if (!isRecord4(parsed)) {
12284
+ if (!isRecord5(parsed)) {
12200
12285
  return void 0;
12201
12286
  }
12202
12287
  const { authorization, anthropicVersion, anthropicClientPlatform } = parsed;
@@ -12226,7 +12311,7 @@ function createRcCredentialStore(fs13, dir) {
12226
12311
  } catch {
12227
12312
  return void 0;
12228
12313
  }
12229
- return isRecord4(parsed) ? parsed : void 0;
12314
+ return isRecord5(parsed) ? parsed : void 0;
12230
12315
  };
12231
12316
  return {
12232
12317
  read: (sessionId) => {
@@ -14163,6 +14248,7 @@ function parseSiwcFile(raw, filePath) {
14163
14248
 
14164
14249
  // src/doctorReport.ts
14165
14250
  init_load();
14251
+ init_unrecognisedKeys();
14166
14252
  init_schema();
14167
14253
  init_credential();
14168
14254
  init_credentialCache();
@@ -14373,11 +14459,11 @@ function validateJson(schema, input) {
14373
14459
  } catch (error) {
14374
14460
  return { ok: false, message: `${input.path} is not valid JSON: ${error instanceof Error ? error.message : String(error)}` };
14375
14461
  }
14376
- const result = schema.safeParse(parsed);
14462
+ const result = parseIgnoringUnrecognisedKeys(schema, parsed);
14377
14463
  if (!result.success) {
14378
- return { ok: false, message: new ConfigValidationError(input.path, result.error.issues).message };
14464
+ return { ok: false, message: new ConfigValidationError(input.path, result.issues).message };
14379
14465
  }
14380
- return { ok: true, data: result.data };
14466
+ return { ok: true, data: result.data, ...result.ignored.length === 0 ? {} : { warning: describeIgnoredKeys(input.path, result.ignored) } };
14381
14467
  }
14382
14468
  function tcpPortEraRecord(raw) {
14383
14469
  let parsed;
@@ -14470,11 +14556,14 @@ function pushProvider(push, entry, cacheEnv, signIn) {
14470
14556
  push("provider", "fail", new LegacyProviderFileError(entry.path, conversion).message, entry.name);
14471
14557
  return;
14472
14558
  }
14473
- const validated3 = ProviderSchema.safeParse(parsed);
14559
+ const validated3 = parseIgnoringUnrecognisedKeys(ProviderSchema, parsed);
14474
14560
  if (!validated3.success) {
14475
- push("provider", "fail", new ConfigValidationError(entry.path, validated3.error.issues).message, entry.name);
14561
+ push("provider", "fail", new ConfigValidationError(entry.path, validated3.issues).message, entry.name);
14476
14562
  return;
14477
14563
  }
14564
+ if (validated3.ignored.length > 0) {
14565
+ push("provider", "warn", describeIgnoredKeys(entry.path, validated3.ignored), entry.name);
14566
+ }
14478
14567
  const cache = cacheClause(cacheEnv, `provider ${entry.name}`, validated3.data.credential);
14479
14568
  push("provider", cache.unreadable ? "fail" : "pass", `${entry.name} is valid (${describeProviderEndpoint(validated3.data)}, credential ${describeCredential(validated3.data.credential)})${cache.text}.`, entry.name);
14480
14569
  if (validated3.data.env?.ENABLE_TOOL_SEARCH === void 0) {
@@ -14509,6 +14598,13 @@ function runDoctor(params) {
14509
14598
  const push = (section, severity, message, subject) => {
14510
14599
  findings.push({ section, severity, message, ...subject === void 0 ? {} : { subject } });
14511
14600
  };
14601
+ const validate = (schema, input, section, subject) => {
14602
+ const validated3 = validateJson(schema, input);
14603
+ if (validated3.ok && validated3.warning !== void 0) {
14604
+ push(section, "warn", validated3.warning, subject);
14605
+ }
14606
+ return validated3;
14607
+ };
14512
14608
  const checkPin = (section, subject, where, version) => {
14513
14609
  const installed = params.installedClaudeVersions;
14514
14610
  if (version === void 0 || installed === void 0 || installed.includes(version)) {
@@ -14548,7 +14644,7 @@ function runDoctor(params) {
14548
14644
  pushLegacyName(push, params);
14549
14645
  const profileSources = /* @__PURE__ */ new Map();
14550
14646
  for (const entry of params.configProfiles) {
14551
- const validated3 = validateJson(ConfigProfileSchema, entry);
14647
+ const validated3 = validate(ConfigProfileSchema, entry, "config-profile", entry.name);
14552
14648
  if (!validated3.ok) {
14553
14649
  push("config-profile", "fail", validated3.message, entry.name);
14554
14650
  continue;
@@ -14570,7 +14666,7 @@ function runDoctor(params) {
14570
14666
  const validProfileNames = new Set(profileSources.keys());
14571
14667
  const validIdentityNames = /* @__PURE__ */ new Set();
14572
14668
  for (const entry of params.identities) {
14573
- const validated3 = validateJson(IdentitySchema, entry);
14669
+ const validated3 = validate(IdentitySchema, entry, "identity", entry.name);
14574
14670
  if (!validated3.ok) {
14575
14671
  push("identity", "fail", validated3.message, entry.name);
14576
14672
  continue;
@@ -14656,7 +14752,7 @@ function runDoctor(params) {
14656
14752
  if (params.directoryRules.raw === void 0) {
14657
14753
  push("directory-rules", "pass", "No directory-rules.json configured.");
14658
14754
  } else {
14659
- const validated3 = validateJson(DirectoryRulesSchema, params.directoryRules);
14755
+ const validated3 = validate(DirectoryRulesSchema, params.directoryRules, "directory-rules");
14660
14756
  if (!validated3.ok) {
14661
14757
  push("directory-rules", "fail", validated3.message);
14662
14758
  } else {
@@ -14681,7 +14777,7 @@ function runDoctor(params) {
14681
14777
  if (params.globalConfig.raw === void 0) {
14682
14778
  push("global-config", "pass", "No config.json configured.");
14683
14779
  } else {
14684
- const validated3 = validateJson(GlobalConfigSchema, params.globalConfig);
14780
+ const validated3 = validate(GlobalConfigSchema, params.globalConfig, "global-config");
14685
14781
  if (!validated3.ok) {
14686
14782
  push("global-config", "fail", validated3.message);
14687
14783
  } else {
@@ -14701,7 +14797,7 @@ function runDoctor(params) {
14701
14797
  if (params.categoriesLocal.raw === void 0) {
14702
14798
  push("categories-local", "pass", "No categories.local.json configured.");
14703
14799
  } else {
14704
- const validated3 = validateJson(CategoryClassificationOverlaySchema, params.categoriesLocal);
14800
+ const validated3 = validate(CategoryClassificationOverlaySchema, params.categoriesLocal, "categories-local");
14705
14801
  push(
14706
14802
  "categories-local",
14707
14803
  validated3.ok ? "pass" : "fail",
@@ -16312,15 +16408,15 @@ function createQuotaExpiringPublisher(hub, deps) {
16312
16408
 
16313
16409
  // src/frontdoor/rcLiveUsage.ts
16314
16410
  var RC_RATE_LIMIT_EVENT_TYPE = "rate_limit_event";
16315
- function isRecord7(value) {
16411
+ function isRecord8(value) {
16316
16412
  return typeof value === "object" && value !== null && !Array.isArray(value);
16317
16413
  }
16318
16414
  function rcRateLimitInfoOf(event) {
16319
16415
  const payload = event.envelope.payload;
16320
- if (!isRecord7(payload) || payload.type !== RC_RATE_LIMIT_EVENT_TYPE) {
16416
+ if (!isRecord8(payload) || payload.type !== RC_RATE_LIMIT_EVENT_TYPE) {
16321
16417
  return void 0;
16322
16418
  }
16323
- if (!isRecord7(payload.rate_limit_info)) {
16419
+ if (!isRecord8(payload.rate_limit_info)) {
16324
16420
  return void 0;
16325
16421
  }
16326
16422
  const parsed = RcRateLimitInfoSchema.safeParse(payload.rate_limit_info);
@@ -16408,7 +16504,7 @@ function createSseParser() {
16408
16504
  }
16409
16505
  };
16410
16506
  }
16411
- function isRecord8(value) {
16507
+ function isRecord9(value) {
16412
16508
  return typeof value === "object" && value !== null && !Array.isArray(value);
16413
16509
  }
16414
16510
  function sequenceNumOf(value) {
@@ -16430,7 +16526,7 @@ function parseRcStreamEnvelope(parsed) {
16430
16526
  } catch {
16431
16527
  return void 0;
16432
16528
  }
16433
- if (!isRecord8(data)) {
16529
+ if (!isRecord9(data)) {
16434
16530
  return void 0;
16435
16531
  }
16436
16532
  const eventType = data.event_type;
@@ -16671,7 +16767,7 @@ init_capability();
16671
16767
  // src/frontdoor/rcSelfHostEndpoints.ts
16672
16768
  var RC_SOURCE_WORKER = "worker";
16673
16769
  var RC_SOURCE_CLIENT = "client";
16674
- function isRecord9(value) {
16770
+ function isRecord10(value) {
16675
16771
  return typeof value === "object" && value !== null && !Array.isArray(value);
16676
16772
  }
16677
16773
  function parseJsonObject2(body) {
@@ -16681,7 +16777,7 @@ function parseJsonObject2(body) {
16681
16777
  } catch {
16682
16778
  return void 0;
16683
16779
  }
16684
- return isRecord9(parsed) ? parsed : void 0;
16780
+ return isRecord10(parsed) ? parsed : void 0;
16685
16781
  }
16686
16782
  function nonEmptyString2(record, field) {
16687
16783
  const value = record === void 0 ? void 0 : record[field];
@@ -16755,7 +16851,7 @@ async function serveRcClientChannels(ctx, tail, method, maxBatchEvents) {
16755
16851
  }
16756
16852
  const results = [];
16757
16853
  for (const event of events) {
16758
- if (!isRecord9(event) || !isRecord9(event.payload)) {
16854
+ if (!isRecord10(event) || !isRecord10(event.payload)) {
16759
16855
  await ctx.answerJson(response, HTTP_STATUS.badRequest, { type: "error", error: { type: "invalid_request_error", message: "every event in a teleport write is an object carrying one payload object" } });
16760
16856
  return true;
16761
16857
  }
@@ -16855,7 +16951,7 @@ async function serveRcCompatSessions(ctx, pathname, compatPath) {
16855
16951
  // src/frontdoor/rcSelfHostConversations.ts
16856
16952
  var RC_CONVERSATIONS_PATH_PREFIX = "/v1/code/conversations";
16857
16953
  var RC_CONVERSATION_ID_PREFIX = "conv_";
16858
- function isRecord10(value) {
16954
+ function isRecord11(value) {
16859
16955
  return typeof value === "object" && value !== null && !Array.isArray(value);
16860
16956
  }
16861
16957
  function parseJsonObject3(body) {
@@ -16865,7 +16961,7 @@ function parseJsonObject3(body) {
16865
16961
  } catch {
16866
16962
  return void 0;
16867
16963
  }
16868
- return isRecord10(parsed) ? parsed : void 0;
16964
+ return isRecord11(parsed) ? parsed : void 0;
16869
16965
  }
16870
16966
  function nonEmptyString3(record, field) {
16871
16967
  const value = record === void 0 ? void 0 : record[field];
@@ -16919,7 +17015,7 @@ async function serveRcConversations(ctx, pathname, method) {
16919
17015
  }
16920
17016
  const results = [];
16921
17017
  for (const event of events) {
16922
- if (!isRecord10(event) || !isRecord10(event.payload)) {
17018
+ if (!isRecord11(event) || !isRecord11(event.payload)) {
16923
17019
  await ctx.answerJson(response, HTTP_STATUS.badRequest, { type: "error", error: { type: "invalid_request_error", message: "every event in a write is an object carrying one payload object" } });
16924
17020
  return;
16925
17021
  }
@@ -16951,7 +17047,7 @@ var RC_SELF_HOST_SCOPE_LIST = ["user:profile", "user:inference", "user:sessions:
16951
17047
  var RC_SELF_HOST_OAUTH_TOKEN_TTL_SECONDS = 3600;
16952
17048
  var MS_PER_SECOND5 = 1e3;
16953
17049
  var HTTP_SERVICE_UNAVAILABLE = 503;
16954
- function isRecord11(value) {
17050
+ function isRecord12(value) {
16955
17051
  return typeof value === "object" && value !== null && !Array.isArray(value);
16956
17052
  }
16957
17053
  function parseJsonObject4(body) {
@@ -16961,7 +17057,7 @@ function parseJsonObject4(body) {
16961
17057
  } catch {
16962
17058
  return void 0;
16963
17059
  }
16964
- return isRecord11(parsed) ? parsed : void 0;
17060
+ return isRecord12(parsed) ? parsed : void 0;
16965
17061
  }
16966
17062
  function growthBookFeatures() {
16967
17063
  return {
@@ -17315,7 +17411,7 @@ var RC_SELF_HOST_WORKER_EPOCH = 1;
17315
17411
  var RC_STREAM_EVENT_NAME2 = "client_event";
17316
17412
  var CONFLICT_REASON_HEADER2 = "x-ccr-conflict-reason";
17317
17413
  var CONFLICT_REASON_EPOCH_STALE = "epoch_stale";
17318
- function isRecord12(value) {
17414
+ function isRecord13(value) {
17319
17415
  return typeof value === "object" && value !== null && !Array.isArray(value);
17320
17416
  }
17321
17417
  function isWebSearchRefusal(value) {
@@ -17399,7 +17495,7 @@ function parseJsonObject5(body) {
17399
17495
  } catch {
17400
17496
  return void 0;
17401
17497
  }
17402
- return isRecord12(parsed) ? parsed : void 0;
17498
+ return isRecord13(parsed) ? parsed : void 0;
17403
17499
  }
17404
17500
  function mintWorkerJwt(randomToken, issuedAt) {
17405
17501
  const encode = (value) => Buffer.from(JSON.stringify(value), "utf8").toString("base64url");
@@ -17659,7 +17755,7 @@ data: ${JSON.stringify(envelope)}
17659
17755
  if (status !== void 0) {
17660
17756
  session.workerStatus = status;
17661
17757
  }
17662
- if (isRecord12(body?.external_metadata)) {
17758
+ if (isRecord13(body?.external_metadata)) {
17663
17759
  session.externalMetadata = body.external_metadata;
17664
17760
  }
17665
17761
  await answerJson2(response, HTTP_STATUS.ok, {});
@@ -17689,7 +17785,7 @@ data: ${JSON.stringify(envelope)}
17689
17785
  }
17690
17786
  const results = [];
17691
17787
  for (const event of events) {
17692
- if (!isRecord12(event) || !isRecord12(event.payload)) {
17788
+ if (!isRecord13(event) || !isRecord13(event.payload)) {
17693
17789
  await answerJson2(response, HTTP_STATUS.badRequest, { type: "error", error: { type: "invalid_request_error", message: "every event in a batch is an object carrying one payload object" } });
17694
17790
  return;
17695
17791
  }
@@ -17722,7 +17818,7 @@ data: ${JSON.stringify(envelope)}
17722
17818
  return;
17723
17819
  }
17724
17820
  for (const event of events) {
17725
- if (isRecord12(event)) {
17821
+ if (isRecord13(event)) {
17726
17822
  session.internalEvents.push({ eventId: deps.newUuid(), body: event });
17727
17823
  }
17728
17824
  }
@@ -17818,7 +17914,7 @@ data: ${JSON.stringify(envelope)}
17818
17914
  }
17819
17915
  const results = [];
17820
17916
  for (const event of events) {
17821
- if (!isRecord12(event) || !isRecord12(event.payload)) {
17917
+ if (!isRecord13(event) || !isRecord13(event.payload)) {
17822
17918
  await answerJson2(response, HTTP_STATUS.badRequest, { type: "error", error: { type: "invalid_request_error", message: "every event in a write is an object carrying one payload object" } });
17823
17919
  return;
17824
17920
  }
@@ -17955,7 +18051,7 @@ var RC_SELF_HOST_RECORD_DIR = "rc-selfhost";
17955
18051
  var RC_SELF_HOST_RECORD_FILE = "credential.json";
17956
18052
  var SELF_HOST_EMAIL = "selfhost@agent-shim.invalid";
17957
18053
  var SELF_HOST_SUBSCRIPTION_TYPE = "max";
17958
- function isRecord13(value) {
18054
+ function isRecord14(value) {
17959
18055
  return typeof value === "object" && value !== null && !Array.isArray(value);
17960
18056
  }
17961
18057
  function readJsonObject(fs13, file) {
@@ -17969,7 +18065,7 @@ function readJsonObject(fs13, file) {
17969
18065
  } catch {
17970
18066
  return void 0;
17971
18067
  }
17972
- return isRecord13(parsed) ? parsed : void 0;
18068
+ return isRecord14(parsed) ? parsed : void 0;
17973
18069
  }
17974
18070
  function readRcSelfHostRecord(fs13, frontdoorDir) {
17975
18071
  const parsed = readJsonObject(fs13, import_node_path33.default.join(frontdoorDir, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE));
@@ -17993,7 +18089,7 @@ function mintRcSelfHostCredential(deps) {
17993
18089
  const recordFile = import_node_path33.default.join(recordDir, RC_SELF_HOST_RECORD_FILE);
17994
18090
  const previousRecord = readRcSelfHostRecord(deps.fs, deps.frontdoorDir);
17995
18091
  const existingCredentials = readJsonObject(deps.fs, credentialsFile);
17996
- const existingOauth = isRecord13(existingCredentials?.claudeAiOauth) ? existingCredentials.claudeAiOauth : void 0;
18092
+ const existingOauth = isRecord14(existingCredentials?.claudeAiOauth) ? existingCredentials.claudeAiOauth : void 0;
17997
18093
  const existingToken = typeof existingOauth?.accessToken === "string" && existingOauth.accessToken !== "" ? existingOauth.accessToken : void 0;
17998
18094
  const existingIsOwn = existingToken !== void 0 && previousRecord?.accessToken === existingToken;
17999
18095
  if (existingToken !== void 0 && !existingIsOwn && !deps.force) {
@@ -18010,7 +18106,7 @@ function mintRcSelfHostCredential(deps) {
18010
18106
  deps.fs.writeFilePrivate(credentialsFile, `${JSON.stringify({ ...existingCredentials, claudeAiOauth: { accessToken, refreshToken, expiresAt: null, scopes: [...RC_SELF_HOST_SCOPE_LIST], subscriptionType: SELF_HOST_SUBSCRIPTION_TYPE, rateLimitTier: null } }, null, 2)}
18011
18107
  `);
18012
18108
  const claudeJson = readJsonObject(deps.fs, claudeJsonFile) ?? {};
18013
- const existingBlock = (value) => isRecord13(value) ? value : {};
18109
+ const existingBlock = (value) => isRecord14(value) ? value : {};
18014
18110
  deps.fs.writeFilePrivate(claudeJsonFile, `${JSON.stringify({
18015
18111
  ...claudeJson,
18016
18112
  oauthAccount: {