glimmervoid 0.35.1 → 0.37.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.
Files changed (50) hide show
  1. package/README.md +86 -82
  2. package/dist/bin/glimmervoid.js +58 -114
  3. package/dist/chunks/{adapters-CADejSpq.js → adapters-BmfVPxlH.js} +29 -61
  4. package/dist/chunks/adapters-CqFFmM2R.js +1 -0
  5. package/dist/chunks/{agent-api-cli-CRj_FYbz.js → agent-api-cli-BTHEyJKS.js} +1 -1
  6. package/dist/chunks/{agent-api-cli-vGwstJ1j.js → agent-api-cli-CBgOKXoO.js} +41 -12
  7. package/dist/chunks/{agent-api-core-D1233u1U.js → agent-api-core-DzKhakCv.js} +94 -3
  8. package/dist/chunks/{agent-setup-cli-BTAFcckd.js → agent-setup-cli-C8DGxlA-.js} +1 -1
  9. package/dist/chunks/{config-rPbbL4nW.js → config-BYc2z1Oc.js} +60 -779
  10. package/dist/chunks/config-store-B7MpiYxG.js +4181 -0
  11. package/dist/chunks/config-store-CsUoy88Q.js +1 -0
  12. package/dist/chunks/{contracts-DjIgIuDk.js → contracts-C6ipN_zw.js} +100 -12
  13. package/dist/chunks/git-version-6QFnKbWa.js +139 -0
  14. package/dist/chunks/{grok-KKgdSe-7.js → grok-CZ6kP_vD.js} +7 -3
  15. package/dist/chunks/guardrails-deps-Cb-ki4EU.js +70 -0
  16. package/dist/chunks/{sandbox-proxy-core-hnQgKR0T.js → guardrails-proxy-core-BI3rdY-m.js} +4 -4
  17. package/dist/chunks/{hook-command-core-DclEoE9e.js → hook-command-core-qTNK-xMF.js} +4 -1
  18. package/dist/chunks/{hook-tools-UX2fmt81.js → hook-tools-BkxllUHE.js} +9 -16
  19. package/dist/chunks/{knowledge-graph-cli-Rj5nj87L.js → knowledge-graph-cli-DApeMzA8.js} +1 -1
  20. package/dist/chunks/{loopback-post-DepQfdcM.js → loopback-post-DJ6iYWuL.js} +9 -9
  21. package/dist/chunks/{main-C-T2Uk20.js → main-BUfjroXE.js} +16282 -12595
  22. package/dist/chunks/{pair-cli-Dcyzv3In.js → pair-cli-GZ9t1mIO.js} +2 -2
  23. package/dist/chunks/{remote-config-Dd1T-VJA.js → remote-config-D2Is89Kj.js} +1 -1
  24. package/dist/chunks/{rtk-hook-core-BmEz2aq9.js → rtk-hook-core-VrUafGAp.js} +15 -5
  25. package/dist/chunks/rtk-resolver-B8BPgN9L.js +1 -0
  26. package/dist/chunks/{rtk-resolver-B9pzjLsM.js → rtk-resolver-C_micGrL.js} +1 -1
  27. package/dist/chunks/session-BZbariv5.js +1032 -0
  28. package/dist/chunks/{session-routes-BYy3am9m.js → session-routes-C4t8O8yg.js} +9 -9
  29. package/dist/chunks/settings-cli-DQOjmjev.js +484 -0
  30. package/dist/chunks/{ssh-sign-cli-DPHpT22B.js → ssh-sign-cli-LIBP8ppO.js} +2 -2
  31. package/dist/client/assets/index-B_Qt7fbZ.css +1 -0
  32. package/dist/client/assets/index-D-upBor0.js +265 -0
  33. package/dist/client/index.html +5 -3
  34. package/dist/scripts/postinstall-path-check.js +4 -4
  35. package/dist/server/index.js +1 -1
  36. package/dist/session/command-hook-relay.js +1 -1
  37. package/dist/session/{sandbox-open-launcher.js → guardrails-open-launcher.js} +10 -10
  38. package/dist/session/hook-relay.js +1 -1
  39. package/dist/session/hook-tool-relay.js +3 -3
  40. package/dist/session/statusline-relay.js +1 -1
  41. package/package.json +6 -5
  42. package/dist/chunks/adapters-B37wqNti.js +0 -1
  43. package/dist/chunks/config-store-BeIxAZNn.js +0 -1
  44. package/dist/chunks/config-store-BtsYbNC3.js +0 -1713
  45. package/dist/chunks/git-version-CUcDtF5k.js +0 -58
  46. package/dist/chunks/rtk-resolver-SWU5VVM7.js +0 -1
  47. package/dist/chunks/sandbox-deps-CWiH1d1w.js +0 -70
  48. package/dist/chunks/session-D6xXN0UU.js +0 -232
  49. package/dist/client/assets/index-CUxRHbCS.js +0 -254
  50. package/dist/client/assets/index-DE2GUmqs.css +0 -1
