glimmervoid 0.40.1 → 0.41.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/bin/glimmervoid.js +18 -18
  2. package/dist/chunks/{adapters-D86Do-kG.js → adapters-CyDflXHy.js} +316 -23
  3. package/dist/chunks/{adapters-CTm8gTiM.js → adapters-D8BJffFW.js} +1 -1
  4. package/dist/chunks/{agent-api-cli-Cj73fMC7.js → agent-api-cli-B7-ToJul.js} +12 -3
  5. package/dist/chunks/{agent-api-cli-CS62LiST.js → agent-api-cli-CvCov9_e.js} +1 -1
  6. package/dist/chunks/{agent-api-core-Cf70N-eJ.js → agent-api-core-CLxZAole.js} +22 -4
  7. package/dist/chunks/{agent-setup-cli-BffFfN-1.js → agent-setup-cli-py1gUMvJ.js} +1 -1
  8. package/dist/chunks/child-process-safe-CjVtRjDD.js +1 -0
  9. package/dist/chunks/{child-process-safe-CbQnyh7D.js → child-process-safe-D4hyVIXj.js} +4 -1
  10. package/dist/chunks/{config-store-BSk1Ai2Z.js → config-store-CxYqTNbe.js} +38 -2
  11. package/dist/chunks/config-store-DcVWBJOV.js +1 -0
  12. package/dist/chunks/{contracts-CLBzEau4.js → contracts-C9Jj9iDo.js} +167 -6
  13. package/dist/chunks/{control-messages-CMIEvS1e.js → control-messages-C6JGCTuy.js} +112 -3
  14. package/dist/chunks/{git-version-B3CmEw-k.js → git-version-D_iXgYTZ.js} +2 -2
  15. package/dist/chunks/{grok-mti-4OsU.js → grok-BUGgQVE3.js} +1 -1
  16. package/dist/chunks/{guardrails-deps-CLxK4J-g.js → guardrails-deps-BjPzk1rE.js} +1 -1
  17. package/dist/chunks/{main-Dyr9DbUw.js → main-CRU5ahjl.js} +8581 -5772
  18. package/dist/chunks/{pair-cli-D754Z91h.js → pair-cli-CL1D9xc7.js} +2 -2
  19. package/dist/chunks/{remote-config-CLI_gHAh.js → remote-config-CaW0mpwr.js} +1 -1
  20. package/dist/chunks/{rtk-resolver-BgoPsEhT.js → rtk-resolver-BDHi6RMv.js} +1 -1
  21. package/dist/chunks/rtk-resolver-Dr4iJsiS.js +1 -0
  22. package/dist/chunks/{session-BmjBq2rH.js → session-C8IpFmGQ.js} +38 -2
  23. package/dist/chunks/{session-routes-Dv0vvLc6.js → session-routes-nySS7DUE.js} +36 -2
  24. package/dist/chunks/{settings-cli-CsDruT8O.js → settings-cli-Duculey3.js} +5 -5
  25. package/dist/chunks/{settings-readout-core-CPm5ONXm.js → settings-readout-core-CX7DmEuG.js} +2 -2
  26. package/dist/chunks/{ssh-sign-cli-BG29CY0B.js → ssh-sign-cli-BEAAFjXg.js} +3 -3
  27. package/dist/chunks/{visions-cli-CYujESdJ.js → visions-cli-CVRB9IWA.js} +1 -1
  28. package/dist/chunks/{visions-setup-B-ZeRdsi.js → visions-setup-DB2P8JUL.js} +1 -1
  29. package/dist/client/assets/index-CBjFGcSs.js +176 -0
  30. package/dist/client/assets/index-Cbb5NKHK.css +2 -0
  31. package/dist/client/index.html +2 -2
  32. package/dist/scripts/postinstall-path-check.js +1 -1
  33. package/dist/server/index.js +1 -1
  34. package/dist/session/guardrails-open-launcher.js +1 -1
  35. package/dist/session/hook-tool-relay.js +1 -1
  36. package/dist/session/statusline-relay.js +1 -1
  37. package/package.json +1 -1
  38. package/dist/chunks/child-process-safe-ChRmWAJP.js +0 -1
  39. package/dist/chunks/config-store-B67fnqQ1.js +0 -1
  40. package/dist/chunks/rtk-resolver-BGE6Hd_L.js +0 -1
  41. package/dist/client/assets/index-B-19NksJ.js +0 -148
  42. package/dist/client/assets/index-Dp9irA7v.css +0 -2
@@ -2,13 +2,13 @@
2
2
  import { o as nodePtyRebuildHint, r as firstLine, t as probeNodePty } from "../chunks/node-pty-preflight-C8QIlrtU.js";
3
3
  import { i as errorText } from "../chunks/text-DoirglWV.js";
4
4
  import { a as packageRoot } from "../chunks/runtime-paths-BkeftE60.js";
5
- import { t as AGENT_API_VERBS } from "../chunks/session-BmjBq2rH.js";
6
- import { i as execSync } from "../chunks/child-process-safe-CbQnyh7D.js";
7
- import { r as agentCommandHelpLines } from "../chunks/agent-api-core-Cf70N-eJ.js";
5
+ import { t as AGENT_API_VERBS } from "../chunks/session-C8IpFmGQ.js";
6
+ import { i as execSync } from "../chunks/child-process-safe-D4hyVIXj.js";
7
+ import { r as agentCommandHelpLines } from "../chunks/agent-api-core-CLxZAole.js";
8
8
  import { t as renderTable } from "../chunks/ascii-figure-core-pDAwtlKO.js";
9
9
  import { n as glimmervoidHomeDir, t as decideConfigPath } from "../chunks/config-path-core-DFt-TemS.js";
