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.mjs CHANGED
@@ -263,7 +263,11 @@ var init_schema = __esm({
263
263
  headroom: z.boolean().optional(),
264
264
  trackUsage: z.boolean().optional(),
265
265
  /** 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. */
266
- claudeVersion: z.string().regex(NUMERIC_DOTTED_VERSION_RE, "must be an exact dotted-numeric Claude Code version such as 2.1.220").optional()
266
+ claudeVersion: z.string().regex(NUMERIC_DOTTED_VERSION_RE, "must be an exact dotted-numeric Claude Code version such as 2.1.220").optional(),
267
+ /** 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. */
268
+ delay: z.string().regex(DURATION_RE, "must be a duration such as 5s or 500ms").optional(),
269
+ /** 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. */
270
+ pause: z.boolean().optional()
267
271
  });
268
272
  CREDENTIAL_TARGETS = ["bearer", "apiKey", "oauthToken"];
269
273
  PROVIDER_CREDENTIAL_TARGETS = ["bearer", "apiKey"];
@@ -1366,6 +1370,12 @@ function flattenLayers(layers, options) {
1366
1370
  if (layer.launch.claudeVersion !== void 0) {
1367
1371
  launch.claudeVersion = layer.launch.claudeVersion;
1368
1372
  }
1373
+ if (layer.launch.delay !== void 0) {
1374
+ launch.delay = layer.launch.delay;
1375
+ }
1376
+ if (layer.launch.pause !== void 0) {
1377
+ launch.pause = layer.launch.pause;
1378
+ }
1369
1379
  }
