claude-use 9.5.1 → 9.6.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.mjs CHANGED
@@ -2625,7 +2625,7 @@ var init_package = __esm({
2625
2625
  "package.json"() {
2626
2626
  package_default = {
2627
2627
  name: "claude-use",
2628
- version: "9.5.1",
2628
+ version: "9.6.0",
2629
2629
  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.",
2630
2630
  license: "MIT",
2631
2631
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -2676,6 +2676,7 @@ var init_package = __esm({
2676
2676
  dependencies: {
2677
2677
  "@anthropic-ai/claude-agent-sdk": "0.3.292",
2678
2678
  "@clack/prompts": "^1.8.0",
2679
+ "@modelcontextprotocol/sdk": "1.32.0",
2679
2680
  "@orpc/client": "2.0.0-beta.41",
2680
2681
  "@orpc/openapi": "2.0.0-beta.41",
2681
2682
  "@orpc/server": "2.0.0-beta.41",
@@ -5742,7 +5743,7 @@ function cascadeProviderName(cascade) {
5742
5743
  }
5743
5744
  return name;
5744
5745
  }
5745
- function resolveProvider(params) {
5746
+ function selectProvider(params) {
5746
5747
  const cliName = params.cliProvider !== void 0 && params.cliProvider !== "" ? params.cliProvider : void 0;
5747
5748
  const name = cliName ?? (params.cascade === void 0 ? void 0 : cascadeProviderName(params.cascade));
5748
5749
  if (name === void 0) {
@@ -5757,6 +5758,14 @@ function resolveProvider(params) {
5757
5758
  message: `agent-shim: no provider named "${name}". ` + (known.length > 0 ? `Known providers: ${known.join(", ")}.` : "No providers are defined yet; run `agent-shim provider add`.")
5758
5759
  };
5759
5760
  }
5761
+ return { ok: true, provider: { name, definition } };
5762
+ }
5763
+ function resolveProvider(params) {
5764
+ const selection = selectProvider(params);
5765
+ if (selection?.ok !== true) {
5766
+ return selection;
5767
+ }
5768
+ const { name, definition } = selection.provider;
5760
5769
  if (params.credentials === void 0) {
5761
5770
  return { ok: false, status: 1, message: `agent-shim: provider ${name} needs its credential resolved, but this launcher has no credential port wired` };
5762
5771
  }
@@ -6037,6 +6046,51 @@ var init_claudeShim = __esm({
6037
6046
  }
6038
6047
  });
6039
6048
 
6049
+ // src/update/update.ts
6050
+ function compareVersions3(left, right) {
6051
+ const parse = (version) => {
6052
+ const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(version);
6053
+ if (match === null) {
6054
+ throw new Error(`not a plain release version: ${version}`);
6055
+ }
6056
+ return [Number(match[1]), Number(match[2]), Number(match[3])];
6057
+ };
6058
+ const leftParts = parse(left);
6059
+ const rightParts = parse(right);
6060
+ return leftParts.map((part, index) => part - (rightParts[index] ?? 0)).find((difference) => difference !== 0) ?? 0;
6061
+ }
6062
+ function releaseTagFromUrl(url) {
6063
+ const segment = url.split("?")[0]?.split("/").at(-1);
6064
+ const candidate = segment?.startsWith("v") === true ? segment.slice(1) : void 0;
6065
+ return candidate !== void 0 && /^\d+\.\d+\.\d+$/.test(candidate) ? candidate : void 0;
6066
+ }
6067
+ var LATEST_RELEASE_URL, UpdateChannelError, UpdateConflictError, UpdateDownloadError;
6068
+ var init_update = __esm({
6069
+ "src/update/update.ts"() {
6070
+ "use strict";
6071
+ init_cliError();
6072
+ LATEST_RELEASE_URL = "https://github.com/ExaDev/agent-shim/releases/latest";
6073
+ UpdateChannelError = class extends CliError {
6074
+ constructor(message) {
6075
+ super(message);
6076
+ this.name = "UpdateChannelError";
6077
+ }
6078
+ };
6079
+ UpdateConflictError = class extends CliError {
6080
+ constructor(message) {
6081
+ super(message);
6082
+ this.name = "UpdateConflictError";
6083
+ }
6084
+ };
6085
+ UpdateDownloadError = class extends CliError {
6086
+ constructor(message) {
6087
+ super(message);
6088
+ this.name = "UpdateDownloadError";
6089
+ }
6090
+ };
6091
+ }
6092
+ });
6093
+
6040
6094
  // src/frontdoor/ensure.ts
6041
6095
  import { randomUUID as randomUUID3 } from "node:crypto";
6042
6096
  function ensureFrontDoor(params) {
@@ -6442,7 +6496,7 @@ var init_headers = __esm({
6442
6496
  });
6443
6497
 
6444
6498
  // src/launcher/flags.ts
6445
- import path31 from "node:path";
6499
+ import path32 from "node:path";
6446
6500
  function resolveLaunchFlags(params) {
6447
6501
  return {
6448
6502
  skipPermissions: params.flags?.skipPermissions ?? parseEnvBool("AGENT_SHIM_SKIP_PERMISSIONS", params.env.AGENT_SHIM_SKIP_PERMISSIONS) ?? params.cascade?.skipPermissions ?? false,
@@ -6473,7 +6527,7 @@ function buildEnv(params) {
6473
6527
  const parentCustomHeaders = params.baseEnv.ANTHROPIC_CUSTOM_HEADERS;
6474
6528
  let providerCustomHeaders;
6475
6529
  if (!params.configDirEscapeHatch && params.resolvedIdentityName !== void 0) {
6476
- env.CLAUDE_CONFIG_DIR = path31.join(params.identitiesDir, params.resolvedIdentityName);
6530
+ env.CLAUDE_CONFIG_DIR = path32.join(params.identitiesDir, params.resolvedIdentityName);
6477
6531
  }
6478
6532
  if (params.provider !== void 0) {
6479
6533
  const providerEnv = params.provider.definition.env ?? {};
@@ -6596,7 +6650,9 @@ function resolvePoolLaunch(params) {
6596
6650
  }
6597
6651
  const { pick, earliestReturn, movedOff } = graph.ranking;
6598
6652
  if (pick !== void 0) {
6599
- recordStickyPick(params.usageFs, params.paths.usagePicksFile, params.cwd, pick.identity, nowMs);
6653
+ if (params.recordPick) {
6654
+ recordStickyPick(params.usageFs, params.paths.usagePicksFile, params.cwd, pick.identity, nowMs);
6655
+ }
6600
6656
  const move = movedOff === void 0 ? "" : `moved off ${movedOff.identity} (${movedOff.reason}); `;
6601
6657
  return {
6602
6658
  ok: true,
@@ -6662,33 +6718,6 @@ var init_spawn = __esm({
6662
6718
  }
6663
6719
  });
6664
6720
 
6665
- // src/update/update.ts
6666
- function compareVersions3(left, right) {
6667
- const parse = (version) => {
6668
- const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(version);
6669
- if (match === null) {
6670
- throw new Error(`not a plain release version: ${version}`);
6671
- }
6672
- return [Number(match[1]), Number(match[2]), Number(match[3])];
6673
- };
6674
- const leftParts = parse(left);
6675
- const rightParts = parse(right);
6676
- return leftParts.map((part, index) => part - (rightParts[index] ?? 0)).find((difference) => difference !== 0) ?? 0;
6677
- }
6678
- function releaseTagFromUrl(url) {
6679
- const segment = url.split("?")[0]?.split("/").at(-1);
6680
- const candidate = segment?.startsWith("v") === true ? segment.slice(1) : void 0;
6681
- return candidate !== void 0 && /^\d+\.\d+\.\d+$/.test(candidate) ? candidate : void 0;
6682
- }
6683
- var LATEST_RELEASE_URL;
6684
- var init_update = __esm({
6685
- "src/update/update.ts"() {
6686
- "use strict";
6687
- init_cliError();
6688
- LATEST_RELEASE_URL = "https://github.com/ExaDev/agent-shim/releases/latest";
6689
- }
6690
- });
6691
-
6692
6721
  // src/update/launchHook.ts
6693
6722
  function resolveUpdateMode(globalConfig) {
6694
6723
  return globalConfig?.update?.mode ?? "off";
@@ -6760,7 +6789,7 @@ var init_launchHook = __esm({
6760
6789
 
6761
6790
  // src/launcher.ts
6762
6791
  import { randomUUID as randomUUID4 } from "node:crypto";
6763
- import path32 from "node:path";
6792
+ import path33 from "node:path";
6764
6793
  function resolveIdentityCredential(identity, credential, env, port) {
6765
6794
  if (port === void 0) {
6766
6795
  return { ok: false, status: 1, message: `agent-shim: identity ${identity} needs its credential resolved, but this launcher has no credential port wired` };
@@ -6768,7 +6797,7 @@ function resolveIdentityCredential(identity, credential, env, port) {
6768
6797
  const resolution = resolveCredential({ credential, env, port, subject: `identity ${identity}` });
6769
6798
  return resolution.ok ? resolution : { ok: false, status: CREDENTIAL_UNAVAILABLE_EXIT, message: resolution.message };
6770
6799
  }
6771
- function pickFromPool(decided, params, parsedArgv) {
6800
+ function pickFromPool(decided, params, parsedArgv, readOnly) {
6772
6801
  const { paths, fs: fs12, proc, log } = params;
6773
6802
  if (decided.pool === void 0) {
6774
6803
  return { identityDecision: decided };
@@ -6789,7 +6818,9 @@ function pickFromPool(decided, params, parsedArgv) {
6789
6818
  now: farmRuntime.now,
6790
6819
  sleep: farmRuntime.lock.sleep,
6791
6820
  passthrough: parsedArgv.rest,
6792
- wait: parsedArgv.wait === true,
6821
+ // A read-only decision never sleeps for a refused pool and never records its pick, so asking what a launch would pick leaves the next real launch's keep-warm preference as it was.
6822
+ wait: !readOnly && parsedArgv.wait === true,
6823
+ recordPick: !readOnly,
6793
6824
  log
6794
6825
  });
6795
6826
  if (!resolution.ok) {
@@ -6802,7 +6833,7 @@ function pickFromPool(decided, params, parsedArgv) {
6802
6833
  poolPick: { name: decided.pool, reasons: resolution.reasons, ...resolution.movedOff === void 0 ? {} : { movedOff: resolution.movedOff } }
6803
6834
  };
6804
6835
  }
6805
- function prepareLaunch(params) {
6836
+ function decideLaunch(params, readOnly) {
6806
6837
  const { paths, fs: fs12, proc, log } = params;
6807
6838
  const { env, argv } = proc;
6808
6839
  const parsedArgv = parseLauncherArgv(argv);
@@ -6826,10 +6857,10 @@ function prepareLaunch(params) {
6826
6857
  return trimmed === "" ? void 0 : trimmed;
6827
6858
  }
6828
6859
  });
6829
- const { identityDecision, poolExplanation, poolPick } = pickFromPool(decidedIdentity, params, parsedArgv);
6860
+ const { identityDecision, poolExplanation, poolPick } = pickFromPool(decidedIdentity, params, parsedArgv, readOnly);
6830
6861
  const farmIdentity = configDirEscapeHatchApplies ? void 0 : identityDecision.name;
6831
6862
  const farm = farmIdentity === void 0 ? void 0 : params.farm;
6832
- if (farm !== void 0 && farmIdentity !== void 0) {
6863
+ if (!readOnly && farm !== void 0 && farmIdentity !== void 0) {
6833
6864
  let recovery;
6834
6865
  try {
6835
6866
  recovery = recoverFarm({
@@ -6868,33 +6899,44 @@ function prepareLaunch(params) {
6868
6899
  identityDefaultConfigProfile: loadedIdentity?.config.defaultConfigProfile,
6869
6900
  globalDefaultConfigProfile: params.globalDefaultConfigProfile
6870
6901
  });
6871
- if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(path32.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
6902
+ if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(path33.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
6872
6903
  log.error(
6873
6904
  `agent-shim: no configuration profile named "${configProfileDecision.name}" (selected via ${configProfileDecision.source}). Run \`agent-shim profile add ${configProfileDecision.name}\` first.`
6874
6905
  );
6875
6906
  proc.exit(1);
6876
6907
  }
6877
6908
  const farmContext = farm !== void 0 && farmIdentity !== void 0 ? { farm, identity: farmIdentity, cascade: farm.loadCascade(configProfileDecision.name, cliOverride) } : void 0;
6878
- const provider = parsedArgv.provider === false ? void 0 : resolveProvider({
6909
+ const providerParams = {
6879
6910
  paths,
6880
6911
  port: fs12,
6881
- env,
6882
- ...params.credentials === void 0 ? {} : { credentials: params.credentials },
6883
- ...parsedArgv.provider === void 0 ? {} : { cliProvider: parsedArgv.provider },
6912
+ ...parsedArgv.provider === void 0 || parsedArgv.provider === false ? {} : { cliProvider: parsedArgv.provider },
6884
6913
  ...farmContext === void 0 ? {} : { cascade: farmContext.cascade }
6885
- });
6886
- if (provider !== void 0 && !provider.ok) {
6887
- log.error(provider.message);
6888
- proc.exit(provider.status);
6889
- }
6890
- const resolvedProvider = provider?.ok === true ? provider.provider : void 0;
6891
- for (const warning of provider?.ok === true ? provider.warnings : []) {
6892
- log.warn(warning);
6914
+ };
6915
+ let selectedProvider;
6916
+ let resolvedProvider;
6917
+ if (parsedArgv.provider !== false && readOnly) {
6918
+ const selection = selectProvider(providerParams);
6919
+ if (selection !== void 0 && !selection.ok) {
6920
+ log.error(selection.message);
6921
+ proc.exit(selection.status);
6922
+ }
6923
+ selectedProvider = selection?.ok === true ? selection.provider : void 0;
6924
+ } else if (parsedArgv.provider !== false) {
6925
+ const provider = resolveProvider({ ...providerParams, env, ...params.credentials === void 0 ? {} : { credentials: params.credentials } });
6926
+ if (provider !== void 0 && !provider.ok) {
6927
+ log.error(provider.message);
6928
+ proc.exit(provider.status);
6929
+ }
6930
+ resolvedProvider = provider?.ok === true ? provider.provider : void 0;
6931
+ selectedProvider = resolvedProvider;
6932
+ for (const warning of provider?.ok === true ? provider.warnings : []) {
6933
+ log.warn(warning);
6934
+ }
6893
6935
  }
6894
6936
  if (farm !== void 0 && farmIdentity !== void 0) {
6895
6937
  try {
6896
6938
  const snapshot = readUsageSnapshot(farm.fs, paths.usageSnapshotsDir, farmIdentity);
6897
- for (const warning of quotaWarnings(snapshot, resolvedProvider?.name ?? ANTHROPIC_PROVIDER, farm.now())) {
6939
+ for (const warning of quotaWarnings(snapshot, selectedProvider?.name ?? ANTHROPIC_PROVIDER, farm.now())) {
6898
6940
  log.warn(warning);
6899
6941
  }
6900
6942
  } catch (error) {
@@ -6904,8 +6946,8 @@ function prepareLaunch(params) {
6904
6946
  log.warn(`agent-shim: ${error.message}`);
6905
6947
  }
6906
6948
  }
6907
- const identityCredentialBlock = loadedIdentity?.config.credential;
6908
- const identityResolution = resolvedProvider === void 0 && farmIdentity !== void 0 && identityCredentialBlock !== void 0 ? resolveIdentityCredential(farmIdentity, identityCredentialBlock, env, params.credentials) : void 0;
6949
+ const identityCredentialBlock = selectedProvider === void 0 && farmIdentity !== void 0 ? loadedIdentity?.config.credential : void 0;
6950
+ const identityResolution = !readOnly && identityCredentialBlock !== void 0 && farmIdentity !== void 0 ? resolveIdentityCredential(farmIdentity, identityCredentialBlock, env, params.credentials) : void 0;
6909
6951
  if (identityResolution !== void 0 && !identityResolution.ok) {
6910
6952
  log.error(identityResolution.message);
6911
6953
  proc.exit(identityResolution.status);
@@ -6919,25 +6961,97 @@ function prepareLaunch(params) {
6919
6961
  allowAmbientCredential: loadedIdentity?.config.allowAmbientCredential ?? false,
6920
6962
  allowAmbientCredentialOverride: parseEnvBool("AGENT_SHIM_ALLOW_AMBIENT_CREDENTIAL", env.AGENT_SHIM_ALLOW_AMBIENT_CREDENTIAL) === true,
6921
6963
  identityName: identityDecision.name,
6922
- providerSelected: resolvedProvider !== void 0,
6964
+ providerSelected: selectedProvider !== void 0,
6923
6965
  ...identityCredential === void 0 ? {} : { injectedCredential: { variable: CREDENTIAL_TARGET_VARS[identityCredential.target], token: identityCredential.token } }
6924
6966
  });
6925
6967
  if (!guardResult.ok) {
6926
- log.error(guardResult.message);
6927
- proc.exit(1);
6968
+ if (readOnly && identityCredentialBlock !== void 0) {
6969
+ log.warn(`${guardResult.message} (not resolved here: the launch proceeds only if that value is the identity's own injected credential)`);
6970
+ } else {
6971
+ log.error(guardResult.message);
6972
+ proc.exit(1);
6973
+ }
6928
6974
  }
6975
+ const launchCascade = farmContext?.cascade ?? (params.farm === void 0 ? void 0 : params.farm.loadCascade(configProfileDecision.name, cliOverride));
6976
+ let cascadeLaunch;
6977
+ if (launchCascade !== void 0 && params.farm !== void 0) {
6978
+ const assembled = assembleCascade(launchCascade);
6979
+ const flattened = flattenLayers(assembled.layers, { home: params.farm.home });
6980
+ cascadeLaunch = flattened.launch;
6981
+ if (readOnly) {
6982
+ for (const diagnostic of [...assembled.diagnostics, ...flattened.diagnostics]) {
6983
+ if (diagnostic.severity !== "info") {
6984
+ log.warn(`agent-shim: ${diagnostic.code}: ${diagnostic.message}`);
6985
+ }
6986
+ }
6987
+ }
6988
+ }
6989
+ const pinnedVersion = resolveClaudeVersion({ env, ...parsedArgv.claudeVersion === void 0 ? {} : { flag: parsedArgv.claudeVersion }, ...cascadeLaunch?.claudeVersion === void 0 ? {} : { cascade: cascadeLaunch.claudeVersion } });
6990
+ const discovered = params.resolveClaudeBinary(pinnedVersion === void 0 ? void 0 : { version: pinnedVersion.version });
6991
+ const flags = resolveLaunchFlags({
6992
+ env,
6993
+ // A pool pick reads the usage the front door records, so a pool launch records its own unless something says otherwise.
6994
+ ...poolExplanation === void 0 ? {} : { trackUsageDefault: true },
6995
+ ...cascadeLaunch === void 0 ? {} : { cascade: cascadeLaunch },
6996
+ flags: {
6997
+ ...parsedArgv.skipPermissions === void 0 ? {} : { skipPermissions: parsedArgv.skipPermissions },
6998
+ ...parsedArgv.remoteControl === void 0 ? {} : { remoteControl: parsedArgv.remoteControl },
6999
+ ...parsedArgv.headroom === void 0 ? {} : { headroom: parsedArgv.headroom },
7000
+ ...parsedArgv.trackUsage === void 0 ? {} : { trackUsage: parsedArgv.trackUsage }
7001
+ }
7002
+ });
7003
+ const args = buildArgv({
7004
+ toolFlags: buildFlagArgs(flags),
7005
+ extraFlags: splitExtraFlags(env.CLAUDE_EXTRA_FLAGS),
7006
+ passthrough: parsedArgv.rest
7007
+ });
7008
+ const configDir = configDirEscapeHatchApplies || identityDecision.name === void 0 ? env.CLAUDE_CONFIG_DIR : path33.join(paths.identitiesDir, identityDecision.name);
7009
+ const decision = {
7010
+ identitySource: identityDecision.source,
7011
+ configDirEscapeHatch: identityDecision.configDirEscapeHatch,
7012
+ configProfileSource: configProfileDecision.source,
7013
+ ...identityDecision.name === void 0 ? {} : { identity: identityDecision.name },
7014
+ ...poolPick === void 0 ? {} : { pool: poolPick },
7015
+ ...configDir === void 0 || configDir === "" ? {} : { configDir },
7016
+ ...configProfileDecision.name === void 0 ? {} : { configProfile: configProfileDecision.name },
7017
+ ...selectedProvider === void 0 ? {} : { provider: selectedProvider.name }
7018
+ };
7019
+ return {
7020
+ parsedArgv,
7021
+ identityDecision,
7022
+ poolExplanation,
7023
+ poolPick,
7024
+ configDirEscapeHatch: configDirEscapeHatchApplies,
7025
+ farmIdentity,
7026
+ farmContext,
7027
+ configProfileDecision,
7028
+ provider: selectedProvider,
7029
+ resolvedProvider,
7030
+ identityCredentialBlock,
7031
+ identityCredential,
7032
+ pinnedVersion,
7033
+ flags,
7034
+ bin: discovered.path,
7035
+ args,
7036
+ decision
7037
+ };
7038
+ }
7039
+ function prepareLaunch(params) {
7040
+ const { paths, proc, log } = params;
7041
+ const { env } = proc;
7042
+ const decided = decideLaunch(params, false);
7043
+ const { identityDecision, configProfileDecision, resolvedProvider, identityCredential, poolExplanation, flags: resolvedFlags, args: finalArgv, configDirEscapeHatch: configDirEscapeHatchApplies, decision } = decided;
6929
7044
  log.info(
6930
7045
  `agent-shim: identity ${identityDecision.name ?? "(none)"} (${identityDecision.source}${poolExplanation === void 0 ? "" : `, ${poolExplanation}`}), config profile ${configProfileDecision.name ?? "(none)"} (${configProfileDecision.source})` + (resolvedProvider === void 0 ? "" : `, provider ${resolvedProvider.name} (credential ${resolvedProvider.credential.target} from ${describeSource(resolvedProvider.credential.source)})`) + (identityCredential === void 0 ? "" : `, identity credential ${identityCredential.target} from ${describeSource(identityCredential.source)}`)
6931
7046
  );
6932
7047
  const updateCheck = runLaunchUpdateCheck({
6933
7048
  mode: params.updateMode ?? "off",
6934
- checkPath: path32.join(paths.root, "update.check"),
7049
+ checkPath: path33.join(paths.root, "update.check"),
6935
7050
  currentVersion: package_default.version,
6936
7051
  port: params.update
6937
7052
  });
6938
- let cascadeLaunch;
6939
- if (farmContext !== void 0) {
6940
- const { farm: resyncFarmRuntime, identity: resyncIdentity, cascade } = farmContext;
7053
+ if (decided.farmContext !== void 0) {
7054
+ const { farm: resyncFarmRuntime, identity: resyncIdentity, cascade } = decided.farmContext;
6941
7055
  let result;
6942
7056
  try {
6943
7057
  result = resyncFarm({
@@ -6974,27 +7088,10 @@ function prepareLaunch(params) {
6974
7088
  log.info(
6975
7089
  result.noOp ? `agent-shim: farm at ${result.farmRoot} already matches the resolved cascade` : `agent-shim: farm at ${result.farmRoot} resynced (${String(result.manifest.links.length)} link(s), ${String(result.manifest.materialised.length)} built director(ies)${result.adopted.length === 0 ? "" : `, ${String(result.adopted.length)} adopted into ${resyncFarmRuntime.claudeHome}`})`
6976
7090
  );
6977
- cascadeLaunch = result.resolved.flattened.launch;
6978
- } else if (params.farm !== void 0) {
6979
- cascadeLaunch = flattenLayers(assembleCascade(params.farm.loadCascade(configProfileDecision.name, cliOverride)).layers, { home: params.farm.home }).launch;
6980
7091
  }
6981
- const pinnedVersion = resolveClaudeVersion({ env, ...parsedArgv.claudeVersion === void 0 ? {} : { flag: parsedArgv.claudeVersion }, ...cascadeLaunch?.claudeVersion === void 0 ? {} : { cascade: cascadeLaunch.claudeVersion } });
6982
- const discovered = params.resolveClaudeBinary(pinnedVersion === void 0 ? void 0 : { version: pinnedVersion.version });
6983
- if (pinnedVersion !== void 0) {
6984
- log.info(`agent-shim: Claude Code ${pinnedVersion.version} (pinned by ${pinnedVersion.source})`);
7092
+ if (decided.pinnedVersion !== void 0) {
7093
+ log.info(`agent-shim: Claude Code ${decided.pinnedVersion.version} (pinned by ${decided.pinnedVersion.source})`);
6985
7094
  }
6986
- const resolvedFlags = resolveLaunchFlags({
6987
- env,
6988
- // A pool pick reads the usage the front door records, so a pool launch records its own unless something says otherwise.
6989
- ...poolExplanation === void 0 ? {} : { trackUsageDefault: true },
6990
- ...cascadeLaunch === void 0 ? {} : { cascade: cascadeLaunch },
6991
- flags: {
6992
- ...parsedArgv.skipPermissions === void 0 ? {} : { skipPermissions: parsedArgv.skipPermissions },
6993
- ...parsedArgv.remoteControl === void 0 ? {} : { remoteControl: parsedArgv.remoteControl },
6994
- ...parsedArgv.headroom === void 0 ? {} : { headroom: parsedArgv.headroom },
6995
- ...parsedArgv.trackUsage === void 0 ? {} : { trackUsage: parsedArgv.trackUsage }
6996
- }
6997
- });
6998
7095
  const frontDoorPort = params.frontdoor;
6999
7096
  const frontDoorEngaged = resolvedProvider !== void 0 || resolvedFlags.headroom || resolvedFlags.trackUsage;
7000
7097
  if (frontDoorEngaged && frontDoorPort === void 0) {
@@ -7018,11 +7115,6 @@ function prepareLaunch(params) {
7018
7115
  log.info(`agent-shim: routing through the front door on 127.0.0.1:${String(frontDoor.port)}${resolvedProvider === void 0 ? ` (OAuth via the door's CONNECT surface on 127.0.0.1:${String(frontDoor.connectPort)}, usage recorded)` : ` (provider ${resolvedProvider.name})`}`);
7019
7116
  }
7020
7117
  const frontDoorRelease = frontDoor === void 0 ? void 0 : frontDoorPort?.release;
7021
- const finalArgv = buildArgv({
7022
- toolFlags: buildFlagArgs(resolvedFlags),
7023
- extraFlags: splitExtraFlags(env.CLAUDE_EXTRA_FLAGS),
7024
- passthrough: parsedArgv.rest
7025
- });
7026
7118
  const finalEnv = buildEnv({
7027
7119
  baseEnv: env,
7028
7120
  configDirEscapeHatch: configDirEscapeHatchApplies,
@@ -7040,18 +7132,35 @@ function prepareLaunch(params) {
7040
7132
  registered();
7041
7133
  }
7042
7134
  };
7043
- const configDir = finalEnv.CLAUDE_CONFIG_DIR;
7044
- const decision = {
7045
- identitySource: identityDecision.source,
7046
- configDirEscapeHatch: identityDecision.configDirEscapeHatch,
7047
- configProfileSource: configProfileDecision.source,
7048
- ...identityDecision.name === void 0 ? {} : { identity: identityDecision.name },
7049
- ...poolPick === void 0 ? {} : { pool: poolPick },
7050
- ...configDir === void 0 || configDir === "" ? {} : { configDir },
7051
- ...configProfileDecision.name === void 0 ? {} : { configProfile: configProfileDecision.name },
7052
- ...resolvedProvider === void 0 ? {} : { provider: resolvedProvider.name }
7135
+ return { bin: decided.bin, args: finalArgv, env: finalEnv, release, markChildStarted: updateCheck.markChildStarted, decision };
7136
+ }
7137
+ function resolveLaunch(params) {
7138
+ const decided = decideLaunch(params, true);
7139
+ const { env } = params.proc;
7140
+ const frontDoor = decided.provider !== void 0 || decided.flags.headroom || decided.flags.trackUsage;
7141
+ const built = buildEnv({
7142
+ baseEnv: env,
7143
+ configDirEscapeHatch: decided.configDirEscapeHatch,
7144
+ resolvedIdentityName: decided.identityDecision.name,
7145
+ identitiesDir: params.paths.identitiesDir,
7146
+ ...decided.provider === void 0 ? {} : { provider: decided.provider },
7147
+ ...frontDoor ? { frontdoor: { port: 0, connectPort: 0, trustBundlePath: "", sessionToken: "" } } : {},
7148
+ ...decided.flags.headroom ? { headroom: { socketPath: "", projectId: "" } } : {},
7149
+ sessionId: ""
7150
+ });
7151
+ const credentialNames = decided.identityCredentialBlock === void 0 ? [] : Object.keys(credentialVariables(decided.identityCredentialBlock.target ?? "bearer", ""));
7152
+ const environment = [.../* @__PURE__ */ new Set([...Object.keys(built).filter((name) => built[name] !== env[name]), ...credentialNames])].sort();
7153
+ const credential = decided.provider !== void 0 ? { subject: "provider", name: decided.provider.name, summary: summariseCredential(decided.provider.definition.credential) } : decided.identityCredentialBlock !== void 0 && decided.farmIdentity !== void 0 ? { subject: "identity", name: decided.farmIdentity, summary: summariseCredential(decided.identityCredentialBlock) } : void 0;
7154
+ return {
7155
+ decision: decided.decision,
7156
+ flags: decided.flags,
7157
+ ...decided.pinnedVersion === void 0 ? {} : { claudeVersion: decided.pinnedVersion },
7158
+ bin: decided.bin,
7159
+ args: decided.args,
7160
+ ...credential === void 0 ? {} : { credential },
7161
+ routing: { frontDoor, headroom: decided.flags.headroom },
7162
+ environment
7053
7163
  };
7054
- return { bin: discovered.path, args: finalArgv, env: finalEnv, release, markChildStarted: updateCheck.markChildStarted, decision };
7055
7164
  }
7056
7165
  function runLaunchPlan(plan, spawn2) {
7057
7166
  try {
@@ -7097,12 +7206,12 @@ var init_launcher = __esm({
7097
7206
  });
7098
7207
 
7099
7208
  // src/ownCli.ts
7100
- import path33 from "node:path";
7209
+ import path34 from "node:path";
7101
7210
  function agentShimCliPath(distDir = typeof __AGENT_SHIM_DIST_DIR__ === "string" ? __AGENT_SHIM_DIST_DIR__ : void 0) {
7102
7211
  if (distDir === void 0) {
7103
7212
  throw new OwnCliPathUnknownError();
7104
7213
  }
7105
- return path33.join(distDir, OWN_CLI_FILE_NAME);
7214
+ return path34.join(distDir, OWN_CLI_FILE_NAME);
7106
7215
  }
7107
7216
  var OWN_CLI_FILE_NAME, OwnCliPathUnknownError;
7108
7217
  var init_ownCli = __esm({
@@ -7191,10 +7300,10 @@ request.on("error", (error) => finish(failed, (error.code ? error.code + ": " :
7191
7300
 
7192
7301
  // src/frontdoor/trust.ts
7193
7302
  import { createHash as createHash6 } from "node:crypto";
7194
- import path34 from "node:path";
7303
+ import path35 from "node:path";
7195
7304
  function resolveTrustBundle(params) {
7196
7305
  const { caCertFile, bundlesDir, variable, inherited, fs: fs12 } = params;
7197
- if (inherited === void 0 || inherited === "" || path34.resolve(inherited) === path34.resolve(caCertFile)) {
7306
+ if (inherited === void 0 || inherited === "" || path35.resolve(inherited) === path35.resolve(caCertFile)) {
7198
7307
  return { path: caCertFile };
7199
7308
  }
7200
7309
  const caPem = fs12.readFileUtf8(caCertFile);
@@ -7212,7 +7321,7 @@ function resolveTrustBundle(params) {
7212
7321
  }
7213
7322
  const combined = `${inheritedPem.trimEnd()}
7214
7323
  ${caPem}`;
7215
- const bundle = path34.join(bundlesDir, `${createHash6("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
7324
+ const bundle = path35.join(bundlesDir, `${createHash6("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
7216
7325
  if (!fs12.exists(bundle)) {
7217
7326
  fs12.mkdirp(bundlesDir);
7218
7327
  fs12.writeFileAtomic(bundle, combined);
@@ -7369,6 +7478,31 @@ function prepareClaudeLaunch(options) {
7369
7478
  const spawnDaemon = daemonSpawnerFor(options.agentShim);
7370
7479
  return prepareLaunch(realPrepareLaunchParams(paths, { proc, log, spawnDaemon, farm: buildFarmRuntime(paths, options.cwd) }));
7371
7480
  }
7481
+ function resolveClaudeLaunch(options) {
7482
+ const paths = options.paths ?? resolveLayoutPaths();
7483
+ const refusals = [];
7484
+ const warnings = [];
7485
+ const log = {
7486
+ info: () => void 0,
7487
+ warn: (message) => {
7488
+ warnings.push(message);
7489
+ },
7490
+ error: (message) => {
7491
+ refusals.push(message);
7492
+ }
7493
+ };
7494
+ const proc = {
7495
+ env: options.env,
7496
+ argv: options.argv,
7497
+ exit: (code) => {
7498
+ throw new LaunchRefusedError(refusals.join("\n") || `the launch was refused (exit ${String(code)})`, code);
7499
+ }
7500
+ };
7501
+ const spawnDaemon = () => {
7502
+ throw new Error("resolving a launch starts no daemon");
7503
+ };
7504
+ return { resolution: resolveLaunch(realPrepareLaunchParams(paths, { proc, log, spawnDaemon, farm: buildFarmRuntime(paths, options.cwd) })), warnings };
7505
+ }
7372
7506
  var LaunchRefusedError;
7373
7507
  var init_launchWiring = __esm({
7374
7508
  "src/launchWiring.ts"() {
@@ -7535,7 +7669,7 @@ var init_anthropicUsageRefresh = __esm({
7535
7669
  });
7536
7670
 
7537
7671
  // src/usage/providerQuota.ts
7538
- import { z as z21 } from "zod";
7672
+ import { z as z22 } from "zod";
7539
7673
  var MS_PER_SECOND7, SECONDS_PER_HOUR, HOURS_PER_DAY3, DAYS_PER_MONTH, ZAI_HOST, ZAI_QUOTA_URL, ZAI_UNIT_HOURS, ZAI_UNIT_MONTHS, ZAI_UNIT_MS, ZaiLimitSchema, ZaiResponseSchema, OPENROUTER_HOST, OPENROUTER_KEY_URL, OPENROUTER_CREDITS_URL, MS_PER_DAY3, OpenRouterKeySchema, OpenRouterCreditsSchema;
7540
7674
  var init_providerQuota = __esm({
7541
7675
  "src/usage/providerQuota.ts"() {
@@ -7553,35 +7687,35 @@ var init_providerQuota = __esm({
7553
7687
  [ZAI_UNIT_HOURS, SECONDS_PER_HOUR * MS_PER_SECOND7],
7554
7688
  [ZAI_UNIT_MONTHS, DAYS_PER_MONTH * HOURS_PER_DAY3 * SECONDS_PER_HOUR * MS_PER_SECOND7]
7555
7689
  ]);
7556
- ZaiLimitSchema = z21.object({
7557
- type: z21.string(),
7558
- unit: z21.number().int(),
7559
- number: z21.number().int().positive(),
7560
- percentage: z21.number().nonnegative(),
7561
- nextResetTime: z21.number().positive().optional(),
7562
- usage: z21.number().nonnegative().optional(),
7563
- currentValue: z21.number().nonnegative().optional(),
7564
- remaining: z21.number().nonnegative().optional()
7690
+ ZaiLimitSchema = z22.object({
7691
+ type: z22.string(),
7692
+ unit: z22.number().int(),
7693
+ number: z22.number().int().positive(),
7694
+ percentage: z22.number().nonnegative(),
7695
+ nextResetTime: z22.number().positive().optional(),
7696
+ usage: z22.number().nonnegative().optional(),
7697
+ currentValue: z22.number().nonnegative().optional(),
7698
+ remaining: z22.number().nonnegative().optional()
7565
7699
  });
7566
- ZaiResponseSchema = z21.object({
7567
- success: z21.boolean(),
7568
- msg: z21.string().optional(),
7569
- data: z21.object({ level: z21.string().optional(), limits: z21.array(ZaiLimitSchema) })
7700
+ ZaiResponseSchema = z22.object({
7701
+ success: z22.boolean(),
7702
+ msg: z22.string().optional(),
7703
+ data: z22.object({ level: z22.string().optional(), limits: z22.array(ZaiLimitSchema) })
7570
7704
  });
7571
7705
  OPENROUTER_HOST = "openrouter.ai";
7572
7706
  OPENROUTER_KEY_URL = `https://${OPENROUTER_HOST}/api/v1/key`;
7573
7707
  OPENROUTER_CREDITS_URL = `https://${OPENROUTER_HOST}/api/v1/credits`;
7574
7708
  MS_PER_DAY3 = HOURS_PER_DAY3 * SECONDS_PER_HOUR * MS_PER_SECOND7;
7575
- OpenRouterKeySchema = z21.object({
7576
- data: z21.object({
7577
- limit: z21.number().nonnegative().nullable(),
7578
- limit_remaining: z21.number().nullable(),
7579
- limit_reset: z21.string().nullable(),
7580
- is_free_tier: z21.boolean().optional(),
7581
- free_model_daily_requests: z21.object({ used: z21.number().nonnegative(), limit: z21.number().nonnegative(), remaining: z21.number() }).optional()
7709
+ OpenRouterKeySchema = z22.object({
7710
+ data: z22.object({
7711
+ limit: z22.number().nonnegative().nullable(),
7712
+ limit_remaining: z22.number().nullable(),
7713
+ limit_reset: z22.string().nullable(),
7714
+ is_free_tier: z22.boolean().optional(),
7715
+ free_model_daily_requests: z22.object({ used: z22.number().nonnegative(), limit: z22.number().nonnegative(), remaining: z22.number() }).optional()
7582
7716
  })
7583
7717
  });
7584
- OpenRouterCreditsSchema = z21.object({ data: z21.object({ total_credits: z21.number().nonnegative(), total_usage: z21.number().nonnegative() }) });
7718
+ OpenRouterCreditsSchema = z22.object({ data: z22.object({ total_credits: z22.number().nonnegative(), total_usage: z22.number().nonnegative() }) });
7585
7719
  }
7586
7720
  });
7587
7721
 
@@ -8197,8 +8331,8 @@ function parseConnectTarget(authority) {
8197
8331
  function isInterceptedHost(host, interceptHosts) {
8198
8332
  return interceptHosts.includes(host);
8199
8333
  }
8200
- function servedByPipeline(path35) {
8201
- return path35?.startsWith(ROUTED_PATH_PREFIX) === true;
8334
+ function servedByPipeline(path36) {
8335
+ return path36?.startsWith(ROUTED_PATH_PREFIX) === true;
8202
8336
  }
8203
8337
  var HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
8204
8338
  "connection",
@@ -8732,11 +8866,11 @@ function createRcSessionTracker(deps) {
8732
8866
  };
8733
8867
  const observeExchange = (request4) => {
8734
8868
  const method = (request4.method ?? "").toUpperCase();
8735
- const path35 = new URL(request4.url ?? "/", "http://127.0.0.1").pathname;
8736
- if (!path35.startsWith(RC_SESSIONS_PATH_PREFIX)) {
8869
+ const path36 = new URL(request4.url ?? "/", "http://127.0.0.1").pathname;
8870
+ if (!path36.startsWith(RC_SESSIONS_PATH_PREFIX)) {
8737
8871
  return void 0;
8738
8872
  }
8739
- const tail = path35.slice(RC_SESSIONS_PATH_PREFIX.length);
8873
+ const tail = path36.slice(RC_SESSIONS_PATH_PREFIX.length);
8740
8874
  const facts = {
8741
8875
  oauthAuthorization: oauthAuthorizationOf(request4.headers),
8742
8876
  anthropicVersion: singleHeader(request4.headers, "anthropic-version"),
@@ -9118,8 +9252,8 @@ var RC_READ_FILE_ENCODINGS = ["utf-8", "base64"];
9118
9252
  function isRcReadFileEncoding(value) {
9119
9253
  return RC_READ_FILE_ENCODINGS.some((encoding) => encoding === value);
9120
9254
  }
9121
- function buildRcReadFilePayload(requestId, path35, options) {
9122
- return buildRcControlRequestPayload(requestId, { subtype: "read_file", path: path35, ...options?.maxBytes === void 0 ? {} : { max_bytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } });
9255
+ function buildRcReadFilePayload(requestId, path36, options) {
9256
+ return buildRcControlRequestPayload(requestId, { subtype: "read_file", path: path36, ...options?.maxBytes === void 0 ? {} : { max_bytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } });
9123
9257
  }
9124
9258
  function buildRcFileSuggestionsPayload(requestId, query) {
9125
9259
  return buildRcControlRequestPayload(requestId, { subtype: "file_suggestions", query });
@@ -9221,15 +9355,15 @@ async function getRcSessionContextUsage(deps, sessionId, detail) {
9221
9355
  const result = await deliverRcClientPayload(deps, sessionId, buildRcGetContextUsagePayload(requestId, detail), `request the context usage of session ${sessionId}`);
9222
9356
  return result.ok ? { ...result, requestId } : result;
9223
9357
  }
9224
- async function readRcSessionFile(deps, sessionId, path35, options) {
9225
- if (path35 === "") {
9358
+ async function readRcSessionFile(deps, sessionId, path36, options) {
9359
+ if (path36 === "") {
9226
9360
  return { ok: false, message: "a read-file write needs a non-empty path: the SDK's own field names the file the worker resolves against the session's cwd, and an empty string names none" };
9227
9361
  }
9228
9362
  if (options?.maxBytes !== void 0 && (!Number.isInteger(options.maxBytes) || options.maxBytes <= 0)) {
9229
9363
  return { ok: false, message: "a read-file write's max-bytes is a positive whole number of bytes: the SDK's own field caps the read, and a zero or negative cap reads nothing" };
9230
9364
  }
9231
9365
  const requestId = deps.newUuid();
9232
- const result = await deliverRcClientPayload(deps, sessionId, buildRcReadFilePayload(requestId, path35, options), `read ${path35} from session ${sessionId}`);
9366
+ const result = await deliverRcClientPayload(deps, sessionId, buildRcReadFilePayload(requestId, path36, options), `read ${path36} from session ${sessionId}`);
9233
9367
  return result.ok ? { ...result, requestId } : result;
9234
9368
  }
9235
9369
  async function suggestRcSessionFiles(deps, sessionId, query) {
@@ -9398,11 +9532,11 @@ function createRcControlHandler(deps) {
9398
9532
  path: "read-file",
9399
9533
  read: (body) => {
9400
9534
  const session = bodyString(body, "session");
9401
- const path35 = bodyString(body, "path");
9535
+ const path36 = bodyString(body, "path");
9402
9536
  const maxBytes = "maxBytes" in body ? bodyPositiveInteger(body, "maxBytes") : void 0;
9403
9537
  const encoding = "encoding" in body && isRcReadFileEncoding(body.encoding) ? body.encoding : void 0;
9404
- const refused2 = session === void 0 || path35 === void 0 || "maxBytes" in body && maxBytes === void 0 || "encoding" in body && encoding === void 0;
9405
- return refused2 ? { error: `the read-file body must be JSON naming a non-empty session id and path, maxBytes only as a positive whole number or absent, and an encoding the SDK's own type permits (${RC_READ_FILE_ENCODINGS.join(", ")}) or none` } : { session, run: async () => await deps.readFile(session, path35, { ...maxBytes === void 0 ? {} : { maxBytes }, ...encoding === void 0 ? {} : { encoding } }) };
9538
+ const refused2 = session === void 0 || path36 === void 0 || "maxBytes" in body && maxBytes === void 0 || "encoding" in body && encoding === void 0;
9539
+ return refused2 ? { error: `the read-file body must be JSON naming a non-empty session id and path, maxBytes only as a positive whole number or absent, and an encoding the SDK's own type permits (${RC_READ_FILE_ENCODINGS.join(", ")}) or none` } : { session, run: async () => await deps.readFile(session, path36, { ...maxBytes === void 0 ? {} : { maxBytes }, ...encoding === void 0 ? {} : { encoding } }) };
9406
9540
  }
9407
9541
  },
9408
9542
  {
@@ -9712,9 +9846,9 @@ function requestIdOfBody(body) {
9712
9846
  }
9713
9847
  function frontDoorRcControl(transport, token) {
9714
9848
  const headers = { authorization: `Bearer ${token}` };
9715
- const listAnswerOf = async (path35, what) => {
9849
+ const listAnswerOf = async (path36, what) => {
9716
9850
  try {
9717
- return await transport.request({ method: "GET", path: path35, headers });
9851
+ return await transport.request({ method: "GET", path: path36, headers });
9718
9852
  } catch (error) {
9719
9853
  throw new Error(`${what}: could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
9720
9854
  }
@@ -9786,10 +9920,10 @@ function frontDoorRcControl(transport, token) {
9786
9920
  }
9787
9921
  return pending;
9788
9922
  };
9789
- const writeOf = async (path35, body, describeFailure) => {
9923
+ const writeOf = async (path36, body, describeFailure) => {
9790
9924
  let answer;
9791
9925
  try {
9792
- answer = await transport.request({ method: "POST", path: path35, headers: { ...headers, "content-type": "application/json" }, body });
9926
+ answer = await transport.request({ method: "POST", path: path36, headers: { ...headers, "content-type": "application/json" }, body });
9793
9927
  } catch (error) {
9794
9928
  return { ok: false, message: `could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}` };
9795
9929
  }
@@ -9820,10 +9954,10 @@ function frontDoorRcControl(transport, token) {
9820
9954
  endSession: async (sessionId, reason) => await writeOf(`${CONTROL_PATH_PREFIX}/end-session`, JSON.stringify({ session: sessionId, ...reason === void 0 ? {} : { reason } }), (status, message) => `ending ${sessionId} failed (HTTP ${String(status)}): ${message}`),
9821
9955
  getUsage: async (sessionId, skipBehaviors) => await writeOf(`${CONTROL_PATH_PREFIX}/get-usage`, JSON.stringify({ session: sessionId, ...skipBehaviors === void 0 ? {} : { skipBehaviors } }), (status, message) => `requesting the usage of ${sessionId} failed (HTTP ${String(status)}): ${message}`),
9822
9956
  getContextUsage: async (sessionId, detail) => await writeOf(`${CONTROL_PATH_PREFIX}/get-context-usage`, JSON.stringify({ session: sessionId, ...detail === void 0 ? {} : { detail } }), (status, message) => `requesting the context usage of ${sessionId} failed (HTTP ${String(status)}): ${message}`),
9823
- readFile: async (sessionId, path35, options) => await writeOf(
9957
+ readFile: async (sessionId, path36, options) => await writeOf(
9824
9958
  `${CONTROL_PATH_PREFIX}/read-file`,
9825
- JSON.stringify({ session: sessionId, path: path35, ...options?.maxBytes === void 0 ? {} : { maxBytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } }),
9826
- (status, message) => `reading ${path35} from ${sessionId} failed (HTTP ${String(status)}): ${message}`
9959
+ JSON.stringify({ session: sessionId, path: path36, ...options?.maxBytes === void 0 ? {} : { maxBytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } }),
9960
+ (status, message) => `reading ${path36} from ${sessionId} failed (HTTP ${String(status)}): ${message}`
9827
9961
  ),
9828
9962
  fileSuggestions: async (sessionId, query) => await writeOf(`${CONTROL_PATH_PREFIX}/file-suggestions`, JSON.stringify({ session: sessionId, query }), (status, message) => `requesting file suggestions from ${sessionId} failed (HTTP ${String(status)}): ${message}`),
9829
9963
  keepAlive: async (sessionId) => await writeOf(`${CONTROL_PATH_PREFIX}/keep-alive`, JSON.stringify({ session: sessionId }), (status, message) => `keeping ${sessionId} alive failed (HTTP ${String(status)}): ${message}`),
@@ -9982,12 +10116,12 @@ function tlsFacts(options) {
9982
10116
  }
9983
10117
  function realRcEventDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
9984
10118
  const agent = new ExemptTlsAgent();
9985
- const post = async (path35, headers, body) => await new Promise((resolve, reject) => {
10119
+ const post = async (path36, headers, body) => await new Promise((resolve, reject) => {
9986
10120
  const options = {
9987
10121
  host: target.host,
9988
10122
  port: target.port,
9989
10123
  method: "POST",
9990
- path: path35,
10124
+ path: path36,
9991
10125
  // The Host header names the host whose API this is, not the address dialled: a redirected test dials a loopback stand-in while still speaking to the API host by name, exactly as the forwarded paths present their SNI.
9992
10126
  headers: { ...headers, host: target.servername ?? target.host, "content-length": String(Buffer.byteLength(body, "utf8")) },
9993
10127
  agent
@@ -10052,12 +10186,12 @@ function lateRcStreamDial(resolve) {
10052
10186
  }
10053
10187
  function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
10054
10188
  const agent = new ExemptTlsAgent();
10055
- const request4 = async (method, path35, headers, body, signal) => await new Promise((resolve, reject) => {
10189
+ const request4 = async (method, path36, headers, body, signal) => await new Promise((resolve, reject) => {
10056
10190
  const options = {
10057
10191
  host: target.host,
10058
10192
  port: target.port,
10059
10193
  method,
10060
- path: path35,
10194
+ path: path36,
10061
10195
  // The Host header names the host whose API this is, not the address dialled: a redirected test dials a loopback stand-in while still speaking to the API host by name, exactly as the forwarded paths present their SNI.
10062
10196
  headers: { ...headers, host: target.servername ?? target.host, ...body === void 0 ? {} : { "content-length": String(Buffer.byteLength(body, "utf8")) } },
10063
10197
  agent,
@@ -10099,9 +10233,9 @@ function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_P
10099
10233
  return { status, body: await readAll(response) };
10100
10234
  },
10101
10235
  openStream: async (sessionId, headers, resume, signal) => {
10102
- const path35 = resume === void 0 ? `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream` : `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream?from_sequence_num=${String(resume.fromSequenceNum)}`;
10236
+ const path36 = resume === void 0 ? `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream` : `/v1/code/sessions/${encodeURIComponent(sessionId)}/events/stream?from_sequence_num=${String(resume.fromSequenceNum)}`;
10103
10237
  const streamHeaders = resume === void 0 ? headers : { ...headers, "last-event-id": String(resume.fromSequenceNum) };
10104
- const { status, response } = await request4("GET", path35, streamHeaders, void 0, signal);
10238
+ const { status, response } = await request4("GET", path36, streamHeaders, void 0, signal);
10105
10239
  if (!isSuccessful2(status)) {
10106
10240
  await readAll(response);
10107
10241
  return { status, chunks: NO_CHUNKS };
@@ -10700,11 +10834,15 @@ function doorApiNodeHandlerOf(router, expectedToken) {
10700
10834
  }
10701
10835
  return { matched: true };
10702
10836
  }
10703
- const rest = await restHandler.handle(request4, response, { context: { headers: request4.headers }, prefix: RC_ORPC_PATH_PREFIX });
10837
+ const rest = await restHandler.handle(request4, response, { context: { headers: request4.headers, afterResponse: (action) => {
10838
+ response.once("finish", action);
10839
+ } }, prefix: RC_ORPC_PATH_PREFIX });
10704
10840
  if (rest.matched) {
10705
10841
  return rest;
10706
10842
  }
10707
- return await rpcHandler.handle(request4, response, { context: { headers: request4.headers }, prefix: RC_ORPC_PATH_PREFIX });
10843
+ return await rpcHandler.handle(request4, response, { context: { headers: request4.headers, afterResponse: (action) => {
10844
+ response.once("finish", action);
10845
+ } }, prefix: RC_ORPC_PATH_PREFIX });
10708
10846
  }
10709
10847
  };
10710
10848
  }
@@ -10741,8 +10879,8 @@ init_cliError();
10741
10879
  init_realPorts();
10742
10880
 
10743
10881
  // src/frontdoor/controlApi.ts
10744
- import { createORPCClient as createORPCClient2, ORPCError as ORPCError3 } from "@orpc/client";
10745
- import { openapi as openapi3 } from "@orpc/openapi";
10882
+ import { createORPCClient as createORPCClient2, ORPCError as ORPCError5 } from "@orpc/client";
10883
+ import { openapi as openapi6 } from "@orpc/openapi";
10746
10884
 
10747
10885
  // src/checkReport.ts
10748
10886
  init_classify();
@@ -10969,19 +11107,19 @@ function writePools(paths, pools) {
10969
11107
  applyPatch(paths.globalConfigFile, GlobalConfigSchema, { pools }, { defaults: {} });
10970
11108
  }
10971
11109
  function poolCycleOf(pools, name) {
10972
- const walk = (current, path35) => {
11110
+ const walk = (current, path36) => {
10973
11111
  for (const entry of pools[current]?.identities ?? []) {
10974
11112
  const nested = poolNameOf(poolMemberIdentity(entry));
10975
11113
  if (nested === void 0) {
10976
11114
  continue;
10977
11115
  }
10978
11116
  if (nested === name) {
10979
- return [...path35, nested];
11117
+ return [...path36, nested];
10980
11118
  }
10981
- if (path35.includes(nested)) {
11119
+ if (path36.includes(nested)) {
10982
11120
  continue;
10983
11121
  }
10984
- const found = walk(nested, [...path35, nested]);
11122
+ const found = walk(nested, [...path36, nested]);
10985
11123
  if (found !== void 0) {
10986
11124
  return found;
10987
11125
  }
@@ -12552,10 +12690,48 @@ var DoctorRunOutputSchema = z19.strictObject({
12552
12690
  ok: z19.boolean(),
12553
12691
  findings: z19.readonly(z19.array(DoctorFindingSchema))
12554
12692
  });
12693
+ var FrontDoorRestartOutputSchema = z19.strictObject({
12694
+ action: z19.literal("restarting"),
12695
+ previousPid: z19.int().positive()
12696
+ });
12697
+ var UpdateCheckOutputSchema = z19.strictObject({
12698
+ current: z19.string(),
12699
+ latest: z19.string(),
12700
+ action: z19.enum(["current", "available", "updated"])
12701
+ });
12702
+ var CodexSignInSchema = z19.discriminatedUnion("state", [
12703
+ z19.strictObject({ state: z19.literal("none") }),
12704
+ z19.strictObject({ state: z19.literal("signed-in"), email: z19.string().optional(), planScope: z19.boolean(), accessTokenExpiresAt: z19.number() }),
12705
+ z19.strictObject({ state: z19.literal("unreadable"), message: z19.string() })
12706
+ ]);
12707
+ var CodexStatusOutputSchema = z19.strictObject({
12708
+ signIn: CodexSignInSchema,
12709
+ codexProviders: z19.readonly(z19.array(z19.string()))
12710
+ });
12711
+ var CodexLogoutOutputSchema = z19.strictObject({
12712
+ hadGrant: z19.boolean(),
12713
+ revoked: z19.boolean()
12714
+ });
12715
+
12716
+ // src/frontdoor/codexApi.ts
12717
+ import { openapi as openapi2 } from "@orpc/openapi";
12718
+ var CODEX_API_TAG = "codex";
12719
+ function createCodexApiRouter(deps) {
12720
+ const authed = doorApiAuth(deps.expectedToken);
12721
+ return {
12722
+ codex: {
12723
+ status: authed.meta(openapi2({ method: "GET", path: "/rest/codex/status", summary: "Read the Codex sign-in and the codex providers", tags: [CODEX_API_TAG] })).output(CodexStatusOutputSchema).handler(() => {
12724
+ const status = deps.codexStatus();
12725
+ return { signIn: status.signIn, codexProviders: status.codexProviders };
12726
+ }),
12727
+ logout: authed.meta(openapi2({ method: "POST", path: "/rest/codex/logout", summary: "Revoke the Sign in with ChatGPT login and remove it", tags: [CODEX_API_TAG] })).output(CodexLogoutOutputSchema).handler(async () => await deps.codexLogout())
12728
+ }
12729
+ };
12730
+ }
12555
12731
 
12556
12732
  // src/frontdoor/eventsApi.ts
12557
12733
  import { ORPCError as ORPCError2 } from "@orpc/client";
12558
- import { openapi as openapi2 } from "@orpc/openapi";
12734
+ import { openapi as openapi3 } from "@orpc/openapi";
12559
12735
  import { eventIterator as eventIterator2, withEventMeta as withEventMeta2 } from "@orpc/server";
12560
12736
 
12561
12737
  // src/frontdoor/eventSchemas.ts
@@ -12602,7 +12778,7 @@ function createEventsApiRouter(deps) {
12602
12778
  const authed = doorApiAuth(deps.expectedToken);
12603
12779
  return {
12604
12780
  events: {
12605
- subscribe: authed.meta(openapi2({ method: "GET", path: "/rest/events", summary: "Stream the door's every event source (SSE)", tags: [EVENTS_API_TAG] })).input(DoorEventSourceQuerySchema).output(eventIterator2(DoorEventSchema)).handler(async function* ({ input, signal }) {
12781
+ subscribe: authed.meta(openapi3({ method: "GET", path: "/rest/events", summary: "Stream the door's every event source (SSE)", tags: [EVENTS_API_TAG] })).input(DoorEventSourceQuerySchema).output(eventIterator2(DoorEventSchema)).handler(async function* ({ input, signal }) {
12606
12782
  if (input.sources !== void 0) {
12607
12783
  const live = deps.events.sources();
12608
12784
  const unknown = input.sources.filter((source) => !live.includes(source));
@@ -12634,9 +12810,120 @@ function createEventsApiRouter(deps) {
12634
12810
  };
12635
12811
  }
12636
12812
 
12813
+ // src/frontdoor/lifecycleApi.ts
12814
+ init_update();
12815
+ import { ORPCError as ORPCError3 } from "@orpc/client";
12816
+ import { openapi as openapi4 } from "@orpc/openapi";
12817
+ var FRONTDOOR_API_TAG = "frontdoor";
12818
+ var UPDATE_API_TAG = "update";
12819
+ function createLifecycleApiRouter(deps) {
12820
+ const authed = doorApiAuth(deps.expectedToken);
12821
+ return {
12822
+ frontdoor: {
12823
+ restart: authed.meta(openapi4({ method: "POST", path: "/rest/frontdoor/restart", summary: "Replace the serving front door in place", description: "Answers with the pid of the door being replaced, then replaces it. The replacement is a new generation with its own control token: the caller reopens its client from the state root once the door's supervisor pid differs from the one returned.", tags: [FRONTDOOR_API_TAG] })).output(FrontDoorRestartOutputSchema).handler(({ context }) => {
12824
+ context.afterResponse(deps.restartDoor);
12825
+ return { action: "restarting", previousPid: deps.doorPid };
12826
+ })
12827
+ },
12828
+ update: {
12829
+ check: authed.meta(openapi4({ method: "GET", path: "/rest/update/check", summary: "Check whether a newer release exists", tags: [UPDATE_API_TAG] })).output(UpdateCheckOutputSchema).handler(async () => {
12830
+ try {
12831
+ return await deps.checkForUpdate();
12832
+ } catch (error) {
12833
+ if (error instanceof UpdateChannelError) {
12834
+ throw new ORPCError3("PRECONDITION_FAILED", { message: error.message });
12835
+ }
12836
+ if (error instanceof UpdateConflictError) {
12837
+ throw new ORPCError3("CONFLICT", { message: error.message });
12838
+ }
12839
+ if (error instanceof UpdateDownloadError) {
12840
+ throw new ORPCError3("BAD_GATEWAY", { message: error.message });
12841
+ }
12842
+ throw error;
12843
+ }
12844
+ })
12845
+ }
12846
+ };
12847
+ }
12848
+
12849
+ // src/frontdoor/launchApi.ts
12850
+ init_cliError();
12851
+ import { ORPCError as ORPCError4 } from "@orpc/client";
12852
+ import { openapi as openapi5 } from "@orpc/openapi";
12853
+
12854
+ // src/frontdoor/launchSchemas.ts
12855
+ import path30 from "node:path";
12856
+ import { z as z21 } from "zod";
12857
+ init_claudeVersion();
12858
+ init_identity();
12859
+ var LaunchResolveInputSchema = z21.strictObject({
12860
+ path: z21.string().min(1),
12861
+ /** `@name`, launch flags, then the arguments for `claude`; empty for a bare launch. */
12862
+ argv: z21.readonly(z21.array(z21.string())).optional(),
12863
+ /** The launch's inherited environment. Absent means an empty one: the door's own environment is never a substitute for the caller's, so a caller that wants `AGENT_SHIM_*` switches or a `CLAUDE_CONFIG_DIR` considered names them here. Values are read, never reported. */
12864
+ env: z21.record(z21.string(), z21.string()).optional()
12865
+ }).refine((input) => path30.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
12866
+ var LaunchPoolDecisionSchema = z21.strictObject({
12867
+ name: z21.string(),
12868
+ reasons: z21.readonly(z21.array(z21.string())),
12869
+ movedOff: z21.strictObject({ identity: z21.string(), reason: z21.string() }).optional()
12870
+ });
12871
+ var LaunchDecisionSchema = z21.strictObject({
12872
+ identity: z21.string().optional(),
12873
+ identitySource: z21.enum(IDENTITY_DECISION_SOURCES),
12874
+ pool: LaunchPoolDecisionSchema.optional(),
12875
+ configDirEscapeHatch: z21.boolean(),
12876
+ configDir: z21.string().optional(),
12877
+ configProfile: z21.string().optional(),
12878
+ configProfileSource: z21.enum(CONFIG_PROFILE_DECISION_SOURCES),
12879
+ provider: z21.string().optional()
12880
+ });
12881
+ var LaunchFlagsSchema = z21.strictObject({
12882
+ skipPermissions: z21.boolean(),
12883
+ remoteControl: z21.boolean(),
12884
+ headroom: z21.boolean(),
12885
+ trackUsage: z21.boolean()
12886
+ });
12887
+ var LaunchResolveOutputSchema = z21.strictObject({
12888
+ decision: LaunchDecisionSchema,
12889
+ flags: LaunchFlagsSchema,
12890
+ claudeVersion: z21.strictObject({ version: z21.string(), source: z21.enum(CLAUDE_VERSION_SOURCES) }).optional(),
12891
+ /** The real `claude` binary the launch would spawn, on the door's host. */
12892
+ bin: z21.string(),
12893
+ /** The arguments the launch would pass it: the tool's own flags, then `CLAUDE_EXTRA_FLAGS`, then the caller's own. */
12894
+ args: z21.readonly(z21.array(z21.string())),
12895
+ /** The credential the launch would authenticate with, by target and source kinds. Absent when none applies. */
12896
+ credential: z21.strictObject({ subject: z21.enum(["provider", "identity"]), name: z21.string(), summary: CredentialSummarySchema }).optional(),
12897
+ routing: z21.strictObject({ frontDoor: z21.boolean(), headroom: z21.boolean() }),
12898
+ /** The names of the environment variables the launch would set or unset, sorted. Values are not reported. */
12899
+ environment: z21.readonly(z21.array(z21.string())),
12900
+ warnings: z21.readonly(z21.array(z21.string()))
12901
+ });
12902
+
12903
+ // src/frontdoor/launchApi.ts
12904
+ var LAUNCH_API_TAG = "launch";
12905
+ function createLaunchApiRouter(deps) {
12906
+ const authed = doorApiAuth(deps.expectedToken);
12907
+ return {
12908
+ launch: {
12909
+ resolve: authed.meta(openapi5({ method: "POST", path: "/rest/launch/resolve", summary: "Resolve what a launch from one directory would do, without performing it", tags: [LAUNCH_API_TAG] })).input(LaunchResolveInputSchema).output(LaunchResolveOutputSchema).handler(({ input }) => {
12910
+ try {
12911
+ const { resolution, warnings } = deps.resolveLaunch({ path: input.path, argv: input.argv ?? [], env: input.env ?? {} });
12912
+ return { ...resolution, warnings };
12913
+ } catch (error) {
12914
+ if (error instanceof CliError) {
12915
+ throw new ORPCError4("BAD_REQUEST", { message: error.message });
12916
+ }
12917
+ throw error;
12918
+ }
12919
+ })
12920
+ }
12921
+ };
12922
+ }
12923
+
12637
12924
  // src/frontdoor/controlApi.ts
12638
12925
  var USAGE_API_TAG = "usage";
12639
- var FRONTDOOR_API_TAG = "frontdoor";
12926
+ var FRONTDOOR_API_TAG2 = "frontdoor";
12640
12927
  var CHECK_API_TAG = "check";
12641
12928
  var DOCTOR_API_TAG = "doctor";
12642
12929
  var POOL_API_TAG = "pool";
@@ -12644,11 +12931,11 @@ function createControlApiRouter(deps) {
12644
12931
  const authed = doorApiAuth(deps.expectedToken);
12645
12932
  return {
12646
12933
  usage: {
12647
- list: authed.meta(openapi3({ method: "GET", path: "/rest/usage/snapshots", summary: "List every identity's usage snapshot", tags: [USAGE_API_TAG] })).output(UsageListOutputSchema).handler(() => ({ snapshots: deps.usageSnapshots() })),
12648
- effectiveWindow: authed.meta(openapi3({ method: "GET", path: "/rest/usage/windows", summary: "Read one identity's effective quota windows", tags: [USAGE_API_TAG] })).input(UsageWindowsInputSchema).output(UsageWindowsOutputSchema).handler(({ input }) => {
12934
+ list: authed.meta(openapi6({ method: "GET", path: "/rest/usage/snapshots", summary: "List every identity's usage snapshot", tags: [USAGE_API_TAG] })).output(UsageListOutputSchema).handler(() => ({ snapshots: deps.usageSnapshots() })),
12935
+ effectiveWindow: authed.meta(openapi6({ method: "GET", path: "/rest/usage/windows", summary: "Read one identity's effective quota windows", tags: [USAGE_API_TAG] })).input(UsageWindowsInputSchema).output(UsageWindowsOutputSchema).handler(({ input }) => {
12649
12936
  const snapshot = deps.usageSnapshotOf(input.identity);
12650
12937
  if (snapshot === void 0) {
12651
- throw new ORPCError3("NOT_FOUND", { message: `identity ${input.identity} has no usage snapshot yet, so no quota window has been observed for it` });
12938
+ throw new ORPCError5("NOT_FOUND", { message: `identity ${input.identity} has no usage snapshot yet, so no quota window has been observed for it` });
12652
12939
  }
12653
12940
  const provider = input.provider ?? ANTHROPIC_PROVIDER;
12654
12941
  const rateLimit = snapshot.providers[provider]?.rateLimit;
@@ -12662,34 +12949,34 @@ function createControlApiRouter(deps) {
12662
12949
  ...unified?.sevenDay === void 0 ? {} : { sevenDay: effectiveWindow(unified.sevenDay, now) }
12663
12950
  };
12664
12951
  }),
12665
- live: authed.meta(openapi3({ method: "GET", path: "/rest/usage/live", summary: "Read the live rate-limit observations the event backbone files", tags: [USAGE_API_TAG] })).input(RcSessionQuerySchema).output(UsageLiveOutputSchema).handler(({ input }) => {
12952
+ live: authed.meta(openapi6({ method: "GET", path: "/rest/usage/live", summary: "Read the live rate-limit observations the event backbone files", tags: [USAGE_API_TAG] })).input(RcSessionQuerySchema).output(UsageLiveOutputSchema).handler(({ input }) => {
12666
12953
  const sessions = deps.liveRateLimits(input.session);
12667
12954
  if (input.session !== void 0 && sessions.length === 0) {
12668
12955
  if (deps.list().some((session) => session.id === input.session)) {
12669
- throw new ORPCError3("NOT_FOUND", { message: `session ${input.session} has filed no rate_limit_event on its stream yet: the worker emits one only once a turn has completed, so retry after this session's next turn` });
12956
+ throw new ORPCError5("NOT_FOUND", { message: `session ${input.session} has filed no rate_limit_event on its stream yet: the worker emits one only once a turn has completed, so retry after this session's next turn` });
12670
12957
  }
12671
- throw new ORPCError3("NOT_FOUND", { message: rcSessionNotObservedMessage(input.session) });
12958
+ throw new ORPCError5("NOT_FOUND", { message: rcSessionNotObservedMessage(input.session) });
12672
12959
  }
12673
12960
  return { latest: deps.latestRateLimit(), sessions };
12674
12961
  })
12675
12962
  },
12676
12963
  frontdoor: {
12677
- status: authed.meta(openapi3({ method: "GET", path: "/rest/frontdoor/status", summary: "Read the front door's status", tags: [FRONTDOOR_API_TAG] })).output(FrontDoorStatusOutputSchema).handler(() => deps.frontDoorStatus()),
12678
- sessions: authed.meta(openapi3({ method: "GET", path: "/rest/frontdoor/sessions", summary: "Read the front door's session registry", tags: [FRONTDOOR_API_TAG] })).output(FrontDoorSessionsOutputSchema).handler(() => ({ sessions: deps.frontDoorStatus().sessions }))
12964
+ status: authed.meta(openapi6({ method: "GET", path: "/rest/frontdoor/status", summary: "Read the front door's status", tags: [FRONTDOOR_API_TAG2] })).output(FrontDoorStatusOutputSchema).handler(() => deps.frontDoorStatus()),
12965
+ sessions: authed.meta(openapi6({ method: "GET", path: "/rest/frontdoor/sessions", summary: "Read the front door's session registry", tags: [FRONTDOOR_API_TAG2] })).output(FrontDoorSessionsOutputSchema).handler(() => ({ sessions: deps.frontDoorStatus().sessions }))
12679
12966
  },
12680
12967
  check: {
12681
12968
  // The report's own JSON shape is the contract (the same one `check --json` prints and `checkReportSchema.ts` defines), so the procedure returns exactly that conversion.
12682
- run: authed.meta(openapi3({ method: "GET", path: "/rest/check", summary: "Run the check report for one directory", tags: [CHECK_API_TAG] })).input(CheckRunInputSchema).output(CheckReportJsonSchema).handler(({ input }) => checkReportToJson(deps.checkReport(input.path, input.identity)))
12969
+ run: authed.meta(openapi6({ method: "GET", path: "/rest/check", summary: "Run the check report for one directory", tags: [CHECK_API_TAG] })).input(CheckRunInputSchema).output(CheckReportJsonSchema).handler(({ input }) => checkReportToJson(deps.checkReport(input.path, input.identity)))
12683
12970
  },
12684
12971
  doctor: {
12685
- run: authed.meta(openapi3({ method: "GET", path: "/rest/doctor", summary: "Run the doctor report", tags: [DOCTOR_API_TAG] })).output(DoctorRunOutputSchema).handler(() => deps.doctorReport())
12972
+ run: authed.meta(openapi6({ method: "GET", path: "/rest/doctor", summary: "Run the doctor report", tags: [DOCTOR_API_TAG] })).output(DoctorRunOutputSchema).handler(() => deps.doctorReport())
12686
12973
  },
12687
12974
  pool: {
12688
- pick: authed.meta(openapi3({ method: "GET", path: "/rest/pool/pick", summary: "Rank one pool exactly as a launch from a directory would right now", tags: [POOL_API_TAG] })).input(PoolPickInputSchema).output(PoolPickReportSchema).handler(({ input }) => {
12975
+ pick: authed.meta(openapi6({ method: "GET", path: "/rest/pool/pick", summary: "Rank one pool exactly as a launch from a directory would right now", tags: [POOL_API_TAG] })).input(PoolPickInputSchema).output(PoolPickReportSchema).handler(({ input }) => {
12689
12976
  const report = deps.poolPick(input.pool, input.path);
12690
12977
  if (report === void 0) {
12691
12978
  const live = deps.poolNames();
12692
- throw new ORPCError3("NOT_FOUND", {
12979
+ throw new ORPCError5("NOT_FOUND", {
12693
12980
  message: live.length === 0 ? `no pools are configured, so none is named ${input.pool}` : `no pool is named ${input.pool}; the live pools are ${live.map((name) => `"${name}"`).join(", ")}`
12694
12981
  });
12695
12982
  }
@@ -12699,7 +12986,9 @@ function createControlApiRouter(deps) {
12699
12986
  };
12700
12987
  }
12701
12988
  function createDoorApiRouter(deps) {
12702
- return { ...createRcApiRouter(deps), ...createControlApiRouter(deps), ...createEventsApiRouter(deps) };
12989
+ const control = createControlApiRouter(deps);
12990
+ const lifecycle = createLifecycleApiRouter(deps);
12991
+ return { ...createRcApiRouter(deps), ...control, ...lifecycle, ...createCodexApiRouter(deps), ...createLaunchApiRouter(deps), ...createEventsApiRouter(deps), frontdoor: { ...control.frontdoor, ...lifecycle.frontdoor } };
12703
12992
  }
12704
12993
  function createDoorApiNodeHandler(deps) {
12705
12994
  return doorApiNodeHandlerOf(createDoorApiRouter(deps), deps.expectedToken);
@@ -14660,7 +14949,7 @@ data: ${JSON.stringify(envelope)}
14660
14949
 
14661
14950
  // src/frontdoor/rcSelfHostMint.ts
14662
14951
  init_account();
14663
- import path30 from "node:path";
14952
+ import path31 from "node:path";
14664
14953
  var CREDENTIALS_FILE = ".credentials.json";
14665
14954
  var CLAUDE_JSON2 = ".claude.json";
14666
14955
  var RC_SELF_HOST_RECORD_DIR = "rc-selfhost";
@@ -14684,7 +14973,7 @@ function readJsonObject(fs12, file) {
14684
14973
  return isRecord11(parsed) ? parsed : void 0;
14685
14974
  }
14686
14975
  function readRcSelfHostRecord(fs12, frontdoorDir) {
14687
- const parsed = readJsonObject(fs12, path30.join(frontdoorDir, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE));
14976
+ const parsed = readJsonObject(fs12, path31.join(frontdoorDir, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE));
14688
14977
  if (parsed === void 0) {
14689
14978
  return void 0;
14690
14979
  }
@@ -14698,11 +14987,11 @@ function mintRcSelfHostCredential(deps) {
14698
14987
  if (!isIdentityName(deps.identity)) {
14699
14988
  throw new Error(`"${deps.identity}" is not a valid identity name.`);
14700
14989
  }
14701
- const identityDir = path30.join(deps.identitiesDir, deps.identity);
14702
- const credentialsFile = path30.join(identityDir, CREDENTIALS_FILE);
14703
- const claudeJsonFile = path30.join(identityDir, CLAUDE_JSON2);
14704
- const recordDir = path30.join(deps.frontdoorDir, RC_SELF_HOST_RECORD_DIR);
14705
- const recordFile = path30.join(recordDir, RC_SELF_HOST_RECORD_FILE);
14990
+ const identityDir = path31.join(deps.identitiesDir, deps.identity);
14991
+ const credentialsFile = path31.join(identityDir, CREDENTIALS_FILE);
14992
+ const claudeJsonFile = path31.join(identityDir, CLAUDE_JSON2);
14993
+ const recordDir = path31.join(deps.frontdoorDir, RC_SELF_HOST_RECORD_DIR);
14994
+ const recordFile = path31.join(recordDir, RC_SELF_HOST_RECORD_FILE);
14706
14995
  const previousRecord = readRcSelfHostRecord(deps.fs, deps.frontdoorDir);
14707
14996
  const existingCredentials = readJsonObject(deps.fs, credentialsFile);
14708
14997
  const existingOauth = isRecord11(existingCredentials?.claudeAiOauth) ? existingCredentials.claudeAiOauth : void 0;
@@ -14718,7 +15007,7 @@ function mintRcSelfHostCredential(deps) {
14718
15007
  const organizationUuid = deps.newUuid();
14719
15008
  const accountUuid = deps.newUuid();
14720
15009
  const mintedAt = new Date(deps.now()).toISOString();
14721
- deps.fs.mkdirPrivate(path30.dirname(credentialsFile));
15010
+ deps.fs.mkdirPrivate(path31.dirname(credentialsFile));
14722
15011
  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)}
14723
15012
  `);
14724
15013
  const claudeJson = readJsonObject(deps.fs, claudeJsonFile) ?? {};
@@ -14972,6 +15261,9 @@ export {
14972
15261
  CheckReportJsonSchema,
14973
15262
  CheckRunInputSchema,
14974
15263
  CliError,
15264
+ CodexLogoutOutputSchema,
15265
+ CodexSignInSchema,
15266
+ CodexStatusOutputSchema,
14975
15267
  ConfigProfileSchema,
14976
15268
  CredentialCacheSchema,
14977
15269
  CredentialSchema,
@@ -14996,6 +15288,7 @@ export {
14996
15288
  FARM_MANIFEST_FILENAME,
14997
15289
  FrontDoorControlMaterialError,
14998
15290
  FrontDoorNotServingError,
15291
+ FrontDoorRestartOutputSchema,
14999
15292
  FrontDoorSessionStatusSchema,
15000
15293
  FrontDoorSessionsOutputSchema,
15001
15294
  FrontDoorStartError,
@@ -15013,6 +15306,8 @@ export {
15013
15306
  LAUNCH_EVENT_SOURCE,
15014
15307
  LaunchLifecycleEventSchema,
15015
15308
  LaunchRefusedError,
15309
+ LaunchResolveInputSchema,
15310
+ LaunchResolveOutputSchema,
15016
15311
  LegacyProviderFileError,
15017
15312
  OWN_CLI_FILE_NAME,
15018
15313
  PROMPT_CACHE_TTL_MS,
@@ -15059,6 +15354,7 @@ export {
15059
15354
  RcStreamEnvelopeSchema,
15060
15355
  RcStreamEventSchema,
15061
15356
  USAGE_EVENT_SOURCE,
15357
+ UpdateCheckOutputSchema,
15062
15358
  UsageError,
15063
15359
  UsageListOutputSchema,
15064
15360
  UsageLiveOutputSchema,
@@ -15101,14 +15397,17 @@ export {
15101
15397
  collectDoctorReport,
15102
15398
  collectFrontDoorStatus,
15103
15399
  collectPoolPick,
15400
+ createCodexApiRouter,
15104
15401
  createControlApiRouter,
15105
15402
  createDoorApiNodeHandler,
15106
15403
  createDoorApiRouter,
15107
15404
  createDoorEventHub,
15108
15405
  createDoorHealthPublisher,
15109
15406
  createEventsApiRouter,
15407
+ createLaunchApiRouter,
15110
15408
  createLaunchEventPublisher,
15111
15409
  createLeafCache,
15410
+ createLifecycleApiRouter,
15112
15411
  createProfile,
15113
15412
  createQuotaExpiringPublisher,
15114
15413
  createRcApiNodeHandler,
@@ -15216,7 +15515,9 @@ export {
15216
15515
  requirePool,
15217
15516
  resolveAgentShimHome,
15218
15517
  resolveClaudeHome,
15518
+ resolveClaudeLaunch,
15219
15519
  resolveDecisions,
15520
+ resolveLaunch,
15220
15521
  resolveLaunchSelection,
15221
15522
  resolveLayoutPaths,
15222
15523
  resolveSupervisorConfig,