10
- import { i as parseCommandLine, r as gitDoctorRows, t as probeGitVersion } from "../chunks/git-version-B3CmEw-k.js";
11
- import { i as guardrailsDoctorRows, r as probeGuardrailsDependencies } from "../chunks/guardrails-deps-CLxK4J-g.js";
10
+ import { i as parseCommandLine, r as gitDoctorRows, t as probeGitVersion } from "../chunks/git-version-D_iXgYTZ.js";
11
+ import { i as guardrailsDoctorRows, r as probeGuardrailsDependencies } from "../chunks/guardrails-deps-BjPzk1rE.js";
12
12
  import { i as pnpmGlobalBinDir, n as npmGlobalBinDir, r as onPath, t as formatPathNotice } from "../chunks/path-doctor-C23VAqeu.js";
13
13
  import fs from "node:fs";
14
14
  import path from "node:path";
@@ -65,29 +65,29 @@ var OWN_SUBCOMMAND_RUNNERS = [
65
65
  return 0;
66
66
  }],
67
67
  ["pair", async (subcommandArgs) => {
68
- const { runPairCli } = await import("../chunks/pair-cli-D754Z91h.js");
68
+ const { runPairCli } = await import("../chunks/pair-cli-CL1D9xc7.js");
69
69
  return runPairCli(subcommandArgs);
70
70
  }],
71
71
  ["agent", async (subcommandArgs) => {
72
- const { runAgentSetupCli } = await import("../chunks/agent-setup-cli-BffFfN-1.js");
72
+ const { runAgentSetupCli } = await import("../chunks/agent-setup-cli-py1gUMvJ.js");
73
73
  return runAgentSetupCli(subcommandArgs);
74
74
  }],
75
75
  ["settings", async (subcommandArgs) => {
76
- const { runSettingsCli } = await import("../chunks/settings-cli-CsDruT8O.js");
76
+ const { runSettingsCli } = await import("../chunks/settings-cli-Duculey3.js");
77
77
  return runSettingsCli(subcommandArgs);
78
78
  }],
79
79
  ["visions", async (subcommandArgs) => {
80
- const { runVisionsCli } = await import("../chunks/visions-cli-CYujESdJ.js");
80
+ const { runVisionsCli } = await import("../chunks/visions-cli-CVRB9IWA.js");
81
81
  return runVisionsCli(subcommandArgs);
82
82
  }],
83
83
  ["ssh-sign", async (subcommandArgs) => {
84
- const { runSshSignCli } = await import("../chunks/ssh-sign-cli-BG29CY0B.js");
84
+ const { runSshSignCli } = await import("../chunks/ssh-sign-cli-BEAAFjXg.js");
85
85
  return runSshSignCli(subcommandArgs);
86
86
  }]
87
87
  ];
88
88
  var ownSubcommandNames = new Set(OWN_SUBCOMMAND_RUNNERS.map(([name]) => name));
89
89
  var SUBCOMMAND_RUNNERS = new Map([...OWN_SUBCOMMAND_RUNNERS, ...AGENT_API_VERBS.filter((verb) => !ownSubcommandNames.has(verb)).map((verb) => [verb, async (subcommandArgs, subcommandName) => {
90
- const { runAgentApiCli } = await import("../chunks/agent-api-cli-CS62LiST.js");
90
+ const { runAgentApiCli } = await import("../chunks/agent-api-cli-CvCov9_e.js");
91
91
  return runAgentApiCli([subcommandName, ...subcommandArgs]);
92
92
  }])]);