1370
1380
  if (layer.entries === void 0) {
1371
1381
  continue;
@@ -1464,11 +1474,15 @@ var init_flatten = __esm({
1464
1474
  });
1465
1475
 
1466
1476
  // src/resolve/decide.ts
1467
- function unclassifiedEntryMessage(names) {
1477
+ function unclassifiedEntrySummary(names) {
1468
1478
  const quoted = names.map((name) => `"${name}"`).join(", ");
1469
- const subject = names.length === 1 ? `${quoted} is not` : `${String(names.length)} entries are not`;
1470
- const excluded = names.length === 1 ? "it is excluded" : `they are excluded: ${quoted}`;
1471
- 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.`;
1479
+ 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}`;
1480
+ }
1481
+ function unclassifiedEntryFix(names) {
1482
+ return `Run \`agent-shim configure\` to classify ${names.length === 1 ? "it" : "them"}`;
1483
+ }
1484
+ function unclassifiedEntryMessage(names) {
1485
+ return `${unclassifiedEntrySummary(names)}. ${unclassifiedEntryFix(names)}.`;
1472
1486
  }
1473
1487
  function selectRule(relPath, flattened, context) {
1474
1488
  const eliminated = [];
@@ -2940,7 +2954,7 @@ var init_package = __esm({
2940
2954
  "package.json"() {
2941
2955
  package_default = {
2942
2956
  name: "agent-shim",
2943
- version: "11.27.0",
2957
+ version: "11.29.0",
2944
2958
  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.",
2945
2959
  license: "MIT",
2946
2960
  author: "Joseph Mearman <joseph@mearman.co.uk>",
@@ -4105,21 +4119,54 @@ var init_supervisor = __esm({
4105
4119
  }
4106
4120
  });
4107
4121
 
4122
+ // src/launcher/report.ts
4123
+ function renderReport(rows, style) {
4124
+ if (rows.length === 0) {
4125
+ return [];
4126
+ }
4127
+ const labelWidth = Math.max(...rows.map((row) => row.label.length));
4128
+ const indent = " ".repeat(COLUMN_GAP.length);
4129
+ const lines = [style(["bold"], REPORT_HEADING)];
4130
+ for (const row of rows) {
4131
+ const detail = row.detail === void 0 ? "" : ` ${style(["dim"], `(${row.detail})`)}`;
4132
+ lines.push(`${indent}${style(["dim"], row.label.padEnd(labelWidth))}${COLUMN_GAP}${row.value}${detail}`);
4133
+ for (const note of row.notes ?? []) {
4134
+ lines.push(`${indent}${" ".repeat(labelWidth)}${COLUMN_GAP}${style(["dim"], note)}`);
4135
+ }
4136
+ }
4137
+ return lines;
4138
+ }
4139
+ var REPORT_HEADING, COLUMN_GAP;
4140
+ var init_report = __esm({
4141
+ "src/launcher/report.ts"() {
4142
+ "use strict";
4143
+ REPORT_HEADING = "agent-shim";
4144
+ COLUMN_GAP = " ";
4145
+ }
4146
+ });
4147
+
4108
4148
  // src/logStyle.ts
4109
4149
  import { styleText } from "node:util";
4110
- function styledDiagnostic(style, colour, line) {
4111
- const lead = DIAGNOSTIC_LEAD.exec(line);
4112
- if (lead === null) {
4113
- return style([colour], line);
4114
- }
4115
- const [whole, prefix = "", code = "", separator = ""] = lead;
4116
- return `${style([colour], prefix)}${style([colour, "bold"], code)}${style([colour], `${separator}${line.slice(whole.length)}`)}`;
4150
+ function styledDiagnostic(style, colour, text) {
4151
+ return text.split("\n").map((line, index) => {
4152
+ const lead = index === 0 ? DIAGNOSTIC_LEAD.exec(line) : null;
4153
+ if (lead === null) {
4154
+ return style([colour], line);
4155
+ }
4156
+ const [whole, prefix = "", code = "", separator = ""] = lead;
4157
+ return `${style([colour], prefix)}${style([colour, "bold"], code)}${style([colour], `${separator}${line.slice(whole.length)}`)}`;
4158
+ }).join("\n");
4117
4159
  }
4118
4160
  function createLogPort(sinks, styleFor) {
4119
4161
  return {
4120
4162
  info: (message) => {
4121
4163
  sinks.out(styleFor.out(["dim"], message));
4122
4164
  },
4165
+ report: (rows) => {
4166
+ for (const line of renderReport(rows, styleFor.out)) {
4167
+ sinks.out(line);
4168
+ }
4169
+ },
4123
4170
  warn: (message) => {
4124
4171
  sinks.warn(styledDiagnostic(styleFor.err, "yellow", message));
4125
4172
  },
@@ -4135,6 +4182,7 @@ var DIAGNOSTIC_LEAD;
4135
4182
  var init_logStyle = __esm({
4136
4183
  "src/logStyle.ts"() {
4137
4184
  "use strict";
4185
+ init_report();
4138
4186
  DIAGNOSTIC_LEAD = /^(agent-shim: )([A-Z][A-Z0-9_]*)(: )/;
4139
4187
  }
4140
4188
  });
@@ -4383,7 +4431,7 @@ function realResolveClaudeBinary(isOwnBinary) {
4383
4431
  function realInstalledClaudeVersions() {
4384
4432
  return installedVersions(listVersionsDir(defaultVersionsDir()));
4385
4433
  }
4386
- var 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;
4434
+ var 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;
4387
4435
  var init_realPorts = __esm({
4388
4436
  "src/realPorts.ts"() {
4389
4437
  "use strict";
@@ -4526,6 +4574,31 @@ var init_realPorts = __esm({
4526
4574
  }
4527
4575
  };
4528
4576
  INT32_BYTE_LENGTH = 4;
4577
+ KEY_POLL_MS = 25;
4578
+ CTRL_C_BYTE = 3;
4579
+ realHoldPort = {
4580
+ attended: () => process.stdin.isTTY && process.stdout.isTTY,
4581
+ sleep: realSleepSync,
4582
+ waitForKey: () => {
4583
+ process.stdin.setRawMode(true);
4584
+ try {
4585
+ const buffer = Buffer.alloc(1);
4586
+ for (; ; ) {
4587
+ try {
4588
+ const read = fs3.readSync(process.stdin.fd, buffer, 0, buffer.length, null);
4589
+ return read > 0 && buffer[0] === CTRL_C_BYTE ? "interrupt" : "key";
4590
+ } catch (error) {
4591
+ if (!(error instanceof Error && "code" in error && error.code === "EAGAIN")) {
4592
+ throw error;
4593
+ }
4594
+ realSleepSync(KEY_POLL_MS);
4595
+ }
4596
+ }
4597
+ } finally {
4598
+ process.stdin.setRawMode(false);
4599
+ }
4600
+ }
4601
+ };
4529
4602
  PS_TIMEOUT_MS = 2e3;
4530
4603
  realRunPort = {
4531
4604
  run(command, args) {
@@ -7364,6 +7437,7 @@ function parseLauncherArgv(argv) {
7364
7437
  let configProfile;
7365
7438
  let provider;
7366
7439
  let claudeVersion;
7440
+ let delay;
7367
7441
  const booleans = {};
7368
7442
  const categoryFlags = [];
7369
7443
  const shareFlags = [];
@@ -7421,6 +7495,9 @@ function parseLauncherArgv(argv) {
7421
7495
  case "--claude-version":
7422
7496
  claudeVersion = value;
7423
7497
  break;
7498
+ case "--delay":
7499
+ delay = value;
7500
+ break;
7424
7501
  case "--category":
7425
7502
  categoryFlags.push(value);
7426
7503
  break;
@@ -7443,6 +7520,7 @@ function parseLauncherArgv(argv) {
7443
7520
  ...configProfile === void 0 ? {} : { configProfile },
7444
7521
  ...provider === void 0 ? {} : { provider },
7445
7522
  ...claudeVersion === void 0 ? {} : { claudeVersion },
7523
+ ...delay === void 0 ? {} : { delay },
7446
7524
  ...native ? { native: true } : {},
7447
7525
  ...booleans,
7448
7526
  categoryFlags,
@@ -7466,13 +7544,14 @@ var init_argv = __esm({
7466
7544
  positional;
7467
7545
  flag;
7468
7546
  };
7469
- VALUED_FLAGS = ["--identity", "--config-profile", "--provider", "--claude-version", "--category", "--share", "--hide"];
7547
+ VALUED_FLAGS = ["--identity", "--config-profile", "--provider", "--claude-version", "--delay", "--category", "--share", "--hide"];
7470
7548
  BOOLEAN_FLAGS = [
7471
7549
  { flag: "--headroom", key: "headroom" },
7472
7550
  { flag: "--track-usage", key: "trackUsage" },
7473
7551
  { flag: "--skip-permissions", key: "skipPermissions" },
7474
7552
  { flag: "--remote-control", key: "remoteControl" },
7475
- { flag: "--wait", key: "wait" }
7553
+ { flag: "--wait", key: "wait" },
7554
+ { flag: "--pause", key: "pause" }
7476
7555
  ];
7477
7556
  LAUNCHER_FLAG_NAMES = [
7478
7557
  ...VALUED_FLAGS,
@@ -7660,9 +7739,23 @@ function resolveLaunchFlags(params) {
7660
7739
  skipPermissions: params.flags?.skipPermissions ?? parseEnvBool("AGENT_SHIM_SKIP_PERMISSIONS", params.env.AGENT_SHIM_SKIP_PERMISSIONS) ?? params.cascade?.skipPermissions ?? false,
7661
7740
  remoteControl: params.flags?.remoteControl ?? parseEnvBool("AGENT_SHIM_REMOTE_CONTROL", params.env.AGENT_SHIM_REMOTE_CONTROL) ?? params.cascade?.remoteControl ?? false,
7662
7741
  headroom: params.flags?.headroom ?? parseEnvBool("AGENT_SHIM_HEADROOM", params.env.AGENT_SHIM_HEADROOM) ?? params.cascade?.headroom ?? false,
7663
- trackUsage: params.flags?.trackUsage ?? parseEnvBool("AGENT_SHIM_TRACK_USAGE", params.env.AGENT_SHIM_TRACK_USAGE) ?? params.cascade?.trackUsage ?? true
7742
+ trackUsage: params.flags?.trackUsage ?? parseEnvBool("AGENT_SHIM_TRACK_USAGE", params.env.AGENT_SHIM_TRACK_USAGE) ?? params.cascade?.trackUsage ?? true,
7743
+ pause: params.flags?.pause ?? parseEnvBool("AGENT_SHIM_PAUSE", params.env.AGENT_SHIM_PAUSE) ?? params.cascade?.pause ?? false,
7744
+ delayMs: resolveDelayMs(params)
7664
7745
  };
7665
7746
  }
7747
+ function resolveDelayMs(params) {
7748
+ const fromEnv = params.env.AGENT_SHIM_DELAY === "" ? void 0 : params.env.AGENT_SHIM_DELAY;
7749
+ const [literal, source] = params.flags?.delay !== void 0 ? [params.flags.delay, "--delay"] : fromEnv !== void 0 ? [fromEnv, "AGENT_SHIM_DELAY"] : [params.cascade?.delay, "launch.delay"];
7750
+ if (literal === void 0) {
7751
+ return 0;
7752
+ }
7753
+ try {
7754
+ return parseDuration(literal);
7755
+ } catch (error) {
7756
+ throw new UsageError(`${source}: ${error instanceof Error ? error.message : String(error)}`);
7757
+ }
7758
+ }
7666
7759
  function buildFlagArgs(flags) {
7667
7760
  const args = [];
7668
7761
  if (flags.skipPermissions) {
@@ -7734,6 +7827,8 @@ var init_flags = __esm({
7734
7827
  "src/launcher/flags.ts"() {
7735
7828
  "use strict";
7736
7829
  init_envBool();
7830
+ init_cliError();
7831
+ init_conditions();
7737
7832
  init_credential();
7738
7833
  init_headers();
7739
7834
  init_capability();
@@ -7929,7 +8024,9 @@ function diagnosticLines(diagnostics) {
7929
8024
  if (diagnostic.code === "UNCLASSIFIED_ENTRY") {
7930
8025
  if (!unclassifiedReported) {
7931
8026
  unclassifiedReported = true;
7932
- lines.push({ severity: diagnostic.severity, text: `agent-shim: ${diagnostic.code}: ${unclassifiedEntryMessage(unclassified.filter((name) => name !== void 0))}` });
8027
+ const names = unclassified.filter((name) => name !== void 0);
8028
+ lines.push({ severity: diagnostic.severity, text: `agent-shim: ${diagnostic.code}: ${unclassifiedEntrySummary(names)}
8029
+ ${unclassifiedEntryFix(names)}.` });
7933
8030
  }
7934
8031
  continue;
7935
8032
  }
@@ -7937,8 +8034,8 @@ function diagnosticLines(diagnostics) {
7937
8034
  }
7938
8035
  return lines;
7939
8036
  }
7940
- function reportDiagnostics(log, diagnostics, options) {
7941
- for (const line of diagnosticLines(diagnostics)) {
8037
+ function printDiagnosticLines(log, lines, options) {
8038
+ for (const line of lines) {
7942
8039
  if (line.severity === "error" && !options.errorsAsWarnings) {
7943
8040
  log.error(line.text);
7944
8041
  } else {
@@ -7946,6 +8043,9 @@ function reportDiagnostics(log, diagnostics, options) {
7946
8043
  }
7947
8044
  }
7948
8045
  }
8046
+ function reportDiagnostics(log, diagnostics, options) {
8047
+ printDiagnosticLines(log, diagnosticLines(diagnostics), options);
8048
+ }
7949
8049
  var init_diagnostics = __esm({
7950
8050
  "src/launcher/diagnostics.ts"() {
7951
8051
  "use strict";
@@ -7953,6 +8053,84 @@ var init_diagnostics = __esm({
7953
8053
  }
7954
8054
  });
7955
8055
 
8056
+ // src/launcher/hold.ts
8057
+ function describeDelay(ms) {
8058
+ return ms % MS_PER_SECOND7 === 0 ? `${String(ms / MS_PER_SECOND7)}s` : `${String(ms)}ms`;
8059
+ }
8060
+ function holdBeforeLaunch(hold, port, log) {
8061
+ if (port === void 0 || !port.attended() || !hold.pause && hold.delayMs <= 0) {
8062
+ return "go";
8063
+ }
8064
+ if (hold.pause) {
8065
+ log.info("agent-shim: paused before launch; press any key to start, or Ctrl-C to cancel");
8066
+ return port.waitForKey() === "interrupt" ? "cancelled" : "go";
8067
+ }
8068
+ log.info(`agent-shim: starting in ${describeDelay(hold.delayMs)}`);
8069
+ port.sleep(hold.delayMs);
8070
+ return "go";
8071
+ }
8072
+ var LAUNCH_CANCELLED_EXIT, MS_PER_SECOND7;
8073
+ var init_hold = __esm({
8074
+ "src/launcher/hold.ts"() {
8075
+ "use strict";
8076
+ LAUNCH_CANCELLED_EXIT = 130;
8077
+ MS_PER_SECOND7 = 1e3;
8078
+ }
8079
+ });
8080
+
8081
+ // src/launcher/launchReport.ts
8082
+ function poolDetail(pool) {
8083
+ const [reason] = pool.reasons;
8084
+ if (pool.movedOff !== void 0) {
8085
+ return { detail: `moved off ${pool.movedOff.identity}: ${pool.movedOff.reason}`, ...reason === void 0 ? {} : { notes: [reason] } };
8086
+ }
8087
+ return reason === void 0 ? {} : { detail: reason };
8088
+ }
8089
+ function decisionRows(facts) {
8090
+ return [
8091
+ { label: "identity", value: facts.identity ?? "(none)", detail: facts.identitySource },
8092
+ ...facts.pool === void 0 ? [] : [
8093
+ {
8094
+ label: "pool",
8095
+ value: facts.pool.name,
8096
+ ...poolDetail(facts.pool)
8097
+ }
8098
+ ],
8099
+ ...facts.profile === void 0 ? [] : [{ label: "profile", value: facts.profile.name, detail: facts.profile.source }],
8100
+ ...facts.provider === void 0 ? [] : [{ label: "provider", value: facts.provider.name, detail: `credential ${facts.provider.credential}` }],
8101
+ ...facts.identityCredential === void 0 ? [] : [{ label: "credential", value: facts.identityCredential, detail: "the identity's own" }]
8102
+ ];
8103
+ }
8104
+ function pinnedVersionRow(version, source) {
8105
+ return { label: "claude", value: version, detail: `pinned by ${source}` };
8106
+ }
8107
+ function routingRows(facts) {
8108
+ if (facts.frontDoor === void 0) {
8109
+ return [];
8110
+ }
8111
+ return [
8112
+ {
8113
+ label: "routing",
8114
+ value: `front door 127.0.0.1:${String(facts.frontDoor.port)}`,
8115
+ ...facts.provider ? {} : { detail: `OAuth via CONNECT 127.0.0.1:${String(facts.frontDoor.connectPort)}` }
8116
+ },
8117
+ ...facts.headroom === void 0 ? [] : [{ label: "headroom", value: "on", detail: `project ${facts.headroom.projectId}` }]
8118
+ ];
8119
+ }
8120
+ function farmRow(links, builtDirectories, adopted) {
8121
+ const counted = (count, singular, plural) => `${String(count)} ${count === 1 ? singular : plural}`;
8122
+ const parts = [counted(links, "link", "links"), counted(builtDirectories, "built directory", "built directories"), ...adopted === 0 ? [] : [`${String(adopted)} adopted`]];
8123
+ return { label: "farm", value: "resynced", detail: parts.join(", ") };
8124
+ }
8125
+ function noteRow(text) {
8126
+ return { label: "note", value: text };
8127
+ }
8128
+ var init_launchReport = __esm({
8129
+ "src/launcher/launchReport.ts"() {
8130
+ "use strict";
8131
+ }
8132
+ });
8133
+
7956
8134
  // src/antigravity/cloudUpstream.ts
7957
8135
  var init_cloudUpstream = __esm({
7958
8136
  "src/antigravity/cloudUpstream.ts"() {
@@ -8136,20 +8314,20 @@ function filterCatalogue(models, catalogue) {
8136
8314
  const excluded = catalogue.exclude === void 0 ? void 0 : picomatch4(catalogue.exclude, { dot: true });
8137
8315
  return models.filter((model) => included?.(model.id) !== false && excluded?.(model.id) !== true);
8138
8316
  }
8139
- var 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;
8317
+ var 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;
8140
8318
  var init_providerCatalogue = __esm({
8141
8319
  "src/providerCatalogue.ts"() {
8142
8320
  "use strict";
8143
8321
  DEFAULT_CANDIDATE_URLS = 2;
8144
- MS_PER_SECOND7 = 1e3;
8322
+ MS_PER_SECOND8 = 1e3;
8145
8323
  SECONDS_PER_HOUR2 = 3600;
8146
8324
  HOURS_PER_DAY5 = 24;
8147
- MS_PER_HOUR5 = SECONDS_PER_HOUR2 * MS_PER_SECOND7;
8325
+ MS_PER_HOUR5 = SECONDS_PER_HOUR2 * MS_PER_SECOND8;
8148
8326
  HOURS_BETWEEN_RETRIES = 1;
8149
8327
  CATALOGUE_MAX_AGE_MS = HOURS_PER_DAY5 * MS_PER_HOUR5;
8150
8328
  CATALOGUE_RETRY_MS = HOURS_BETWEEN_RETRIES * MS_PER_HOUR5;
8151
8329
  CATALOGUE_REQUEST_SECONDS = 10;
8152
- CATALOGUE_REQUEST_TIMEOUT_MS = CATALOGUE_REQUEST_SECONDS * MS_PER_SECOND7;
8330
+ CATALOGUE_REQUEST_TIMEOUT_MS = CATALOGUE_REQUEST_SECONDS * MS_PER_SECOND8;
8153
8331
  CATALOGUE_REFRESH_TIMEOUT_MS = DEFAULT_CANDIDATE_URLS * CATALOGUE_REQUEST_TIMEOUT_MS;
8154
8332
  CatalogueModelSchema = z30.strictObject({ id: z30.string().min(1), name: z30.string().min(1).optional() });
8155
8333
  CatalogueCacheSchema = z30.strictObject({ fetchedAt: z30.number(), url: z30.string().min(1), models: z30.array(CatalogueModelSchema) });
@@ -8480,7 +8658,7 @@ function pickFromPool(decided, params, parsedArgv, readOnly) {
8480
8658
  }
8481
8659
  if (params.supervised?.member !== void 0) {
8482
8660
  const reasons = ["resumed here by the supervising launcher after the previous member ran out of quota"];
8483
- return { identityDecision: { ...decided, name: params.supervised.member }, poolExplanation: `pool ${decided.pool}: ${reasons.join("; ")}`, poolPick: { name: decided.pool, reasons } };
8661
+ return { identityDecision: { ...decided, name: params.supervised.member }, poolPick: { name: decided.pool, reasons } };
8484
8662
  }
8485
8663
  const farmRuntime = params.farm;
8486
8664
  if (farmRuntime === void 0) {
@@ -8511,7 +8689,6 @@ function pickFromPool(decided, params, parsedArgv, readOnly) {
8511
8689
  }
8512
8690
  return {
8513
8691
  identityDecision: { ...decided, name: resolution.identity },
8514
- poolExplanation: resolution.explanation,
8515
8692
  poolPick: { name: decided.pool, reasons: resolution.reasons, ...resolution.movedOff === void 0 ? {} : { movedOff: resolution.movedOff } }
8516
8693
  };
8517
8694
  }
@@ -8539,7 +8716,7 @@ function decideLaunch(params, readOnly) {
8539
8716
  return trimmed === "" ? void 0 : trimmed;
8540
8717
  }
8541
8718
  });
8542
- const { identityDecision, poolExplanation, poolPick } = pickFromPool(decidedIdentity, params, parsedArgv, readOnly);
8719
+ const { identityDecision, poolPick } = pickFromPool(decidedIdentity, params, parsedArgv, readOnly);
8543
8720
  const farmIdentity = configDirEscapeHatchApplies ? void 0 : identityDecision.name;
8544
8721
  const farm = farmIdentity === void 0 ? void 0 : params.farm;
8545
8722
  if (!readOnly && farm !== void 0 && farmIdentity !== void 0) {
@@ -8673,19 +8850,22 @@ function decideLaunch(params, readOnly) {
8673
8850
  ...parsedArgv.skipPermissions === void 0 ? {} : { skipPermissions: parsedArgv.skipPermissions },
8674
8851
  ...parsedArgv.remoteControl === void 0 ? {} : { remoteControl: parsedArgv.remoteControl },
8675
8852
  ...parsedArgv.headroom === void 0 ? {} : { headroom: parsedArgv.headroom },
8676
- ...parsedArgv.trackUsage === void 0 ? {} : { trackUsage: parsedArgv.trackUsage }
8853
+ ...parsedArgv.trackUsage === void 0 ? {} : { trackUsage: parsedArgv.trackUsage },
8854
+ ...parsedArgv.pause === void 0 ? {} : { pause: parsedArgv.pause },
8855
+ ...parsedArgv.delay === void 0 ? {} : { delay: parsedArgv.delay }
8677
8856
  }
8678
8857
  });
8679
8858
  const loginlessProvider = requestedFlags.remoteControl && selectedProvider !== void 0 && farmIdentity !== void 0 && params.hasStoredLogin?.(farmIdentity) === false ? { identity: farmIdentity, provider: selectedProvider.name } : void 0;
8680
- if (loginlessProvider !== void 0 && !readOnly) {
8681
- 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`);
8859
+ const notes = [];
8860
+ if (loginlessProvider !== void 0) {
8861
+ notes.push(`${loginlessProvider.identity} has no stored login, so Remote Control is off; provider ${loginlessProvider.provider} runs without it`);
8682
8862
  }
8683
8863
  const flags = loginlessProvider === void 0 ? requestedFlags : { ...requestedFlags, remoteControl: false };
8684
8864
  const catalogue = selectedProvider === void 0 ? void 0 : parseCatalogueCache(params.fs.readFileUtf8(catalogueCachePath(paths, selectedProvider.name)));
8685
8865
  const pickerSettings = selectedProvider === void 0 ? void 0 : modelPickerSettings(selectedProvider.definition, catalogue?.models);
8686
8866
  const callerSettings = hasSettingsArgument(parsedArgv.rest);
8687
- if (pickerSettings !== void 0 && callerSettings && !readOnly) {
8688
- 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");
8867
+ if (pickerSettings !== void 0 && callerSettings) {
8868
+ notes.push("--settings was passed, so /model keeps Claude Code's own model names");
8689
8869
  }
8690
8870
  const launcherSettings = mergeSettings([params.supervised?.settings, callerSettings ? void 0 : pickerSettings]);
8691
8871
  const args = buildArgv({
@@ -8707,8 +8887,8 @@ function decideLaunch(params, readOnly) {
8707
8887
  return {
8708
8888
  parsedArgv,
8709
8889
  identityDecision,
8710
- poolExplanation,
8711
8890
  poolPick,
8891
+ notes,
8712
8892
  configDirEscapeHatch: configDirEscapeHatchApplies,
8713
8893
  farmIdentity,
8714
8894
  farmContext,
@@ -8728,10 +8908,18 @@ function prepareLaunch(params) {
8728
8908
  const { paths, proc, log } = params;
8729
8909
  const { env } = proc;
8730
8910
  const decided = decideLaunch(params, false);
8731
- const { identityDecision, configProfileDecision, resolvedProvider, identityCredential, poolExplanation, flags: resolvedFlags, args: finalArgv, configDirEscapeHatch: configDirEscapeHatchApplies, decision } = decided;
8732
- log.info(
8733
- `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)}`)
8734
- );
8911
+ const { identityDecision, configProfileDecision, resolvedProvider, identityCredential, poolPick, notes, flags: resolvedFlags, args: finalArgv, configDirEscapeHatch: configDirEscapeHatchApplies, decision } = decided;
8912
+ const rows = [
8913
+ ...decisionRows({
8914
+ identity: identityDecision.name,
8915
+ identitySource: identityDecision.source,
8916
+ pool: poolPick,
8917
+ profile: configProfileDecision.name === void 0 ? void 0 : { name: configProfileDecision.name, source: configProfileDecision.source },
8918
+ provider: resolvedProvider === void 0 ? void 0 : { name: resolvedProvider.name, credential: `${resolvedProvider.credential.target} from ${describeSource(resolvedProvider.credential.source)}` },
8919
+ identityCredential: identityCredential === void 0 ? void 0 : `${identityCredential.target} from ${describeSource(identityCredential.source)}`
8920
+ })
8921
+ ];
8922
+ let warnings = [];
8735
8923
  const updateCheck = runLaunchUpdateCheck({
8736
8924
  mode: params.updateMode ?? "off",
8737
8925
  checkPath: path39.join(paths.root, "update.check"),
@@ -8766,15 +8954,13 @@ function prepareLaunch(params) {
8766
8954
  }
8767
8955
  throw error;
8768
8956
  }
8769
- reportDiagnostics(log, result.diagnostics, { errorsAsWarnings: false });
8957
+ warnings = diagnosticLines(result.diagnostics);
8770
8958
  if (!result.noOp) {
8771
- log.info(
8772
- `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}`})`
8773
- );
8959
+ rows.push(farmRow(result.manifest.links.length, result.manifest.materialised.length, result.adopted.length));
8774
8960
  }
8775
8961
  }
8776
8962
  if (decided.pinnedVersion !== void 0) {
8777
- log.info(`agent-shim: Claude Code ${decided.pinnedVersion.version} (pinned by ${decided.pinnedVersion.source})`);
8963
+ rows.push(pinnedVersionRow(decided.pinnedVersion.version, decided.pinnedVersion.source));
8778
8964
  }
8779
8965
  const frontDoorPort = params.frontdoor;
8780
8966
  const frontDoorEngaged = resolvedProvider !== void 0 || resolvedFlags.headroom || resolvedFlags.trackUsage;
@@ -8790,14 +8976,11 @@ function prepareLaunch(params) {
8790
8976
  const headroomPort = params.headroom;
8791
8977
  if (resolvedFlags.headroom && headroomPort !== void 0) {
8792
8978
  headroom = headroomPort.ensure({ routesProvider: resolvedProvider !== void 0 });
8793
- const via = resolvedProvider === void 0 ? `OAuth via the door's CONNECT surface on 127.0.0.1:${String(frontDoor?.connectPort ?? 0)}` : `provider ${resolvedProvider.name}`;
8794
- 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})`);
8795
8979
  } else if (resolvedFlags.headroom) {
8796
8980
  log.error("agent-shim: headroom routing was requested but this launcher has no headroom port wired; refusing to launch without it.");
8797
8981
  proc.exit(1);
8798
- } else if (frontDoor !== void 0) {
8799
- 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})`}`);
8800
8982
  }
8983
+ rows.push(...routingRows({ frontDoor, headroom, provider: resolvedProvider !== void 0 }));
8801
8984
  const frontDoorRelease = frontDoor === void 0 ? void 0 : frontDoorPort?.release;
8802
8985
  const sessionId = params.supervised?.sessionId ?? randomUUID4();
8803
8986
  const finalEnv = buildEnv({
@@ -8818,7 +9001,11 @@ function prepareLaunch(params) {
8818
9001
  registered();
8819
9002
  }
8820
9003
  };
8821
- return { bin: decided.bin, args: finalArgv, env: finalEnv, sessionId, release, markChildStarted: updateCheck.markChildStarted, decision };
9004
+ rows.push(...notes.map(noteRow));
9005
+ log.report(rows);
9006
+ printDiagnosticLines(log, warnings, { errorsAsWarnings: false });
9007
+ const hold = () => holdBeforeLaunch({ delayMs: resolvedFlags.delayMs, pause: resolvedFlags.pause }, params.hold, log);
9008
+ return { bin: decided.bin, args: finalArgv, env: finalEnv, sessionId, release, markChildStarted: updateCheck.markChildStarted, hold, decision };
8822
9009
  }
8823
9010
  function resolveLaunch(params) {
8824
9011
  const decided = decideLaunch(params, true);
@@ -8851,6 +9038,9 @@ function resolveLaunch(params) {
8851
9038
  }
8852
9039
  function runLaunchPlan(plan, spawn3) {
8853
9040
  try {
9041
+ if (plan.hold() === "cancelled") {
9042
+ return LAUNCH_CANCELLED_EXIT;
9043
+ }
8854
9044
  plan.markChildStarted();
8855
9045
  const result = spawn3.spawnSync(plan.bin, plan.args, { stdio: "inherit", env: plan.env });
8856
9046
  if (result.error !== void 0) {
@@ -8878,6 +9068,8 @@ var init_launcher = __esm({
8878
9068
  init_extraFlags();
8879
9069
  init_claudeSession();
8880
9070
  init_diagnostics();
9071
+ init_hold();
9072
+ init_launchReport();
8881
9073
  init_modelPicker();
8882
9074
  init_providerCatalogue();
8883
9075
  init_pool();
@@ -9086,6 +9278,7 @@ function realPrepareLaunchParams(paths, options) {
9086
9278
  headroom: realHeadroomPort(paths, { spawnDaemon: options.spawnDaemon, cwd: farm.runtime.cwd }),
9087
9279
  frontdoor: realFrontDoorPort(paths, options.spawnDaemon),
9088
9280
  credentials: { ...realCredentialPort, cache: realCredentialCacheEnv(paths) },
9281
+ hold: realHoldPort,
9089
9282
  hasStoredLogin: (identity) => identitySignIn(realFarmFs, { platform: process.platform, run: realRunPort }, { farmRoot: path42.join(paths.identitiesDir, identity), hasCredentialBlock: false }).state !== "signed-out",
9090
9283
  ...farm.directoryIdentity === void 0 ? {} : { directoryPinnedIdentity: farm.directoryIdentity },
9091
9284
  ...farm.directoryConfigProfile === void 0 ? {} : { directoryRuleConfigProfile: farm.directoryConfigProfile },
@@ -9103,6 +9296,7 @@ function prepareClaudeLaunch(options) {
9103
9296
  const refusals = [];
9104
9297
  const log = {
9105
9298
  info: () => void 0,
9299
+ report: () => void 0,
9106
9300
  warn: () => void 0,
9107
9301
  error: (message) => {
9108
9302
  refusals.push(message);
@@ -9124,6 +9318,7 @@ function resolveClaudeLaunch(options) {
9124
9318
  const warnings = [];
9125
9319
  const log = {
9126
9320
  info: () => void 0,
9321
+ report: () => void 0,
9127
9322
  warn: (message) => {
9128
9323
  warnings.push(message);
9129
9324
  },
@@ -9329,6 +9524,7 @@ async function withIdentityClaude(params, identity, flags, use) {
9329
9524
  },
9330
9525
  log: {
9331
9526
  info: () => void 0,
9527
+ report: () => void 0,
9332
9528
  warn: () => void 0,
9333
9529
  error: (message) => {
9334
9530
  refusals.push(message);
@@ -9362,13 +9558,13 @@ var init_identityClaude = __esm({
9362
9558
 
9363
9559
  // src/usage/providerQuota.ts
9364
9560
  import { z as z31 } from "zod";
9365
- var 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;
9561
+ var 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;
9366
9562
  var init_providerQuota = __esm({
9367
9563
  "src/usage/providerQuota.ts"() {
9368
9564
  "use strict";
9369
9565
  init_cloudUpstream();
9370
9566
  init_schema2();
9371
- MS_PER_SECOND8 = 1e3;
9567
+ MS_PER_SECOND9 = 1e3;
9372
9568
  SECONDS_PER_HOUR3 = 3600;
9373
9569
  HOURS_PER_DAY6 = 24;
9374
9570
  DAYS_PER_MONTH = 30;
@@ -9377,8 +9573,8 @@ var init_providerQuota = __esm({
9377
9573
  ZAI_UNIT_HOURS = 3;
9378
9574
  ZAI_UNIT_MONTHS = 5;
9379
9575
  ZAI_UNIT_MS = /* @__PURE__ */ new Map([
9380
- [ZAI_UNIT_HOURS, SECONDS_PER_HOUR3 * MS_PER_SECOND8],
9381
- [ZAI_UNIT_MONTHS, DAYS_PER_MONTH * HOURS_PER_DAY6 * SECONDS_PER_HOUR3 * MS_PER_SECOND8]
9576
+ [ZAI_UNIT_HOURS, SECONDS_PER_HOUR3 * MS_PER_SECOND9],
9577
+ [ZAI_UNIT_MONTHS, DAYS_PER_MONTH * HOURS_PER_DAY6 * SECONDS_PER_HOUR3 * MS_PER_SECOND9]
9382
9578
  ]);
9383
9579
  ZaiLimitSchema = z31.object({
9384
9580
  type: z31.string(),
@@ -9398,7 +9594,7 @@ var init_providerQuota = __esm({
9398
9594
  OPENROUTER_HOST = "openrouter.ai";
9399
9595
  OPENROUTER_KEY_URL = `https://${OPENROUTER_HOST}/api/v1/key`;
9400
9596
  OPENROUTER_CREDITS_URL = `https://${OPENROUTER_HOST}/api/v1/credits`;
9401
- MS_PER_DAY3 = HOURS_PER_DAY6 * SECONDS_PER_HOUR3 * MS_PER_SECOND8;
9597
+ MS_PER_DAY3 = HOURS_PER_DAY6 * SECONDS_PER_HOUR3 * MS_PER_SECOND9;
9402
9598
  OpenRouterKeySchema = z31.object({
9403
9599
  data: z31.object({
9404
9600
  limit: z31.number().nonnegative().nullable(),
@@ -9414,8 +9610,8 @@ var init_providerQuota = __esm({
9414
9610
  ANTIGRAVITY_USER_URL = `https://${ANTIGRAVITY_HOST}/v1internal:loadCodeAssist`;
9415
9611
  FIVE_HOURS2 = 5;
9416
9612
  DAYS_PER_WEEK2 = 7;
9417
- FIVE_HOURS_MS = FIVE_HOURS2 * SECONDS_PER_HOUR3 * MS_PER_SECOND8;
9418
- WEEK_MS = DAYS_PER_WEEK2 * HOURS_PER_DAY6 * SECONDS_PER_HOUR3 * MS_PER_SECOND8;
9613
+ FIVE_HOURS_MS = FIVE_HOURS2 * SECONDS_PER_HOUR3 * MS_PER_SECOND9;
9614
+ WEEK_MS = DAYS_PER_WEEK2 * HOURS_PER_DAY6 * SECONDS_PER_HOUR3 * MS_PER_SECOND9;
9419
9615
  AntigravityBucketSchema = z31.object({
9420
9616
  bucketId: z31.string(),
9421
9617
  remainingFraction: z31.number().optional(),
@@ -13334,6 +13530,12 @@ function applyProfileChange(paths, name, change) {
13334
13530
  if (change.launchClaudeVersion !== void 0) {
13335
13531
  launchPatch.claudeVersion = change.launchClaudeVersion === false ? void 0 : change.launchClaudeVersion;
13336
13532
  }
13533
+ if (change.launchDelay !== void 0) {
13534
+ launchPatch.delay = change.launchDelay === false ? void 0 : change.launchDelay;
13535
+ }
13536
+ if (change.launchPause !== void 0) {
13537
+ launchPatch.pause = change.launchPause;
13538
+ }
13337
13539
  if (Object.keys(launchPatch).length > 0) {
13338
13540
  setProfileLaunchFlags(paths, name, launchPatch);
13339
13541
  touched = true;
@@ -15549,7 +15751,9 @@ var ConfigProfileSetInputSchema = z24.strictObject({
15549
15751
  headroom: z24.boolean().optional(),
15550
15752
  trackUsage: z24.boolean().optional(),
15551
15753
  provider: z24.union([z24.string().min(1), z24.literal(false)]).optional(),
15552
- claudeVersion: z24.union([z24.string().min(1), z24.literal(false)]).optional()
15754
+ claudeVersion: z24.union([z24.string().min(1), z24.literal(false)]).optional(),
15755
+ delay: z24.union([z24.string().regex(DURATION_RE), z24.literal(false)]).optional(),
15756
+ pause: z24.boolean().optional()
15553
15757
  }).optional()
15554
15758
  });
15555
15759
  var ConfigProfileSetOutputSchema = storedMutationOutput("profile", "updated", ProfileValueSchema);
@@ -15759,7 +15963,9 @@ function createConfigApiRouter(deps) {
15759
15963
  ...launch?.headroom === void 0 ? {} : { launchHeadroom: launch.headroom },
15760
15964
  ...launch?.trackUsage === void 0 ? {} : { launchTrackUsage: launch.trackUsage },
15761
15965
  ...launch?.provider === void 0 ? {} : { launchProvider: launch.provider },
15762
- ...launch?.claudeVersion === void 0 ? {} : { launchClaudeVersion: launch.claudeVersion }
15966
+ ...launch?.claudeVersion === void 0 ? {} : { launchClaudeVersion: launch.claudeVersion },
15967
+ ...launch?.delay === void 0 ? {} : { launchDelay: launch.delay },
15968
+ ...launch?.pause === void 0 ? {} : { launchPause: launch.pause }
15763
15969
  });
15764
15970
  return { action: "updated", kind: "profile", name: input.name, value: profileValue(input.name, paths) };
15765
15971
  })
@@ -16067,7 +16273,10 @@ var LaunchFlagsSchema = z26.strictObject({
16067
16273
  skipPermissions: z26.boolean(),
16068
16274
  remoteControl: z26.boolean(),
16069
16275
  headroom: z26.boolean(),
16070
- trackUsage: z26.boolean()
16276
+ trackUsage: z26.boolean(),
16277
+ pause: z26.boolean(),
16278
+ /** How long the launch waits after its own output before it starts claude, in milliseconds. */
16279
+ delayMs: z26.number()
16071
16280
  });
16072
16281
  var LaunchResolveOutputSchema = z26.strictObject({
16073
16282
  decision: LaunchDecisionSchema,