claude-use 9.5.0 → 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.cjs CHANGED
@@ -2649,7 +2649,7 @@ var init_package = __esm({
2649
2649
  "package.json"() {
2650
2650
  package_default = {
2651
2651
  name: "claude-use",
2652
- version: "9.5.0",
2652
+ version: "9.6.0",
2653
2653
  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.",
2654
2654
  license: "MIT",
2655
2655
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -2700,9 +2700,10 @@ var init_package = __esm({
2700
2700
  dependencies: {
2701
2701
  "@anthropic-ai/claude-agent-sdk": "0.3.292",
2702
2702
  "@clack/prompts": "^1.8.0",
2703
- "@orpc/client": "1.15.4",
2704
- "@orpc/openapi": "1.15.4",
2705
- "@orpc/server": "1.15.4",
2703
+ "@modelcontextprotocol/sdk": "1.32.0",
2704
+ "@orpc/client": "2.0.0-beta.41",
2705
+ "@orpc/openapi": "2.0.0-beta.41",
2706
+ "@orpc/server": "2.0.0-beta.41",
2706
2707
  commander: "^15.0.0",
2707
2708
  cosmiconfig: "^10.0.1",
2708
2709
  picomatch: "^4.0.7",
@@ -5767,7 +5768,7 @@ function cascadeProviderName(cascade) {
5767
5768
  }
5768
5769
  return name;
5769
5770
  }
5770
- function resolveProvider(params) {
5771
+ function selectProvider(params) {
5771
5772
  const cliName = params.cliProvider !== void 0 && params.cliProvider !== "" ? params.cliProvider : void 0;
5772
5773
  const name = cliName ?? (params.cascade === void 0 ? void 0 : cascadeProviderName(params.cascade));
5773
5774
  if (name === void 0) {
@@ -5782,6 +5783,14 @@ function resolveProvider(params) {
5782
5783
  message: `agent-shim: no provider named "${name}". ` + (known.length > 0 ? `Known providers: ${known.join(", ")}.` : "No providers are defined yet; run `agent-shim provider add`.")
5783
5784
  };
5784
5785
  }
5786
+ return { ok: true, provider: { name, definition } };
5787
+ }
5788
+ function resolveProvider(params) {
5789
+ const selection = selectProvider(params);
5790
+ if (selection?.ok !== true) {
5791
+ return selection;
5792
+ }
5793
+ const { name, definition } = selection.provider;
5785
5794
  if (params.credentials === void 0) {
5786
5795
  return { ok: false, status: 1, message: `agent-shim: provider ${name} needs its credential resolved, but this launcher has no credential port wired` };
5787
5796
  }
@@ -6064,6 +6073,51 @@ var init_claudeShim = __esm({
6064
6073
  }
6065
6074
  });
6066
6075
 
6076
+ // src/update/update.ts
6077
+ function compareVersions3(left, right) {
6078
+ const parse = (version) => {
6079
+ const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(version);
6080
+ if (match === null) {
6081
+ throw new Error(`not a plain release version: ${version}`);
6082
+ }
6083
+ return [Number(match[1]), Number(match[2]), Number(match[3])];
6084
+ };
6085
+ const leftParts = parse(left);
6086
+ const rightParts = parse(right);
6087
+ return leftParts.map((part, index) => part - (rightParts[index] ?? 0)).find((difference) => difference !== 0) ?? 0;
6088
+ }
6089
+ function releaseTagFromUrl(url) {
6090
+ const segment = url.split("?")[0]?.split("/").at(-1);
6091
+ const candidate = segment?.startsWith("v") === true ? segment.slice(1) : void 0;
6092
+ return candidate !== void 0 && /^\d+\.\d+\.\d+$/.test(candidate) ? candidate : void 0;
6093
+ }
6094
+ var LATEST_RELEASE_URL, UpdateChannelError, UpdateConflictError, UpdateDownloadError;
6095
+ var init_update = __esm({
6096
+ "src/update/update.ts"() {
6097
+ "use strict";
6098
+ init_cliError();
6099
+ LATEST_RELEASE_URL = "https://github.com/ExaDev/agent-shim/releases/latest";
6100
+ UpdateChannelError = class extends CliError {
6101
+ constructor(message) {
6102
+ super(message);
6103
+ this.name = "UpdateChannelError";
6104
+ }
6105
+ };
6106
+ UpdateConflictError = class extends CliError {
6107
+ constructor(message) {
6108
+ super(message);
6109
+ this.name = "UpdateConflictError";
6110
+ }
6111
+ };
6112
+ UpdateDownloadError = class extends CliError {
6113
+ constructor(message) {
6114
+ super(message);
6115
+ this.name = "UpdateDownloadError";
6116
+ }
6117
+ };
6118
+ }
6119
+ });
6120
+
6067
6121
  // src/frontdoor/ensure.ts
6068
6122
  function ensureFrontDoor(params) {
6069
6123
  const { paths, ports } = params;
@@ -6499,7 +6553,7 @@ function buildEnv(params) {
6499
6553
  const parentCustomHeaders = params.baseEnv.ANTHROPIC_CUSTOM_HEADERS;
6500
6554
  let providerCustomHeaders;
6501
6555
  if (!params.configDirEscapeHatch && params.resolvedIdentityName !== void 0) {
6502
- env.CLAUDE_CONFIG_DIR = import_node_path31.default.join(params.identitiesDir, params.resolvedIdentityName);
6556
+ env.CLAUDE_CONFIG_DIR = import_node_path32.default.join(params.identitiesDir, params.resolvedIdentityName);
6503
6557
  }
6504
6558
  if (params.provider !== void 0) {
6505
6559
  const providerEnv = params.provider.definition.env ?? {};
@@ -6543,11 +6597,11 @@ function buildEnv(params) {
6543
6597
  }
6544
6598
  return env;
6545
6599
  }
6546
- var import_node_path31, LOOPBACK_HOSTS;
6600
+ var import_node_path32, LOOPBACK_HOSTS;
6547
6601
  var init_flags = __esm({
6548
6602
  "src/launcher/flags.ts"() {
6549
6603
  "use strict";
6550
- import_node_path31 = __toESM(require("node:path"), 1);
6604
+ import_node_path32 = __toESM(require("node:path"), 1);
6551
6605
  init_envBool();
6552
6606
  init_credential();
6553
6607
  init_headers();
@@ -6623,7 +6677,9 @@ function resolvePoolLaunch(params) {
6623
6677
  }
6624
6678
  const { pick, earliestReturn, movedOff } = graph.ranking;
6625
6679
  if (pick !== void 0) {
6626
- recordStickyPick(params.usageFs, params.paths.usagePicksFile, params.cwd, pick.identity, nowMs);
6680
+ if (params.recordPick) {
6681
+ recordStickyPick(params.usageFs, params.paths.usagePicksFile, params.cwd, pick.identity, nowMs);
6682
+ }
6627
6683
  const move = movedOff === void 0 ? "" : `moved off ${movedOff.identity} (${movedOff.reason}); `;
6628
6684
  return {
6629
6685
  ok: true,
@@ -6689,33 +6745,6 @@ var init_spawn = __esm({
6689
6745
  }
6690
6746
  });
6691
6747
 
6692
- // src/update/update.ts
6693
- function compareVersions3(left, right) {
6694
- const parse = (version) => {
6695
- const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(version);
6696
- if (match === null) {
6697
- throw new Error(`not a plain release version: ${version}`);
6698
- }
6699
- return [Number(match[1]), Number(match[2]), Number(match[3])];
6700
- };
6701
- const leftParts = parse(left);
6702
- const rightParts = parse(right);
6703
- return leftParts.map((part, index) => part - (rightParts[index] ?? 0)).find((difference) => difference !== 0) ?? 0;
6704
- }
6705
- function releaseTagFromUrl(url) {
6706
- const segment = url.split("?")[0]?.split("/").at(-1);
6707
- const candidate = segment?.startsWith("v") === true ? segment.slice(1) : void 0;
6708
- return candidate !== void 0 && /^\d+\.\d+\.\d+$/.test(candidate) ? candidate : void 0;
6709
- }
6710
- var LATEST_RELEASE_URL;
6711
- var init_update = __esm({
6712
- "src/update/update.ts"() {
6713
- "use strict";
6714
- init_cliError();
6715
- LATEST_RELEASE_URL = "https://github.com/ExaDev/agent-shim/releases/latest";
6716
- }
6717
- });
6718
-
6719
6748
  // src/update/launchHook.ts
6720
6749
  function resolveUpdateMode(globalConfig) {
6721
6750
  return globalConfig?.update?.mode ?? "off";
@@ -6793,7 +6822,7 @@ function resolveIdentityCredential(identity, credential, env, port) {
6793
6822
  const resolution = resolveCredential({ credential, env, port, subject: `identity ${identity}` });
6794
6823
  return resolution.ok ? resolution : { ok: false, status: CREDENTIAL_UNAVAILABLE_EXIT, message: resolution.message };
6795
6824
  }
6796
- function pickFromPool(decided, params, parsedArgv) {
6825
+ function pickFromPool(decided, params, parsedArgv, readOnly) {
6797
6826
  const { paths, fs: fs12, proc, log } = params;
6798
6827
  if (decided.pool === void 0) {
6799
6828
  return { identityDecision: decided };
@@ -6814,7 +6843,9 @@ function pickFromPool(decided, params, parsedArgv) {
6814
6843
  now: farmRuntime.now,
6815
6844
  sleep: farmRuntime.lock.sleep,
6816
6845
  passthrough: parsedArgv.rest,
6817
- wait: parsedArgv.wait === true,
6846
+ // 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.
6847
+ wait: !readOnly && parsedArgv.wait === true,
6848
+ recordPick: !readOnly,
6818
6849
  log
6819
6850
  });
6820
6851
  if (!resolution.ok) {
@@ -6827,7 +6858,7 @@ function pickFromPool(decided, params, parsedArgv) {
6827
6858
  poolPick: { name: decided.pool, reasons: resolution.reasons, ...resolution.movedOff === void 0 ? {} : { movedOff: resolution.movedOff } }
6828
6859
  };
6829
6860
  }
6830
- function prepareLaunch(params) {
6861
+ function decideLaunch(params, readOnly) {
6831
6862
  const { paths, fs: fs12, proc, log } = params;
6832
6863
  const { env, argv } = proc;
6833
6864
  const parsedArgv = parseLauncherArgv(argv);
@@ -6851,10 +6882,10 @@ function prepareLaunch(params) {
6851
6882
  return trimmed === "" ? void 0 : trimmed;
6852
6883
  }
6853
6884
  });
6854
- const { identityDecision, poolExplanation, poolPick } = pickFromPool(decidedIdentity, params, parsedArgv);
6885
+ const { identityDecision, poolExplanation, poolPick } = pickFromPool(decidedIdentity, params, parsedArgv, readOnly);
6855
6886
  const farmIdentity = configDirEscapeHatchApplies ? void 0 : identityDecision.name;
6856
6887
  const farm = farmIdentity === void 0 ? void 0 : params.farm;
6857
- if (farm !== void 0 && farmIdentity !== void 0) {
6888
+ if (!readOnly && farm !== void 0 && farmIdentity !== void 0) {
6858
6889
  let recovery;
6859
6890
  try {
6860
6891
  recovery = recoverFarm({
@@ -6893,33 +6924,44 @@ function prepareLaunch(params) {
6893
6924
  identityDefaultConfigProfile: loadedIdentity?.config.defaultConfigProfile,
6894
6925
  globalDefaultConfigProfile: params.globalDefaultConfigProfile
6895
6926
  });
6896
- if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(import_node_path32.default.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
6927
+ if (configProfileDecision.name !== void 0 && params.allowMissingConfigProfile !== true && fs12.readConfigFile(import_node_path33.default.join(paths.configProfilesDir, `${configProfileDecision.name}.json`)) === void 0) {
6897
6928
  log.error(
6898
6929
  `agent-shim: no configuration profile named "${configProfileDecision.name}" (selected via ${configProfileDecision.source}). Run \`agent-shim profile add ${configProfileDecision.name}\` first.`
6899
6930
  );
6900
6931
  proc.exit(1);
6901
6932
  }
6902
6933
  const farmContext = farm !== void 0 && farmIdentity !== void 0 ? { farm, identity: farmIdentity, cascade: farm.loadCascade(configProfileDecision.name, cliOverride) } : void 0;
6903
- const provider = parsedArgv.provider === false ? void 0 : resolveProvider({
6934
+ const providerParams = {
6904
6935
  paths,
6905
6936
  port: fs12,
6906
- env,
6907
- ...params.credentials === void 0 ? {} : { credentials: params.credentials },
6908
- ...parsedArgv.provider === void 0 ? {} : { cliProvider: parsedArgv.provider },
6937
+ ...parsedArgv.provider === void 0 || parsedArgv.provider === false ? {} : { cliProvider: parsedArgv.provider },
6909
6938
  ...farmContext === void 0 ? {} : { cascade: farmContext.cascade }
6910
- });
6911
- if (provider !== void 0 && !provider.ok) {
6912
- log.error(provider.message);
6913
- proc.exit(provider.status);
6914
- }
6915
- const resolvedProvider = provider?.ok === true ? provider.provider : void 0;
6916
- for (const warning of provider?.ok === true ? provider.warnings : []) {
6917
- log.warn(warning);
6939
+ };
6940
+ let selectedProvider;
6941
+ let resolvedProvider;
6942
+ if (parsedArgv.provider !== false && readOnly) {
6943
+ const selection = selectProvider(providerParams);
6944
+ if (selection !== void 0 && !selection.ok) {
6945
+ log.error(selection.message);
6946
+ proc.exit(selection.status);
6947
+ }
6948
+ selectedProvider = selection?.ok === true ? selection.provider : void 0;
6949
+ } else if (parsedArgv.provider !== false) {
6950
+ const provider = resolveProvider({ ...providerParams, env, ...params.credentials === void 0 ? {} : { credentials: params.credentials } });
6951
+ if (provider !== void 0 && !provider.ok) {
6952
+ log.error(provider.message);
6953
+ proc.exit(provider.status);
6954
+ }
6955
+ resolvedProvider = provider?.ok === true ? provider.provider : void 0;
6956
+ selectedProvider = resolvedProvider;
6957
+ for (const warning of provider?.ok === true ? provider.warnings : []) {
6958
+ log.warn(warning);
6959
+ }
6918
6960
  }
6919
6961
  if (farm !== void 0 && farmIdentity !== void 0) {
6920
6962
  try {
6921
6963
  const snapshot = readUsageSnapshot(farm.fs, paths.usageSnapshotsDir, farmIdentity);
6922
- for (const warning of quotaWarnings(snapshot, resolvedProvider?.name ?? ANTHROPIC_PROVIDER, farm.now())) {
6964
+ for (const warning of quotaWarnings(snapshot, selectedProvider?.name ?? ANTHROPIC_PROVIDER, farm.now())) {
6923
6965
  log.warn(warning);
6924
6966
  }
6925
6967
  } catch (error) {
@@ -6929,8 +6971,8 @@ function prepareLaunch(params) {
6929
6971
  log.warn(`agent-shim: ${error.message}`);
6930
6972
  }
6931
6973
  }
6932
- const identityCredentialBlock = loadedIdentity?.config.credential;
6933
- const identityResolution = resolvedProvider === void 0 && farmIdentity !== void 0 && identityCredentialBlock !== void 0 ? resolveIdentityCredential(farmIdentity, identityCredentialBlock, env, params.credentials) : void 0;
6974
+ const identityCredentialBlock = selectedProvider === void 0 && farmIdentity !== void 0 ? loadedIdentity?.config.credential : void 0;
6975
+ const identityResolution = !readOnly && identityCredentialBlock !== void 0 && farmIdentity !== void 0 ? resolveIdentityCredential(farmIdentity, identityCredentialBlock, env, params.credentials) : void 0;
6934
6976
  if (identityResolution !== void 0 && !identityResolution.ok) {
6935
6977
  log.error(identityResolution.message);
6936
6978
  proc.exit(identityResolution.status);
@@ -6944,25 +6986,97 @@ function prepareLaunch(params) {
6944
6986
  allowAmbientCredential: loadedIdentity?.config.allowAmbientCredential ?? false,
6945
6987
  allowAmbientCredentialOverride: parseEnvBool("AGENT_SHIM_ALLOW_AMBIENT_CREDENTIAL", env.AGENT_SHIM_ALLOW_AMBIENT_CREDENTIAL) === true,
6946
6988
  identityName: identityDecision.name,
6947
- providerSelected: resolvedProvider !== void 0,
6989
+ providerSelected: selectedProvider !== void 0,
6948
6990
  ...identityCredential === void 0 ? {} : { injectedCredential: { variable: CREDENTIAL_TARGET_VARS[identityCredential.target], token: identityCredential.token } }
6949
6991
  });
6950
6992
  if (!guardResult.ok) {
6951
- log.error(guardResult.message);
6952
- proc.exit(1);
6993
+ if (readOnly && identityCredentialBlock !== void 0) {
6994
+ log.warn(`${guardResult.message} (not resolved here: the launch proceeds only if that value is the identity's own injected credential)`);
6995
+ } else {
6996
+ log.error(guardResult.message);
6997
+ proc.exit(1);
6998
+ }
6953
6999
  }
7000
+ const launchCascade = farmContext?.cascade ?? (params.farm === void 0 ? void 0 : params.farm.loadCascade(configProfileDecision.name, cliOverride));
7001
+ let cascadeLaunch;
7002
+ if (launchCascade !== void 0 && params.farm !== void 0) {
7003
+ const assembled = assembleCascade(launchCascade);
7004
+ const flattened = flattenLayers(assembled.layers, { home: params.farm.home });
7005
+ cascadeLaunch = flattened.launch;
7006
+ if (readOnly) {
7007
+ for (const diagnostic of [...assembled.diagnostics, ...flattened.diagnostics]) {
7008
+ if (diagnostic.severity !== "info") {
7009
+ log.warn(`agent-shim: ${diagnostic.code}: ${diagnostic.message}`);
7010
+ }
7011
+ }
7012
+ }
7013
+ }
7014
+ const pinnedVersion = resolveClaudeVersion({ env, ...parsedArgv.claudeVersion === void 0 ? {} : { flag: parsedArgv.claudeVersion }, ...cascadeLaunch?.claudeVersion === void 0 ? {} : { cascade: cascadeLaunch.claudeVersion } });
7015
+ const discovered = params.resolveClaudeBinary(pinnedVersion === void 0 ? void 0 : { version: pinnedVersion.version });
7016
+ const flags = resolveLaunchFlags({
7017
+ env,
7018
+ // A pool pick reads the usage the front door records, so a pool launch records its own unless something says otherwise.
7019
+ ...poolExplanation === void 0 ? {} : { trackUsageDefault: true },
7020
+ ...cascadeLaunch === void 0 ? {} : { cascade: cascadeLaunch },
7021
+ flags: {
7022
+ ...parsedArgv.skipPermissions === void 0 ? {} : { skipPermissions: parsedArgv.skipPermissions },
7023
+ ...parsedArgv.remoteControl === void 0 ? {} : { remoteControl: parsedArgv.remoteControl },
7024
+ ...parsedArgv.headroom === void 0 ? {} : { headroom: parsedArgv.headroom },
7025
+ ...parsedArgv.trackUsage === void 0 ? {} : { trackUsage: parsedArgv.trackUsage }
7026
+ }
7027
+ });
7028
+ const args = buildArgv({
7029
+ toolFlags: buildFlagArgs(flags),
7030
+ extraFlags: splitExtraFlags(env.CLAUDE_EXTRA_FLAGS),
7031
+ passthrough: parsedArgv.rest
7032
+ });
7033
+ const configDir = configDirEscapeHatchApplies || identityDecision.name === void 0 ? env.CLAUDE_CONFIG_DIR : import_node_path33.default.join(paths.identitiesDir, identityDecision.name);
7034
+ const decision = {
7035
+ identitySource: identityDecision.source,
7036
+ configDirEscapeHatch: identityDecision.configDirEscapeHatch,
7037
+ configProfileSource: configProfileDecision.source,
7038
+ ...identityDecision.name === void 0 ? {} : { identity: identityDecision.name },
7039
+ ...poolPick === void 0 ? {} : { pool: poolPick },
7040
+ ...configDir === void 0 || configDir === "" ? {} : { configDir },
7041
+ ...configProfileDecision.name === void 0 ? {} : { configProfile: configProfileDecision.name },
7042
+ ...selectedProvider === void 0 ? {} : { provider: selectedProvider.name }
7043
+ };
7044
+ return {
7045
+ parsedArgv,
7046
+ identityDecision,
7047
+ poolExplanation,
7048
+ poolPick,
7049
+ configDirEscapeHatch: configDirEscapeHatchApplies,
7050
+ farmIdentity,
7051
+ farmContext,
7052
+ configProfileDecision,
7053
+ provider: selectedProvider,
7054
+ resolvedProvider,
7055
+ identityCredentialBlock,
7056
+ identityCredential,
7057
+ pinnedVersion,
7058
+ flags,
7059
+ bin: discovered.path,
7060
+ args,
7061
+ decision
7062
+ };
7063
+ }
7064
+ function prepareLaunch(params) {
7065
+ const { paths, proc, log } = params;
7066
+ const { env } = proc;
7067
+ const decided = decideLaunch(params, false);
7068
+ const { identityDecision, configProfileDecision, resolvedProvider, identityCredential, poolExplanation, flags: resolvedFlags, args: finalArgv, configDirEscapeHatch: configDirEscapeHatchApplies, decision } = decided;
6954
7069
  log.info(
6955
7070
  `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)}`)
6956
7071
  );
6957
7072
  const updateCheck = runLaunchUpdateCheck({
6958
7073
  mode: params.updateMode ?? "off",
6959
- checkPath: import_node_path32.default.join(paths.root, "update.check"),
7074
+ checkPath: import_node_path33.default.join(paths.root, "update.check"),
6960
7075
  currentVersion: package_default.version,
6961
7076
  port: params.update
6962
7077
  });
6963
- let cascadeLaunch;
6964
- if (farmContext !== void 0) {
6965
- const { farm: resyncFarmRuntime, identity: resyncIdentity, cascade } = farmContext;
7078
+ if (decided.farmContext !== void 0) {
7079
+ const { farm: resyncFarmRuntime, identity: resyncIdentity, cascade } = decided.farmContext;
6966
7080
  let result;
6967
7081
  try {
6968
7082
  result = resyncFarm({
@@ -6999,27 +7113,10 @@ function prepareLaunch(params) {
6999
7113
  log.info(
7000
7114
  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}`})`
7001
7115
  );
7002
- cascadeLaunch = result.resolved.flattened.launch;
7003
- } else if (params.farm !== void 0) {
7004
- cascadeLaunch = flattenLayers(assembleCascade(params.farm.loadCascade(configProfileDecision.name, cliOverride)).layers, { home: params.farm.home }).launch;
7005
7116
  }
7006
- const pinnedVersion = resolveClaudeVersion({ env, ...parsedArgv.claudeVersion === void 0 ? {} : { flag: parsedArgv.claudeVersion }, ...cascadeLaunch?.claudeVersion === void 0 ? {} : { cascade: cascadeLaunch.claudeVersion } });
7007
- const discovered = params.resolveClaudeBinary(pinnedVersion === void 0 ? void 0 : { version: pinnedVersion.version });
7008
- if (pinnedVersion !== void 0) {
7009
- log.info(`agent-shim: Claude Code ${pinnedVersion.version} (pinned by ${pinnedVersion.source})`);
7117
+ if (decided.pinnedVersion !== void 0) {
7118
+ log.info(`agent-shim: Claude Code ${decided.pinnedVersion.version} (pinned by ${decided.pinnedVersion.source})`);
7010
7119
  }
7011
- const resolvedFlags = resolveLaunchFlags({
7012
- env,
7013
- // A pool pick reads the usage the front door records, so a pool launch records its own unless something says otherwise.
7014
- ...poolExplanation === void 0 ? {} : { trackUsageDefault: true },
7015
- ...cascadeLaunch === void 0 ? {} : { cascade: cascadeLaunch },
7016
- flags: {
7017
- ...parsedArgv.skipPermissions === void 0 ? {} : { skipPermissions: parsedArgv.skipPermissions },
7018
- ...parsedArgv.remoteControl === void 0 ? {} : { remoteControl: parsedArgv.remoteControl },
7019
- ...parsedArgv.headroom === void 0 ? {} : { headroom: parsedArgv.headroom },
7020
- ...parsedArgv.trackUsage === void 0 ? {} : { trackUsage: parsedArgv.trackUsage }
7021
- }
7022
- });
7023
7120
  const frontDoorPort = params.frontdoor;
7024
7121
  const frontDoorEngaged = resolvedProvider !== void 0 || resolvedFlags.headroom || resolvedFlags.trackUsage;
7025
7122
  if (frontDoorEngaged && frontDoorPort === void 0) {
@@ -7043,11 +7140,6 @@ function prepareLaunch(params) {
7043
7140
  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})`}`);
7044
7141
  }
7045
7142
  const frontDoorRelease = frontDoor === void 0 ? void 0 : frontDoorPort?.release;
7046
- const finalArgv = buildArgv({
7047
- toolFlags: buildFlagArgs(resolvedFlags),
7048
- extraFlags: splitExtraFlags(env.CLAUDE_EXTRA_FLAGS),
7049
- passthrough: parsedArgv.rest
7050
- });
7051
7143
  const finalEnv = buildEnv({
7052
7144
  baseEnv: env,
7053
7145
  configDirEscapeHatch: configDirEscapeHatchApplies,
@@ -7065,18 +7157,35 @@ function prepareLaunch(params) {
7065
7157
  registered();
7066
7158
  }
7067
7159
  };
7068
- const configDir = finalEnv.CLAUDE_CONFIG_DIR;
7069
- const decision = {
7070
- identitySource: identityDecision.source,
7071
- configDirEscapeHatch: identityDecision.configDirEscapeHatch,
7072
- configProfileSource: configProfileDecision.source,
7073
- ...identityDecision.name === void 0 ? {} : { identity: identityDecision.name },
7074
- ...poolPick === void 0 ? {} : { pool: poolPick },
7075
- ...configDir === void 0 || configDir === "" ? {} : { configDir },
7076
- ...configProfileDecision.name === void 0 ? {} : { configProfile: configProfileDecision.name },
7077
- ...resolvedProvider === void 0 ? {} : { provider: resolvedProvider.name }
7160
+ return { bin: decided.bin, args: finalArgv, env: finalEnv, release, markChildStarted: updateCheck.markChildStarted, decision };
7161
+ }
7162
+ function resolveLaunch(params) {
7163
+ const decided = decideLaunch(params, true);
7164
+ const { env } = params.proc;
7165
+ const frontDoor = decided.provider !== void 0 || decided.flags.headroom || decided.flags.trackUsage;
7166
+ const built = buildEnv({
7167
+ baseEnv: env,
7168
+ configDirEscapeHatch: decided.configDirEscapeHatch,
7169
+ resolvedIdentityName: decided.identityDecision.name,
7170
+ identitiesDir: params.paths.identitiesDir,
7171
+ ...decided.provider === void 0 ? {} : { provider: decided.provider },
7172
+ ...frontDoor ? { frontdoor: { port: 0, connectPort: 0, trustBundlePath: "", sessionToken: "" } } : {},
7173
+ ...decided.flags.headroom ? { headroom: { socketPath: "", projectId: "" } } : {},
7174
+ sessionId: ""
7175
+ });
7176
+ const credentialNames = decided.identityCredentialBlock === void 0 ? [] : Object.keys(credentialVariables(decided.identityCredentialBlock.target ?? "bearer", ""));
7177
+ const environment = [.../* @__PURE__ */ new Set([...Object.keys(built).filter((name) => built[name] !== env[name]), ...credentialNames])].sort();
7178
+ 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;
7179
+ return {
7180
+ decision: decided.decision,
7181
+ flags: decided.flags,
7182
+ ...decided.pinnedVersion === void 0 ? {} : { claudeVersion: decided.pinnedVersion },
7183
+ bin: decided.bin,
7184
+ args: decided.args,
7185
+ ...credential === void 0 ? {} : { credential },
7186
+ routing: { frontDoor, headroom: decided.flags.headroom },
7187
+ environment
7078
7188
  };
7079
- return { bin: discovered.path, args: finalArgv, env: finalEnv, release, markChildStarted: updateCheck.markChildStarted, decision };
7080
7189
  }
7081
7190
  function runLaunchPlan(plan, spawn2) {
7082
7191
  try {
@@ -7093,12 +7202,12 @@ function runLaunchPlan(plan, spawn2) {
7093
7202
  function runLauncher(params) {
7094
7203
  params.proc.exit(runLaunchPlan(prepareLaunch(params), params.spawn));
7095
7204
  }
7096
- var import_node_crypto10, import_node_path32;
7205
+ var import_node_crypto10, import_node_path33;
7097
7206
  var init_launcher = __esm({
7098
7207
  "src/launcher.ts"() {
7099
7208
  "use strict";
7100
7209
  import_node_crypto10 = require("node:crypto");
7101
- import_node_path32 = __toESM(require("node:path"), 1);
7210
+ import_node_path33 = __toESM(require("node:path"), 1);
7102
7211
  init_package();
7103
7212
  init_envBool();
7104
7213
  init_argv();
@@ -7129,13 +7238,13 @@ function agentShimCliPath(distDir = typeof __AGENT_SHIM_DIST_DIR__ === "string"
7129
7238
  if (distDir === void 0) {
7130
7239
  throw new OwnCliPathUnknownError();
7131
7240
  }
7132
- return import_node_path33.default.join(distDir, OWN_CLI_FILE_NAME);
7241
+ return import_node_path34.default.join(distDir, OWN_CLI_FILE_NAME);
7133
7242
  }
7134
- var import_node_path33, OWN_CLI_FILE_NAME, OwnCliPathUnknownError;
7243
+ var import_node_path34, OWN_CLI_FILE_NAME, OwnCliPathUnknownError;
7135
7244
  var init_ownCli = __esm({
7136
7245
  "src/ownCli.ts"() {
7137
7246
  "use strict";
7138
- import_node_path33 = __toESM(require("node:path"), 1);
7247
+ import_node_path34 = __toESM(require("node:path"), 1);
7139
7248
  init_cliError();
7140
7249
  OWN_CLI_FILE_NAME = "cli.cjs";
7141
7250
  OwnCliPathUnknownError = class extends CliError {
@@ -7220,7 +7329,7 @@ request.on("error", (error) => finish(failed, (error.code ? error.code + ": " :
7220
7329
  // src/frontdoor/trust.ts
7221
7330
  function resolveTrustBundle(params) {
7222
7331
  const { caCertFile, bundlesDir, variable, inherited, fs: fs12 } = params;
7223
- if (inherited === void 0 || inherited === "" || import_node_path34.default.resolve(inherited) === import_node_path34.default.resolve(caCertFile)) {
7332
+ if (inherited === void 0 || inherited === "" || import_node_path35.default.resolve(inherited) === import_node_path35.default.resolve(caCertFile)) {
7224
7333
  return { path: caCertFile };
7225
7334
  }
7226
7335
  const caPem = fs12.readFileUtf8(caCertFile);
@@ -7238,19 +7347,19 @@ function resolveTrustBundle(params) {
7238
7347
  }
7239
7348
  const combined = `${inheritedPem.trimEnd()}
7240
7349
  ${caPem}`;
7241
- const bundle = import_node_path34.default.join(bundlesDir, `${(0, import_node_crypto11.createHash)("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
7350
+ const bundle = import_node_path35.default.join(bundlesDir, `${(0, import_node_crypto11.createHash)("sha256").update(combined).digest("hex").slice(0, BUNDLE_NAME_HEX_DIGITS)}.pem`);
7242
7351
  if (!fs12.exists(bundle)) {
7243
7352
  fs12.mkdirp(bundlesDir);
7244
7353
  fs12.writeFileAtomic(bundle, combined);
7245
7354
  }
7246
7355
  return { path: bundle };
7247
7356
  }
7248
- var import_node_crypto11, import_node_path34, BUNDLE_NAME_HEX_DIGITS;
7357
+ var import_node_crypto11, import_node_path35, BUNDLE_NAME_HEX_DIGITS;
7249
7358
  var init_trust = __esm({
7250
7359
  "src/frontdoor/trust.ts"() {
7251
7360
  "use strict";
7252
7361
  import_node_crypto11 = require("node:crypto");
7253
- import_node_path34 = __toESM(require("node:path"), 1);
7362
+ import_node_path35 = __toESM(require("node:path"), 1);
7254
7363
  BUNDLE_NAME_HEX_DIGITS = 16;
7255
7364
  }
7256
7365
  });
@@ -7395,6 +7504,31 @@ function prepareClaudeLaunch(options) {
7395
7504
  const spawnDaemon = daemonSpawnerFor(options.agentShim);
7396
7505
  return prepareLaunch(realPrepareLaunchParams(paths, { proc, log, spawnDaemon, farm: buildFarmRuntime(paths, options.cwd) }));
7397
7506
  }
7507
+ function resolveClaudeLaunch(options) {
7508
+ const paths = options.paths ?? resolveLayoutPaths();
7509
+ const refusals = [];
7510
+ const warnings = [];
7511
+ const log = {
7512
+ info: () => void 0,
7513
+ warn: (message) => {
7514
+ warnings.push(message);
7515
+ },
7516
+ error: (message) => {
7517
+ refusals.push(message);
7518
+ }
7519
+ };
7520
+ const proc = {
7521
+ env: options.env,
7522
+ argv: options.argv,
7523
+ exit: (code) => {
7524
+ throw new LaunchRefusedError(refusals.join("\n") || `the launch was refused (exit ${String(code)})`, code);
7525
+ }
7526
+ };
7527
+ const spawnDaemon = () => {
7528
+ throw new Error("resolving a launch starts no daemon");
7529
+ };
7530
+ return { resolution: resolveLaunch(realPrepareLaunchParams(paths, { proc, log, spawnDaemon, farm: buildFarmRuntime(paths, options.cwd) })), warnings };
7531
+ }
7398
7532
  var import_node_os7, import_node_crypto12, LaunchRefusedError;
7399
7533
  var init_launchWiring = __esm({
7400
7534
  "src/launchWiring.ts"() {
@@ -7563,11 +7697,11 @@ var init_anthropicUsageRefresh = __esm({
7563
7697
  });
7564
7698
 
7565
7699
  // src/usage/providerQuota.ts
7566
- var import_zod21, 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;
7700
+ var import_zod22, 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;
7567
7701
  var init_providerQuota = __esm({
7568
7702
  "src/usage/providerQuota.ts"() {
7569
7703
  "use strict";
7570
- import_zod21 = require("zod");
7704
+ import_zod22 = require("zod");
7571
7705
  init_schema2();
7572
7706
  MS_PER_SECOND7 = 1e3;
7573
7707
  SECONDS_PER_HOUR = 3600;
@@ -7581,35 +7715,35 @@ var init_providerQuota = __esm({
7581
7715
  [ZAI_UNIT_HOURS, SECONDS_PER_HOUR * MS_PER_SECOND7],
7582
7716
  [ZAI_UNIT_MONTHS, DAYS_PER_MONTH * HOURS_PER_DAY3 * SECONDS_PER_HOUR * MS_PER_SECOND7]
7583
7717
  ]);
7584
- ZaiLimitSchema = import_zod21.z.object({
7585
- type: import_zod21.z.string(),
7586
- unit: import_zod21.z.number().int(),
7587
- number: import_zod21.z.number().int().positive(),
7588
- percentage: import_zod21.z.number().nonnegative(),
7589
- nextResetTime: import_zod21.z.number().positive().optional(),
7590
- usage: import_zod21.z.number().nonnegative().optional(),
7591
- currentValue: import_zod21.z.number().nonnegative().optional(),
7592
- remaining: import_zod21.z.number().nonnegative().optional()
7718
+ ZaiLimitSchema = import_zod22.z.object({
7719
+ type: import_zod22.z.string(),
7720
+ unit: import_zod22.z.number().int(),
7721
+ number: import_zod22.z.number().int().positive(),
7722
+ percentage: import_zod22.z.number().nonnegative(),
7723
+ nextResetTime: import_zod22.z.number().positive().optional(),
7724
+ usage: import_zod22.z.number().nonnegative().optional(),
7725
+ currentValue: import_zod22.z.number().nonnegative().optional(),
7726
+ remaining: import_zod22.z.number().nonnegative().optional()
7593
7727
  });
7594
- ZaiResponseSchema = import_zod21.z.object({
7595
- success: import_zod21.z.boolean(),
7596
- msg: import_zod21.z.string().optional(),
7597
- data: import_zod21.z.object({ level: import_zod21.z.string().optional(), limits: import_zod21.z.array(ZaiLimitSchema) })
7728
+ ZaiResponseSchema = import_zod22.z.object({
7729
+ success: import_zod22.z.boolean(),
7730
+ msg: import_zod22.z.string().optional(),
7731
+ data: import_zod22.z.object({ level: import_zod22.z.string().optional(), limits: import_zod22.z.array(ZaiLimitSchema) })
7598
7732
  });
7599
7733
  OPENROUTER_HOST = "openrouter.ai";
7600
7734
  OPENROUTER_KEY_URL = `https://${OPENROUTER_HOST}/api/v1/key`;
7601
7735
  OPENROUTER_CREDITS_URL = `https://${OPENROUTER_HOST}/api/v1/credits`;
7602
7736
  MS_PER_DAY3 = HOURS_PER_DAY3 * SECONDS_PER_HOUR * MS_PER_SECOND7;
7603
- OpenRouterKeySchema = import_zod21.z.object({
7604
- data: import_zod21.z.object({
7605
- limit: import_zod21.z.number().nonnegative().nullable(),
7606
- limit_remaining: import_zod21.z.number().nullable(),
7607
- limit_reset: import_zod21.z.string().nullable(),
7608
- is_free_tier: import_zod21.z.boolean().optional(),
7609
- free_model_daily_requests: import_zod21.z.object({ used: import_zod21.z.number().nonnegative(), limit: import_zod21.z.number().nonnegative(), remaining: import_zod21.z.number() }).optional()
7737
+ OpenRouterKeySchema = import_zod22.z.object({
7738
+ data: import_zod22.z.object({
7739
+ limit: import_zod22.z.number().nonnegative().nullable(),
7740
+ limit_remaining: import_zod22.z.number().nullable(),
7741
+ limit_reset: import_zod22.z.string().nullable(),
7742
+ is_free_tier: import_zod22.z.boolean().optional(),
7743
+ free_model_daily_requests: import_zod22.z.object({ used: import_zod22.z.number().nonnegative(), limit: import_zod22.z.number().nonnegative(), remaining: import_zod22.z.number() }).optional()
7610
7744
  })
7611
7745
  });
7612
- OpenRouterCreditsSchema = import_zod21.z.object({ data: import_zod21.z.object({ total_credits: import_zod21.z.number().nonnegative(), total_usage: import_zod21.z.number().nonnegative() }) });
7746
+ OpenRouterCreditsSchema = import_zod22.z.object({ data: import_zod22.z.object({ total_credits: import_zod22.z.number().nonnegative(), total_usage: import_zod22.z.number().nonnegative() }) });
7613
7747
  }
7614
7748
  });
7615
7749
 
@@ -7741,6 +7875,9 @@ __export(index_exports, {
7741
7875
  CheckReportJsonSchema: () => CheckReportJsonSchema,
7742
7876
  CheckRunInputSchema: () => CheckRunInputSchema,
7743
7877
  CliError: () => CliError,
7878
+ CodexLogoutOutputSchema: () => CodexLogoutOutputSchema,
7879
+ CodexSignInSchema: () => CodexSignInSchema,
7880
+ CodexStatusOutputSchema: () => CodexStatusOutputSchema,
7744
7881
  ConfigProfileSchema: () => ConfigProfileSchema,
7745
7882
  CredentialCacheSchema: () => CredentialCacheSchema,
7746
7883
  CredentialSchema: () => CredentialSchema,
@@ -7765,6 +7902,7 @@ __export(index_exports, {
7765
7902
  FARM_MANIFEST_FILENAME: () => FARM_MANIFEST_FILENAME,
7766
7903
  FrontDoorControlMaterialError: () => FrontDoorControlMaterialError,
7767
7904
  FrontDoorNotServingError: () => FrontDoorNotServingError,
7905
+ FrontDoorRestartOutputSchema: () => FrontDoorRestartOutputSchema,
7768
7906
  FrontDoorSessionStatusSchema: () => FrontDoorSessionStatusSchema,
7769
7907
  FrontDoorSessionsOutputSchema: () => FrontDoorSessionsOutputSchema,
7770
7908
  FrontDoorStartError: () => FrontDoorStartError,
@@ -7782,6 +7920,8 @@ __export(index_exports, {
7782
7920
  LAUNCH_EVENT_SOURCE: () => LAUNCH_EVENT_SOURCE,
7783
7921
  LaunchLifecycleEventSchema: () => LaunchLifecycleEventSchema,
7784
7922
  LaunchRefusedError: () => LaunchRefusedError,
7923
+ LaunchResolveInputSchema: () => LaunchResolveInputSchema,
7924
+ LaunchResolveOutputSchema: () => LaunchResolveOutputSchema,
7785
7925
  LegacyProviderFileError: () => LegacyProviderFileError,
7786
7926
  OWN_CLI_FILE_NAME: () => OWN_CLI_FILE_NAME,
7787
7927
  PROMPT_CACHE_TTL_MS: () => PROMPT_CACHE_TTL_MS,
@@ -7828,6 +7968,7 @@ __export(index_exports, {
7828
7968
  RcStreamEnvelopeSchema: () => RcStreamEnvelopeSchema,
7829
7969
  RcStreamEventSchema: () => RcStreamEventSchema,
7830
7970
  USAGE_EVENT_SOURCE: () => USAGE_EVENT_SOURCE,
7971
+ UpdateCheckOutputSchema: () => UpdateCheckOutputSchema,
7831
7972
  UsageError: () => UsageError,
7832
7973
  UsageListOutputSchema: () => UsageListOutputSchema,
7833
7974
  UsageLiveOutputSchema: () => UsageLiveOutputSchema,
@@ -7870,14 +8011,17 @@ __export(index_exports, {
7870
8011
  collectDoctorReport: () => collectDoctorReport,
7871
8012
  collectFrontDoorStatus: () => collectFrontDoorStatus,
7872
8013
  collectPoolPick: () => collectPoolPick,
8014
+ createCodexApiRouter: () => createCodexApiRouter,
7873
8015
  createControlApiRouter: () => createControlApiRouter,
7874
8016
  createDoorApiNodeHandler: () => createDoorApiNodeHandler,
7875
8017
  createDoorApiRouter: () => createDoorApiRouter,
7876
8018
  createDoorEventHub: () => createDoorEventHub,
7877
8019
  createDoorHealthPublisher: () => createDoorHealthPublisher,
7878
8020
  createEventsApiRouter: () => createEventsApiRouter,
8021
+ createLaunchApiRouter: () => createLaunchApiRouter,
7879
8022
  createLaunchEventPublisher: () => createLaunchEventPublisher,
7880
8023
  createLeafCache: () => createLeafCache,
8024
+ createLifecycleApiRouter: () => createLifecycleApiRouter,
7881
8025
  createProfile: () => createProfile,
7882
8026
  createQuotaExpiringPublisher: () => createQuotaExpiringPublisher,
7883
8027
  createRcApiNodeHandler: () => createRcApiNodeHandler,
@@ -7985,7 +8129,9 @@ __export(index_exports, {
7985
8129
  requirePool: () => requirePool,
7986
8130
  resolveAgentShimHome: () => resolveAgentShimHome,
7987
8131
  resolveClaudeHome: () => resolveClaudeHome,
8132
+ resolveClaudeLaunch: () => resolveClaudeLaunch,
7988
8133
  resolveDecisions: () => resolveDecisions,
8134
+ resolveLaunch: () => resolveLaunch,
7989
8135
  resolveLaunchSelection: () => resolveLaunchSelection,
7990
8136
  resolveLayoutPaths: () => resolveLayoutPaths,
7991
8137
  resolveSupervisorConfig: () => resolveSupervisorConfig,
@@ -8522,8 +8668,8 @@ function parseConnectTarget(authority) {
8522
8668
  function isInterceptedHost(host, interceptHosts) {
8523
8669
  return interceptHosts.includes(host);
8524
8670
  }
8525
- function servedByPipeline(path35) {
8526
- return path35?.startsWith(ROUTED_PATH_PREFIX) === true;
8671
+ function servedByPipeline(path36) {
8672
+ return path36?.startsWith(ROUTED_PATH_PREFIX) === true;
8527
8673
  }
8528
8674
  var HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
8529
8675
  "connection",
@@ -9057,11 +9203,11 @@ function createRcSessionTracker(deps) {
9057
9203
  };
9058
9204
  const observeExchange = (request4) => {
9059
9205
  const method = (request4.method ?? "").toUpperCase();
9060
- const path35 = new URL(request4.url ?? "/", "http://127.0.0.1").pathname;
9061
- if (!path35.startsWith(RC_SESSIONS_PATH_PREFIX)) {
9206
+ const path36 = new URL(request4.url ?? "/", "http://127.0.0.1").pathname;
9207
+ if (!path36.startsWith(RC_SESSIONS_PATH_PREFIX)) {
9062
9208
  return void 0;
9063
9209
  }
9064
- const tail = path35.slice(RC_SESSIONS_PATH_PREFIX.length);
9210
+ const tail = path36.slice(RC_SESSIONS_PATH_PREFIX.length);
9065
9211
  const facts = {
9066
9212
  oauthAuthorization: oauthAuthorizationOf(request4.headers),
9067
9213
  anthropicVersion: singleHeader(request4.headers, "anthropic-version"),
@@ -9443,8 +9589,8 @@ var RC_READ_FILE_ENCODINGS = ["utf-8", "base64"];
9443
9589
  function isRcReadFileEncoding(value) {
9444
9590
  return RC_READ_FILE_ENCODINGS.some((encoding) => encoding === value);
9445
9591
  }
9446
- function buildRcReadFilePayload(requestId, path35, options) {
9447
- return buildRcControlRequestPayload(requestId, { subtype: "read_file", path: path35, ...options?.maxBytes === void 0 ? {} : { max_bytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } });
9592
+ function buildRcReadFilePayload(requestId, path36, options) {
9593
+ return buildRcControlRequestPayload(requestId, { subtype: "read_file", path: path36, ...options?.maxBytes === void 0 ? {} : { max_bytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } });
9448
9594
  }
9449
9595
  function buildRcFileSuggestionsPayload(requestId, query) {
9450
9596
  return buildRcControlRequestPayload(requestId, { subtype: "file_suggestions", query });
@@ -9546,15 +9692,15 @@ async function getRcSessionContextUsage(deps, sessionId, detail) {
9546
9692
  const result = await deliverRcClientPayload(deps, sessionId, buildRcGetContextUsagePayload(requestId, detail), `request the context usage of session ${sessionId}`);
9547
9693
  return result.ok ? { ...result, requestId } : result;
9548
9694
  }
9549
- async function readRcSessionFile(deps, sessionId, path35, options) {
9550
- if (path35 === "") {
9695
+ async function readRcSessionFile(deps, sessionId, path36, options) {
9696
+ if (path36 === "") {
9551
9697
  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" };
9552
9698
  }
9553
9699
  if (options?.maxBytes !== void 0 && (!Number.isInteger(options.maxBytes) || options.maxBytes <= 0)) {
9554
9700
  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" };
9555
9701
  }
9556
9702
  const requestId = deps.newUuid();
9557
- const result = await deliverRcClientPayload(deps, sessionId, buildRcReadFilePayload(requestId, path35, options), `read ${path35} from session ${sessionId}`);
9703
+ const result = await deliverRcClientPayload(deps, sessionId, buildRcReadFilePayload(requestId, path36, options), `read ${path36} from session ${sessionId}`);
9558
9704
  return result.ok ? { ...result, requestId } : result;
9559
9705
  }
9560
9706
  async function suggestRcSessionFiles(deps, sessionId, query) {
@@ -9723,11 +9869,11 @@ function createRcControlHandler(deps) {
9723
9869
  path: "read-file",
9724
9870
  read: (body) => {
9725
9871
  const session = bodyString(body, "session");
9726
- const path35 = bodyString(body, "path");
9872
+ const path36 = bodyString(body, "path");
9727
9873
  const maxBytes = "maxBytes" in body ? bodyPositiveInteger(body, "maxBytes") : void 0;
9728
9874
  const encoding = "encoding" in body && isRcReadFileEncoding(body.encoding) ? body.encoding : void 0;
9729
- const refused2 = session === void 0 || path35 === void 0 || "maxBytes" in body && maxBytes === void 0 || "encoding" in body && encoding === void 0;
9730
- 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 } }) };
9875
+ const refused2 = session === void 0 || path36 === void 0 || "maxBytes" in body && maxBytes === void 0 || "encoding" in body && encoding === void 0;
9876
+ 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 } }) };
9731
9877
  }
9732
9878
  },
9733
9879
  {
@@ -10037,9 +10183,9 @@ function requestIdOfBody(body) {
10037
10183
  }
10038
10184
  function frontDoorRcControl(transport, token) {
10039
10185
  const headers = { authorization: `Bearer ${token}` };
10040
- const listAnswerOf = async (path35, what) => {
10186
+ const listAnswerOf = async (path36, what) => {
10041
10187
  try {
10042
- return await transport.request({ method: "GET", path: path35, headers });
10188
+ return await transport.request({ method: "GET", path: path36, headers });
10043
10189
  } catch (error) {
10044
10190
  throw new Error(`${what}: could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
10045
10191
  }
@@ -10111,10 +10257,10 @@ function frontDoorRcControl(transport, token) {
10111
10257
  }
10112
10258
  return pending;
10113
10259
  };
10114
- const writeOf = async (path35, body, describeFailure) => {
10260
+ const writeOf = async (path36, body, describeFailure) => {
10115
10261
  let answer;
10116
10262
  try {
10117
- answer = await transport.request({ method: "POST", path: path35, headers: { ...headers, "content-type": "application/json" }, body });
10263
+ answer = await transport.request({ method: "POST", path: path36, headers: { ...headers, "content-type": "application/json" }, body });
10118
10264
  } catch (error) {
10119
10265
  return { ok: false, message: `could not reach the front door's control listener: ${error instanceof Error ? error.message : String(error)}` };
10120
10266
  }
@@ -10145,10 +10291,10 @@ function frontDoorRcControl(transport, token) {
10145
10291
  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}`),
10146
10292
  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}`),
10147
10293
  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}`),
10148
- readFile: async (sessionId, path35, options) => await writeOf(
10294
+ readFile: async (sessionId, path36, options) => await writeOf(
10149
10295
  `${CONTROL_PATH_PREFIX}/read-file`,
10150
- JSON.stringify({ session: sessionId, path: path35, ...options?.maxBytes === void 0 ? {} : { maxBytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } }),
10151
- (status, message) => `reading ${path35} from ${sessionId} failed (HTTP ${String(status)}): ${message}`
10296
+ JSON.stringify({ session: sessionId, path: path36, ...options?.maxBytes === void 0 ? {} : { maxBytes: options.maxBytes }, ...options?.encoding === void 0 ? {} : { encoding: options.encoding } }),
10297
+ (status, message) => `reading ${path36} from ${sessionId} failed (HTTP ${String(status)}): ${message}`
10152
10298
  ),
10153
10299
  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}`),
10154
10300
  keepAlive: async (sessionId) => await writeOf(`${CONTROL_PATH_PREFIX}/keep-alive`, JSON.stringify({ session: sessionId }), (status, message) => `keeping ${sessionId} alive failed (HTTP ${String(status)}): ${message}`),
@@ -10307,12 +10453,12 @@ function tlsFacts(options) {
10307
10453
  }
10308
10454
  function realRcEventDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
10309
10455
  const agent = new ExemptTlsAgent();
10310
- const post = async (path35, headers, body) => await new Promise((resolve, reject) => {
10456
+ const post = async (path36, headers, body) => await new Promise((resolve, reject) => {
10311
10457
  const options = {
10312
10458
  host: target.host,
10313
10459
  port: target.port,
10314
10460
  method: "POST",
10315
- path: path35,
10461
+ path: path36,
10316
10462
  // 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.
10317
10463
  headers: { ...headers, host: target.servername ?? target.host, "content-length": String(Buffer.byteLength(body, "utf8")) },
10318
10464
  agent
@@ -10377,12 +10523,12 @@ function lateRcStreamDial(resolve) {
10377
10523
  }
10378
10524
  function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_PORT }) {
10379
10525
  const agent = new ExemptTlsAgent();
10380
- const request4 = async (method, path35, headers, body, signal) => await new Promise((resolve, reject) => {
10526
+ const request4 = async (method, path36, headers, body, signal) => await new Promise((resolve, reject) => {
10381
10527
  const options = {
10382
10528
  host: target.host,
10383
10529
  port: target.port,
10384
10530
  method,
10385
- path: path35,
10531
+ path: path36,
10386
10532
  // 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.
10387
10533
  headers: { ...headers, host: target.servername ?? target.host, ...body === void 0 ? {} : { "content-length": String(Buffer.byteLength(body, "utf8")) } },
10388
10534
  agent,
@@ -10424,9 +10570,9 @@ function realRcStreamDial(target = { host: CONNECT_INTERCEPT_HOST, port: HTTPS_P
10424
10570
  return { status, body: await readAll(response) };
10425
10571
  },
10426
10572
  openStream: async (sessionId, headers, resume, signal) => {
10427
- 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)}`;
10573
+ 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)}`;
10428
10574
  const streamHeaders = resume === void 0 ? headers : { ...headers, "last-event-id": String(resume.fromSequenceNum) };
10429
- const { status, response } = await request4("GET", path35, streamHeaders, void 0, signal);
10575
+ const { status, response } = await request4("GET", path36, streamHeaders, void 0, signal);
10430
10576
  if (!isSuccessful2(status)) {
10431
10577
  await readAll(response);
10432
10578
  return { status, chunks: NO_CHUNKS };
@@ -10926,41 +11072,41 @@ function createRcApiRouter(deps) {
10926
11072
  };
10927
11073
  return {
10928
11074
  rc: {
10929
- list: authed.route({ method: "GET", path: "/rest/rc/sessions", summary: "List the observed Remote Control sessions", tags: [RC_API_TAG] }).output(RcListOutputSchema).handler(() => ({ sessions: deps.list() })),
10930
- status: authed.route({ method: "GET", path: "/rest/rc/status", summary: "Read session status, one session's when named", tags: [RC_API_TAG] }).input(RcSessionQuerySchema).output(RcStatusOutputSchema).handler(({ input }) => {
11075
+ list: authed.meta((0, import_openapi.openapi)({ method: "GET", path: "/rest/rc/sessions", summary: "List the observed Remote Control sessions", tags: [RC_API_TAG] })).output(RcListOutputSchema).handler(() => ({ sessions: deps.list() })),
11076
+ status: authed.meta((0, import_openapi.openapi)({ method: "GET", path: "/rest/rc/status", summary: "Read session status, one session's when named", tags: [RC_API_TAG] })).input(RcSessionQuerySchema).output(RcStatusOutputSchema).handler(({ input }) => {
10931
11077
  const statuses = deps.statusOf(input.session);
10932
11078
  if (input.session !== void 0 && !statuses.some((entry) => entry.id === input.session)) {
10933
11079
  throw new import_client.ORPCError("NOT_FOUND", { message: rcSessionNotObservedMessage(input.session) });
10934
11080
  }
10935
11081
  return { statuses };
10936
11082
  }),
10937
- pending: authed.route({ method: "GET", path: "/rest/rc/pending", summary: "Read the control requests awaiting an answer", tags: [RC_API_TAG] }).input(RcSessionQuerySchema).output(RcPendingOutputSchema).handler(({ input }) => {
11083
+ pending: authed.meta((0, import_openapi.openapi)({ method: "GET", path: "/rest/rc/pending", summary: "Read the control requests awaiting an answer", tags: [RC_API_TAG] })).input(RcSessionQuerySchema).output(RcPendingOutputSchema).handler(({ input }) => {
10938
11084
  const pending = deps.pendingOf(input.session);
10939
11085
  if (input.session !== void 0 && deps.statusOf(input.session).length === 0) {
10940
11086
  throw new import_client.ORPCError("NOT_FOUND", { message: rcSessionNotObservedMessage(input.session) });
10941
11087
  }
10942
11088
  return { pending };
10943
11089
  }),
10944
- send: authed.route({ method: "POST", path: "/rest/rc/send", summary: "Send one message into a session", tags: [RC_API_TAG] }).input(RcSendInputSchema).output(RcWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, sequenceNums: delivered(input.session, await deps.inject(input.session, input.text)) })),
10945
- answer: authed.route({ method: "POST", path: "/rest/rc/answer", summary: "Answer one pending control request", tags: [RC_API_TAG] }).input(RcAnswerInputSchema).output(RcAnswerOutputSchema).handler(async ({ input }) => {
11090
+ send: authed.meta((0, import_openapi.openapi)({ method: "POST", path: "/rest/rc/send", summary: "Send one message into a session", tags: [RC_API_TAG] })).input(RcSendInputSchema).output(RcWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, sequenceNums: delivered(input.session, await deps.inject(input.session, input.text)) })),
11091
+ answer: authed.meta((0, import_openapi.openapi)({ method: "POST", path: "/rest/rc/answer", summary: "Answer one pending control request", tags: [RC_API_TAG] })).input(RcAnswerInputSchema).output(RcAnswerOutputSchema).handler(async ({ input }) => {
10946
11092
  const decision = { approve: input.approve, message: input.approve || input.text === void 0 ? void 0 : input.text };
10947
11093
  return { session: input.session, request: input.request, sequenceNums: delivered(input.session, await deps.answer(input.session, input.request, decision)) };
10948
11094
  }),
10949
- interrupt: authed.route({ method: "POST", path: "/rest/rc/interrupt", summary: "Interrupt a session's running turn", tags: [RC_API_TAG] }).input(RcInterruptInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.interrupt(input.session)) })),
10950
- setModel: authed.route({ method: "POST", path: "/rest/rc/set-model", summary: "Switch a session's model", tags: [RC_API_TAG] }).input(RcSetModelInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.setModel(input.session, input.model)) })),
10951
- setPermissionMode: authed.route({ method: "POST", path: "/rest/rc/set-permission-mode", summary: "Switch a session's permission mode", tags: [RC_API_TAG] }).input(RcSetPermissionModeInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.setPermissionMode(input.session, input.mode)) })),
10952
- endSession: authed.route({ method: "POST", path: "/rest/rc/end-session", summary: "End a session", tags: [RC_API_TAG] }).input(RcEndSessionInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.endSession(input.session, input.reason)) })),
10953
- getUsage: authed.route({ method: "POST", path: "/rest/rc/get-usage", summary: "Ask a session for its usage snapshot", tags: [RC_API_TAG] }).input(RcGetUsageInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.getUsage(input.session, input.skipBehaviors)) })),
10954
- getContextUsage: authed.route({ method: "POST", path: "/rest/rc/get-context-usage", summary: "Ask a session for its context usage", tags: [RC_API_TAG] }).input(RcGetContextUsageInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.getContextUsage(input.session, input.detail)) })),
10955
- readFile: authed.route({ method: "POST", path: "/rest/rc/read-file", summary: "Ask a session to read one file", tags: [RC_API_TAG] }).input(RcReadFileInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.readFile(input.session, input.path, { ...input.maxBytes === void 0 ? {} : { maxBytes: input.maxBytes }, ...input.encoding === void 0 ? {} : { encoding: input.encoding } })) })),
10956
- fileSuggestions: authed.route({ method: "POST", path: "/rest/rc/file-suggestions", summary: "Ask a session for file-path suggestions", tags: [RC_API_TAG] }).input(RcFileSuggestionsInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.fileSuggestions(input.session, input.query)) })),
10957
- keepAlive: authed.route({ method: "POST", path: "/rest/rc/keep-alive", summary: "Keep a session's bridge alive", tags: [RC_API_TAG] }).input(RcKeepAliveInputSchema).output(RcWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, sequenceNums: delivered(input.session, await deps.keepAlive(input.session)) })),
10958
- mcpStatus: authed.route({ method: "POST", path: "/rest/rc/mcp-status", summary: "Ask a session for its MCP servers' status", tags: [RC_API_TAG] }).input(RcMcpStatusInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpStatus(input.session)) })),
10959
- mcpReconnect: authed.route({ method: "POST", path: "/rest/rc/mcp-reconnect", summary: "Ask a session to reconnect one MCP server", tags: [RC_API_TAG] }).input(RcMcpReconnectInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpReconnect(input.session, input.serverName)) })),
10960
- mcpAuthenticate: authed.route({ method: "POST", path: "/rest/rc/mcp-authenticate", summary: "Start OAuth for one MCP server on a session", tags: [RC_API_TAG] }).input(RcMcpAuthenticateInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpAuthenticate(input.session, input.serverName, input.redirectUri)) })),
10961
- mcpOAuthCallbackUrl: authed.route({ method: "POST", path: "/rest/rc/mcp-oauth-callback-url", summary: "Hand a completed MCP OAuth callback to a session", tags: [RC_API_TAG] }).input(RcMcpOAuthCallbackUrlInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpOAuthCallbackUrl(input.session, input.serverName, input.callbackUrl)) })),
10962
- teleport: authed.route({ method: "POST", path: "/rest/rc/teleport", summary: "Teleport a session to a conversation marker", tags: [RC_API_TAG] }).input(RcTeleportInputSchema).output(RcWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, sequenceNums: delivered(input.session, await deps.teleport(input.session, input.marker)) })),
10963
- subscribe: authed.route({ method: "GET", path: "/rest/rc/events", summary: "Stream a session's Remote Control events (SSE)", tags: [RC_API_TAG] }).input(RcSessionQuerySchema).output((0, import_server2.eventIterator)(RcStreamEventSchema)).handler(async function* ({ input, signal }) {
11095
+ interrupt: authed.meta((0, import_openapi.openapi)({ method: "POST", path: "/rest/rc/interrupt", summary: "Interrupt a session's running turn", tags: [RC_API_TAG] })).input(RcInterruptInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.interrupt(input.session)) })),
11096
+ setModel: authed.meta((0, import_openapi.openapi)({ method: "POST", path: "/rest/rc/set-model", summary: "Switch a session's model", tags: [RC_API_TAG] })).input(RcSetModelInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.setModel(input.session, input.model)) })),
11097
+ setPermissionMode: authed.meta((0, import_openapi.openapi)({ method: "POST", path: "/rest/rc/set-permission-mode", summary: "Switch a session's permission mode", tags: [RC_API_TAG] })).input(RcSetPermissionModeInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.setPermissionMode(input.session, input.mode)) })),
11098
+ endSession: authed.meta((0, import_openapi.openapi)({ method: "POST", path: "/rest/rc/end-session", summary: "End a session", tags: [RC_API_TAG] })).input(RcEndSessionInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.endSession(input.session, input.reason)) })),
11099
+ getUsage: authed.meta((0, import_openapi.openapi)({ method: "POST", path: "/rest/rc/get-usage", summary: "Ask a session for its usage snapshot", tags: [RC_API_TAG] })).input(RcGetUsageInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.getUsage(input.session, input.skipBehaviors)) })),
11100
+ getContextUsage: authed.meta((0, import_openapi.openapi)({ method: "POST", path: "/rest/rc/get-context-usage", summary: "Ask a session for its context usage", tags: [RC_API_TAG] })).input(RcGetContextUsageInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.getContextUsage(input.session, input.detail)) })),
11101
+ readFile: authed.meta((0, import_openapi.openapi)({ method: "POST", path: "/rest/rc/read-file", summary: "Ask a session to read one file", tags: [RC_API_TAG] })).input(RcReadFileInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.readFile(input.session, input.path, { ...input.maxBytes === void 0 ? {} : { maxBytes: input.maxBytes }, ...input.encoding === void 0 ? {} : { encoding: input.encoding } })) })),
11102
+ fileSuggestions: authed.meta((0, import_openapi.openapi)({ method: "POST", path: "/rest/rc/file-suggestions", summary: "Ask a session for file-path suggestions", tags: [RC_API_TAG] })).input(RcFileSuggestionsInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.fileSuggestions(input.session, input.query)) })),
11103
+ keepAlive: authed.meta((0, import_openapi.openapi)({ method: "POST", path: "/rest/rc/keep-alive", summary: "Keep a session's bridge alive", tags: [RC_API_TAG] })).input(RcKeepAliveInputSchema).output(RcWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, sequenceNums: delivered(input.session, await deps.keepAlive(input.session)) })),
11104
+ mcpStatus: authed.meta((0, import_openapi.openapi)({ method: "POST", path: "/rest/rc/mcp-status", summary: "Ask a session for its MCP servers' status", tags: [RC_API_TAG] })).input(RcMcpStatusInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpStatus(input.session)) })),
11105
+ mcpReconnect: authed.meta((0, import_openapi.openapi)({ method: "POST", path: "/rest/rc/mcp-reconnect", summary: "Ask a session to reconnect one MCP server", tags: [RC_API_TAG] })).input(RcMcpReconnectInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpReconnect(input.session, input.serverName)) })),
11106
+ mcpAuthenticate: authed.meta((0, import_openapi.openapi)({ method: "POST", path: "/rest/rc/mcp-authenticate", summary: "Start OAuth for one MCP server on a session", tags: [RC_API_TAG] })).input(RcMcpAuthenticateInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpAuthenticate(input.session, input.serverName, input.redirectUri)) })),
11107
+ mcpOAuthCallbackUrl: authed.meta((0, import_openapi.openapi)({ method: "POST", path: "/rest/rc/mcp-oauth-callback-url", summary: "Hand a completed MCP OAuth callback to a session", tags: [RC_API_TAG] })).input(RcMcpOAuthCallbackUrlInputSchema).output(RcControlWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, ...deliveredControl(input.session, await deps.mcpOAuthCallbackUrl(input.session, input.serverName, input.callbackUrl)) })),
11108
+ teleport: authed.meta((0, import_openapi.openapi)({ method: "POST", path: "/rest/rc/teleport", summary: "Teleport a session to a conversation marker", tags: [RC_API_TAG] })).input(RcTeleportInputSchema).output(RcWriteOutputSchema).handler(async ({ input }) => ({ session: input.session, sequenceNums: delivered(input.session, await deps.teleport(input.session, input.marker)) })),
11109
+ subscribe: authed.meta((0, import_openapi.openapi)({ method: "GET", path: "/rest/rc/events", summary: "Stream a session's Remote Control events (SSE)", tags: [RC_API_TAG] })).input(RcSessionQuerySchema).output((0, import_server2.eventIterator)(RcStreamEventSchema)).handler(async function* ({ input, signal }) {
10964
11110
  const queue = [];
10965
11111
  let wake;
10966
11112
  const detach = deps.fanout.subscribe(input.session, (event) => {
@@ -11002,7 +11148,7 @@ function doorApiNodeHandlerOf(router, expectedToken) {
11002
11148
  const rpcHandler = new import_node2.RPCHandler(router, { plugins });
11003
11149
  const restHandler = new import_node.OpenAPIHandler(router, { plugins });
11004
11150
  let document;
11005
- const documentOf = async () => document ??= new import_openapi.OpenAPIGenerator().generate(router, { info: { title: "agent-shim front door API", version: package_default.version } });
11151
+ const documentOf = async () => document ??= new import_openapi.OpenAPIGenerator().generate(router, { base: { info: { title: "agent-shim front door API", version: package_default.version } } });
11006
11152
  return {
11007
11153
  pathPrefix: RC_ORPC_PATH_PREFIX,
11008
11154
  handle: async (request4, response) => {
@@ -11025,11 +11171,15 @@ function doorApiNodeHandlerOf(router, expectedToken) {
11025
11171
  }
11026
11172
  return { matched: true };
11027
11173
  }
11028
- const rest = await restHandler.handle(request4, response, { context: { headers: request4.headers }, prefix: RC_ORPC_PATH_PREFIX });
11174
+ const rest = await restHandler.handle(request4, response, { context: { headers: request4.headers, afterResponse: (action) => {
11175
+ response.once("finish", action);
11176
+ } }, prefix: RC_ORPC_PATH_PREFIX });
11029
11177
  if (rest.matched) {
11030
11178
  return rest;
11031
11179
  }
11032
- return await rpcHandler.handle(request4, response, { context: { headers: request4.headers }, prefix: RC_ORPC_PATH_PREFIX });
11180
+ return await rpcHandler.handle(request4, response, { context: { headers: request4.headers, afterResponse: (action) => {
11181
+ response.once("finish", action);
11182
+ } }, prefix: RC_ORPC_PATH_PREFIX });
11033
11183
  }
11034
11184
  };
11035
11185
  }
@@ -11039,10 +11189,12 @@ function createRcApiNodeHandler(deps) {
11039
11189
  function frontDoorApiLink(port, ca, token) {
11040
11190
  const dispatcher = new import_undici.Agent({ connect: { ca } });
11041
11191
  return new import_fetch.RPCLink({
11042
- url: `https://127.0.0.1:${String(port)}${RC_ORPC_PATH_PREFIX}`,
11192
+ origin: `https://127.0.0.1:${String(port)}`,
11193
+ url: RC_ORPC_PATH_PREFIX,
11043
11194
  headers: { authorization: `Bearer ${token}` },
11044
11195
  // undici's own Request and Response types and the global ones are distinct declarations of the same standard shapes (the package's bundled types sit beside @types/node's own), and its fetch refuses the global Request instance outright, so the call is rebuilt from the request's parts and the answer re-wrapped through the global constructors, never cast between the two. The request body is one bounded JSON object (the same protocol cap the handler enforces), so reading it whole costs nothing; it is the answer that streams.
11045
- fetch: async (request4, _init, options) => {
11196
+ fetch: async (url, init, options) => {
11197
+ const request4 = new Request(url, init);
11046
11198
  const body = request4.body === null ? void 0 : Buffer.from(await request4.arrayBuffer());
11047
11199
  const answered = await (0, import_undici.fetch)(request4.url, {
11048
11200
  method: request4.method,
@@ -11064,7 +11216,8 @@ init_cliError();
11064
11216
  init_realPorts();
11065
11217
 
11066
11218
  // src/frontdoor/controlApi.ts
11067
- var import_client3 = require("@orpc/client");
11219
+ var import_client5 = require("@orpc/client");
11220
+ var import_openapi6 = require("@orpc/openapi");
11068
11221
 
11069
11222
  // src/checkReport.ts
11070
11223
  var import_node_os5 = __toESM(require("node:os"), 1);
@@ -11291,19 +11444,19 @@ function writePools(paths, pools) {
11291
11444
  applyPatch(paths.globalConfigFile, GlobalConfigSchema, { pools }, { defaults: {} });
11292
11445
  }
11293
11446
  function poolCycleOf(pools, name) {
11294
- const walk = (current, path35) => {
11447
+ const walk = (current, path36) => {
11295
11448
  for (const entry of pools[current]?.identities ?? []) {
11296
11449
  const nested = poolNameOf(poolMemberIdentity(entry));
11297
11450
  if (nested === void 0) {
11298
11451
  continue;
11299
11452
  }
11300
11453
  if (nested === name) {
11301
- return [...path35, nested];
11454
+ return [...path36, nested];
11302
11455
  }
11303
- if (path35.includes(nested)) {
11456
+ if (path36.includes(nested)) {
11304
11457
  continue;
11305
11458
  }
11306
- const found = walk(nested, [...path35, nested]);
11459
+ const found = walk(nested, [...path36, nested]);
11307
11460
  if (found !== void 0) {
11308
11461
  return found;
11309
11462
  }
@@ -12874,9 +13027,48 @@ var DoctorRunOutputSchema = import_zod19.z.strictObject({
12874
13027
  ok: import_zod19.z.boolean(),
12875
13028
  findings: import_zod19.z.readonly(import_zod19.z.array(DoctorFindingSchema))
12876
13029
  });
13030
+ var FrontDoorRestartOutputSchema = import_zod19.z.strictObject({
13031
+ action: import_zod19.z.literal("restarting"),
13032
+ previousPid: import_zod19.z.int().positive()
13033
+ });
13034
+ var UpdateCheckOutputSchema = import_zod19.z.strictObject({
13035
+ current: import_zod19.z.string(),
13036
+ latest: import_zod19.z.string(),
13037
+ action: import_zod19.z.enum(["current", "available", "updated"])
13038
+ });
13039
+ var CodexSignInSchema = import_zod19.z.discriminatedUnion("state", [
13040
+ import_zod19.z.strictObject({ state: import_zod19.z.literal("none") }),
13041
+ import_zod19.z.strictObject({ state: import_zod19.z.literal("signed-in"), email: import_zod19.z.string().optional(), planScope: import_zod19.z.boolean(), accessTokenExpiresAt: import_zod19.z.number() }),
13042
+ import_zod19.z.strictObject({ state: import_zod19.z.literal("unreadable"), message: import_zod19.z.string() })
13043
+ ]);
13044
+ var CodexStatusOutputSchema = import_zod19.z.strictObject({
13045
+ signIn: CodexSignInSchema,
13046
+ codexProviders: import_zod19.z.readonly(import_zod19.z.array(import_zod19.z.string()))
13047
+ });
13048
+ var CodexLogoutOutputSchema = import_zod19.z.strictObject({
13049
+ hadGrant: import_zod19.z.boolean(),
13050
+ revoked: import_zod19.z.boolean()
13051
+ });
13052
+
13053
+ // src/frontdoor/codexApi.ts
13054
+ var import_openapi2 = require("@orpc/openapi");
13055
+ var CODEX_API_TAG = "codex";
13056
+ function createCodexApiRouter(deps) {
13057
+ const authed = doorApiAuth(deps.expectedToken);
13058
+ return {
13059
+ codex: {
13060
+ status: authed.meta((0, import_openapi2.openapi)({ method: "GET", path: "/rest/codex/status", summary: "Read the Codex sign-in and the codex providers", tags: [CODEX_API_TAG] })).output(CodexStatusOutputSchema).handler(() => {
13061
+ const status = deps.codexStatus();
13062
+ return { signIn: status.signIn, codexProviders: status.codexProviders };
13063
+ }),
13064
+ logout: authed.meta((0, import_openapi2.openapi)({ 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())
13065
+ }
13066
+ };
13067
+ }
12877
13068
 
12878
13069
  // src/frontdoor/eventsApi.ts
12879
13070
  var import_client2 = require("@orpc/client");
13071
+ var import_openapi3 = require("@orpc/openapi");
12880
13072
  var import_server3 = require("@orpc/server");
12881
13073
 
12882
13074
  // src/frontdoor/eventSchemas.ts
@@ -12923,7 +13115,7 @@ function createEventsApiRouter(deps) {
12923
13115
  const authed = doorApiAuth(deps.expectedToken);
12924
13116
  return {
12925
13117
  events: {
12926
- subscribe: authed.route({ method: "GET", path: "/rest/events", summary: "Stream the door's every event source (SSE)", tags: [EVENTS_API_TAG] }).input(DoorEventSourceQuerySchema).output((0, import_server3.eventIterator)(DoorEventSchema)).handler(async function* ({ input, signal }) {
13118
+ subscribe: authed.meta((0, import_openapi3.openapi)({ method: "GET", path: "/rest/events", summary: "Stream the door's every event source (SSE)", tags: [EVENTS_API_TAG] })).input(DoorEventSourceQuerySchema).output((0, import_server3.eventIterator)(DoorEventSchema)).handler(async function* ({ input, signal }) {
12927
13119
  if (input.sources !== void 0) {
12928
13120
  const live = deps.events.sources();
12929
13121
  const unknown = input.sources.filter((source) => !live.includes(source));
@@ -12955,9 +13147,120 @@ function createEventsApiRouter(deps) {
12955
13147
  };
12956
13148
  }
12957
13149
 
13150
+ // src/frontdoor/lifecycleApi.ts
13151
+ var import_client3 = require("@orpc/client");
13152
+ var import_openapi4 = require("@orpc/openapi");
13153
+ init_update();
13154
+ var FRONTDOOR_API_TAG = "frontdoor";
13155
+ var UPDATE_API_TAG = "update";
13156
+ function createLifecycleApiRouter(deps) {
13157
+ const authed = doorApiAuth(deps.expectedToken);
13158
+ return {
13159
+ frontdoor: {
13160
+ restart: authed.meta((0, import_openapi4.openapi)({ 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 }) => {
13161
+ context.afterResponse(deps.restartDoor);
13162
+ return { action: "restarting", previousPid: deps.doorPid };
13163
+ })
13164
+ },
13165
+ update: {
13166
+ check: authed.meta((0, import_openapi4.openapi)({ method: "GET", path: "/rest/update/check", summary: "Check whether a newer release exists", tags: [UPDATE_API_TAG] })).output(UpdateCheckOutputSchema).handler(async () => {
13167
+ try {
13168
+ return await deps.checkForUpdate();
13169
+ } catch (error) {
13170
+ if (error instanceof UpdateChannelError) {
13171
+ throw new import_client3.ORPCError("PRECONDITION_FAILED", { message: error.message });
13172
+ }
13173
+ if (error instanceof UpdateConflictError) {
13174
+ throw new import_client3.ORPCError("CONFLICT", { message: error.message });
13175
+ }
13176
+ if (error instanceof UpdateDownloadError) {
13177
+ throw new import_client3.ORPCError("BAD_GATEWAY", { message: error.message });
13178
+ }
13179
+ throw error;
13180
+ }
13181
+ })
13182
+ }
13183
+ };
13184
+ }
13185
+
13186
+ // src/frontdoor/launchApi.ts
13187
+ var import_client4 = require("@orpc/client");
13188
+ var import_openapi5 = require("@orpc/openapi");
13189
+ init_cliError();
13190
+
13191
+ // src/frontdoor/launchSchemas.ts
13192
+ var import_node_path30 = __toESM(require("node:path"), 1);
13193
+ var import_zod21 = require("zod");
13194
+ init_claudeVersion();
13195
+ init_identity();
13196
+ var LaunchResolveInputSchema = import_zod21.z.strictObject({
13197
+ path: import_zod21.z.string().min(1),
13198
+ /** `@name`, launch flags, then the arguments for `claude`; empty for a bare launch. */
13199
+ argv: import_zod21.z.readonly(import_zod21.z.array(import_zod21.z.string())).optional(),
13200
+ /** 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. */
13201
+ env: import_zod21.z.record(import_zod21.z.string(), import_zod21.z.string()).optional()
13202
+ }).refine((input) => import_node_path30.default.isAbsolute(input.path), { message: "path must be absolute: the door cannot resolve a relative path against the caller's working directory" });
13203
+ var LaunchPoolDecisionSchema = import_zod21.z.strictObject({
13204
+ name: import_zod21.z.string(),
13205
+ reasons: import_zod21.z.readonly(import_zod21.z.array(import_zod21.z.string())),
13206
+ movedOff: import_zod21.z.strictObject({ identity: import_zod21.z.string(), reason: import_zod21.z.string() }).optional()
13207
+ });
13208
+ var LaunchDecisionSchema = import_zod21.z.strictObject({
13209
+ identity: import_zod21.z.string().optional(),
13210
+ identitySource: import_zod21.z.enum(IDENTITY_DECISION_SOURCES),
13211
+ pool: LaunchPoolDecisionSchema.optional(),
13212
+ configDirEscapeHatch: import_zod21.z.boolean(),
13213
+ configDir: import_zod21.z.string().optional(),
13214
+ configProfile: import_zod21.z.string().optional(),
13215
+ configProfileSource: import_zod21.z.enum(CONFIG_PROFILE_DECISION_SOURCES),
13216
+ provider: import_zod21.z.string().optional()
13217
+ });
13218
+ var LaunchFlagsSchema = import_zod21.z.strictObject({
13219
+ skipPermissions: import_zod21.z.boolean(),
13220
+ remoteControl: import_zod21.z.boolean(),
13221
+ headroom: import_zod21.z.boolean(),
13222
+ trackUsage: import_zod21.z.boolean()
13223
+ });
13224
+ var LaunchResolveOutputSchema = import_zod21.z.strictObject({
13225
+ decision: LaunchDecisionSchema,
13226
+ flags: LaunchFlagsSchema,
13227
+ claudeVersion: import_zod21.z.strictObject({ version: import_zod21.z.string(), source: import_zod21.z.enum(CLAUDE_VERSION_SOURCES) }).optional(),
13228
+ /** The real `claude` binary the launch would spawn, on the door's host. */
13229
+ bin: import_zod21.z.string(),
13230
+ /** The arguments the launch would pass it: the tool's own flags, then `CLAUDE_EXTRA_FLAGS`, then the caller's own. */
13231
+ args: import_zod21.z.readonly(import_zod21.z.array(import_zod21.z.string())),
13232
+ /** The credential the launch would authenticate with, by target and source kinds. Absent when none applies. */
13233
+ credential: import_zod21.z.strictObject({ subject: import_zod21.z.enum(["provider", "identity"]), name: import_zod21.z.string(), summary: CredentialSummarySchema }).optional(),
13234
+ routing: import_zod21.z.strictObject({ frontDoor: import_zod21.z.boolean(), headroom: import_zod21.z.boolean() }),
13235
+ /** The names of the environment variables the launch would set or unset, sorted. Values are not reported. */
13236
+ environment: import_zod21.z.readonly(import_zod21.z.array(import_zod21.z.string())),
13237
+ warnings: import_zod21.z.readonly(import_zod21.z.array(import_zod21.z.string()))
13238
+ });
13239
+
13240
+ // src/frontdoor/launchApi.ts
13241
+ var LAUNCH_API_TAG = "launch";
13242
+ function createLaunchApiRouter(deps) {
13243
+ const authed = doorApiAuth(deps.expectedToken);
13244
+ return {
13245
+ launch: {
13246
+ resolve: authed.meta((0, import_openapi5.openapi)({ 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 }) => {
13247
+ try {
13248
+ const { resolution, warnings } = deps.resolveLaunch({ path: input.path, argv: input.argv ?? [], env: input.env ?? {} });
13249
+ return { ...resolution, warnings };
13250
+ } catch (error) {
13251
+ if (error instanceof CliError) {
13252
+ throw new import_client4.ORPCError("BAD_REQUEST", { message: error.message });
13253
+ }
13254
+ throw error;
13255
+ }
13256
+ })
13257
+ }
13258
+ };
13259
+ }
13260
+
12958
13261
  // src/frontdoor/controlApi.ts
12959
13262
  var USAGE_API_TAG = "usage";
12960
- var FRONTDOOR_API_TAG = "frontdoor";
13263
+ var FRONTDOOR_API_TAG2 = "frontdoor";
12961
13264
  var CHECK_API_TAG = "check";
12962
13265
  var DOCTOR_API_TAG = "doctor";
12963
13266
  var POOL_API_TAG = "pool";
@@ -12965,11 +13268,11 @@ function createControlApiRouter(deps) {
12965
13268
  const authed = doorApiAuth(deps.expectedToken);
12966
13269
  return {
12967
13270
  usage: {
12968
- list: authed.route({ method: "GET", path: "/rest/usage/snapshots", summary: "List every identity's usage snapshot", tags: [USAGE_API_TAG] }).output(UsageListOutputSchema).handler(() => ({ snapshots: deps.usageSnapshots() })),
12969
- effectiveWindow: authed.route({ method: "GET", path: "/rest/usage/windows", summary: "Read one identity's effective quota windows", tags: [USAGE_API_TAG] }).input(UsageWindowsInputSchema).output(UsageWindowsOutputSchema).handler(({ input }) => {
13271
+ list: authed.meta((0, import_openapi6.openapi)({ method: "GET", path: "/rest/usage/snapshots", summary: "List every identity's usage snapshot", tags: [USAGE_API_TAG] })).output(UsageListOutputSchema).handler(() => ({ snapshots: deps.usageSnapshots() })),
13272
+ effectiveWindow: authed.meta((0, import_openapi6.openapi)({ method: "GET", path: "/rest/usage/windows", summary: "Read one identity's effective quota windows", tags: [USAGE_API_TAG] })).input(UsageWindowsInputSchema).output(UsageWindowsOutputSchema).handler(({ input }) => {
12970
13273
  const snapshot = deps.usageSnapshotOf(input.identity);
12971
13274
  if (snapshot === void 0) {
12972
- throw new import_client3.ORPCError("NOT_FOUND", { message: `identity ${input.identity} has no usage snapshot yet, so no quota window has been observed for it` });
13275
+ throw new import_client5.ORPCError("NOT_FOUND", { message: `identity ${input.identity} has no usage snapshot yet, so no quota window has been observed for it` });
12973
13276
  }
12974
13277
  const provider = input.provider ?? ANTHROPIC_PROVIDER;
12975
13278
  const rateLimit = snapshot.providers[provider]?.rateLimit;
@@ -12983,34 +13286,34 @@ function createControlApiRouter(deps) {
12983
13286
  ...unified?.sevenDay === void 0 ? {} : { sevenDay: effectiveWindow(unified.sevenDay, now) }
12984
13287
  };
12985
13288
  }),
12986
- live: authed.route({ 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 }) => {
13289
+ live: authed.meta((0, import_openapi6.openapi)({ 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 }) => {
12987
13290
  const sessions = deps.liveRateLimits(input.session);
12988
13291
  if (input.session !== void 0 && sessions.length === 0) {
12989
13292
  if (deps.list().some((session) => session.id === input.session)) {
12990
- throw new import_client3.ORPCError("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` });
13293
+ throw new import_client5.ORPCError("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` });
12991
13294
  }
12992
- throw new import_client3.ORPCError("NOT_FOUND", { message: rcSessionNotObservedMessage(input.session) });
13295
+ throw new import_client5.ORPCError("NOT_FOUND", { message: rcSessionNotObservedMessage(input.session) });
12993
13296
  }
12994
13297
  return { latest: deps.latestRateLimit(), sessions };
12995
13298
  })
12996
13299
  },
12997
13300
  frontdoor: {
12998
- status: authed.route({ method: "GET", path: "/rest/frontdoor/status", summary: "Read the front door's status", tags: [FRONTDOOR_API_TAG] }).output(FrontDoorStatusOutputSchema).handler(() => deps.frontDoorStatus()),
12999
- sessions: authed.route({ 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 }))
13301
+ status: authed.meta((0, import_openapi6.openapi)({ method: "GET", path: "/rest/frontdoor/status", summary: "Read the front door's status", tags: [FRONTDOOR_API_TAG2] })).output(FrontDoorStatusOutputSchema).handler(() => deps.frontDoorStatus()),
13302
+ sessions: authed.meta((0, import_openapi6.openapi)({ 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 }))
13000
13303
  },
13001
13304
  check: {
13002
13305
  // 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.
13003
- run: authed.route({ 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)))
13306
+ run: authed.meta((0, import_openapi6.openapi)({ 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)))
13004
13307
  },
13005
13308
  doctor: {
13006
- run: authed.route({ method: "GET", path: "/rest/doctor", summary: "Run the doctor report", tags: [DOCTOR_API_TAG] }).output(DoctorRunOutputSchema).handler(() => deps.doctorReport())
13309
+ run: authed.meta((0, import_openapi6.openapi)({ method: "GET", path: "/rest/doctor", summary: "Run the doctor report", tags: [DOCTOR_API_TAG] })).output(DoctorRunOutputSchema).handler(() => deps.doctorReport())
13007
13310
  },
13008
13311
  pool: {
13009
- pick: authed.route({ 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 }) => {
13312
+ pick: authed.meta((0, import_openapi6.openapi)({ 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 }) => {
13010
13313
  const report = deps.poolPick(input.pool, input.path);
13011
13314
  if (report === void 0) {
13012
13315
  const live = deps.poolNames();
13013
- throw new import_client3.ORPCError("NOT_FOUND", {
13316
+ throw new import_client5.ORPCError("NOT_FOUND", {
13014
13317
  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(", ")}`
13015
13318
  });
13016
13319
  }
@@ -13020,13 +13323,15 @@ function createControlApiRouter(deps) {
13020
13323
  };
13021
13324
  }
13022
13325
  function createDoorApiRouter(deps) {
13023
- return { ...createRcApiRouter(deps), ...createControlApiRouter(deps), ...createEventsApiRouter(deps) };
13326
+ const control = createControlApiRouter(deps);
13327
+ const lifecycle = createLifecycleApiRouter(deps);
13328
+ return { ...createRcApiRouter(deps), ...control, ...lifecycle, ...createCodexApiRouter(deps), ...createLaunchApiRouter(deps), ...createEventsApiRouter(deps), frontdoor: { ...control.frontdoor, ...lifecycle.frontdoor } };
13024
13329
  }
13025
13330
  function createDoorApiNodeHandler(deps) {
13026
13331
  return doorApiNodeHandlerOf(createDoorApiRouter(deps), deps.expectedToken);
13027
13332
  }
13028
13333
  function frontDoorApiClient(port, ca, token) {
13029
- return (0, import_client3.createORPCClient)(frontDoorApiLink(port, ca, token));
13334
+ return (0, import_client5.createORPCClient)(frontDoorApiLink(port, ca, token));
13030
13335
  }
13031
13336
 
13032
13337
  // src/frontdoor/doorClient.ts
@@ -14980,7 +15285,7 @@ data: ${JSON.stringify(envelope)}
14980
15285
  }
14981
15286
 
14982
15287
  // src/frontdoor/rcSelfHostMint.ts
14983
- var import_node_path30 = __toESM(require("node:path"), 1);
15288
+ var import_node_path31 = __toESM(require("node:path"), 1);
14984
15289
  init_account();
14985
15290
  var CREDENTIALS_FILE = ".credentials.json";
14986
15291
  var CLAUDE_JSON2 = ".claude.json";
@@ -15005,7 +15310,7 @@ function readJsonObject(fs12, file) {
15005
15310
  return isRecord11(parsed) ? parsed : void 0;
15006
15311
  }
15007
15312
  function readRcSelfHostRecord(fs12, frontdoorDir) {
15008
- const parsed = readJsonObject(fs12, import_node_path30.default.join(frontdoorDir, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE));
15313
+ const parsed = readJsonObject(fs12, import_node_path31.default.join(frontdoorDir, RC_SELF_HOST_RECORD_DIR, RC_SELF_HOST_RECORD_FILE));
15009
15314
  if (parsed === void 0) {
15010
15315
  return void 0;
15011
15316
  }
@@ -15019,11 +15324,11 @@ function mintRcSelfHostCredential(deps) {
15019
15324
  if (!isIdentityName(deps.identity)) {
15020
15325
  throw new Error(`"${deps.identity}" is not a valid identity name.`);
15021
15326
  }
15022
- const identityDir = import_node_path30.default.join(deps.identitiesDir, deps.identity);
15023
- const credentialsFile = import_node_path30.default.join(identityDir, CREDENTIALS_FILE);
15024
- const claudeJsonFile = import_node_path30.default.join(identityDir, CLAUDE_JSON2);
15025
- const recordDir = import_node_path30.default.join(deps.frontdoorDir, RC_SELF_HOST_RECORD_DIR);
15026
- const recordFile = import_node_path30.default.join(recordDir, RC_SELF_HOST_RECORD_FILE);
15327
+ const identityDir = import_node_path31.default.join(deps.identitiesDir, deps.identity);
15328
+ const credentialsFile = import_node_path31.default.join(identityDir, CREDENTIALS_FILE);
15329
+ const claudeJsonFile = import_node_path31.default.join(identityDir, CLAUDE_JSON2);
15330
+ const recordDir = import_node_path31.default.join(deps.frontdoorDir, RC_SELF_HOST_RECORD_DIR);
15331
+ const recordFile = import_node_path31.default.join(recordDir, RC_SELF_HOST_RECORD_FILE);
15027
15332
  const previousRecord = readRcSelfHostRecord(deps.fs, deps.frontdoorDir);
15028
15333
  const existingCredentials = readJsonObject(deps.fs, credentialsFile);
15029
15334
  const existingOauth = isRecord11(existingCredentials?.claudeAiOauth) ? existingCredentials.claudeAiOauth : void 0;
@@ -15039,7 +15344,7 @@ function mintRcSelfHostCredential(deps) {
15039
15344
  const organizationUuid = deps.newUuid();
15040
15345
  const accountUuid = deps.newUuid();
15041
15346
  const mintedAt = new Date(deps.now()).toISOString();
15042
- deps.fs.mkdirPrivate(import_node_path30.default.dirname(credentialsFile));
15347
+ deps.fs.mkdirPrivate(import_node_path31.default.dirname(credentialsFile));
15043
15348
  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)}
15044
15349
  `);
15045
15350
  const claudeJson = readJsonObject(deps.fs, claudeJsonFile) ?? {};
@@ -15294,6 +15599,9 @@ init_ownCli();
15294
15599
  CheckReportJsonSchema,
15295
15600
  CheckRunInputSchema,
15296
15601
  CliError,
15602
+ CodexLogoutOutputSchema,
15603
+ CodexSignInSchema,
15604
+ CodexStatusOutputSchema,
15297
15605
  ConfigProfileSchema,
15298
15606
  CredentialCacheSchema,
15299
15607
  CredentialSchema,
@@ -15318,6 +15626,7 @@ init_ownCli();
15318
15626
  FARM_MANIFEST_FILENAME,
15319
15627
  FrontDoorControlMaterialError,
15320
15628
  FrontDoorNotServingError,
15629
+ FrontDoorRestartOutputSchema,
15321
15630
  FrontDoorSessionStatusSchema,
15322
15631
  FrontDoorSessionsOutputSchema,
15323
15632
  FrontDoorStartError,
@@ -15335,6 +15644,8 @@ init_ownCli();
15335
15644
  LAUNCH_EVENT_SOURCE,
15336
15645
  LaunchLifecycleEventSchema,
15337
15646
  LaunchRefusedError,
15647
+ LaunchResolveInputSchema,
15648
+ LaunchResolveOutputSchema,
15338
15649
  LegacyProviderFileError,
15339
15650
  OWN_CLI_FILE_NAME,
15340
15651
  PROMPT_CACHE_TTL_MS,
@@ -15381,6 +15692,7 @@ init_ownCli();
15381
15692
  RcStreamEnvelopeSchema,
15382
15693
  RcStreamEventSchema,
15383
15694
  USAGE_EVENT_SOURCE,
15695
+ UpdateCheckOutputSchema,
15384
15696
  UsageError,
15385
15697
  UsageListOutputSchema,
15386
15698
  UsageLiveOutputSchema,
@@ -15423,14 +15735,17 @@ init_ownCli();
15423
15735
  collectDoctorReport,
15424
15736
  collectFrontDoorStatus,
15425
15737
  collectPoolPick,
15738
+ createCodexApiRouter,
15426
15739
  createControlApiRouter,
15427
15740
  createDoorApiNodeHandler,
15428
15741
  createDoorApiRouter,
15429
15742
  createDoorEventHub,
15430
15743
  createDoorHealthPublisher,
15431
15744
  createEventsApiRouter,
15745
+ createLaunchApiRouter,
15432
15746
  createLaunchEventPublisher,
15433
15747
  createLeafCache,
15748
+ createLifecycleApiRouter,
15434
15749
  createProfile,
15435
15750
  createQuotaExpiringPublisher,
15436
15751
  createRcApiNodeHandler,
@@ -15538,7 +15853,9 @@ init_ownCli();
15538
15853
  requirePool,
15539
15854
  resolveAgentShimHome,
15540
15855
  resolveClaudeHome,
15856
+ resolveClaudeLaunch,
15541
15857
  resolveDecisions,
15858
+ resolveLaunch,
15542
15859
  resolveLaunchSelection,
15543
15860
  resolveLayoutPaths,
15544
15861
  resolveSupervisorConfig,