agent-shim 11.27.0 → 11.29.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
@@ -285,7 +285,11 @@ var init_schema = __esm({
285
285
  headroom: import_zod.z.boolean().optional(),
286
286
  trackUsage: import_zod.z.boolean().optional(),
287
287
  /** The exact Claude Code version to run, as it is named in Claude Code's versions directory (`2.1.220`). A pin that is not installed fails the launch; it never falls back to the highest version. */
288
- claudeVersion: import_zod.z.string().regex(NUMERIC_DOTTED_VERSION_RE, "must be an exact dotted-numeric Claude Code version such as 2.1.220").optional()
288
+ claudeVersion: import_zod.z.string().regex(NUMERIC_DOTTED_VERSION_RE, "must be an exact dotted-numeric Claude Code version such as 2.1.220").optional(),
289
+ /** How long the launcher waits after its own output before it starts claude, so that output can be read before Claude Code takes over the terminal (`5s`, `500ms`). Applies only when a terminal is watching. */
290
+ delay: import_zod.z.string().regex(DURATION_RE, "must be a duration such as 5s or 500ms").optional(),
291
+ /** Whether the launcher waits for a key press after its own output before it starts claude. Takes the place of `delay` when both are set. Applies only when a terminal is watching. */
292
+ pause: import_zod.z.boolean().optional()
289
293
  });
290
294
  CREDENTIAL_TARGETS = ["bearer", "apiKey", "oauthToken"];
291
295
  PROVIDER_CREDENTIAL_TARGETS = ["bearer", "apiKey"];
@@ -1388,6 +1392,12 @@ function flattenLayers(layers, options) {
1388
1392
  if (layer.launch.claudeVersion !== void 0) {
1389
1393
  launch.claudeVersion = layer.launch.claudeVersion;
1390
1394
  }
1395
+ if (layer.launch.delay !== void 0) {
1396
+ launch.delay = layer.launch.delay;
1397
+ }
1398
+ if (layer.launch.pause !== void 0) {
1399
+ launch.pause = layer.launch.pause;
1400
+ }
1391
1401
  }
