claude-use 11.18.0 → 11.19.1

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
@@ -583,25 +583,102 @@ var init_schema = __esm({
583
583
  }
584
584
  });
585
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
+
586
663
  // src/config/load.ts
587
664
  function createExplorer(moduleName = "agent-shim") {
588
665
  return (0, import_cosmiconfig.cosmiconfigSync)(moduleName, { searchPlaces: [] });
589
666
  }
590
- function isRecord(value) {
667
+ function isRecord2(value) {
591
668
  return typeof value === "object" && value !== null && !Array.isArray(value);
592
669
  }
593
670
  function captureEntryOrder(value) {
594
- if (!isRecord(value)) {
671
+ if (!isRecord2(value)) {
595
672
  return [];
596
673
  }
597
674
  const entries = value.entries;
598
- if (!isRecord(entries)) {
675
+ if (!isRecord2(entries)) {
599
676
  return [];
600
677
  }
601
678
  return Object.keys(entries);
602
679
  }
603
680
  function captureRuleEntryOrders(value) {
604
- if (!isRecord(value)) {
681
+ if (!isRecord2(value)) {
605
682
  return [];
606
683
  }
607
684
  const rules = value.rules;
@@ -616,7 +693,7 @@ function cosmiconfigReader(explorer = createExplorer()) {
616
693
  try {
617
694
  result = explorer.load(filepath);
618
695
  } catch (error) {
619
- const code = isRecord(error) ? error.code : void 0;
696
+ const code = isRecord2(error) ? error.code : void 0;
620
697
  if (code === "ENOENT") {
621
698
  return void 0;
622
699
  }
@@ -633,10 +710,11 @@ function loadConfigFile(filepath, schema, read = cosmiconfigReader()) {
633
710
  if (raw === void 0) {
634
711
  return void 0;
635
712
  }
636
- const parsed = schema.safeParse(raw);
713
+ const parsed = parseIgnoringUnrecognisedKeys(schema, raw);
637
714
  if (!parsed.success) {
638
- throw new ConfigValidationError(filepath, parsed.error.issues);
715
+ throw new ConfigValidationError(filepath, parsed.issues);
639
716
  }
717
+ noteIgnoredKeys(filepath, parsed.ignored);
640
718
  return {
641
719
  filepath,
642
720
  config: parsed.data,
@@ -650,6 +728,7 @@ var init_load = __esm({
650
728
  "use strict";
651
729
  import_cosmiconfig = require("cosmiconfig");
652
730
  init_cliError();
731
+ init_unrecognisedKeys();
653
732
  ConfigValidationError = class extends CliError {
654
733
  constructor(filepath, issues) {
655
734
  const detail = issues.map((issue) => ` ${issue.path.join(".") || "(root)"}: ${issue.message}`).join("\n");
@@ -675,10 +754,11 @@ function readJson(filePath, schema, storeFs = nodeStoreFs) {
675
754
  return void 0;
676
755
  }
677
756
  const parsed = JSON.parse(raw);
678
- const result = schema.safeParse(parsed);
757
+ const result = parseIgnoringUnrecognisedKeys(schema, parsed);
679
758
  if (!result.success) {
680
- throw new ConfigValidationError(filePath, result.error.issues);
759
+ throw new ConfigValidationError(filePath, result.issues);
681
760
  }
761
+ noteIgnoredKeys(filePath, result.ignored);
682
762
  return result.data;
683
763
  }
684
764
  function writeTextAtomic(filePath, contents, storeFs = nodeStoreFs) {
@@ -694,7 +774,7 @@ function writeTextAtomic(filePath, contents, storeFs = nodeStoreFs) {
694
774
  }
695
775
  }
696
776
  function writeJsonAtomic(filePath, data, storeFs = nodeStoreFs) {
697
- writeTextAtomic(filePath, `${JSON.stringify(data, null, 2)}
777
+ writeTextAtomic(filePath, `${JSON.stringify(restoreIgnoredKeys(filePath, data), null, 2)}
698
778
  `, storeFs);
699
779
  }
700
780
  function applyPatch(filePath, schema, patch, options = {}) {
@@ -720,6 +800,7 @@ var init_store = __esm({
720
800
  import_node_path3 = __toESM(require("node:path"), 1);
721
801
  import_node_crypto = require("node:crypto");
722
802
  init_load();
803
+ init_unrecognisedKeys();
723
804
  nodeStoreFs = {
724
805
  readFileUtf8(filePath) {
725
806
  try {
@@ -2839,7 +2920,7 @@ var init_package = __esm({
2839
2920
  "package.json"() {
2840
2921
  package_default = {
2841
2922
  name: "claude-use",
2842
- version: "11.18.0",
2923
+ version: "11.19.1",
2843
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.",
2844
2925
  license: "MIT",
2845
2926
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -6203,7 +6284,7 @@ function formatCredentialSummary(summary) {
6203
6284
  function describeCredential(credential) {
6204
6285
  return formatCredentialSummary(summariseCredential(credential));
6205
6286
  }
6206
- function isRecord5(value) {
6287
+ function isRecord6(value) {
6207
6288
  return typeof value === "object" && value !== null && !Array.isArray(value);
6208
6289
  }
6209
6290
  function unpackKeyringToken(raw) {
@@ -6215,7 +6296,7 @@ function unpackKeyringToken(raw) {
6215
6296
  const base64Str = trimmed.slice(GO_KEYRING_BASE64_PREFIX.length);
6216
6297
  const decoded = Buffer.from(base64Str, "base64").toString("utf8");
6217
6298
  const parsed = JSON.parse(decoded);
6218
- if (isRecord5(parsed) && isRecord5(parsed.token)) {
6299
+ if (isRecord6(parsed) && isRecord6(parsed.token)) {
6219
6300
  const accessToken = parsed.token.access_token;
6220
6301
  if (typeof accessToken === "string" && accessToken.trim() !== "") {
6221
6302
  return accessToken.trim();
@@ -6329,14 +6410,14 @@ function providerJsonPath(paths, name) {
6329
6410
  function providerExists(paths, name) {
6330
6411
  return import_node_fs6.default.existsSync(providerJsonPath(paths, name));
6331
6412
  }
6332
- function isRecord6(value) {
6413
+ function isRecord7(value) {
6333
6414
  return typeof value === "object" && value !== null && !Array.isArray(value);
6334
6415
  }
6335
6416
  function legacyProviderConversion(raw) {
6336
- if (!isRecord6(raw) || "credential" in raw) {
6417
+ if (!isRecord7(raw) || "credential" in raw) {
6337
6418
  return void 0;
6338
6419
  }
6339
- const env = isRecord6(raw.env) ? raw.env : void 0;
6420
+ const env = isRecord7(raw.env) ? raw.env : void 0;
6340
6421
  const legacyEnvKeys = env === void 0 ? [] : Object.keys(env).filter((key) => LEGACY_ENV_CREDENTIAL_KEYS.includes(key));
6341
6422
  const fields = [...LEGACY_PROVIDER_FIELDS.filter((field) => field in raw), ...legacyEnvKeys.map((key) => `env.${key}`)];
6342
6423
  if (fields.length === 0) {
@@ -6369,10 +6450,11 @@ function parseProviderFile(filePath, raw) {
6369
6450
  if (conversion !== void 0) {
6370
6451
  throw new LegacyProviderFileError(filePath, conversion);
6371
6452
  }
6372
- const parsed = ProviderSchema.safeParse(raw);
6453
+ const parsed = parseIgnoringUnrecognisedKeys(ProviderSchema, raw);
6373
6454
  if (!parsed.success) {
6374
- throw new ConfigValidationError(filePath, parsed.error.issues);
6455
+ throw new ConfigValidationError(filePath, parsed.issues);
6375
6456
  }
6457
+ noteIgnoredKeys(filePath, parsed.ignored);
6376
6458
  return parsed.data;
6377
6459
  }
6378
6460
  function readProvider(paths, name) {
@@ -6582,6 +6664,7 @@ var init_providersStore = __esm({
6582
6664
  import_node_path25 = __toESM(require("node:path"), 1);
6583
6665
  init_load();
6584
6666
  init_store();
6667
+ init_unrecognisedKeys();
6585
6668
  init_schema();
6586
6669
  init_cliError();
6587
6670
  init_credential();
@@ -7564,7 +7647,7 @@ function resolvePoolLaunch(params) {
7564
7647
  if (stickyRead.problem !== void 0) {
7565
7648
  log.warn(`agent-shim: ${stickyRead.problem}; ignoring the last-pick record`);
7566
7649
  }
7567
- const warned = /* @__PURE__ */ new Set();
7650
+ const warned2 = /* @__PURE__ */ new Set();
7568
7651
  for (; ; ) {
7569
7652
  const nowMs = params.now();
7570
7653
  let graph;
@@ -7588,8 +7671,8 @@ function resolvePoolLaunch(params) {
7588
7671
  }
7589
7672
  for (const gone of graph.missing) {
7590
7673
  const key = `${gone.pool}:${gone.identity}`;
7591
- if (!warned.has(key)) {
7592
- warned.add(key);
7674
+ if (!warned2.has(key)) {
7675
+ warned2.add(key);
7593
7676
  log.warn(`agent-shim: pool "${gone.pool}" names identity "${gone.identity}", which does not exist; skipping it`);
7594
7677
  }
7595
7678
  }
@@ -9081,6 +9164,7 @@ __export(index_exports, {
9081
9164
  buildRcSetPermissionModePayload: () => buildRcSetPermissionModePayload,
9082
9165
  buildRcUserMessagePayload: () => buildRcUserMessagePayload,
9083
9166
  carryOver: () => carryOver,
9167
+ changePool: () => changePool,
9084
9168
  checkReportHasWarnings: () => checkReportHasWarnings,
9085
9169
  checkReportToJson: () => checkReportToJson,
9086
9170
  collectCheckReport: () => collectCheckReport,
@@ -9238,7 +9322,6 @@ __export(index_exports, {
9238
9322
  setDefaultConfigProfile: () => setDefaultConfigProfile,
9239
9323
  setGlobalDefaultProfile: () => setGlobalDefaultProfile,
9240
9324
  setIdentityCredential: () => setIdentityCredential,
9241
- setPool: () => setPool,
9242
9325
  setProfileCategories: () => setProfileCategories,
9243
9326
  setProfileEntries: () => setProfileEntries,
9244
9327
  setProfileLaunchFlags: () => setProfileLaunchFlags,
@@ -10304,7 +10387,7 @@ var LiveTaskSchema = import_zod5.z.strictObject({
10304
10387
  observedAt: import_zod5.z.number()
10305
10388
  });
10306
10389
  var SYSTEM_SUBTYPES = ["task_started", "task_progress", "task_updated", "task_notification", "background_tasks_changed"];
10307
- function isRecord2(value) {
10390
+ function isRecord3(value) {
10308
10391
  return typeof value === "object" && value !== null && !Array.isArray(value);
10309
10392
  }
10310
10393
  function stringField(record, field) {
@@ -10321,7 +10404,7 @@ function booleanField(record, field) {
10321
10404
  }
10322
10405
  function usageOf(record) {
10323
10406
  const raw = record.usage;
10324
- if (!isRecord2(raw)) {
10407
+ if (!isRecord3(raw)) {
10325
10408
  return void 0;
10326
10409
  }
10327
10410
  const totalTokens = numberField(raw, "total_tokens");
@@ -10353,7 +10436,7 @@ function bounded(book) {
10353
10436
  return book;
10354
10437
  }
10355
10438
  function applyAgentTaskEvent(book, sessionId, payload, observedAt2) {
10356
- if (!isRecord2(payload) || payload.type !== "system") {
10439
+ if (!isRecord3(payload) || payload.type !== "system") {
10357
10440
  return book;
10358
10441
  }
10359
10442
  const subtype = payload.subtype;
@@ -10369,8 +10452,8 @@ function applyAgentTaskEvent(book, sessionId, payload, observedAt2) {
10369
10452
  if (subtype === "background_tasks_changed") {
10370
10453
  const tasks = Array.isArray(payload.tasks) ? payload.tasks : [];
10371
10454
  for (const raw of tasks) {
10372
- const taskId2 = isRecord2(raw) ? stringField(raw, "task_id") : void 0;
10373
- if (isRecord2(raw) && taskId2 !== void 0) {
10455
+ const taskId2 = isRecord3(raw) ? stringField(raw, "task_id") : void 0;
10456
+ if (isRecord3(raw) && taskId2 !== void 0) {
10374
10457
  upsert(taskId2, { runId: stringField(raw, "run_id"), taskType: stringField(raw, "task_type"), description: stringField(raw, "description") });
10375
10458
  }
10376
10459
  }
@@ -10393,7 +10476,7 @@ function applyAgentTaskEvent(book, sessionId, payload, observedAt2) {
10393
10476
  } else if (subtype === "task_progress") {
10394
10477
  upsert(taskId, { ...common, subagentType: stringField(payload, "subagent_type"), lastToolName: stringField(payload, "last_tool_name"), usage: usageOf(payload) });
10395
10478
  } else if (subtype === "task_updated") {
10396
- const patch = isRecord2(payload.patch) ? payload.patch : {};
10479
+ const patch = isRecord3(payload.patch) ? payload.patch : {};
10397
10480
  upsert(taskId, { runId: stringField(payload, "run_id"), status: stringField(patch, "status") });
10398
10481
  } else {
10399
10482
  upsert(taskId, { ...common, status: stringField(payload, "status"), outputFile: stringField(payload, "output_file"), summary: stringField(payload, "summary"), usage: usageOf(payload) });
@@ -10475,7 +10558,7 @@ function sessionCreateId(body) {
10475
10558
  const id = session.id;
10476
10559
  return typeof id === "string" && id.startsWith(RC_SESSION_ID_PREFIX) ? id : void 0;
10477
10560
  }
10478
- function isRecord3(value) {
10561
+ function isRecord4(value) {
10479
10562
  return typeof value === "object" && value !== null && !Array.isArray(value);
10480
10563
  }
10481
10564
  function parseJsonObject(body) {
@@ -10485,7 +10568,7 @@ function parseJsonObject(body) {
10485
10568
  } catch {
10486
10569
  return void 0;
10487
10570
  }
10488
- return isRecord3(parsed) ? parsed : void 0;
10571
+ return isRecord4(parsed) ? parsed : void 0;
10489
10572
  }
10490
10573
  function nonEmptyString(record, field) {
10491
10574
  const value = record === void 0 ? void 0 : record[field];
@@ -10506,11 +10589,11 @@ function payloadEventsOf(body) {
10506
10589
  }
10507
10590
  const payloads = [];
10508
10591
  for (const event of events) {
10509
- if (!isRecord3(event)) {
10592
+ if (!isRecord4(event)) {
10510
10593
  continue;
10511
10594
  }
10512
10595
  const payload = event.payload;
10513
- if (!isRecord3(payload)) {
10596
+ if (!isRecord4(payload)) {
10514
10597
  continue;
10515
10598
  }
10516
10599
  payloads.push(payload);
@@ -10525,7 +10608,7 @@ function pendingOfControlRequestPayload(payload) {
10525
10608
  if (requestId === void 0) {
10526
10609
  return void 0;
10527
10610
  }
10528
- const request4 = isRecord3(payload.request) ? payload.request : void 0;
10611
+ const request4 = isRecord4(payload.request) ? payload.request : void 0;
10529
10612
  const subtype = nonEmptyString(request4, "subtype");
10530
10613
  const type = subtype ?? "control_request";
10531
10614
  let summary = "";
@@ -10542,7 +10625,7 @@ function answeredRequestIdsOfControlResponsePayload(payload) {
10542
10625
  if (payload.type !== "control_response") {
10543
10626
  return [];
10544
10627
  }
10545
- const response = isRecord3(payload.response) ? payload.response : void 0;
10628
+ const response = isRecord4(payload.response) ? payload.response : void 0;
10546
10629
  const id = nonEmptyString(response, "request_id") ?? nonEmptyString(payload, "request_id") ?? nonEmptyString(payload, "uuid");
10547
10630
  return id === void 0 ? [] : [id];
10548
10631
  }
@@ -10771,7 +10854,7 @@ function createRcSessionTracker(deps) {
10771
10854
  return;
10772
10855
  }
10773
10856
  entry.sequenceNum = entry.sequenceNum === void 0 || event.sequence_num > entry.sequenceNum ? event.sequence_num : entry.sequenceNum;
10774
- if (!isRecord3(event.payload)) {
10857
+ if (!isRecord4(event.payload)) {
10775
10858
  return;
10776
10859
  }
10777
10860
  entry.liveTasks = applyAgentTaskEvent(entry.liveTasks, sessionId, event.payload, deps.now());
@@ -12194,11 +12277,11 @@ var import_node_path10 = __toESM(require("node:path"), 1);
12194
12277
  function isSafeSessionId(sessionId) {
12195
12278
  return /^[A-Za-z0-9_-]+$/.test(sessionId);
12196
12279
  }
12197
- function isRecord4(value) {
12280
+ function isRecord5(value) {
12198
12281
  return typeof value === "object" && value !== null && !Array.isArray(value);
12199
12282
  }
12200
12283
  function credentialOfJson(parsed) {
12201
- if (!isRecord4(parsed)) {
12284
+ if (!isRecord5(parsed)) {
12202
12285
  return void 0;
12203
12286
  }
12204
12287
  const { authorization, anthropicVersion, anthropicClientPlatform } = parsed;
@@ -12228,7 +12311,7 @@ function createRcCredentialStore(fs13, dir) {
12228
12311
  } catch {
12229
12312
  return void 0;
12230
12313
  }
12231
- return isRecord4(parsed) ? parsed : void 0;
12314
+ return isRecord5(parsed) ? parsed : void 0;
12232
12315
  };
12233
12316
  return {
12234
12317
  read: (sessionId) => {
@@ -13164,7 +13247,13 @@ function validateMembers(pools, name, members) {
13164
13247
  throw new UsageError(`Member "pool:${cycle[1] ?? name}" would make pool "${name}" reach itself: ${cycle.join(" -> ")}. A pool cannot nest itself, directly or through another pool.`);
13165
13248
  }
13166
13249
  }
13167
- function addPool(paths, name, identities, preference) {
13250
+ function poolPolicyOf(policy) {
13251
+ return { ...policy.preference === void 0 ? {} : { preference: policy.preference } };
13252
+ }
13253
+ function isPoolChange(change) {
13254
+ return change.identities !== void 0 || change.preference !== void 0;
13255
+ }
13256
+ function addPool(paths, name, identities, policy = {}) {
13168
13257
  if (!PoolNameSchema.safeParse(name).success) {
13169
13258
  throw new InvalidPoolNameError(name);
13170
13259
  }
@@ -13173,14 +13262,16 @@ function addPool(paths, name, identities, preference) {
13173
13262
  throw new PoolAlreadyExistsError(name);
13174
13263
  }
13175
13264
  validateMembers(pools, name, identities);
13176
- const pool = { identities: [...identities], ...preference === void 0 ? {} : { preference } };
13265
+ const pool = { identities: [...identities], ...poolPolicyOf(policy) };
13177
13266
  writePools(paths, { ...pools, [name]: pool });
13178
13267
  return pool;
13179
13268
  }
13180
- function setPool(paths, name, identities, preference) {
13181
- requirePool(paths, name);
13269
+ function changePool(paths, name, change) {
13270
+ const existing = requirePool(paths, name);
13271
+ const identities = change.identities ?? existing.identities;
13182
13272
  validateMembers(readPools(paths), name, identities);
13183
- const pool = { identities: [...identities], ...preference === void 0 ? {} : { preference } };
13273
+ const preference = change.preference === void 0 ? existing.preference : change.preference === false ? void 0 : change.preference;
13274
+ const pool = { identities: [...identities], ...poolPolicyOf({ preference }) };
13184
13275
  writePools(paths, { ...readPools(paths), [name]: pool });
13185
13276
  return pool;
13186
13277
  }
@@ -14165,6 +14256,7 @@ function parseSiwcFile(raw, filePath) {
14165
14256
 
14166
14257
  // src/doctorReport.ts
14167
14258
  init_load();
14259
+ init_unrecognisedKeys();
14168
14260
  init_schema();
14169
14261
  init_credential();
14170
14262
  init_credentialCache();
@@ -14375,11 +14467,11 @@ function validateJson(schema, input) {
14375
14467
  } catch (error) {
14376
14468
  return { ok: false, message: `${input.path} is not valid JSON: ${error instanceof Error ? error.message : String(error)}` };
14377
14469
  }
14378
- const result = schema.safeParse(parsed);
14470
+ const result = parseIgnoringUnrecognisedKeys(schema, parsed);
14379
14471
  if (!result.success) {
14380
- return { ok: false, message: new ConfigValidationError(input.path, result.error.issues).message };
14472
+ return { ok: false, message: new ConfigValidationError(input.path, result.issues).message };
14381
14473
  }
14382
- return { ok: true, data: result.data };
14474
+ return { ok: true, data: result.data, ...result.ignored.length === 0 ? {} : { warning: describeIgnoredKeys(input.path, result.ignored) } };
14383
14475
  }
14384
14476
  function tcpPortEraRecord(raw) {
14385
14477
  let parsed;
@@ -14472,11 +14564,14 @@ function pushProvider(push, entry, cacheEnv, signIn) {
14472
14564
  push("provider", "fail", new LegacyProviderFileError(entry.path, conversion).message, entry.name);
14473
14565
  return;
14474
14566
  }
14475
- const validated3 = ProviderSchema.safeParse(parsed);
14567
+ const validated3 = parseIgnoringUnrecognisedKeys(ProviderSchema, parsed);
14476
14568
  if (!validated3.success) {
14477
- push("provider", "fail", new ConfigValidationError(entry.path, validated3.error.issues).message, entry.name);
14569
+ push("provider", "fail", new ConfigValidationError(entry.path, validated3.issues).message, entry.name);
14478
14570
  return;
14479
14571
  }
14572
+ if (validated3.ignored.length > 0) {
14573
+ push("provider", "warn", describeIgnoredKeys(entry.path, validated3.ignored), entry.name);
14574
+ }
14480
14575
  const cache = cacheClause(cacheEnv, `provider ${entry.name}`, validated3.data.credential);
14481
14576
  push("provider", cache.unreadable ? "fail" : "pass", `${entry.name} is valid (${describeProviderEndpoint(validated3.data)}, credential ${describeCredential(validated3.data.credential)})${cache.text}.`, entry.name);
14482
14577
  if (validated3.data.env?.ENABLE_TOOL_SEARCH === void 0) {
@@ -14511,6 +14606,13 @@ function runDoctor(params) {
14511
14606
  const push = (section, severity, message, subject) => {
14512
14607
  findings.push({ section, severity, message, ...subject === void 0 ? {} : { subject } });
14513
14608
  };
14609
+ const validate = (schema, input, section, subject) => {
14610
+ const validated3 = validateJson(schema, input);
14611
+ if (validated3.ok && validated3.warning !== void 0) {
14612
+ push(section, "warn", validated3.warning, subject);
14613
+ }
14614
+ return validated3;
14615
+ };
14514
14616
  const checkPin = (section, subject, where, version) => {
14515
14617
  const installed = params.installedClaudeVersions;
14516
14618
  if (version === void 0 || installed === void 0 || installed.includes(version)) {
@@ -14550,7 +14652,7 @@ function runDoctor(params) {
14550
14652
  pushLegacyName(push, params);
14551
14653
  const profileSources = /* @__PURE__ */ new Map();
14552
14654
  for (const entry of params.configProfiles) {
14553
- const validated3 = validateJson(ConfigProfileSchema, entry);
14655
+ const validated3 = validate(ConfigProfileSchema, entry, "config-profile", entry.name);
14554
14656
  if (!validated3.ok) {
14555
14657
  push("config-profile", "fail", validated3.message, entry.name);
14556
14658
  continue;
@@ -14572,7 +14674,7 @@ function runDoctor(params) {
14572
14674
  const validProfileNames = new Set(profileSources.keys());
14573
14675
  const validIdentityNames = /* @__PURE__ */ new Set();
14574
14676
  for (const entry of params.identities) {
14575
- const validated3 = validateJson(IdentitySchema, entry);
14677
+ const validated3 = validate(IdentitySchema, entry, "identity", entry.name);
14576
14678
  if (!validated3.ok) {
14577
14679
  push("identity", "fail", validated3.message, entry.name);
14578
14680
  continue;
@@ -14658,7 +14760,7 @@ function runDoctor(params) {
14658
14760
  if (params.directoryRules.raw === void 0) {
14659
14761
  push("directory-rules", "pass", "No directory-rules.json configured.");
14660
14762
  } else {
14661
- const validated3 = validateJson(DirectoryRulesSchema, params.directoryRules);
14763
+ const validated3 = validate(DirectoryRulesSchema, params.directoryRules, "directory-rules");
14662
14764
  if (!validated3.ok) {
14663
14765
  push("directory-rules", "fail", validated3.message);
14664
14766
  } else {
@@ -14683,7 +14785,7 @@ function runDoctor(params) {
14683
14785
  if (params.globalConfig.raw === void 0) {
14684
14786
  push("global-config", "pass", "No config.json configured.");
14685
14787
  } else {
14686
- const validated3 = validateJson(GlobalConfigSchema, params.globalConfig);
14788
+ const validated3 = validate(GlobalConfigSchema, params.globalConfig, "global-config");
14687
14789
  if (!validated3.ok) {
14688
14790
  push("global-config", "fail", validated3.message);
14689
14791
  } else {
@@ -14703,7 +14805,7 @@ function runDoctor(params) {
14703
14805
  if (params.categoriesLocal.raw === void 0) {
14704
14806
  push("categories-local", "pass", "No categories.local.json configured.");
14705
14807
  } else {
14706
- const validated3 = validateJson(CategoryClassificationOverlaySchema, params.categoriesLocal);
14808
+ const validated3 = validate(CategoryClassificationOverlaySchema, params.categoriesLocal, "categories-local");
14707
14809
  push(
14708
14810
  "categories-local",
14709
14811
  validated3.ok ? "pass" : "fail",
@@ -15517,20 +15619,19 @@ function createConfigApiRouter(deps) {
15517
15619
  add: route("/rest/config/pool/add", "Define a pool").input(ConfigPoolAddInputSchema).output(ConfigPoolAddOutputSchema).handler(
15518
15620
  ({ input }) => guarded(() => {
15519
15621
  requireIdentityNames(paths, input.identities);
15520
- const created = addPool(paths, input.name, input.identities, input.preference);
15622
+ const created = addPool(paths, input.name, input.identities, { preference: input.preference });
15521
15623
  return { action: "created", kind: "pool", name: input.name, value: created };
15522
15624
  })
15523
15625
  ),
15524
15626
  set: route("/rest/config/pool/set", "Replace a pool's members, its preference or both").input(ConfigPoolSetInputSchema).output(ConfigPoolSetOutputSchema).handler(
15525
15627
  ({ input }) => guarded(() => {
15526
- requireChange(input.identities !== void 0 || input.preference !== void 0, "identities or preference");
15527
- const existing = requirePool(paths, input.name);
15628
+ const change = { identities: input.identities, preference: input.preference };
15629
+ requireChange(isPoolChange(change), "identities or preference");
15630
+ requirePool(paths, input.name);
15528
15631
  if (input.identities !== void 0) {
15529
15632
  requireIdentityNames(paths, input.identities);
15530
15633
  }
15531
- const members = input.identities ?? existing.identities;
15532
- const preference = input.preference === void 0 ? existing.preference : input.preference === false ? void 0 : input.preference;
15533
- return { action: "updated", kind: "pool", name: input.name, value: setPool(paths, input.name, members, preference) };
15634
+ return { action: "updated", kind: "pool", name: input.name, value: changePool(paths, input.name, change) };
15534
15635
  })
15535
15636
  ),
15536
15637
  remove: route("/rest/config/pool/remove", "Delete a pool").input(ConfigPoolRemoveInputSchema).output(ConfigPoolRemoveOutputSchema).handler(({ input }) => {
@@ -16314,15 +16415,15 @@ function createQuotaExpiringPublisher(hub, deps) {
16314
16415
 
16315
16416
  // src/frontdoor/rcLiveUsage.ts
16316
16417
  var RC_RATE_LIMIT_EVENT_TYPE = "rate_limit_event";
16317
- function isRecord7(value) {
16418
+ function isRecord8(value) {
16318
16419
  return typeof value === "object" && value !== null && !Array.isArray(value);
16319
16420
  }
16320
16421
  function rcRateLimitInfoOf(event) {
16321
16422
  const payload = event.envelope.payload;
16322
- if (!isRecord7(payload) || payload.type !== RC_RATE_LIMIT_EVENT_TYPE) {
16423
+ if (!isRecord8(payload) || payload.type !== RC_RATE_LIMIT_EVENT_TYPE) {
16323
16424
  return void 0;
16324
16425
  }
16325
- if (!isRecord7(payload.rate_limit_info)) {
16426
+ if (!isRecord8(payload.rate_limit_info)) {
16326
16427
  return void 0;
16327
16428
  }
16328
16429
  const parsed = RcRateLimitInfoSchema.safeParse(payload.rate_limit_info);
@@ -16410,7 +16511,7 @@ function createSseParser() {
16410
16511
  }
16411
16512
  };
16412
16513
  }
16413
- function isRecord8(value) {
16514
+ function isRecord9(value) {
16414
16515
  return typeof value === "object" && value !== null && !Array.isArray(value);
16415
16516
  }
16416
16517
  function sequenceNumOf(value) {
@@ -16432,7 +16533,7 @@ function parseRcStreamEnvelope(parsed) {
16432
16533
  } catch {
16433
16534
  return void 0;
16434
16535
  }
16435
- if (!isRecord8(data)) {
16536
+ if (!isRecord9(data)) {
16436
16537
  return void 0;
16437
16538
  }
16438
16539
  const eventType = data.event_type;
@@ -16673,7 +16774,7 @@ init_capability();
16673
16774
  // src/frontdoor/rcSelfHostEndpoints.ts
16674
16775
  var RC_SOURCE_WORKER = "worker";
16675
16776
  var RC_SOURCE_CLIENT = "client";
16676
- function isRecord9(value) {
16777
+ function isRecord10(value) {
16677
16778
  return typeof value === "object" && value !== null && !Array.isArray(value);
16678
16779
  }
16679
16780
  function parseJsonObject2(body) {
@@ -16683,7 +16784,7 @@ function parseJsonObject2(body) {
16683
16784
  } catch {
16684
16785
  return void 0;
16685
16786
  }
16686
- return isRecord9(parsed) ? parsed : void 0;
16787
+ return isRecord10(parsed) ? parsed : void 0;
16687
16788
  }
16688
16789
  function nonEmptyString2(record, field) {
16689
16790
  const value = record === void 0 ? void 0 : record[field];
@@ -16757,7 +16858,7 @@ async function serveRcClientChannels(ctx, tail, method, maxBatchEvents) {
16757
16858
  }
16758
16859
  const results = [];
16759
16860
  for (const event of events) {
16760
- if (!isRecord9(event) || !isRecord9(event.payload)) {
16861
+ if (!isRecord10(event) || !isRecord10(event.payload)) {
16761
16862
  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" } });
16762
16863
  return true;
16763
16864
  }
@@ -16857,7 +16958,7 @@ async function serveRcCompatSessions(ctx, pathname, compatPath) {
16857
16958
  // src/frontdoor/rcSelfHostConversations.ts
16858
16959
  var RC_CONVERSATIONS_PATH_PREFIX = "/v1/code/conversations";
16859
16960
  var RC_CONVERSATION_ID_PREFIX = "conv_";
16860
- function isRecord10(value) {
16961
+ function isRecord11(value) {
16861
16962
  return typeof value === "object" && value !== null && !Array.isArray(value);
16862
16963
  }
16863
16964
  function parseJsonObject3(body) {
@@ -16867,7 +16968,7 @@ function parseJsonObject3(body) {
16867
16968
  } catch {
16868
16969
  return void 0;
16869
16970
  }
16870
- return isRecord10(parsed) ? parsed : void 0;
16971
+ return isRecord11(parsed) ? parsed : void 0;
16871
16972
  }
16872
16973
  function nonEmptyString3(record, field) {
16873
16974
  const value = record === void 0 ? void 0 : record[field];
@@ -16921,7 +17022,7 @@ async function serveRcConversations(ctx, pathname, method) {
16921
17022
  }
16922
17023
  const results = [];
16923
17024
  for (const event of events) {
16924
- if (!isRecord10(event) || !isRecord10(event.payload)) {
17025
+ if (!isRecord11(event) || !isRecord11(event.payload)) {
16925
17026
  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" } });
16926
17027
  return;
16927
17028
  }
@@ -16953,7 +17054,7 @@ var RC_SELF_HOST_SCOPE_LIST = ["user:profile", "user:inference", "user:sessions:
16953
17054
  var RC_SELF_HOST_OAUTH_TOKEN_TTL_SECONDS = 3600;
16954
17055
  var MS_PER_SECOND5 = 1e3;
16955
17056
  var HTTP_SERVICE_UNAVAILABLE = 503;
16956
- function isRecord11(value) {
17057
+ function isRecord12(value) {
16957
17058
  return typeof value === "object" && value !== null && !Array.isArray(value);
16958
17059
  }
16959
17060
  function parseJsonObject4(body) {
@@ -16963,7 +17064,7 @@ function parseJsonObject4(body) {
16963
17064
  } catch {
16964
17065
  return void 0;
16965
17066
  }
16966
- return isRecord11(parsed) ? parsed : void 0;
17067
+ return isRecord12(parsed) ? parsed : void 0;
16967
17068
  }
16968
17069
  function growthBookFeatures() {
16969
17070
  return {
@@ -17317,7 +17418,7 @@ var RC_SELF_HOST_WORKER_EPOCH = 1;
17317
17418
  var RC_STREAM_EVENT_NAME2 = "client_event";
17318
17419
  var CONFLICT_REASON_HEADER2 = "x-ccr-conflict-reason";
17319
17420
  var CONFLICT_REASON_EPOCH_STALE = "epoch_stale";
17320
- function isRecord12(value) {
17421
+ function isRecord13(value) {
17321
17422
  return typeof value === "object" && value !== null && !Array.isArray(value);
17322
17423
  }
17323
17424
  function isWebSearchRefusal(value) {
@@ -17401,7 +17502,7 @@ function parseJsonObject5(body) {
17401
17502
  } catch {
17402
17503
  return void 0;
17403
17504
  }
17404
- return isRecord12(parsed) ? parsed : void 0;
17505
+ return isRecord13(parsed) ? parsed : void 0;
17405
17506
  }
17406
17507
  function mintWorkerJwt(randomToken, issuedAt) {
17407
17508
  const encode = (value) => Buffer.from(JSON.stringify(value), "utf8").toString("base64url");
@@ -17661,7 +17762,7 @@ data: ${JSON.stringify(envelope)}
17661
17762
  if (status !== void 0) {
17662
17763
  session.workerStatus = status;
17663
17764
  }
17664
- if (isRecord12(body?.external_metadata)) {
17765
+ if (isRecord13(body?.external_metadata)) {
17665
17766
  session.externalMetadata = body.external_metadata;
17666
17767
  }
17667
17768
  await answerJson2(response, HTTP_STATUS.ok, {});
@@ -17691,7 +17792,7 @@ data: ${JSON.stringify(envelope)}
17691
17792
  }
17692
17793
  const results = [];
17693
17794
  for (const event of events) {
17694
- if (!isRecord12(event) || !isRecord12(event.payload)) {
17795
+ if (!isRecord13(event) || !isRecord13(event.payload)) {
17695
17796
  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" } });
17696
17797
  return;
17697
17798
  }
@@ -17724,7 +17825,7 @@ data: ${JSON.stringify(envelope)}
17724
17825
  return;
17725
17826
  }
17726
17827
  for (const event of events) {
17727
- if (isRecord12(event)) {
17828
+ if (isRecord13(event)) {
17728
17829
  session.internalEvents.push({ eventId: deps.newUuid(), body: event });
17729
17830
  }
17730
17831
  }
@@ -17820,7 +17921,7 @@ data: ${JSON.stringify(envelope)}
17820
17921
  }
17821
17922
  const results = [];
17822
17923
  for (const event of events) {
17823
- if (!isRecord12(event) || !isRecord12(event.payload)) {
17924
+ if (!isRecord13(event) || !isRecord13(event.payload)) {
17824
17925
  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" } });
17825
17926
  return;
17826
17927
  }
@@ -17957,7 +18058,7 @@ var RC_SELF_HOST_RECORD_DIR = "rc-selfhost";
17957
18058
  var RC_SELF_HOST_RECORD_FILE = "credential.json";
17958
18059
  var SELF_HOST_EMAIL = "selfhost@agent-shim.invalid";
17959
18060
  var SELF_HOST_SUBSCRIPTION_TYPE = "max";
17960
- function isRecord13(value) {
18061
+ function isRecord14(value) {
17961
18062
  return typeof value === "object" && value !== null && !Array.isArray(value);
17962
18063
  }
17963
18064
  function readJsonObject(fs13, file) {
@@ -17971,7 +18072,7 @@ function readJsonObject(fs13, file) {
17971
18072
  } catch {
17972
18073
  return void 0;
17973
18074
  }
17974
- return isRecord13(parsed) ? parsed : void 0;
18075
+ return isRecord14(parsed) ? parsed : void 0;
17975
18076
  }
17976
18077
  function readRcSelfHostRecord(fs13, frontdoorDir) {
17977
18078
  const parsed = readJsonObject(fs13, import_node_path33.default.join(frontdoorDir, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE));
@@ -17995,7 +18096,7 @@ function mintRcSelfHostCredential(deps) {
17995
18096
  const recordFile = import_node_path33.default.join(recordDir, RC_SELF_HOST_RECORD_FILE);
17996
18097
  const previousRecord = readRcSelfHostRecord(deps.fs, deps.frontdoorDir);
17997
18098
  const existingCredentials = readJsonObject(deps.fs, credentialsFile);
17998
- const existingOauth = isRecord13(existingCredentials?.claudeAiOauth) ? existingCredentials.claudeAiOauth : void 0;
18099
+ const existingOauth = isRecord14(existingCredentials?.claudeAiOauth) ? existingCredentials.claudeAiOauth : void 0;
17999
18100
  const existingToken = typeof existingOauth?.accessToken === "string" && existingOauth.accessToken !== "" ? existingOauth.accessToken : void 0;
18000
18101
  const existingIsOwn = existingToken !== void 0 && previousRecord?.accessToken === existingToken;
18001
18102
  if (existingToken !== void 0 && !existingIsOwn && !deps.force) {
@@ -18012,7 +18113,7 @@ function mintRcSelfHostCredential(deps) {
18012
18113
  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)}
18013
18114
  `);
18014
18115
  const claudeJson = readJsonObject(deps.fs, claudeJsonFile) ?? {};
18015
- const existingBlock = (value) => isRecord13(value) ? value : {};
18116
+ const existingBlock = (value) => isRecord14(value) ? value : {};
18016
18117
  deps.fs.writeFilePrivate(claudeJsonFile, `${JSON.stringify({
18017
18118
  ...claudeJson,
18018
18119
  oauthAccount: {
@@ -18747,6 +18848,7 @@ init_ownCli();
18747
18848
  buildRcSetPermissionModePayload,
18748
18849
  buildRcUserMessagePayload,
18749
18850
  carryOver,
18851
+ changePool,
18750
18852
  checkReportHasWarnings,
18751
18853
  checkReportToJson,
18752
18854
  collectCheckReport,
@@ -18904,7 +19006,6 @@ init_ownCli();
18904
19006
  setDefaultConfigProfile,
18905
19007
  setGlobalDefaultProfile,
18906
19008
  setIdentityCredential,
18907
- setPool,
18908
19009
  setProfileCategories,
18909
19010
  setProfileEntries,
18910
19011
  setProfileLaunchFlags,