93
93
  var AGENT_INSTALL_COMMAND_BY_ID = {
@@ -101,7 +101,7 @@ function missingAgentText(agentId) {
101
101
  }
102
102
  async function printSessionLimits() {
103
103
  if (!process.env["GLIMMERVOID_AGENT_URL"]) return;
104
- const { sessionLimitsHelpLines } = await import("../chunks/agent-api-cli-CS62LiST.js");
104
+ const { sessionLimitsHelpLines } = await import("../chunks/agent-api-cli-CvCov9_e.js");
105
105
  const limitsLines = await sessionLimitsHelpLines();
106
106
  console.log(`\n${limitsLines.join("\n")}`);
107
107
  }
@@ -158,7 +158,7 @@ async function readDeclaredCustomAgents() {
158
158
  declared: [],
159
159
  error: null
160
160
  };
161
- const { loadConfigFile } = await import("../chunks/config-store-B67fnqQ1.js");
161
+ const { loadConfigFile } = await import("../chunks/config-store-DcVWBJOV.js");
162
162
  try {
163
163
  const loaded = loadConfigFile(decided.path, { exitOnError: false });
164
164
  if (!loaded.config) return {
@@ -234,7 +234,7 @@ async function runDoctor() {
234
234
  }
235
235
  switchSection("Agents");
236
236
  try {
237
- const { listAgentIds, describeAgentResolvability, setCustomAgents } = await import("../chunks/adapters-CTm8gTiM.js");
237
+ const { listAgentIds, describeAgentResolvability, setCustomAgents } = await import("../chunks/adapters-D8BJffFW.js");
238
238
  const declaredCustomAgents = await readDeclaredCustomAgents();
239
239
  if (declaredCustomAgents.error) line("config", declaredCustomAgents.error);
240
240
  setCustomAgents(declaredCustomAgents.declared);
@@ -242,7 +242,7 @@ async function runDoctor() {
242
242
  const { label, path: resolvedPath } = describeAgentResolvability(id);
243
243
  line(`${id} (${label})`, resolvedPath ?? missingAgentText(id));
244
244
  }
245
- const { inspectGrokAgentSetup } = await import("../chunks/agent-setup-cli-BffFfN-1.js");
245
+ const { inspectGrokAgentSetup } = await import("../chunks/agent-setup-cli-py1gUMvJ.js");
246
246
  const grokSetup = inspectGrokAgentSetup();
247
247
  line("grok hook setup", `${grokSetup.classification}: ${grokSetup.filePath}`);
248
248
  } catch (err) {
@@ -250,7 +250,7 @@ async function runDoctor() {
250
250
  }
251
251
  switchSection("rtk");
252
252
  try {
253
- const { getRtkPath } = await import("../chunks/rtk-resolver-BGE6Hd_L.js");
253
+ const { getRtkPath } = await import("../chunks/rtk-resolver-Dr4iJsiS.js");
254
254
  line("rtk", getRtkPath() || "not installed (Glimmervoid installs it when the rtk setting is on)");
255
255
  } catch (err) {
256
256
  line("rtk", `probe failed: ${firstLine(errorText(err))}`);
@@ -258,8 +258,8 @@ async function runDoctor() {
258
258
  switchSection("Sane YOLO");
259
259
  try {
260
260
  const { resolvePackageBin } = await import("../chunks/runtime-paths-DSmormp7.js");
261
- const { execFileSync } = await import("../chunks/child-process-safe-ChRmWAJP.js");
262
- const { inspectGrokAgentSetup } = await import("../chunks/agent-setup-cli-BffFfN-1.js");
261
+ const { execFileSync } = await import("../chunks/child-process-safe-CjVtRjDD.js");
262
+ const { inspectGrokAgentSetup } = await import("../chunks/agent-setup-cli-py1gUMvJ.js");
263
263
  const binPath = resolvePackageBin("cc-safety-net", "cc-safety-net");
264
264
  line("Sane YOLO", binPath || "not installed");
265
265
  if (binPath) line("cc-safety-net version", execFileSync(process.execPath, [binPath, "--version"], {
@@ -1,13 +1,14 @@
1
1
  import { o as relayPath } from "./runtime-paths-BkeftE60.js";
2
- import { r as execFileSync } from "./child-process-safe-CbQnyh7D.js";
3
- import "./control-messages-CMIEvS1e.js";
4
- import { o as supervisionLine } from "./session-routes-Dv0vvLc6.js";
2
+ import { Lt as FULL_SHA_RE, zt as shortSha$1 } from "./session-C8IpFmGQ.js";
3
+ import { n as execFileAsync, r as execFileSync } from "./child-process-safe-D4hyVIXj.js";
4
+ import { a as InstallFlavor } from "./control-messages-C6JGCTuy.js";
5
+ import { o as supervisionLine } from "./session-routes-nySS7DUE.js";
5
6
  import { n as resolveAgentCommand, t as buildAgentSpawnCommand } from "./spawn-command-Cc40FiZI.js";
6
- import { s as rawTextOr } from "./coerce-NSst8oRP.js";
7
+ import { c as textOr, s as rawTextOr } from "./coerce-NSst8oRP.js";
7
8
  import { r as nextBackoffMs } from "./backoff-DjVpfHk7.js";
8
- import { i as isSpinnerChar, n as classifyAgentTitle, r as isBrailleChar, s as buildAgentEnv, t as grok } from "./grok-mti-4OsU.js";
9
+ import { i as isSpinnerChar, n as classifyAgentTitle, r as isBrailleChar, s as buildAgentEnv, t as grok } from "./grok-BUGgQVE3.js";
9
10
  import { t as buildHookCommand } from "./hook-command-core-qTNK-xMF.js";
10
- import "./contracts-CLBzEau4.js";
11
+ import "./contracts-C9Jj9iDo.js";
11
12
  import { n as mergeCodexPreToolUse, t as HOOK_TOOLS } from "./hook-tools-Dl7-r2Eb.js";
12
13
  import fs from "node:fs";
13
14
  import path from "node:path";
@@ -77,6 +78,7 @@ function mapHookToSignal$1(event, payload) {
77
78
  case "sessionend": return "session-end";
78
79
  case "userpromptsubmit": return "resume";
79
80
  case "stop": return "ready";
81
+ case "stopfailure": return payload?.error === "authentication_failed" ? "auth-failed" : "ready";
80
82
  case "subagentstart": return "subagent-start";
81
83
  case "subagentstop": return "subagent-stop";
82
84
  case "taskcreated": return "task-created";
@@ -396,18 +398,240 @@ function codexSessionIdFromPath(filePath) {
396
398
  return base || null;
397
399
  }
398
400
  //#endregion
399
- //#region session/adapters/codex.ts
400
- var ID = "codex";
401
- var COMMAND_NAME = "codex";
402
- var RELAY_PATH = relayPath("hook-relay");
403
- var HOOK_TOOL_RELAY_PATH = relayPath("hook-tool-relay");
404
- var HOOK_EVENTS = [
401
+ //#region shared/repo.ts
402
+ var REPO_SLUG = "johncwaters/glimmervoid";
403
+ //#endregion
404
+ //#region server/core/update-core.ts
405
+ var NPM_PACKAGE_NAME = "glimmervoid";
406
+ var NPM_GLOBAL_COMMAND = `npm install -g ${NPM_PACKAGE_NAME}@latest`;
407
+ var NODE_PTY_INSTALL_SCRIPT_FLAG = "--allow-scripts=node-pty";
408
+ var NPX_CACHE_DIRECTORY_NAME = "_npx";
409
+ var CLONE_COMMAND = "git pull --ff-only && npm ci && npm run build";
410
+ var INSTALL_FLAVORS = new Set(InstallFlavor.options);
411
+ var TAG_VERSION_RE = /^v(\d+\.\d+\.\d+)$/;
412
+ var UPDATE_CHANNELS = /* @__PURE__ */ new Set(["release", "main"]);
413
+ var DEPRECATION_MESSAGE_MAX_CHARS = 500;
414
+ function normalizeSha(value) {
415
+ if (typeof value !== "string") return null;
416
+ const sha = value.trim().toLowerCase();
417
+ if (!FULL_SHA_RE.test(sha)) return null;
418
+ return sha;
419
+ }
420
+ function shortSha(value) {
421
+ return shortSha$1(normalizeSha(value) ?? "");
422
+ }
423
+ function parseResolvedSha(resolved) {
424
+ if (typeof resolved !== "string") return null;
425
+ const fragmentAt = resolved.lastIndexOf("#");
426
+ if (fragmentAt === -1) return null;
427
+ return normalizeSha(resolved.slice(fragmentAt + 1));
428
+ }
429
+ function parseTagVersion(ref) {
430
+ if (typeof ref !== "string") return null;
431
+ const normalized = ref.trim().replace(/^refs\/tags\//, "").replace(/\^\{\}$/, "");
432
+ const matched = TAG_VERSION_RE.exec(normalized);
433
+ if (!matched) return null;
434
+ return matched[1];
435
+ }
436
+ function isNpxCachePath(packageRoot) {
437
+ if (typeof packageRoot !== "string") return false;
438
+ return packageRoot.split(/[\\/]/).includes(NPX_CACHE_DIRECTORY_NAME);
439
+ }
440
+ function decideInstallFlavor({ packageRoot, lockfileSha, gitHeadSha, hasGitDir, isInsideNodeModules } = {}) {
441
+ const fromLockfile = normalizeSha(lockfileSha);
442
+ if (isNpxCachePath(packageRoot)) return {
443
+ flavor: "npx",
444
+ installedSha: fromLockfile ?? normalizeSha(gitHeadSha)
445
+ };
446
+ if (fromLockfile) return {
447
+ flavor: "npm-global",
448
+ installedSha: fromLockfile
449
+ };
450
+ const fromGitHead = normalizeSha(gitHeadSha);
451
+ if (fromGitHead) return {
452
+ flavor: "npm-global",
453
+ installedSha: fromGitHead
454
+ };
455
+ if (hasGitDir) return {
456
+ flavor: "clone",
457
+ installedSha: null
458
+ };
459
+ if (isInsideNodeModules) return {
460
+ flavor: "npm-global",
461
+ installedSha: null
462
+ };
463
+ return {
464
+ flavor: "unknown",
465
+ installedSha: null
466
+ };
467
+ }
468
+ function buildNpxCommand(latestVersion, platform) {
469
+ const packageSpec = `${NPM_PACKAGE_NAME}@${textOr(latestVersion, null) ?? "latest"}`;
470
+ if (platform === "linux") return `npx ${NODE_PTY_INSTALL_SCRIPT_FLAG} ${packageSpec}`;
471
+ return `npx ${packageSpec}`;
472
+ }
473
+ function buildNpmGlobalCommand(latestVersion, platform) {
474
+ const version = textOr(latestVersion, null);
475
+ const installCommand = version ? `npm install -g ${NPM_PACKAGE_NAME}@${version}` : NPM_GLOBAL_COMMAND;
476
+ if (platform === "linux") return `${installCommand} ${NODE_PTY_INSTALL_SCRIPT_FLAG}`;
477
+ return installCommand;
478
+ }
479
+ function buildUpdateCommand(flavor, latestVersion, platform) {
480
+ if (flavor === "npx") return buildNpxCommand(latestVersion, platform);
481
+ if (flavor === "npm-global") return buildNpmGlobalCommand(latestVersion, platform);
482
+ return CLONE_COMMAND;
483
+ }
484
+ function buildReleaseUrl(version) {
485
+ const releaseVersion = textOr(version, null);
486
+ if (!releaseVersion) return null;
487
+ return `https://github.com/${REPO_SLUG}/releases/tag/v${releaseVersion}`;
488
+ }
489
+ function parseVersionTriple(version) {
490
+ if (typeof version !== "string") return null;
491
+ const parts = version.trim().replace(/^v/, "").split(/[-+]/)[0].split(".");
492
+ if (parts.length !== 3) return null;
493
+ const triple = [];
494
+ for (const part of parts) {
495
+ if (!/^\d+$/.test(part)) return null;
496
+ triple.push(Number.parseInt(part, 10));
497
+ }
498
+ return triple;
499
+ }
500
+ function compareSemver(a, b) {
501
+ const ta = parseVersionTriple(a);
502
+ const tb = parseVersionTriple(b);
503
+ if (!ta || !tb) return 0;
504
+ for (let i = 0; i < 3; i += 1) {
505
+ if (ta[i] > tb[i]) return 1;
506
+ if (ta[i] < tb[i]) return -1;
507
+ }
508
+ return 0;
509
+ }
510
+ function parseRegistryLatest(doc) {
511
+ if (!doc || typeof doc !== "object") return null;
512
+ const registryDocument = doc;
513
+ const publishedVersion = textOr(registryDocument.version, null);
514
+ if (!publishedVersion) return null;
515
+ const version = parseTagVersion(`v${publishedVersion}`);
516
+ if (!version) return null;
517
+ return {
518
+ version,
519
+ sha: normalizeSha(registryDocument.gitHead)
520
+ };
521
+ }
522
+ function parseRegistryDeprecation(doc) {
523
+ if (!doc || typeof doc !== "object") return null;
524
+ const deprecated = doc.deprecated;
525
+ if (typeof deprecated !== "string") return null;
526
+ const message = deprecated.trim();
527
+ if (!message) return null;
528
+ return message.slice(0, DEPRECATION_MESSAGE_MAX_CHARS);
529
+ }
530
+ function normalizeFlavor(flavor) {
531
+ if (typeof flavor === "string" && INSTALL_FLAVORS.has(flavor)) return flavor;
532
+ return "unknown";
533
+ }
534
+ function normalizeUpdateChannel(channel) {
535
+ if (typeof channel === "string" && UPDATE_CHANNELS.has(channel)) return channel;
536
+ return "release";
537
+ }
538
+ function normalizeBehindCount(value) {
539
+ if (!Number.isInteger(value)) return null;
540
+ const count = Number(value);
541
+ if (count < 0) return null;
542
+ return count;
543
+ }
544
+ function decideUpdateReason({ isReleaseAlreadyCheckedOut, reason }) {
545
+ if (isReleaseAlreadyCheckedOut) return "release-already-checked-out";
546
+ return textOr(reason, null);
547
+ }
548
+ function decideUpdateStatus({ installedSha, latestSha: remoteSha, currentVersion, latestVersion, flavor, platform, channel, behindCount, reason, isLatestReleaseAncestorOfHead, deprecation } = {}) {
549
+ const currentSha = normalizeSha(installedSha);
550
+ const latestSha = normalizeSha(remoteSha);
551
+ const current = textOr(currentVersion, null);
552
+ const latest = textOr(latestVersion, null);
553
+ const normalizedFlavor = normalizeFlavor(flavor);
554
+ const normalizedChannel = normalizeUpdateChannel(channel);
555
+ const normalizedBehindCount = normalizeBehindCount(behindCount);
556
+ const isReleaseAlreadyCheckedOut = normalizedChannel === "release" && normalizedFlavor === "clone" && isLatestReleaseAncestorOfHead === true && compareSemver(latest, current) > 0;
557
+ return {
558
+ updateAvailable: normalizedChannel === "main" ? normalizedBehindCount !== null && normalizedBehindCount > 0 && currentSha !== latestSha : !isReleaseAlreadyCheckedOut && compareSemver(latest, current) > 0,
559
+ current,
560
+ latest,
561
+ currentSha,
562
+ latestSha,
563
+ releaseUrl: buildReleaseUrl(latest),
564
+ command: buildUpdateCommand(flavor, latest, platform),
565
+ flavor: normalizedFlavor,
566
+ channel: normalizedChannel,
567
+ behindCount: normalizedBehindCount,
568
+ reason: decideUpdateReason({
569
+ isReleaseAlreadyCheckedOut,
570
+ reason
571
+ }),
572
+ deprecation: isReleaseAlreadyCheckedOut ? null : parseRegistryDeprecation({ deprecated: deprecation })
573
+ };
574
+ }
575
+ function isCheckFresh(lastCheckAt, nowMs, ttlMs) {
576
+ if (!Number.isFinite(lastCheckAt)) return false;
577
+ if (!Number.isFinite(nowMs)) return false;
578
+ if (!Number.isFinite(ttlMs)) return false;
579
+ const age = Number(nowMs) - Number(lastCheckAt);
580
+ if (age < 0) return false;
581
+ return age < Number(ttlMs);
582
+ }
583
+ //#endregion
584
+ //#region session/core/codex-version-core.ts
585
+ var CODEX_EXTENDED_HOOKS_FLOOR = "0.163.0";
586
+ var LEGACY_HOOK_EVENTS = [
405
587
  "SessionStart",
406
588
  "SessionEnd",
407
589
  "UserPromptSubmit",
408
590
  "Stop",
409
591
  "PermissionRequest"
410
592
  ];
593
+ var EXTENDED_HOOK_EVENTS = [
594
+ ...LEGACY_HOOK_EVENTS,
595
+ "PreCompact",
596
+ "PostCompact",
597
+ "SubagentStart",
598
+ "SubagentStop"
599
+ ];
600
+ var EXTENDED_MATCHED_RELAY_HOOKS = [{
601
+ event: "PreToolUse",
602
+ matcher: "request_user_input"
603
+ }, {
604
+ event: "PostToolUse",
605
+ matcher: "Bash"
606
+ }];
607
+ var CODEX_VERSION_RE = /\bcodex-cli\s+(\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)\b/;
608
+ var PRERELEASE_SUFFIX_RE = /^[^+]*-/;
609
+ function parseCodexVersion(versionOutput) {
610
+ if (typeof versionOutput !== "string") return null;
611
+ return CODEX_VERSION_RE.exec(versionOutput)?.[1] ?? null;
612
+ }
613
+ function isAtOrAboveExtendedHooksFloor(installedVersion) {
614
+ const releaseOrder = compareSemver(installedVersion, CODEX_EXTENDED_HOOKS_FLOOR);
615
+ if (releaseOrder !== 0) return releaseOrder > 0;
616
+ return !PRERELEASE_SUFFIX_RE.test(installedVersion);
617
+ }
618
+ function codexHookPlanFor(installedVersion) {
619
+ if (!(installedVersion !== null && isAtOrAboveExtendedHooksFloor(installedVersion))) return {
620
+ events: [...LEGACY_HOOK_EVENTS],
621
+ matchedRelayHooks: []
622
+ };
623
+ return {
624
+ events: [...EXTENDED_HOOK_EVENTS],
625
+ matchedRelayHooks: EXTENDED_MATCHED_RELAY_HOOKS
626
+ };
627
+ }
628
+ //#endregion
629
+ //#region session/adapters/codex.ts
630
+ var ID = "codex";
631
+ var COMMAND_NAME = "codex";
632
+ var RELAY_PATH = relayPath("hook-relay");
633
+ var HOOK_TOOL_RELAY_PATH = relayPath("hook-tool-relay");
634
+ var HOOK_EVENTS = LEGACY_HOOK_EVENTS;
411
635
  var envProfile$1 = {
412
636
  scrub: [],
413
637
  set: {}
@@ -432,21 +656,34 @@ var titleProfile = {
432
656
  agentSuffix: ` - ${ID}`
433
657
  }
434
658
  };
435
- function mapHookToSignal(event) {
436
- switch (String(event || "").toLowerCase()) {
659
+ var REQUEST_USER_INPUT_TOOL_NAME = "request_user_input";
660
+ function isRequestUserInput(event, payload) {
661
+ return event === "pretooluse" && payload?.tool_name === REQUEST_USER_INPUT_TOOL_NAME;
662
+ }
663
+ function mapHookToSignal(event, payload) {
664
+ const e = String(event || "").toLowerCase();
665
+ switch (e) {
437
666
  case "sessionstart": return "session-start";
438
667
  case "sessionend": return "session-end";
439
668
  case "userpromptsubmit": return "resume";
440
669
  case "stop": return "ready";
441
670
  case "permissionrequest": return "awaiting-input";
671
+ case "precompact": return "compaction-start";
672
+ case "postcompact": return "compaction-end";
673
+ case "subagentstart": return "subagent-start";
674
+ case "subagentstop": return "subagent-stop";
675
+ case "pretooluse": return isRequestUserInput(e, payload) ? "awaiting-input" : null;
442
676
  default: return null;
443
677
  }
444
678
  }
445
679
  function mapHookConfidence() {
446
680
  return null;
447
681
  }
448
- function mapHookPromptKind(event) {
449
- return String(event || "").toLowerCase() === "permissionrequest" ? "permission" : null;
682
+ function mapHookPromptKind(event, payload) {
683
+ const e = String(event || "").toLowerCase();
684
+ if (e === "permissionrequest") return "permission";
685
+ if (isRequestUserInput(e, payload)) return "elicitation";
686
+ return null;
450
687
  }
451
688
  function sessionIdOf(payload) {
452
689
  return payload?.session_id;
@@ -468,11 +705,13 @@ function userConfigFolders(env) {
468
705
  return codexHomes(env, null);
469
706
  }
470
707
  var TOML_LITERAL_STRING_FORBIDDEN = /[\x00-\x08\x0a-\x1f\x27\x7f]/;
471
- function buildHookArgs({ relayPath = RELAY_PATH, events = HOOK_EVENTS, bypassHookTrust = false, hookTools = [], hookToolRelayPath = HOOK_TOOL_RELAY_PATH, userHooks = [] } = {}) {
708
+ function buildHookArgs({ relayPath = RELAY_PATH, events = HOOK_EVENTS, matchedRelayHooks = [], bypassHookTrust = false, hookTools = [], hookToolRelayPath = HOOK_TOOL_RELAY_PATH, userHooks = [], observeToolCalls = false } = {}) {
472
709
  const args = bypassHookTrust ? [TRUST_BYPASS_FLAG] : [];
473
710
  const preToolUseGroups = [];
474
711
  const groupsByEvent = /* @__PURE__ */ new Map();
475
- for (const event of events) {
712
+ const relayedEvents = observeToolCalls && !events.includes("PreToolUse") ? [...events, "PreToolUse"] : events;
713
+ const relayedMatchedHooks = observeToolCalls ? matchedRelayHooks.filter(({ event }) => event !== "PreToolUse") : matchedRelayHooks;
714
+ for (const event of relayedEvents) {
476
715
  const command = buildHookCommand(relayPath, event);
477
716
  if (!command) return null;
478
717
  if (event === "PreToolUse") {
@@ -481,6 +720,16 @@ function buildHookArgs({ relayPath = RELAY_PATH, events = HOOK_EVENTS, bypassHoo
481
720
  }
482
721
  groupsByEvent.set(event, [`{hooks=[{type='command',command='${command}'}]}`]);
483
722
  }
723
+ for (const { event, matcher } of relayedMatchedHooks) {
724
+ const command = buildHookCommand(relayPath, event);
725
+ if (!command) return null;
726
+ const group = `{matcher='${matcher}',hooks=[{type='command',command='${command}'}]}`;
727
+ if (event === "PreToolUse") {
728
+ preToolUseGroups.push(group);
729
+ continue;
730
+ }
731
+ groupsByEvent.set(event, [...groupsByEvent.get(event) ?? [], group]);
732
+ }
484
733
  const groups = hookTools.flatMap((tool) => {
485
734
  const group = HOOK_TOOLS[tool.id].codexGroup(tool, hookToolRelayPath);
486
735
  return group ? [group] : [];
@@ -505,6 +754,50 @@ function buildHookArgs({ relayPath = RELAY_PATH, events = HOOK_EVENTS, bypassHoo
505
754
  args.push(...mergeCodexPreToolUse(preToolUseGroups));
506
755
  return args;
507
756
  }
757
+ var installedHookPlan = null;
758
+ function probeInstalledCodexVersion() {
759
+ const versionCommand = buildSpawnCommand({
760
+ platform: process.platform,
761
+ resolved: resolveCommand(),
762
+ agentArgs: ["--version"]
763
+ });
764
+ try {
765
+ return parseCodexVersion(execFileSync(versionCommand.file, versionCommand.args, {
766
+ encoding: "utf8",
767
+ timeout: 3e3,
768
+ windowsHide: true
769
+ }));
770
+ } catch {
771
+ return null;
772
+ }
773
+ }
774
+ async function readHostCodexVersion() {
775
+ const versionCommand = buildSpawnCommand({
776
+ platform: process.platform,
777
+ resolved: resolveCommand(),
778
+ agentArgs: ["--version"]
779
+ });
780
+ try {
781
+ const { stdout } = await execFileAsync(versionCommand.file, versionCommand.args, {
782
+ encoding: "utf8",
783
+ timeout: 3e3,
784
+ windowsHide: true
785
+ });
786
+ return parseCodexVersion(stdout);
787
+ } catch {
788
+ return null;
789
+ }
790
+ }
791
+ function hookPlanForInstalledCodex() {
792
+ installedHookPlan ??= codexHookPlanFor(probeInstalledCodexVersion());
793
+ return installedHookPlan;
794
+ }
795
+ function buildInstalledHookArgs(options = {}) {
796
+ return buildHookArgs({
797
+ ...hookPlanForInstalledCodex(),
798
+ ...options
799
+ });
800
+ }
508
801
  var hooks = {
509
802
  mapSignal: mapHookToSignal,
510
803
  mapConfidence: mapHookConfidence,
@@ -513,7 +806,7 @@ var hooks = {
513
806
  kind: "argv-config",
514
807
  relayPath: RELAY_PATH,
515
808
  events: HOOK_EVENTS,
516
- buildHookArgs,
809
+ buildHookArgs: buildInstalledHookArgs,
517
810
  projectConfigCandidates: PROJECT_CONFIG_CANDIDATES,
518
811
  userConfigFolders,
519
812
  mayContributeHooks
@@ -612,12 +905,12 @@ var codex = {
612
905
  capabilities: {
613
906
  hooks: true,
614
907
  awaitingInput: true,
615
- backgroundAgents: false,
908
+ backgroundAgents: true,
616
909
  resume: true,
617
- statusLine: false,
910
+ statusLine: true,
618
911
  rtk: true,
619
912
  saneYolo: true,
620
- compactQuiet: false,
913
+ compactQuiet: true,
621
914
  skipPermissionsFlag: true,
622
915
  headless: true
623
916
  }
@@ -803,4 +1096,4 @@ function resetCommandCache() {
803
1096
  resolvedCommands.clear();
804
1097
  }
805
1098
  //#endregion
806
- export { splitLines as A, isUsageFile as C, scopedClaudeRoots as D, resolveProjectsDirs as E, shouldEvaluateDespiteIoFailures as O, grokRootCandidates as S, projectDirCandidates as T, continuationDelayMs as _, describeAgentResolvability as a, expandTilde as b, isKnownAgentId as c, resolveAdapter as d, setCustomAgents as f, codexSessionIdFromPath as g, codexRootCandidates as h, customAgentFingerprint as i, claudeCode as j, shouldPersistWarehouse as k, listAgentIds as l, codexHomes as m, cachedAgentResolvability as n, getAdapter as o, codexFallbackRoots as p, commandFor as r, hookProfileOf as s, DEFAULT_AGENT_ID as t, resetCommandCache as u, decideFileRead as v, passOutcome as w, grokHomes as x, dedupeCodexFiles as y };
1099
+ export { dedupeCodexFiles as A, shouldPersistWarehouse as B, shortSha as C, codexSessionIdFromPath as D, codexRootCandidates as E, passOutcome as F, claudeCode as H, projectDirCandidates as I, resolveProjectsDirs as L, grokHomes as M, grokRootCandidates as N, continuationDelayMs as O, isUsageFile as P, scopedClaudeRoots as R, parseResolvedSha as S, codexHomes as T, splitLines as V, isCheckFresh as _, describeAgentResolvability as a, parseRegistryDeprecation as b, isKnownAgentId as c, resolveAdapter as d, setCustomAgents as f, decideUpdateStatus as g, decideInstallFlavor as h, customAgentFingerprint as i, expandTilde as j, decideFileRead as k, listAgentIds as l, readHostCodexVersion as m, cachedAgentResolvability as n, getAdapter as o, codex as p, commandFor as r, hookProfileOf as s, DEFAULT_AGENT_ID as t, resetCommandCache as u, normalizeSha as v, codexFallbackRoots as w, parseRegistryLatest as x, normalizeUpdateChannel as y, shouldEvaluateDespiteIoFailures as z };
@@ -1 +1 @@
1
- export { a as describeAgentResolvability, l as listAgentIds, f as setCustomAgents } from "./adapters-D86Do-kG.js";
1
+ export { a as describeAgentResolvability, l as listAgentIds, f as setCustomAgents } from "./adapters-CyDflXHy.js";
@@ -1,7 +1,7 @@
1
1
  import { t as errorCode } from "./text-DoirglWV.js";
2
- import { n as AGENT_URL_ENV, o as AgentLimitsReply } from "./session-BmjBq2rH.js";
3
- import { i as formatSessionLimits } from "./session-routes-Dv0vvLc6.js";
4
- import { l as isAgentApiVerb, t as AGENT_COMMAND_HELP } from "./agent-api-core-Cf70N-eJ.js";
2
+ import { n as AGENT_URL_ENV, s as AgentLimitsReply } from "./session-C8IpFmGQ.js";
3
+ import { i as formatSessionLimits } from "./session-routes-nySS7DUE.js";
4
+ import { l as isAgentApiVerb, t as AGENT_COMMAND_HELP } from "./agent-api-core-CLxZAole.js";
5
5
  import { i as resolveHookTarget } from "./hook-relay-core-DA_bz2KA.js";
6
6
  import { n as decideGuardrailsProxy } from "./guardrails-proxy-core-BI3rdY-m.js";
7
7
  import { t as parseJsonOrNull } from "./json-core-dfa_7Fak.js";
@@ -20,6 +20,15 @@ var BODY_BUILDERS = {
20
20
  const prompt = rest.join(" ").trim();
21
21
  return prompt ? { prompt } : null;
22
22
  },
23
+ send: (rest) => rest.join(" ").trim() ? { words: rest } : null,
24
+ read: (rest) => {
25
+ const child = rest.join(" ").trim();
26
+ return child ? { child } : {};
27
+ },
28
+ close: (rest) => {
29
+ const child = rest.join(" ").trim();
30
+ return child ? { child } : null;
31
+ },
23
32
  attention: (rest) => {
24
33
  const note = rest.join(" ").trim();
25
34
  return note ? { note } : null;
@@ -1 +1 @@
1
- export { t as askAgentApi, r as runAgentApiCli, i as sessionLimitsHelpLines } from "./agent-api-cli-Cj73fMC7.js";
1
+ export { t as askAgentApi, r as runAgentApiCli, i as sessionLimitsHelpLines } from "./agent-api-cli-B7-ToJul.js";
@@ -1,6 +1,6 @@
1
- import { a as AgentEditRequest, i as AgentAttentionRequest, l as AgentSettingsRequest, s as AgentPullRequestRequest, t as AGENT_API_VERBS, u as AgentSpawnRequest } from "./session-BmjBq2rH.js";
2
- import { a as pullRequestKeyFromReference } from "./control-messages-CMIEvS1e.js";
3
- import { n as NO_OWN_WORKTREE_REASON, t as COMMAND_ROUTES } from "./session-routes-Dv0vvLc6.js";
1
+ import { a as AgentCloseRequest, c as AgentPullRequestRequest, f as AgentSettingsRequest, i as AgentAttentionRequest, l as AgentReadRequest, o as AgentEditRequest, p as AgentSpawnRequest, t as AGENT_API_VERBS, u as AgentSendRequest } from "./session-C8IpFmGQ.js";
2
+ import { c as pullRequestKeyFromReference } from "./control-messages-C6JGCTuy.js";
3
+ import { n as NO_OWN_WORKTREE_REASON, t as COMMAND_ROUTES } from "./session-routes-nySS7DUE.js";
4
4
  import crypto from "node:crypto";
5
5
  var MAX_SPAWNS_IN_FLIGHT = 1;
6
6
  var REFUSAL_REASON = "unknown session";
@@ -117,6 +117,9 @@ var parsePullRequestBody = (payload) => {
117
117
  };
118
118
  var REQUEST_PARSERS = Object.freeze({
119
119
  spawn: bodyParser(AgentSpawnRequest),
120
+ send: bodyParser(AgentSendRequest),
121
+ read: bodyParser(AgentReadRequest),
122
+ close: bodyParser(AgentCloseRequest),
120
123
  attention: bodyParser(AgentAttentionRequest),
121
124
  board: parseEmptyBody,
122
125
  push: parseEmptyBody,
@@ -243,9 +246,24 @@ var USAGE_COLUMN_WIDTH = 20;
243
246
  var AGENT_COMMAND_HELP = Object.freeze({
244
247
  spawn: {
245
248
  usage: "spawn <prompt>",
246
- summary: "Start a sibling session on that prompt",
249
+ summary: "Start a session on that prompt that this session owns until its task is done",
247
250
  missingArgumentHint: "glimmervoid spawn: this command needs text, for example \"glimmervoid spawn check the failing test\""
248
251
  },
252
+ send: {
253
+ usage: "send [child] <text>",
254
+ summary: "Message a session this one spawned; a spawned session messages its parent with send <text>",
255
+ missingArgumentHint: "glimmervoid send: this command needs text, for example \"glimmervoid send the tests pass\" or, to a spawned session, \"glimmervoid send <child> fix the failing test\""
256
+ },
257
+ read: {
258
+ usage: "read [child]",
259
+ summary: "Read what this session's spawned sessions sent; a spawned session reads its parent's messages",
260
+ missingArgumentHint: null
261
+ },
262
+ close: {
263
+ usage: "close <child>",
264
+ summary: "End a session this one spawned, once its task is done",
265
+ missingArgumentHint: "glimmervoid close: this command needs the spawned session, for example \"glimmervoid close <child>\""
266
+ },
249
267
  attention: {
250
268
  usage: "attention <note>",
251
269
  summary: "Flag this session as needing the operator",
@@ -1,5 +1,5 @@
1
1
  import { a as isMissingFileError, r as errorMessage } from "./text-DoirglWV.js";
2
- import { a as classifyGrokHooksFile, o as renderGrokHooksFile, t as grok } from "./grok-mti-4OsU.js";
2
+ import { a as classifyGrokHooksFile, o as renderGrokHooksFile, t as grok } from "./grok-BUGgQVE3.js";
3
3
  import { p as writeTextAtomicSync } from "./json-file-DFCTvPjj.js";
4
4
  import fs from "node:fs";
5
5
  import path from "node:path";
@@ -0,0 +1 @@
1
+ export { r as execFileSync } from "./child-process-safe-D4hyVIXj.js";
@@ -47,7 +47,10 @@ var execFile = Object.assign(function execFile(file, ...rest) {
47
47
  const child = cp.execFile(file, args, execOptions, callback);
48
48
  if (typeof input !== "string") return;
49
49
  if (!child.stdin) return reject(/* @__PURE__ */ new Error("execFile stdin unavailable"));
50
- child.stdin.on("error", reject);
50
+ child.stdin.on("error", (error) => {
51
+ if (error.code === "EPIPE") return;
52
+ reject(error);
53
+ });
51
54
  child.stdin.end(input);
52
55
  }) });
53
56
  function execFileSync(file, ...rest) {