1392
1402
  if (layer.entries === void 0) {
1393
1403
  continue;
@@ -1486,11 +1496,15 @@ var init_flatten = __esm({
1486
1496
  });
1487
1497
 
1488
1498
  // src/resolve/decide.ts
1489
- function unclassifiedEntryMessage(names) {
1499
+ function unclassifiedEntrySummary(names) {
1490
1500
  const quoted = names.map((name) => `"${name}"`).join(", ");
1491
- const subject = names.length === 1 ? `${quoted} is not` : `${String(names.length)} entries are not`;
1492
- const excluded = names.length === 1 ? "it is excluded" : `they are excluded: ${quoted}`;
1493
- return `${subject} in the category map, so ${excluded}. Run \`agent-shim configure\` to classify ${names.length === 1 ? "it" : "them"}, which records the answer in the local overlay without touching the shipped default map.`;
1501
+ return names.length === 1 ? `${quoted} is not in the category map, so it is excluded` : `${String(names.length)} entries are not in the category map, so they are excluded: ${quoted}`;
1502
+ }
1503
+ function unclassifiedEntryFix(names) {
1504
+ return `Run \`agent-shim configure\` to classify ${names.length === 1 ? "it" : "them"}`;
1505
+ }
1506
+ function unclassifiedEntryMessage(names) {
1507
+ return `${unclassifiedEntrySummary(names)}. ${unclassifiedEntryFix(names)}.`;
1494
1508
  }
1495
1509
  function selectRule(relPath, flattened, context) {
1496
1510
  const eliminated = [];
@@ -2964,7 +2978,7 @@ var init_package = __esm({
2964
2978
  "package.json"() {
2965
2979
  package_default = {
2966
2980
  name: "agent-shim",
2967
- version: "11.27.0",
2981
+ version: "11.29.0",
2968
2982
  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.",
2969
2983
  license: "MIT",
2970
2984
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -4130,20 +4144,53 @@ var init_supervisor = __esm({
4130
4144
  }
4131
4145
  });
4132
4146
 
4133
- // src/logStyle.ts
4134
- function styledDiagnostic(style, colour, line) {
4135
- const lead = DIAGNOSTIC_LEAD.exec(line);
4136
- if (lead === null) {
4137
- return style([colour], line);
4147
+ // src/launcher/report.ts
4148
+ function renderReport(rows, style) {
4149
+ if (rows.length === 0) {
4150
+ return [];
4151
+ }
4152
+ const labelWidth = Math.max(...rows.map((row) => row.label.length));
4153
+ const indent = " ".repeat(COLUMN_GAP.length);
4154
+ const lines = [style(["bold"], REPORT_HEADING)];
4155
+ for (const row of rows) {
4156
+ const detail = row.detail === void 0 ? "" : ` ${style(["dim"], `(${row.detail})`)}`;
4157
+ lines.push(`${indent}${style(["dim"], row.label.padEnd(labelWidth))}${COLUMN_GAP}${row.value}${detail}`);
4158
+ for (const note of row.notes ?? []) {
4159
+ lines.push(`${indent}${" ".repeat(labelWidth)}${COLUMN_GAP}${style(["dim"], note)}`);
4160
+ }
4138
4161
  }
4139
- const [whole, prefix = "", code = "", separator = ""] = lead;
4140
- return `${style([colour], prefix)}${style([colour, "bold"], code)}${style([colour], `${separator}${line.slice(whole.length)}`)}`;
4162
+ return lines;
4163
+ }
4164
+ var REPORT_HEADING, COLUMN_GAP;
4165
+ var init_report = __esm({
4166
+ "src/launcher/report.ts"() {
4167
+ "use strict";
4168
+ REPORT_HEADING = "agent-shim";
4169
+ COLUMN_GAP = " ";
4170
+ }
4171
+ });
4172
+
4173
+ // src/logStyle.ts
4174
+ function styledDiagnostic(style, colour, text) {
4175
+ return text.split("\n").map((line, index) => {
4176
+ const lead = index === 0 ? DIAGNOSTIC_LEAD.exec(line) : null;
4177
+ if (lead === null) {
4178
+ return style([colour], line);
4179
+ }
4180
+ const [whole, prefix = "", code = "", separator = ""] = lead;
4181
+ return `${style([colour], prefix)}${style([colour, "bold"], code)}${style([colour], `${separator}${line.slice(whole.length)}`)}`;
4182
+ }).join("\n");
4141
4183
  }
4142
4184
  function createLogPort(sinks, styleFor) {
4143
4185
  return {
4144
4186
  info: (message) => {
4145
4187
  sinks.out(styleFor.out(["dim"], message));
4146
4188
  },
4189
+ report: (rows) => {
4190
+ for (const line of renderReport(rows, styleFor.out)) {
4191
+ sinks.out(line);
4192
+ }
4193
+ },
4147
4194
  warn: (message) => {
4148
4195
  sinks.warn(styledDiagnostic(styleFor.err, "yellow", message));
4149
4196
  },
@@ -4160,6 +4207,7 @@ var init_logStyle = __esm({
4160
4207
  "src/logStyle.ts"() {
4161
4208
  "use strict";
4162
4209
  import_node_util = require("node:util");
4210
+ init_report();
4163
4211
  DIAGNOSTIC_LEAD = /^(agent-shim: )([A-Z][A-Z0-9_]*)(: )/;
4164
4212
  }
4165
4213
  });
@@ -4402,7 +4450,7 @@ function realResolveClaudeBinary(isOwnBinary) {
4402
4450
  function realInstalledClaudeVersions() {
4403
4451
  return installedVersions(listVersionsDir(defaultVersionsDir()));
4404
4452
  }
4405
- var import_node_child_process2, import_node_crypto8, import_node_fs2, import_node_os2, import_node_path14, import_node_sea, realFsPort, OWNER_ONLY_DIR_MODE, OWNER_ONLY_FILE_MODE, PERMISSION_BITS, realFarmFs, INT32_BYTE_LENGTH, PS_TIMEOUT_MS, realRunPort, MACOS_GUI_SESSION_MANAGER, realCredentialPort, SOCKET_PERMISSION_BITS, realHeadroomSocketTrust, realSpawnPort, realProcPort, realLogPort, EXECUTE_BITS_MASK, WINDOWS_DEFAULT_PATHEXT;
4453
+ var import_node_child_process2, import_node_crypto8, import_node_fs2, import_node_os2, import_node_path14, import_node_sea, realFsPort, OWNER_ONLY_DIR_MODE, OWNER_ONLY_FILE_MODE, PERMISSION_BITS, realFarmFs, INT32_BYTE_LENGTH, KEY_POLL_MS, CTRL_C_BYTE, realHoldPort, PS_TIMEOUT_MS, realRunPort, MACOS_GUI_SESSION_MANAGER, realCredentialPort, SOCKET_PERMISSION_BITS, realHeadroomSocketTrust, realSpawnPort, realProcPort, realLogPort, EXECUTE_BITS_MASK, WINDOWS_DEFAULT_PATHEXT;
4406
4454
  var init_realPorts = __esm({
4407
4455
  "src/realPorts.ts"() {
4408
4456
  "use strict";
@@ -4551,6 +4599,31 @@ var init_realPorts = __esm({
4551
4599
  }
4552
4600
  };
4553
4601
  INT32_BYTE_LENGTH = 4;
4602
+ KEY_POLL_MS = 25;
4603
+ CTRL_C_BYTE = 3;
4604
+ realHoldPort = {
4605
+ attended: () => process.stdin.isTTY && process.stdout.isTTY,
4606
+ sleep: realSleepSync,
4607
+ waitForKey: () => {
4608
+ process.stdin.setRawMode(true);
4609
+ try {
4610
+ const buffer = Buffer.alloc(1);
4611
+ for (; ; ) {
4612
+ try {
4613
+ const read = import_node_fs2.default.readSync(process.stdin.fd, buffer, 0, buffer.length, null);
4614
+ return read > 0 && buffer[0] === CTRL_C_BYTE ? "interrupt" : "key";
4615
+ } catch (error) {
4616
+ if (!(error instanceof Error && "code" in error && error.code === "EAGAIN")) {
4617
+ throw error;
4618
+ }
4619
+ realSleepSync(KEY_POLL_MS);
4620
+ }
4621
+ }
4622
+ } finally {
4623
+ process.stdin.setRawMode(false);
4624
+ }
4625
+ }
4626
+ };
4554
4627
  PS_TIMEOUT_MS = 2e3;
4555
4628
  realRunPort = {
4556
4629
  run(command, args) {
@@ -7391,6 +7464,7 @@ function parseLauncherArgv(argv) {
7391
7464
  let configProfile;
7392
7465
  let provider;
7393
7466
  let claudeVersion;
7467
+ let delay;
7394
7468
  const booleans = {};
7395
7469
  const categoryFlags = [];
7396
7470
  const shareFlags = [];
@@ -7448,6 +7522,9 @@ function parseLauncherArgv(argv) {
7448
7522
  case "--claude-version":
7449
7523
  claudeVersion = value;
7450
7524
  break;
7525
+ case "--delay":
7526
+ delay = value;
7527
+ break;
7451
7528
  case "--category":
7452
7529
  categoryFlags.push(value);
7453
7530
  break;
@@ -7470,6 +7547,7 @@ function parseLauncherArgv(argv) {
7470
7547
  ...configProfile === void 0 ? {} : { configProfile },
7471
7548
  ...provider === void 0 ? {} : { provider },
7472
7549
  ...claudeVersion === void 0 ? {} : { claudeVersion },
7550
+ ...delay === void 0 ? {} : { delay },
7473
7551
  ...native ? { native: true } : {},
7474
7552
  ...booleans,
7475
7553
  categoryFlags,
@@ -7493,13 +7571,14 @@ var init_argv = __esm({
7493
7571
  positional;
7494
7572
  flag;
7495
7573
  };
7496
- VALUED_FLAGS = ["--identity", "--config-profile", "--provider", "--claude-version", "--category", "--share", "--hide"];
7574
+ VALUED_FLAGS = ["--identity", "--config-profile", "--provider", "--claude-version", "--delay", "--category", "--share", "--hide"];
7497
7575
  BOOLEAN_FLAGS = [
7498
7576
  { flag: "--headroom", key: "headroom" },
7499
7577
  { flag: "--track-usage", key: "trackUsage" },
7500
7578
  { flag: "--skip-permissions", key: "skipPermissions" },
7501
7579
  { flag: "--remote-control", key: "remoteControl" },
7502
- { flag: "--wait", key: "wait" }
7580
+ { flag: "--wait", key: "wait" },
7581
+ { flag: "--pause", key: "pause" }
7503
7582
  ];
7504
7583
  LAUNCHER_FLAG_NAMES = [
7505
7584
  ...VALUED_FLAGS,
@@ -7686,9 +7765,23 @@ function resolveLaunchFlags(params) {
7686
7765
  skipPermissions: params.flags?.skipPermissions ?? parseEnvBool("AGENT_SHIM_SKIP_PERMISSIONS", params.env.AGENT_SHIM_SKIP_PERMISSIONS) ?? params.cascade?.skipPermissions ?? false,
7687
7766
  remoteControl: params.flags?.remoteControl ?? parseEnvBool("AGENT_SHIM_REMOTE_CONTROL", params.env.AGENT_SHIM_REMOTE_CONTROL) ?? params.cascade?.remoteControl ?? false,
7688
7767
  headroom: params.flags?.headroom ?? parseEnvBool("AGENT_SHIM_HEADROOM", params.env.AGENT_SHIM_HEADROOM) ?? params.cascade?.headroom ?? false,
7689
- trackUsage: params.flags?.trackUsage ?? parseEnvBool("AGENT_SHIM_TRACK_USAGE", params.env.AGENT_SHIM_TRACK_USAGE) ?? params.cascade?.trackUsage ?? true
7768
+ trackUsage: params.flags?.trackUsage ?? parseEnvBool("AGENT_SHIM_TRACK_USAGE", params.env.AGENT_SHIM_TRACK_USAGE) ?? params.cascade?.trackUsage ?? true,
7769
+ pause: params.flags?.pause ?? parseEnvBool("AGENT_SHIM_PAUSE", params.env.AGENT_SHIM_PAUSE) ?? params.cascade?.pause ?? false,
7770
+ delayMs: resolveDelayMs(params)
7690
7771
  };
7691
7772
  }
7773
+ function resolveDelayMs(params) {
7774
+ const fromEnv = params.env.AGENT_SHIM_DELAY === "" ? void 0 : params.env.AGENT_SHIM_DELAY;
7775
+ const [literal, source] = params.flags?.delay !== void 0 ? [params.flags.delay, "--delay"] : fromEnv !== void 0 ? [fromEnv, "AGENT_SHIM_DELAY"] : [params.cascade?.delay, "launch.delay"];
7776
+ if (literal === void 0) {
7777
+ return 0;
7778
+ }
7779
+ try {
7780
+ return parseDuration(literal);
7781
+ } catch (error) {
7782
+ throw new UsageError(`${source}: ${error instanceof Error ? error.message : String(error)}`);
7783
+ }
7784
+ }
7692
7785
  function buildFlagArgs(flags) {
7693
7786
  const args = [];
7694
7787
  if (flags.skipPermissions) {
@@ -7761,6 +7854,8 @@ var init_flags = __esm({
7761
7854
  "use strict";
7762
7855
  import_node_path36 = __toESM(require("node:path"), 1);
7763
7856
  init_envBool();
7857
+ init_cliError();
7858
+ init_conditions();
7764
7859
  init_credential();
7765
7860
  init_headers();
7766
7861
  init_capability();
@@ -7957,7 +8052,9 @@ function diagnosticLines(diagnostics) {
7957
8052
  if (diagnostic.code === "UNCLASSIFIED_ENTRY") {
7958
8053
  if (!unclassifiedReported) {
7959
8054
  unclassifiedReported = true;
7960
- lines.push({ severity: diagnostic.severity, text: `agent-shim: ${diagnostic.code}: ${unclassifiedEntryMessage(unclassified.filter((name) => name !== void 0))}` });
8055
+ const names = unclassified.filter((name) => name !== void 0);
8056
+ lines.push({ severity: diagnostic.severity, text: `agent-shim: ${diagnostic.code}: ${unclassifiedEntrySummary(names)}
8057
+ ${unclassifiedEntryFix(names)}.` });
7961
8058
  }
7962
8059
  continue;
7963
8060
  }
@@ -7965,8 +8062,8 @@ function diagnosticLines(diagnostics) {
7965
8062
  }
7966
8063
  return lines;
7967
8064
  }
7968
- function reportDiagnostics(log, diagnostics, options) {
7969
- for (const line of diagnosticLines(diagnostics)) {
8065
+ function printDiagnosticLines(log, lines, options) {
8066
+ for (const line of lines) {
7970
8067
  if (line.severity === "error" && !options.errorsAsWarnings) {
7971
8068
  log.error(line.text);
7972
8069
  } else {
@@ -7974,6 +8071,9 @@ function reportDiagnostics(log, diagnostics, options) {
7974
8071
  }
7975
8072
  }
7976
8073
  }
8074
+ function reportDiagnostics(log, diagnostics, options) {
8075
+ printDiagnosticLines(log, diagnosticLines(diagnostics), options);
8076
+ }
7977
8077
  var init_diagnostics = __esm({
7978
8078
  "src/launcher/diagnostics.ts"() {
7979
8079
  "use strict";
@@ -7981,6 +8081,84 @@ var init_diagnostics = __esm({
7981
8081
  }
7982
8082
  });
7983
8083
 
8084
+ // src/launcher/hold.ts
8085
+ function describeDelay(ms) {
8086
+ return ms % MS_PER_SECOND7 === 0 ? `${String(ms / MS_PER_SECOND7)}s` : `${String(ms)}ms`;
8087
+ }
8088
+ function holdBeforeLaunch(hold, port, log) {
8089
+ if (port === void 0 || !port.attended() || !hold.pause && hold.delayMs <= 0) {
8090
+ return "go";
8091
+ }
8092
+ if (hold.pause) {
8093
+ log.info("agent-shim: paused before launch; press any key to start, or Ctrl-C to cancel");
8094
+ return port.waitForKey() === "interrupt" ? "cancelled" : "go";
8095
+ }
8096
+ log.info(`agent-shim: starting in ${describeDelay(hold.delayMs)}`);
8097
+ port.sleep(hold.delayMs);
8098
+ return "go";
8099
+ }
8100
+ var LAUNCH_CANCELLED_EXIT, MS_PER_SECOND7;
8101
+ var init_hold = __esm({
8102
+ "src/launcher/hold.ts"() {
8103
+ "use strict";
8104
+ LAUNCH_CANCELLED_EXIT = 130;
8105
+ MS_PER_SECOND7 = 1e3;
8106
+ }
8107
+ });
8108
+
8109
+ // src/launcher/launchReport.ts
8110
+ function poolDetail(pool) {
8111
+ const [reason] = pool.reasons;
8112
+ if (pool.movedOff !== void 0) {
8113
+ return { detail: `moved off ${pool.movedOff.identity}: ${pool.movedOff.reason}`, ...reason === void 0 ? {} : { notes: [reason] } };
8114
+ }
8115
+ return reason === void 0 ? {} : { detail: reason };
8116
+ }
8117
+ function decisionRows(facts) {
8118
+ return [
8119
+ { label: "identity", value: facts.identity ?? "(none)", detail: facts.identitySource },
8120
+ ...facts.pool === void 0 ? [] : [
8121
+ {
8122
+ label: "pool",
8123
+ value: facts.pool.name,
8124
+ ...poolDetail(facts.pool)
8125
+ }
8126
+ ],
8127
+ ...facts.profile === void 0 ? [] : [{ label: "profile", value: facts.profile.name, detail: facts.profile.source }],
8128
+ ...facts.provider === void 0 ? [] : [{ label: "provider", value: facts.provider.name, detail: `credential ${facts.provider.credential}` }],
8129
+ ...facts.identityCredential === void 0 ? [] : [{ label: "credential", value: facts.identityCredential, detail: "the identity's own" }]
8130
+ ];
8131
+ }
8132
+ function pinnedVersionRow(version, source) {
8133
+ return { label: "claude", value: version, detail: `pinned by ${source}` };
8134
+ }
8135
+ function routingRows(facts) {
8136
+ if (facts.frontDoor === void 0) {
8137
+ return [];
8138
+ }
8139
+ return [
8140
+ {
8141
+ label: "routing",
8142
+ value: `front door 127.0.0.1:${String(facts.frontDoor.port)}`,
8143
+ ...facts.provider ? {} : { detail: `OAuth via CONNECT 127.0.0.1:${String(facts.frontDoor.connectPort)}` }
8144
+ },
8145
+ ...facts.headroom === void 0 ? [] : [{ label: "headroom", value: "on", detail: `project ${facts.headroom.projectId}` }]
8146
+ ];
8147
+ }
8148
+ function farmRow(links, builtDirectories, adopted) {
8149
+ const counted = (count, singular, plural) => `${String(count)} ${count === 1 ? singular : plural}`;
8150
+ const parts = [counted(links, "link", "links"), counted(builtDirectories, "built directory", "built directories"), ...adopted === 0 ? [] : [`${String(adopted)} adopted`]];
8151
+ return { label: "farm", value: "resynced", detail: parts.join(", ") };
8152
+ }
8153
+ function noteRow(text) {
8154
+ return { label: "note", value: text };
8155
+ }
8156
+ var init_launchReport = __esm({
8157
+ "src/launcher/launchReport.ts"() {
8158
+ "use strict";
8159
+ }
8160
+ });
8161
+
7984
8162
  // src/antigravity/cloudUpstream.ts
7985
8163
  var init_cloudUpstream = __esm({
7986
8164
  "src/antigravity/cloudUpstream.ts"() {
@@ -8161,7 +8339,7 @@ function filterCatalogue(models, catalogue) {
8161
8339
  const excluded = catalogue.exclude === void 0 ? void 0 : (0, import_picomatch4.default)(catalogue.exclude, { dot: true });
8162
8340
  return models.filter((model) => included?.(model.id) !== false && excluded?.(model.id) !== true);
8163
8341
  }
8164
- var import_node_path38, import_picomatch4, import_zod30, DEFAULT_CANDIDATE_URLS, MS_PER_SECOND7, SECONDS_PER_HOUR2, HOURS_PER_DAY5, MS_PER_HOUR5, HOURS_BETWEEN_RETRIES, CATALOGUE_MAX_AGE_MS, CATALOGUE_RETRY_MS, CATALOGUE_REQUEST_SECONDS, CATALOGUE_REQUEST_TIMEOUT_MS, CATALOGUE_REFRESH_TIMEOUT_MS, CatalogueModelSchema, CatalogueCacheSchema;
8342
+ var import_node_path38, import_picomatch4, import_zod30, DEFAULT_CANDIDATE_URLS, MS_PER_SECOND8, SECONDS_PER_HOUR2, HOURS_PER_DAY5, MS_PER_HOUR5, HOURS_BETWEEN_RETRIES, CATALOGUE_MAX_AGE_MS, CATALOGUE_RETRY_MS, CATALOGUE_REQUEST_SECONDS, CATALOGUE_REQUEST_TIMEOUT_MS, CATALOGUE_REFRESH_TIMEOUT_MS, CatalogueModelSchema, CatalogueCacheSchema;
8165
8343
  var init_providerCatalogue = __esm({
8166
8344
  "src/providerCatalogue.ts"() {
8167
8345
  "use strict";
@@ -8169,15 +8347,15 @@ var init_providerCatalogue = __esm({
8169
8347
  import_picomatch4 = __toESM(require("picomatch"), 1);
8170
8348
  import_zod30 = require("zod");
8171
8349
  DEFAULT_CANDIDATE_URLS = 2;
8172
- MS_PER_SECOND7 = 1e3;
8350
+ MS_PER_SECOND8 = 1e3;
8173
8351
  SECONDS_PER_HOUR2 = 3600;
8174
8352
  HOURS_PER_DAY5 = 24;
8175
- MS_PER_HOUR5 = SECONDS_PER_HOUR2 * MS_PER_SECOND7;
8353
+ MS_PER_HOUR5 = SECONDS_PER_HOUR2 * MS_PER_SECOND8;
8176
8354
  HOURS_BETWEEN_RETRIES = 1;
8177
8355
  CATALOGUE_MAX_AGE_MS = HOURS_PER_DAY5 * MS_PER_HOUR5;
8178
8356
  CATALOGUE_RETRY_MS = HOURS_BETWEEN_RETRIES * MS_PER_HOUR5;
8179
8357
  CATALOGUE_REQUEST_SECONDS = 10;
8180
- CATALOGUE_REQUEST_TIMEOUT_MS = CATALOGUE_REQUEST_SECONDS * MS_PER_SECOND7;
8358
+ CATALOGUE_REQUEST_TIMEOUT_MS = CATALOGUE_REQUEST_SECONDS * MS_PER_SECOND8;
8181
8359
  CATALOGUE_REFRESH_TIMEOUT_MS = DEFAULT_CANDIDATE_URLS * CATALOGUE_REQUEST_TIMEOUT_MS;
8182
8360
  CatalogueModelSchema = import_zod30.z.strictObject({ id: import_zod30.z.string().min(1), name: import_zod30.z.string().min(1).optional() });
8183
8361
  CatalogueCacheSchema = import_zod30.z.strictObject({ fetchedAt: import_zod30.z.number(), url: import_zod30.z.string().min(1), models: import_zod30.z.array(CatalogueModelSchema) });
@@ -8506,7 +8684,7 @@ function pickFromPool(decided, params, parsedArgv, readOnly) {
8506
8684
  }
8507
8685
  if (params.supervised?.member !== void 0) {
8508
8686
  const reasons = ["resumed here by the supervising launcher after the previous member ran out of quota"];
8509
- return { identityDecision: { ...decided, name: params.supervised.member }, poolExplanation: `pool ${decided.pool}: ${reasons.join("; ")}`, poolPick: { name: decided.pool, reasons } };
8687
+ return { identityDecision: { ...decided, name: params.supervised.member }, poolPick: { name: decided.pool, reasons } };
8510
8688
  }
8511
8689
  const farmRuntime = params.farm;
8512
8690
  if (farmRuntime === void 0) {
@@ -8537,7 +8715,6 @@ function pickFromPool(decided, params, parsedArgv, readOnly) {
8537
8715
  }
8538
8716
  return {
8539
8717
  identityDecision: { ...decided, name: resolution.identity },
8540
- poolExplanation: resolution.explanation,
8541
8718
  poolPick: { name: decided.pool, reasons: resolution.reasons, ...resolution.movedOff === void 0 ? {} : { movedOff: resolution.movedOff } }
8542
8719
  };
8543
8720
  }
@@ -8565,7 +8742,7 @@ function decideLaunch(params, readOnly) {
8565
8742
  return trimmed === "" ? void 0 : trimmed;
8566
8743
  }
8567
8744
  });
8568
- const { identityDecision, poolExplanation, poolPick } = pickFromPool(decidedIdentity, params, parsedArgv, readOnly);
8745
+ const { identityDecision, poolPick } = pickFromPool(decidedIdentity, params, parsedArgv, readOnly);
8569
8746
  const farmIdentity = configDirEscapeHatchApplies ? void 0 : identityDecision.name;
8570
8747
  const farm = farmIdentity === void 0 ? void 0 : params.farm;
8571
8748
  if (!readOnly && farm !== void 0 && farmIdentity !== void 0) {
@@ -8699,19 +8876,22 @@ function decideLaunch(params, readOnly) {
8699
8876
  ...parsedArgv.skipPermissions === void 0 ? {} : { skipPermissions: parsedArgv.skipPermissions },
8700
8877
  ...parsedArgv.remoteControl === void 0 ? {} : { remoteControl: parsedArgv.remoteControl },
8701
8878
  ...parsedArgv.headroom === void 0 ? {} : { headroom: parsedArgv.headroom },
8702
- ...parsedArgv.trackUsage === void 0 ? {} : { trackUsage: parsedArgv.trackUsage }
8879
+ ...parsedArgv.trackUsage === void 0 ? {} : { trackUsage: parsedArgv.trackUsage },
8880
+ ...parsedArgv.pause === void 0 ? {} : { pause: parsedArgv.pause },
8881
+ ...parsedArgv.delay === void 0 ? {} : { delay: parsedArgv.delay }
8703
8882
  }
8704
8883
  });
8705
8884
  const loginlessProvider = requestedFlags.remoteControl && selectedProvider !== void 0 && farmIdentity !== void 0 && params.hasStoredLogin?.(farmIdentity) === false ? { identity: farmIdentity, provider: selectedProvider.name } : void 0;
8706
- if (loginlessProvider !== void 0 && !readOnly) {
8707
- log.info(`agent-shim: identity ${loginlessProvider.identity} has no stored login, so Remote Control, which needs one, is off for this launch; provider ${loginlessProvider.provider} runs without it`);
8885
+ const notes = [];
8886
+ if (loginlessProvider !== void 0) {
8887
+ notes.push(`${loginlessProvider.identity} has no stored login, so Remote Control is off; provider ${loginlessProvider.provider} runs without it`);
8708
8888
  }
8709
8889
  const flags = loginlessProvider === void 0 ? requestedFlags : { ...requestedFlags, remoteControl: false };
8710
8890
  const catalogue = selectedProvider === void 0 ? void 0 : parseCatalogueCache(params.fs.readFileUtf8(catalogueCachePath(paths, selectedProvider.name)));
8711
8891
  const pickerSettings = selectedProvider === void 0 ? void 0 : modelPickerSettings(selectedProvider.definition, catalogue?.models);
8712
8892
  const callerSettings = hasSettingsArgument(parsedArgv.rest);
8713
- if (pickerSettings !== void 0 && callerSettings && !readOnly) {
8714
- log.info("agent-shim: this launch passes its own --settings, so /model keeps Claude Code's own model names instead of listing the provider's models");
8893
+ if (pickerSettings !== void 0 && callerSettings) {
8894
+ notes.push("--settings was passed, so /model keeps Claude Code's own model names");
8715
8895
  }
8716
8896
  const launcherSettings = mergeSettings([params.supervised?.settings, callerSettings ? void 0 : pickerSettings]);
8717
8897
  const args = buildArgv({
@@ -8733,8 +8913,8 @@ function decideLaunch(params, readOnly) {
8733
8913
  return {
8734
8914
  parsedArgv,
8735
8915
  identityDecision,
8736
- poolExplanation,
8737
8916
  poolPick,
8917
+ notes,
8738
8918
  configDirEscapeHatch: configDirEscapeHatchApplies,
8739
8919
  farmIdentity,
8740
8920
  farmContext,
@@ -8754,10 +8934,18 @@ function prepareLaunch(params) {
8754
8934
  const { paths, proc, log } = params;
8755
8935
  const { env } = proc;
8756
8936
  const decided = decideLaunch(params, false);
8757
- const { identityDecision, configProfileDecision, resolvedProvider, identityCredential, poolExplanation, flags: resolvedFlags, args: finalArgv, configDirEscapeHatch: configDirEscapeHatchApplies, decision } = decided;
8758
- log.info(
8759
- `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)}`)
8760
- );
8937
+ const { identityDecision, configProfileDecision, resolvedProvider, identityCredential, poolPick, notes, flags: resolvedFlags, args: finalArgv, configDirEscapeHatch: configDirEscapeHatchApplies, decision } = decided;
8938
+ const rows = [
8939
+ ...decisionRows({
8940
+ identity: identityDecision.name,
8941
+ identitySource: identityDecision.source,
8942
+ pool: poolPick,
8943
+ profile: configProfileDecision.name === void 0 ? void 0 : { name: configProfileDecision.name, source: configProfileDecision.source },
8944
+ provider: resolvedProvider === void 0 ? void 0 : { name: resolvedProvider.name, credential: `${resolvedProvider.credential.target} from ${describeSource(resolvedProvider.credential.source)}` },
8945
+ identityCredential: identityCredential === void 0 ? void 0 : `${identityCredential.target} from ${describeSource(identityCredential.source)}`
8946
+ })
8947
+ ];
8948
+ let warnings = [];
8761
8949
  const updateCheck = runLaunchUpdateCheck({
8762
8950
  mode: params.updateMode ?? "off",
8763
8951
  checkPath: import_node_path39.default.join(paths.root, "update.check"),
@@ -8792,15 +8980,13 @@ function prepareLaunch(params) {
8792
8980
  }
8793
8981
  throw error;
8794
8982
  }
8795
- reportDiagnostics(log, result.diagnostics, { errorsAsWarnings: false });
8983
+ warnings = diagnosticLines(result.diagnostics);
8796
8984
  if (!result.noOp) {
8797
- log.info(
8798
- `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}`})`
8799
- );
8985
+ rows.push(farmRow(result.manifest.links.length, result.manifest.materialised.length, result.adopted.length));
8800
8986
  }
8801
8987
  }
8802
8988
  if (decided.pinnedVersion !== void 0) {
8803
- log.info(`agent-shim: Claude Code ${decided.pinnedVersion.version} (pinned by ${decided.pinnedVersion.source})`);
8989
+ rows.push(pinnedVersionRow(decided.pinnedVersion.version, decided.pinnedVersion.source));
8804
8990
  }
8805
8991
  const frontDoorPort = params.frontdoor;
8806
8992
  const frontDoorEngaged = resolvedProvider !== void 0 || resolvedFlags.headroom || resolvedFlags.trackUsage;
@@ -8816,14 +9002,11 @@ function prepareLaunch(params) {
8816
9002
  const headroomPort = params.headroom;
8817
9003
  if (resolvedFlags.headroom && headroomPort !== void 0) {
8818
9004
  headroom = headroomPort.ensure({ routesProvider: resolvedProvider !== void 0 });
8819
- const via = resolvedProvider === void 0 ? `OAuth via the door's CONNECT surface on 127.0.0.1:${String(frontDoor?.connectPort ?? 0)}` : `provider ${resolvedProvider.name}`;
8820
- log.info(`agent-shim: routing through the front door on 127.0.0.1:${String(frontDoor?.port ?? 0)} with headroom on unix socket ${headroom.socketPath} (${via}, project ${headroom.projectId})`);
8821
9005
  } else if (resolvedFlags.headroom) {
8822
9006
  log.error("agent-shim: headroom routing was requested but this launcher has no headroom port wired; refusing to launch without it.");
8823
9007
  proc.exit(1);
8824
- } else if (frontDoor !== void 0) {
8825
- 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})`}`);
8826
9008
  }
9009
+ rows.push(...routingRows({ frontDoor, headroom, provider: resolvedProvider !== void 0 }));
8827
9010
  const frontDoorRelease = frontDoor === void 0 ? void 0 : frontDoorPort?.release;
8828
9011
  const sessionId = params.supervised?.sessionId ?? (0, import_node_crypto11.randomUUID)();
8829
9012
  const finalEnv = buildEnv({
@@ -8844,7 +9027,11 @@ function prepareLaunch(params) {
8844
9027
  registered();
8845
9028
  }
8846
9029
  };
8847
- return { bin: decided.bin, args: finalArgv, env: finalEnv, sessionId, release, markChildStarted: updateCheck.markChildStarted, decision };
9030
+ rows.push(...notes.map(noteRow));
9031
+ log.report(rows);
9032
+ printDiagnosticLines(log, warnings, { errorsAsWarnings: false });
9033
+ const hold = () => holdBeforeLaunch({ delayMs: resolvedFlags.delayMs, pause: resolvedFlags.pause }, params.hold, log);
9034
+ return { bin: decided.bin, args: finalArgv, env: finalEnv, sessionId, release, markChildStarted: updateCheck.markChildStarted, hold, decision };
8848
9035
  }
8849
9036
  function resolveLaunch(params) {
8850
9037
  const decided = decideLaunch(params, true);
@@ -8877,6 +9064,9 @@ function resolveLaunch(params) {
8877
9064
  }
8878
9065
  function runLaunchPlan(plan, spawn3) {
8879
9066
  try {
9067
+ if (plan.hold() === "cancelled") {
9068
+ return LAUNCH_CANCELLED_EXIT;
9069
+ }
8880
9070
  plan.markChildStarted();
8881
9071
  const result = spawn3.spawnSync(plan.bin, plan.args, { stdio: "inherit", env: plan.env });
8882
9072
  if (result.error !== void 0) {
@@ -8907,6 +9097,8 @@ var init_launcher = __esm({
8907
9097
  init_extraFlags();
8908
9098
  init_claudeSession();
8909
9099
  init_diagnostics();
9100
+ init_hold();
9101
+ init_launchReport();
8910
9102
  init_modelPicker();
8911
9103
  init_providerCatalogue();
8912
9104
  init_pool();
@@ -9112,6 +9304,7 @@ function realPrepareLaunchParams(paths, options) {
9112
9304
  headroom: realHeadroomPort(paths, { spawnDaemon: options.spawnDaemon, cwd: farm.runtime.cwd }),
9113
9305
  frontdoor: realFrontDoorPort(paths, options.spawnDaemon),
9114
9306
  credentials: { ...realCredentialPort, cache: realCredentialCacheEnv(paths) },
9307
+ hold: realHoldPort,
9115
9308
  hasStoredLogin: (identity) => identitySignIn(realFarmFs, { platform: process.platform, run: realRunPort }, { farmRoot: import_node_path42.default.join(paths.identitiesDir, identity), hasCredentialBlock: false }).state !== "signed-out",
9116
9309
  ...farm.directoryIdentity === void 0 ? {} : { directoryPinnedIdentity: farm.directoryIdentity },
9117
9310
  ...farm.directoryConfigProfile === void 0 ? {} : { directoryRuleConfigProfile: farm.directoryConfigProfile },
@@ -9129,6 +9322,7 @@ function prepareClaudeLaunch(options) {
9129
9322
  const refusals = [];
9130
9323
  const log = {
9131
9324
  info: () => void 0,
9325
+ report: () => void 0,
9132
9326
  warn: () => void 0,
9133
9327
  error: (message) => {
9134
9328
  refusals.push(message);
@@ -9150,6 +9344,7 @@ function resolveClaudeLaunch(options) {
9150
9344
  const warnings = [];
9151
9345
  const log = {
9152
9346
  info: () => void 0,
9347
+ report: () => void 0,
9153
9348
  warn: (message) => {
9154
9349
  warnings.push(message);
9155
9350
  },
@@ -9358,6 +9553,7 @@ async function withIdentityClaude(params, identity, flags, use) {
9358
9553
  },
9359
9554
  log: {
9360
9555
  info: () => void 0,
9556
+ report: () => void 0,
9361
9557
  warn: () => void 0,
9362
9558
  error: (message) => {
9363
9559
  refusals.push(message);
@@ -9390,14 +9586,14 @@ var init_identityClaude = __esm({
9390
9586
  });
9391
9587
 
9392
9588
  // src/usage/providerQuota.ts
9393
- var import_zod31, MS_PER_SECOND8, SECONDS_PER_HOUR3, HOURS_PER_DAY6, 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, ANTIGRAVITY_HOST, ANTIGRAVITY_QUOTA_URL, ANTIGRAVITY_USER_URL, FIVE_HOURS2, DAYS_PER_WEEK2, FIVE_HOURS_MS, WEEK_MS, AntigravityBucketSchema, AntigravitySummarySchema, GoogleTokenInfoSchema, AntigravityUserSchema;
9589
+ var import_zod31, MS_PER_SECOND9, SECONDS_PER_HOUR3, HOURS_PER_DAY6, 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, ANTIGRAVITY_HOST, ANTIGRAVITY_QUOTA_URL, ANTIGRAVITY_USER_URL, FIVE_HOURS2, DAYS_PER_WEEK2, FIVE_HOURS_MS, WEEK_MS, AntigravityBucketSchema, AntigravitySummarySchema, GoogleTokenInfoSchema, AntigravityUserSchema;
9394
9590
  var init_providerQuota = __esm({
9395
9591
  "src/usage/providerQuota.ts"() {
9396
9592
  "use strict";
9397
9593
  import_zod31 = require("zod");
9398
9594
  init_cloudUpstream();
9399
9595
  init_schema2();
9400
- MS_PER_SECOND8 = 1e3;
9596
+ MS_PER_SECOND9 = 1e3;
9401
9597
  SECONDS_PER_HOUR3 = 3600;
9402
9598
  HOURS_PER_DAY6 = 24;
9403
9599
  DAYS_PER_MONTH = 30;
@@ -9406,8 +9602,8 @@ var init_providerQuota = __esm({
9406
9602
  ZAI_UNIT_HOURS = 3;
9407
9603
  ZAI_UNIT_MONTHS = 5;
9408
9604
  ZAI_UNIT_MS = /* @__PURE__ */ new Map([
9409
- [ZAI_UNIT_HOURS, SECONDS_PER_HOUR3 * MS_PER_SECOND8],
9410
- [ZAI_UNIT_MONTHS, DAYS_PER_MONTH * HOURS_PER_DAY6 * SECONDS_PER_HOUR3 * MS_PER_SECOND8]
9605
+ [ZAI_UNIT_HOURS, SECONDS_PER_HOUR3 * MS_PER_SECOND9],
9606
+ [ZAI_UNIT_MONTHS, DAYS_PER_MONTH * HOURS_PER_DAY6 * SECONDS_PER_HOUR3 * MS_PER_SECOND9]
9411
9607
  ]);
9412
9608
  ZaiLimitSchema = import_zod31.z.object({
9413
9609
  type: import_zod31.z.string(),
@@ -9427,7 +9623,7 @@ var init_providerQuota = __esm({
9427
9623
  OPENROUTER_HOST = "openrouter.ai";
9428
9624
  OPENROUTER_KEY_URL = `https://${OPENROUTER_HOST}/api/v1/key`;
9429
9625
  OPENROUTER_CREDITS_URL = `https://${OPENROUTER_HOST}/api/v1/credits`;
9430
- MS_PER_DAY3 = HOURS_PER_DAY6 * SECONDS_PER_HOUR3 * MS_PER_SECOND8;
9626
+ MS_PER_DAY3 = HOURS_PER_DAY6 * SECONDS_PER_HOUR3 * MS_PER_SECOND9;
9431
9627
  OpenRouterKeySchema = import_zod31.z.object({
9432
9628
  data: import_zod31.z.object({
9433
9629
  limit: import_zod31.z.number().nonnegative().nullable(),
@@ -9443,8 +9639,8 @@ var init_providerQuota = __esm({
9443
9639
  ANTIGRAVITY_USER_URL = `https://${ANTIGRAVITY_HOST}/v1internal:loadCodeAssist`;
9444
9640
  FIVE_HOURS2 = 5;
9445
9641
  DAYS_PER_WEEK2 = 7;
9446
- FIVE_HOURS_MS = FIVE_HOURS2 * SECONDS_PER_HOUR3 * MS_PER_SECOND8;
9447
- WEEK_MS = DAYS_PER_WEEK2 * HOURS_PER_DAY6 * SECONDS_PER_HOUR3 * MS_PER_SECOND8;
9642
+ FIVE_HOURS_MS = FIVE_HOURS2 * SECONDS_PER_HOUR3 * MS_PER_SECOND9;
9643
+ WEEK_MS = DAYS_PER_WEEK2 * HOURS_PER_DAY6 * SECONDS_PER_HOUR3 * MS_PER_SECOND9;
9448
9644
  AntigravityBucketSchema = import_zod31.z.object({
9449
9645
  bucketId: import_zod31.z.string(),
9450
9646
  remainingFraction: import_zod31.z.number().optional(),
@@ -13747,6 +13943,12 @@ function applyProfileChange(paths, name, change) {
13747
13943
  if (change.launchClaudeVersion !== void 0) {
13748
13944
  launchPatch.claudeVersion = change.launchClaudeVersion === false ? void 0 : change.launchClaudeVersion;
13749
13945
  }
13946
+ if (change.launchDelay !== void 0) {
13947
+ launchPatch.delay = change.launchDelay === false ? void 0 : change.launchDelay;
13948
+ }
13949
+ if (change.launchPause !== void 0) {
13950
+ launchPatch.pause = change.launchPause;
13951
+ }
13750
13952
  if (Object.keys(launchPatch).length > 0) {
13751
13953
  setProfileLaunchFlags(paths, name, launchPatch);
13752
13954
  touched = true;
@@ -15962,7 +16164,9 @@ var ConfigProfileSetInputSchema = import_zod24.z.strictObject({
15962
16164
  headroom: import_zod24.z.boolean().optional(),
15963
16165
  trackUsage: import_zod24.z.boolean().optional(),
15964
16166
  provider: import_zod24.z.union([import_zod24.z.string().min(1), import_zod24.z.literal(false)]).optional(),
15965
- claudeVersion: import_zod24.z.union([import_zod24.z.string().min(1), import_zod24.z.literal(false)]).optional()
16167
+ claudeVersion: import_zod24.z.union([import_zod24.z.string().min(1), import_zod24.z.literal(false)]).optional(),
16168
+ delay: import_zod24.z.union([import_zod24.z.string().regex(DURATION_RE), import_zod24.z.literal(false)]).optional(),
16169
+ pause: import_zod24.z.boolean().optional()
15966
16170
  }).optional()
15967
16171
  });
15968
16172
  var ConfigProfileSetOutputSchema = storedMutationOutput("profile", "updated", ProfileValueSchema);
@@ -16172,7 +16376,9 @@ function createConfigApiRouter(deps) {
16172
16376
  ...launch?.headroom === void 0 ? {} : { launchHeadroom: launch.headroom },
16173
16377
  ...launch?.trackUsage === void 0 ? {} : { launchTrackUsage: launch.trackUsage },
16174
16378
  ...launch?.provider === void 0 ? {} : { launchProvider: launch.provider },
16175
- ...launch?.claudeVersion === void 0 ? {} : { launchClaudeVersion: launch.claudeVersion }
16379
+ ...launch?.claudeVersion === void 0 ? {} : { launchClaudeVersion: launch.claudeVersion },
16380
+ ...launch?.delay === void 0 ? {} : { launchDelay: launch.delay },
16381
+ ...launch?.pause === void 0 ? {} : { launchPause: launch.pause }
16176
16382
  });
16177
16383
  return { action: "updated", kind: "profile", name: input.name, value: profileValue(input.name, paths) };
16178
16384
  })
@@ -16480,7 +16686,10 @@ var LaunchFlagsSchema = import_zod26.z.strictObject({
16480
16686
  skipPermissions: import_zod26.z.boolean(),
16481
16687
  remoteControl: import_zod26.z.boolean(),
16482
16688
  headroom: import_zod26.z.boolean(),
16483
- trackUsage: import_zod26.z.boolean()
16689
+ trackUsage: import_zod26.z.boolean(),
16690
+ pause: import_zod26.z.boolean(),
16691
+ /** How long the launch waits after its own output before it starts claude, in milliseconds. */
16692
+ delayMs: import_zod26.z.number()
16484
16693
  });
16485
16694
  var LaunchResolveOutputSchema = import_zod26.z.strictObject({
16486
16695
  decision: LaunchDecisionSchema,