@@ -1,14 +1,13 @@
1
1
  import { o as relayPath } from "./runtime-paths-BkeftE60.js";
2
- import { A as toolDetailFieldValue, d as PROMPT_DETAIL_HIDDEN_CHARACTERS, k as firstDetailLine, p as PendingPromptQuestion } from "./session-D6xXN0UU.js";
3
2
  import { r as execFileSync } from "./child-process-safe-CbQnyh7D.js";
4
3
  import { n as resolveAgentCommand, t as buildAgentSpawnCommand } from "./spawn-command-Cc40FiZI.js";
5
- import { n as isRecord, s as rawTextOr } from "./coerce-NSst8oRP.js";
4
+ import { s as rawTextOr } from "./coerce-NSst8oRP.js";
6
5
  import { r as nextBackoffMs } from "./backoff-DjVpfHk7.js";
7
- import { l as supervisionLine } from "./session-routes-BYy3am9m.js";
8
- import { c as buildAgentEnv, i as isSpinnerChar, n as classifyAgentTitle, r as isBrailleChar, t as grok } from "./grok-KKgdSe-7.js";
9
- import { t as buildHookCommand } from "./hook-command-core-DclEoE9e.js";
10
- import "./contracts-DjIgIuDk.js";
11
- import { n as mergeCodexPreToolUse, t as HOOK_TOOLS } from "./hook-tools-UX2fmt81.js";
6
+ import { l as supervisionLine } from "./session-routes-C4t8O8yg.js";
7
+ import { c as buildAgentEnv, i as isSpinnerChar, n as classifyAgentTitle, r as isBrailleChar, t as grok } from "./grok-CZ6kP_vD.js";
8
+ import { t as buildHookCommand } from "./hook-command-core-qTNK-xMF.js";
9
+ import "./contracts-C6ipN_zw.js";
10
+ import { n as mergeCodexPreToolUse, t as HOOK_TOOLS } from "./hook-tools-BkxllUHE.js";
12
11
  import fs from "node:fs";
13
12
  import path from "node:path";
14
13
  //#region session/adapters/claude-code.ts
@@ -62,50 +61,12 @@ function mapHookPromptKind$1(event, payload) {
62
61
  }
63
62
  return null;
64
63
  }
65
- function mapHookPromptDetail(event, payload) {
64
+ function mapHookPromptToolName(event, payload) {
66
65
  if (String(event || "").toLowerCase() !== "permissionrequest") return null;
67
66
  if (mapHookPromptKind$1(event, payload) !== "permission") return null;
68
67
  const toolName = payload?.tool_name;
69
68
  if (typeof toolName !== "string" || !toolName) return null;
70
- const fieldValue = toolDetailFieldValue(toolName, payload?.tool_input);
71
- const summary = fieldValue === null ? "" : firstDetailLine(fieldValue);
72
- const isComplete = isWholeBashCommandShown(toolName, payload?.tool_input, fieldValue, summary);
73
- return {
74
- toolName: firstDetailLine(toolName),
75
- summary,
76
- isComplete,
77
- question: answerableQuestionOf(toolName, payload?.tool_input)
78
- };
79
- }
80
- function answerableQuestionOf(toolName, toolInput) {
81
- if (toolName !== "AskUserQuestion" || !isRecord(toolInput)) return null;
82
- const questions = toolInput.questions;
83
- if (!Array.isArray(questions) || questions.length !== 1) return null;
84
- const [entry] = questions;
85
- if (!isRecord(entry) || typeof entry.question !== "string" || !Array.isArray(entry.options)) return null;
86
- const optionLabels = entry.options.flatMap((option) => isRecord(option) && typeof option.label === "string" ? [option.label] : []);
87
- if (optionLabels.length !== entry.options.length) return null;
88
- const parsedQuestion = PendingPromptQuestion.safeParse({
89
- text: entry.question,
90
- options: optionLabels,
91
- multiSelect: entry.multiSelect === true
92
- });
93
- return parsedQuestion.success ? parsedQuestion.data : null;
94
- }
95
- var DISPLAY_IRRELEVANT_BASH_INPUT_KEYS = /* @__PURE__ */ new Set([
96
- "command",
97
- "description",
98
- "timeout"
99
- ]);
100
- function hasOnlyDisplayIrrelevantBashInputKeys(toolInput) {
101
- if (!toolInput || typeof toolInput !== "object") return false;
102
- return Reflect.ownKeys(toolInput).every((key) => typeof key === "string" && DISPLAY_IRRELEVANT_BASH_INPUT_KEYS.has(key));
103
- }
104
- function isWholeBashCommandShown(toolName, toolInput, fieldValue, summary) {
105
- if (toolName !== "Bash" || fieldValue === null) return false;
106
- if (!hasOnlyDisplayIrrelevantBashInputKeys(toolInput)) return false;
107
- if (PROMPT_DETAIL_HIDDEN_CHARACTERS.test(fieldValue)) return false;
108
- return summary === fieldValue;
69
+ return toolName;
109
70
  }
110
71
  function mapHookToSignal$1(event, payload) {
111
72
  switch (String(event || "").toLowerCase()) {
@@ -141,7 +102,7 @@ var hooks$1 = {
141
102
  mapSignal: mapHookToSignal$1,
142
103
  mapConfidence: mapHookConfidence$1,
143
104
  mapPromptKind: mapHookPromptKind$1,
144
- mapPromptDetail: mapHookPromptDetail,
105
+ mapPromptToolName: mapHookPromptToolName,
145
106
  injection: { kind: "settings-file" }
146
107
  };
147
108
  function resolveCommand$1({ platform, execFile = execFileSync, pathExists = fs.existsSync } = {}) {
@@ -191,10 +152,10 @@ var APPENDED_SYSTEM_PROMPT_FLAGS = Object.freeze([APPEND_SYSTEM_PROMPT_FLAG, "--
191
152
  function isAppendedSystemPromptArgument(launchArgument) {
192
153
  return APPENDED_SYSTEM_PROMPT_FLAGS.some((flag) => launchArgument === flag || launchArgument.startsWith(`${flag}=`));
193
154
  }
194
- function buildArgs$1({ dangerouslySkipPermissions = false, resumeSessionId = null, extraArgs = [], initialPrompt = null, hasOuterSandbox = false, canRunHelpCommand = true } = {}) {
155
+ function buildArgs$1({ dangerouslySkipPermissions = false, resumeSessionId = null, extraArgs = [], initialPrompt = null, hasOuterGuardrails = false, canRunHelpCommand = true } = {}) {
195
156
  const args = dangerouslySkipPermissions ? ["--dangerously-skip-permissions"] : [];
196
157
  if (resumeSessionId) args.push("--resume", resumeSessionId);
197
- if (canRunHelpCommand && !extraArgs.some(isAppendedSystemPromptArgument)) args.push(APPEND_SYSTEM_PROMPT_FLAG, supervisionLine({ isSandboxed: hasOuterSandbox }));
158
+ if (canRunHelpCommand && !extraArgs.some(isAppendedSystemPromptArgument)) args.push(APPEND_SYSTEM_PROMPT_FLAG, supervisionLine({ isGuarded: hasOuterGuardrails }));
198
159
  for (let index = 0; index < extraArgs.length; index += 1) {
199
160
  const argument = extraArgs[index];
200
161
  if (resumeSessionId && argument === "--session-id") {
@@ -239,7 +200,7 @@ var claudeCode = {
239
200
  mapHookToSignal: mapHookToSignal$1,
240
201
  mapHookConfidence: mapHookConfidence$1,
241
202
  mapHookPromptKind: mapHookPromptKind$1,
242
- mapHookPromptDetail
203
+ mapHookPromptToolName
243
204
  };
244
205
  //#endregion
245
206
  //#region server/usage/core/usage-scan-core.ts
@@ -494,6 +455,9 @@ function mayContributeHooks(configText) {
494
455
  if (typeof configText !== "string") return false;
495
456
  return HOOKS_DECLARATION_RE.test(configText);
496
457
  }
458
+ function userConfigFolders(env) {
459
+ return codexHomes(env, null);
460
+ }
497
461
  function buildHookArgs({ relayPath = RELAY_PATH, events = HOOK_EVENTS, bypassHookTrust = false, hookTools = [], hookToolRelayPath = HOOK_TOOL_RELAY_PATH } = {}) {
498
462
  const args = bypassHookTrust ? [TRUST_BYPASS_FLAG] : [];
499
463
  const preToolUseGroups = [];
@@ -523,6 +487,7 @@ var hooks = {
523
487
  events: HOOK_EVENTS,
524
488
  buildHookArgs,
525
489
  projectConfigCandidates: PROJECT_CONFIG_CANDIDATES,
490
+ userConfigFolders,
526
491
  mayContributeHooks
527
492
  }
528
493
  };
@@ -552,15 +517,15 @@ var SKIP_PERMISSIONS_ARGS = [
552
517
  "-s",
553
518
  "workspace-write"
554
519
  ];
555
- var OUTER_SANDBOX_ARGS = ["-s", "danger-full-access"];
556
- var OUTER_SANDBOX_SKIP_PERMISSIONS_ARGS = [
520
+ var OUTER_GUARDRAILS_ARGS = ["-s", "danger-full-access"];
521
+ var OUTER_GUARDRAILS_SKIP_PERMISSIONS_ARGS = [
557
522
  "-a",
558
523
  "never",
559
- ...OUTER_SANDBOX_ARGS
524
+ ...OUTER_GUARDRAILS_ARGS
560
525
  ];
561
- function permissionArgs(dangerouslySkipPermissions, hasOuterSandbox) {
562
- if (hasOuterSandbox && dangerouslySkipPermissions) return OUTER_SANDBOX_SKIP_PERMISSIONS_ARGS;
563
- if (hasOuterSandbox) return OUTER_SANDBOX_ARGS;
526
+ function permissionArgs(dangerouslySkipPermissions, hasOuterGuardrails) {
527
+ if (hasOuterGuardrails && dangerouslySkipPermissions) return OUTER_GUARDRAILS_SKIP_PERMISSIONS_ARGS;
528
+ if (hasOuterGuardrails) return OUTER_GUARDRAILS_ARGS;
564
529
  if (dangerouslySkipPermissions) return SKIP_PERMISSIONS_ARGS;
565
530
  return [];
566
531
  }
@@ -578,11 +543,11 @@ function setsOperatorInstructions(operatorConfigText) {
578
543
  function isDeveloperInstructionsOverride(launchArgument) {
579
544
  return launchArgument.startsWith(`${DEVELOPER_INSTRUCTIONS_KEY}=`);
580
545
  }
581
- function buildArgs({ dangerouslySkipPermissions = false, resumeSessionId = null, extraArgs = [], initialPrompt = null, hasOuterSandbox = false, hasOperatorInstructions = false, canRunHelpCommand = true } = {}) {
546
+ function buildArgs({ dangerouslySkipPermissions = false, resumeSessionId = null, extraArgs = [], initialPrompt = null, hasOuterGuardrails = false, hasOperatorInstructions = false, canRunHelpCommand = true } = {}) {
582
547
  const args = [...UPDATE_CHECK_ARGS];
583
- if (canRunHelpCommand && !hasOperatorInstructions && !extraArgs.some(isDeveloperInstructionsOverride)) args.push("-c", `${DEVELOPER_INSTRUCTIONS_KEY}='''${supervisionLine({ isSandboxed: hasOuterSandbox })}'''`);
548
+ if (canRunHelpCommand && !hasOperatorInstructions && !extraArgs.some(isDeveloperInstructionsOverride)) args.push("-c", `${DEVELOPER_INSTRUCTIONS_KEY}='''${supervisionLine({ isGuarded: hasOuterGuardrails })}'''`);
584
549
  if (resumeSessionId) args.push("resume", resumeSessionId);
585
- args.push(...permissionArgs(dangerouslySkipPermissions, hasOuterSandbox));
550
+ args.push(...permissionArgs(dangerouslySkipPermissions, hasOuterGuardrails));
586
551
  if (extraArgs.length > 0) args.push(...extraArgs);
587
552
  if (initialPrompt != null) args.push(initialPrompt);
588
553
  return args;
@@ -806,5 +771,8 @@ function cachedAgentResolvability(agentId) {
806
771
  resolvable: !!cached.path
807
772
  };
808
773
  }
774
+ function resetCommandCache() {
775
+ resolvedCommands.clear();
776
+ }
809
777
  //#endregion
810
- export { claudeCode as A, laneSpendStatus as C, shouldEvaluateDespiteIoFailures as D, resolveProjectsDirs as E, shouldPersistWarehouse as O, isUsageFile as S, projectDirCandidates as T, decideFileRead as _, describeAgentResolvability as a, grokHomes as b, isKnownAgentId as c, setCustomAgents as d, codexFallbackRoots as f, continuationDelayMs as g, codexSessionIdFromPath as h, customAgentFingerprint as i, splitLines as k, listAgentIds as l, codexRootCandidates as m, cachedAgentResolvability as n, getAdapter as o, codexHomes as p, commandFor as r, hookProfileOf as s, DEFAULT_AGENT_ID as t, resolveAdapter as u, dedupeCodexFiles as v, passOutcome as w, grokRootCandidates as x, expandTilde as y };
778
+ export { splitLines as A, isUsageFile as C, resolveProjectsDirs as D, projectDirCandidates as E, shouldEvaluateDespiteIoFailures as O, grokRootCandidates as S, passOutcome 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, laneSpendStatus as w, grokHomes as x, dedupeCodexFiles as y };
@@ -0,0 +1 @@
1
+ export { a as describeAgentResolvability, l as listAgentIds, f as setCustomAgents } from "./adapters-BmfVPxlH.js";
@@ -1 +1 @@
1
- export { n as runAgentApiCli, r as sessionLimitsHelpLines } from "./agent-api-cli-vGwstJ1j.js";
1
+ export { n as runAgentApiCli, r as sessionLimitsHelpLines } from "./agent-api-cli-CBgOKXoO.js";
@@ -1,10 +1,10 @@
1
1
  import { t as errorCode } from "./text-DoirglWV.js";
2
- import { a as AgentDispatchRequest, l as AgentTicketRequest, n as AGENT_URL_ENV, s as AgentLimitsReply } from "./session-D6xXN0UU.js";
2
+ import { a as AgentDispatchRequest, c as AgentFactoryStatusRequest, d as AgentTicketRequest, l as AgentLimitsReply, n as AGENT_URL_ENV, s as AgentFactoryRetryRequest } from "./session-BZbariv5.js";
3
3
  import { i as resolveHookTarget } from "./hook-relay-core-DA_bz2KA.js";
4
- import { n as decideSandboxProxy } from "./sandbox-proxy-core-hnQgKR0T.js";
4
+ import { n as decideGuardrailsProxy } from "./guardrails-proxy-core-BI3rdY-m.js";
5
5
  import { t as parseJsonOrNull } from "./json-core-dfa_7Fak.js";
6
- import { a as formatSessionLimits } from "./session-routes-BYy3am9m.js";
7
- import { d as isOrchestratorAgentVerb, u as isAgentApiVerb } from "./agent-api-core-D1233u1U.js";
6
+ import { a as formatSessionLimits } from "./session-routes-C4t8O8yg.js";
7
+ import { m as isOrchestratorAgentVerb, p as isAgentApiVerb } from "./agent-api-core-DzKhakCv.js";
8
8
  import path from "node:path";
9
9
  import http from "node:http";
10
10
  //#region server/agent-api-cli.ts
@@ -36,7 +36,18 @@ var BODY_BUILDERS = {
36
36
  return parsed.success ? parsed.data : null;
37
37
  },
38
38
  reopen: (rest) => ticketBody(rest),
39
- cancel: (rest) => ticketBody(rest)
39
+ cancel: (rest) => ticketBody(rest),
40
+ "factory-status": (rest) => {
41
+ if (rest.length === 0) return {};
42
+ if (rest.length !== 2 || rest[0] !== "--project") return null;
43
+ const parsed = AgentFactoryStatusRequest.safeParse({ projectId: rest[1] });
44
+ return parsed.success ? parsed.data : null;
45
+ },
46
+ "factory-retry": (rest) => {
47
+ if (rest.length !== 1) return null;
48
+ const parsed = AgentFactoryRetryRequest.safeParse({ intentId: rest[0] });
49
+ return parsed.success ? parsed.data : null;
50
+ }
40
51
  };
41
52
  function bodySaysOk(text) {
42
53
  try {
@@ -52,6 +63,13 @@ function limitsLines(replyText) {
52
63
  return formatSessionLimits(limits.data);
53
64
  }
54
65
  function printableReply(verb, replyText) {
66
+ if (verb === "factory-status" || verb === "factory-retry") {
67
+ const reply = parseJsonOrNull(replyText);
68
+ if (typeof reply !== "object" || reply === null) return replyText;
69
+ if ("text" in reply && typeof reply.text === "string") return reply.text;
70
+ if ("error" in reply && typeof reply.error === "string") return reply.error;
71
+ return replyText;
72
+ }
55
73
  if (verb !== "limits") return replyText;
56
74
  return limitsLines(replyText)?.join("\n") ?? replyText;
57
75
  }
@@ -79,12 +97,12 @@ async function postDirectly({ endpoint, headers, bodyText, deadline }) {
79
97
  text: await response.text()
80
98
  };
81
99
  }
82
- function postThroughSandboxProxy(sandboxProxy, { endpoint, headers, bodyText, deadline }) {
83
- const proxyHeaders = sandboxProxy.authorization ? { "proxy-authorization": sandboxProxy.authorization } : {};
100
+ function postThroughGuardrailsProxy(guardrailsProxy, { endpoint, headers, bodyText, deadline }) {
101
+ const proxyHeaders = guardrailsProxy.authorization ? { "proxy-authorization": guardrailsProxy.authorization } : {};
84
102
  return new Promise((resolve, reject) => {
85
103
  const request = http.request({
86
- host: sandboxProxy.hostname,
87
- port: sandboxProxy.port,
104
+ host: guardrailsProxy.hostname,
105
+ port: guardrailsProxy.port,
88
106
  method: "POST",
89
107
  path: endpoint.href,
90
108
  headers: {
@@ -129,9 +147,9 @@ async function postToAgentIngress({ endpoint, token, body, deadline = null }) {
129
147
  return await postDirectly(post);
130
148
  } catch (error) {
131
149
  if (!wasConnectionRefused(error)) throw error;
132
- const sandboxProxy = decideSandboxProxy(process.env);
133
- if (!sandboxProxy) throw error;
134
- return postThroughSandboxProxy(sandboxProxy, post);
150
+ const guardrailsProxy = decideGuardrailsProxy(process.env);
151
+ if (!guardrailsProxy) throw error;
152
+ return postThroughGuardrailsProxy(guardrailsProxy, post);
135
153
  }
136
154
  }
137
155
  async function sessionLimitsHelpLines({ timeoutMs = HELP_LIMITS_TIMEOUT_MS } = {}) {
@@ -151,6 +169,13 @@ async function sessionLimitsHelpLines({ timeoutMs = HELP_LIMITS_TIMEOUT_MS } = {
151
169
  }
152
170
  }
153
171
  async function runAgentApiCli(args) {
172
+ if (args[0] === "factory") {
173
+ if (args[1] !== "status" && args[1] !== "retry") {
174
+ console.error("glimmervoid factory: expected status [--project <projectId>] or retry <intentId>");
175
+ return 1;
176
+ }
177
+ return runAgentApiCli([`factory-${args[1]}`, ...args.slice(2)]);
178
+ }
154
179
  const verb = args[0];
155
180
  if (!verb || !isAgentApiVerb(verb)) {
156
181
  console.error(`glimmervoid: ${verb || "that"} is not an agent command`);
@@ -158,6 +183,10 @@ async function runAgentApiCli(args) {
158
183
  }
159
184
  const body = BODY_BUILDERS[verb](args.slice(1));
160
185
  if (!body) {
186
+ if (verb === "factory-status" || verb === "factory-retry") {
187
+ console.error(`glimmervoid factory: expected ${verb === "factory-status" ? "status [--project <projectId>]" : "retry <intentId>"}`);
188
+ return 1;
189
+ }
161
190
  if (isOrchestratorAgentVerb(verb)) {
162
191
  console.error(`glimmervoid ${verb}: expected a work id matching wrk-[0-9a-f]{16}`);
163
192
  return 1;
@@ -1,5 +1,5 @@
1
- import { a as AgentDispatchRequest, c as AgentSpawnRequest, i as AgentAttentionRequest, o as AgentEditRequest, t as AGENT_API_VERBS, u as ORCHESTRATOR_AGENT_VERBS } from "./session-D6xXN0UU.js";
2
- import { c as spawnRoute, i as editRoute, n as attentionRoute, s as pushRoute, t as NO_OWN_WORKTREE_REASON } from "./session-routes-BYy3am9m.js";
1
+ import { a as AgentDispatchRequest, c as AgentFactoryStatusRequest, i as AgentAttentionRequest, o as AgentEditRequest, s as AgentFactoryRetryRequest, t as AGENT_API_VERBS, u as AgentSpawnRequest, y as ORCHESTRATOR_AGENT_VERBS } from "./session-BZbariv5.js";
2
+ import { c as spawnRoute, i as editRoute, n as attentionRoute, s as pushRoute, t as NO_OWN_WORKTREE_REASON } from "./session-routes-C4t8O8yg.js";
3
3
  import crypto from "node:crypto";
4
4
  var MAX_SPAWNS_IN_FLIGHT = 1;
5
5
  var SPAWNABLE_DEPTH = 0;
@@ -77,6 +77,16 @@ function decideAttentionAllowance(caller) {
77
77
  function decideEditAllowance(caller) {
78
78
  return refuseByRole(editRoute(caller));
79
79
  }
80
+ function factoryControlRoute({ factoryRole, isEphemeral, isSpawnedChild }) {
81
+ if (!(factoryRole !== null || isEphemeral && !isSpawnedChild)) return { answers: true };
82
+ return {
83
+ answers: false,
84
+ reason: "only an operator session or a session it spawned may read factory status or retry parked work, so factory and lane sessions stay on their own task"
85
+ };
86
+ }
87
+ function decideFactoryControlAllowance(caller) {
88
+ return refuseByRole(factoryControlRoute(caller));
89
+ }
80
90
  function describePushRouteRefusal(caller) {
81
91
  const route = pushRoute(caller);
82
92
  if (route.answers) return null;
@@ -137,6 +147,24 @@ function parseAgentVerb(verb, payload) {
137
147
  status: 404,
138
148
  error: REFUSAL_REASON
139
149
  };
150
+ if (verb === "factory-status") {
151
+ const parsed = AgentFactoryStatusRequest.safeParse(payload);
152
+ if (!parsed.success) return refuseInvalidBody(parsed.error.issues);
153
+ return {
154
+ ok: true,
155
+ verb,
156
+ request: parsed.data
157
+ };
158
+ }
159
+ if (verb === "factory-retry") {
160
+ const parsed = AgentFactoryRetryRequest.safeParse(payload);
161
+ if (!parsed.success) return refuseInvalidBody(parsed.error.issues);
162
+ return {
163
+ ok: true,
164
+ verb,
165
+ request: parsed.data
166
+ };
167
+ }
140
168
  if (verb === "dispatch") {
141
169
  const parsed = AgentDispatchRequest.safeParse(payload);
142
170
  if (!parsed.success) return refuseInvalidBody(parsed.error.issues);
@@ -223,5 +251,68 @@ function deriveChildSessionName(parentName, existingNames) {
223
251
  }
224
252
  return candidate;
225
253
  }
254
+ function factoryTicketNextAction(ticket, intentId) {
255
+ if (ticket.state === "completed" || ticket.state === "cancelled") return "none";
256
+ if (ticket.parked) return `glimmervoid factory retry ${intentId}`;
257
+ if (ticket.state === "blocked") return "orchestrator reopens";
258
+ return "in progress";
259
+ }
260
+ function describeFactoryProjectUnavailability(project) {
261
+ if (project.error !== null) return project.error;
262
+ if (project.heading.action === "refuse") return `orientation refused: ${project.heading.reasons.join("; ") || "no reason given"}`;
263
+ return null;
264
+ }
265
+ function describeUnavailableFactoryState(projects) {
266
+ for (const project of projects) {
267
+ const unavailability = describeFactoryProjectUnavailability(project);
268
+ if (unavailability !== null) return `Factory state for ${project.projectId} is unavailable: ${unavailability}`;
269
+ }
270
+ return null;
271
+ }
272
+ function describeSpentToday(spentTodayUsd) {
273
+ if (spentTodayUsd === void 0) return "unknown";
274
+ return `$${spentTodayUsd.toFixed(2)}`;
275
+ }
276
+ function describeDailyBudget(dailyBudgetUsd) {
277
+ if (dailyBudgetUsd === null) return "unlimited";
278
+ if (dailyBudgetUsd === void 0) return "unknown";
279
+ return `$${dailyBudgetUsd.toFixed(2)}`;
280
+ }
281
+ function formatFactoryStatus(projects, buildDigest) {
282
+ const lines = [];
283
+ for (const project of projects) {
284
+ lines.push(`Project ${project.projectId}: ${project.projectName}`);
285
+ lines.push(`Project spend today: ${describeSpentToday(project.spentTodayUsd)} of ${describeDailyBudget(project.dailyBudgetUsd)} budget`);
286
+ const unavailability = describeFactoryProjectUnavailability(project);
287
+ if (unavailability !== null) lines.push(`Factory exception: ${unavailability}`);
288
+ const ticketsByIntentId = /* @__PURE__ */ new Map();
289
+ const partialIntentIds = new Set(project.partialIntentIds ?? []);
290
+ for (const order of project.orders) {
291
+ if (order.parent === null) continue;
292
+ const tickets = ticketsByIntentId.get(order.parent) ?? [];
293
+ tickets.push(order);
294
+ ticketsByIntentId.set(order.parent, tickets);
295
+ }
296
+ let intentCount = 0;
297
+ for (const intent of project.orders) {
298
+ if (intent.parent !== null || intent.state === "cancelled") continue;
299
+ intentCount += 1;
300
+ const tickets = ticketsByIntentId.get(intent.id) ?? [];
301
+ const digest = buildDigest({
302
+ ...project,
303
+ orders: [intent, ...tickets],
304
+ partialIntentIds: partialIntentIds.has(intent.id) ? [intent.id] : []
305
+ }, intent.id);
306
+ const outcome = intent.state === "completed" ? "completed" : digest.isPartial ? "partial" : "in progress";
307
+ lines.push(`Intent ${intent.id}: ${intent.objective}`, `Outcome: ${outcome}; merged: ${digest.merged.length}; parked: ${digest.parked.length}`);
308
+ for (const ticket of tickets) lines.push(` ${ticket.id} | state: ${ticket.parked ? "parked" : ticket.state} | blocks: ${ticket.blockCount ?? 0} | last reason: ${ticket.blockReason ?? "none"} | next action: ${factoryTicketNextAction(ticket, intent.id)}`);
309
+ lines.push("Confirmed flakes:");
310
+ for (const flake of digest.confirmedFlakes) lines.push(` ${flake}`);
311
+ if (digest.confirmedFlakes.length === 0) lines.push(" none");
312
+ }
313
+ if (intentCount === 0 && unavailability === null) lines.push("No intents.");
314
+ }
315
+ return lines.join("\n") || "No factory projects.";
316
+ }
226
317
  //#endregion
227
- export { decideSpawnAllowance as a, describePushLanding as c, isOrchestratorAgentVerb as d, parseAgentVerb as f, decideEditAllowance as i, describePushRouteRefusal as l, decideAgentRequest as n, decideTicketAction as o, decideAttentionAllowance as r, deriveChildSessionName as s, REFUSAL_REASON as t, isAgentApiVerb as u };
318
+ export { decideFactoryControlAllowance as a, deriveChildSessionName as c, describeUnavailableFactoryState as d, formatFactoryStatus as f, parseAgentVerb as h, decideEditAllowance as i, describePushLanding as l, isOrchestratorAgentVerb as m, decideAgentRequest as n, decideSpawnAllowance as o, isAgentApiVerb as p, decideAttentionAllowance as r, decideTicketAction as s, REFUSAL_REASON as t, describePushRouteRefusal as u };
@@ -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-KKgdSe-7.js";
2
+ import { a as classifyGrokHooksFile, o as renderGrokHooksFile, t as grok } from "./grok-CZ6kP_vD.js";
3
3
  import { p as writeTextAtomicSync } from "./json-file-BaxGcB2R.js";
4
4
  import fs from "node:fs";
5
5
  import path from "node:path";