harnery 0.31.6 → 0.32.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 (218) hide show
  1. package/dist/commander.d.ts.map +1 -1
  2. package/dist/commander.js +2 -0
  3. package/dist/commands/agents.d.ts +0 -9
  4. package/dist/commands/agents.d.ts.map +1 -1
  5. package/dist/commands/agents.js +70 -95
  6. package/dist/commands/browse-session.d.ts +21 -0
  7. package/dist/commands/browse-session.d.ts.map +1 -0
  8. package/dist/commands/browse-session.js +157 -0
  9. package/dist/commands/browse.d.ts.map +1 -1
  10. package/dist/commands/browse.js +205 -37
  11. package/dist/commands/checkpoint.js +1 -1
  12. package/dist/commands/deinit.d.ts.map +1 -1
  13. package/dist/commands/deinit.js +4 -0
  14. package/dist/commands/docs.d.ts.map +1 -1
  15. package/dist/commands/docs.js +40 -0
  16. package/dist/commands/doctor.d.ts.map +1 -1
  17. package/dist/commands/doctor.js +100 -17
  18. package/dist/commands/init.d.ts +1 -2
  19. package/dist/commands/init.d.ts.map +1 -1
  20. package/dist/commands/init.js +16 -5
  21. package/dist/commands/tunnel.d.ts.map +1 -1
  22. package/dist/commands/tunnel.js +2 -3
  23. package/dist/core/agents/canonical-emit.d.ts +1 -2
  24. package/dist/core/agents/canonical-emit.d.ts.map +1 -1
  25. package/dist/core/agents/canonical-emit.js +1 -2
  26. package/dist/core/agents/cli.js +123 -88
  27. package/dist/core/agents/coord-client.d.ts +7 -3
  28. package/dist/core/agents/coord-client.d.ts.map +1 -1
  29. package/dist/core/agents/coord-client.js +5 -4
  30. package/dist/core/agents/finalization.d.ts +68 -0
  31. package/dist/core/agents/finalization.d.ts.map +1 -0
  32. package/dist/core/agents/finalization.js +443 -0
  33. package/dist/core/agents/git-hook.d.ts +51 -0
  34. package/dist/core/agents/git-hook.d.ts.map +1 -0
  35. package/dist/core/agents/git-hook.js +118 -0
  36. package/dist/core/agents/render/prompt-context.d.ts +6 -5
  37. package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
  38. package/dist/core/agents/render/prompt-context.js +26 -13
  39. package/dist/core/agents/render/session-context.d.ts.map +1 -1
  40. package/dist/core/agents/render/session-context.js +15 -2
  41. package/dist/core/agents/rules/claim-conflict.js +3 -3
  42. package/dist/core/agents/rules/commit-conflict.d.ts +15 -6
  43. package/dist/core/agents/rules/commit-conflict.d.ts.map +1 -1
  44. package/dist/core/agents/rules/commit-conflict.js +21 -5
  45. package/dist/core/agents/rules/stop-hook.d.ts +3 -0
  46. package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
  47. package/dist/core/agents/rules/stop-hook.js +59 -23
  48. package/dist/core/agents/session-events.d.ts +8 -16
  49. package/dist/core/agents/session-events.d.ts.map +1 -1
  50. package/dist/core/agents/session-events.js +12 -26
  51. package/dist/core/agents/state/heartbeat-projector.d.ts +3 -0
  52. package/dist/core/agents/state/heartbeat-projector.d.ts.map +1 -1
  53. package/dist/core/agents/state/heartbeat-projector.js +44 -1
  54. package/dist/core/agents/state/heartbeat-writer.d.ts +32 -5
  55. package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
  56. package/dist/core/agents/state/heartbeat-writer.js +54 -17
  57. package/dist/core/agents/state/names.d.ts +22 -1
  58. package/dist/core/agents/state/names.d.ts.map +1 -1
  59. package/dist/core/agents/state/names.js +40 -2
  60. package/dist/core/config.d.ts +30 -2
  61. package/dist/core/config.d.ts.map +1 -1
  62. package/dist/core/config.js +74 -11
  63. package/dist/core/governor/planning.d.ts.map +1 -1
  64. package/dist/core/governor/planning.js +12 -13
  65. package/dist/core/hooks/adapter/detect.d.ts +2 -4
  66. package/dist/core/hooks/adapter/detect.d.ts.map +1 -1
  67. package/dist/core/hooks/adapter/detect.js +4 -14
  68. package/dist/core/hooks/adapter/output.d.ts +1 -1
  69. package/dist/core/hooks/adapter/output.d.ts.map +1 -1
  70. package/dist/core/hooks/adapter/output.js +5 -4
  71. package/dist/core/hooks/adapter/wiring.d.ts +23 -0
  72. package/dist/core/hooks/adapter/wiring.d.ts.map +1 -1
  73. package/dist/core/hooks/adapter/wiring.js +32 -0
  74. package/dist/core/hooks/cli.d.ts +1 -2
  75. package/dist/core/hooks/cli.d.ts.map +1 -1
  76. package/dist/core/hooks/cli.js +169 -27
  77. package/dist/core/hooks/codex-wsl-bridge.d.ts +46 -0
  78. package/dist/core/hooks/codex-wsl-bridge.d.ts.map +1 -0
  79. package/dist/core/hooks/codex-wsl-bridge.js +137 -0
  80. package/dist/core/hooks/effects/index.d.ts +1 -1
  81. package/dist/core/hooks/effects/index.js +3 -3
  82. package/dist/core/hooks/events/schema.d.ts +27 -0
  83. package/dist/core/hooks/events/schema.d.ts.map +1 -1
  84. package/dist/core/hooks/resolve/owner.d.ts +7 -1
  85. package/dist/core/hooks/resolve/owner.d.ts.map +1 -1
  86. package/dist/core/hooks/resolve/owner.js +15 -0
  87. package/dist/core/hooks/resolve/transcript.d.ts +44 -0
  88. package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
  89. package/dist/core/hooks/resolve/transcript.js +176 -1
  90. package/dist/core/hooks/session-name-presence.d.ts +30 -0
  91. package/dist/core/hooks/session-name-presence.d.ts.map +1 -0
  92. package/dist/core/hooks/session-name-presence.js +43 -0
  93. package/dist/core/hooks/unsafe-cross-shell.d.ts +13 -0
  94. package/dist/core/hooks/unsafe-cross-shell.d.ts.map +1 -0
  95. package/dist/core/hooks/unsafe-cross-shell.js +151 -0
  96. package/dist/core/work/state.d.ts +4 -5
  97. package/dist/core/work/state.d.ts.map +1 -1
  98. package/dist/core/work/state.js +5 -8
  99. package/dist/core/workflow/index.d.ts +1 -1
  100. package/dist/core/workflow/index.d.ts.map +1 -1
  101. package/dist/core/workflow/proof.d.ts +2 -2
  102. package/dist/core/workflow/proof.d.ts.map +1 -1
  103. package/dist/core/workflow/proof.js +2 -2
  104. package/dist/core/workflow/run-state.d.ts +2 -2
  105. package/dist/core/workflow/run-state.d.ts.map +1 -1
  106. package/dist/core/workflow/run-state.js +2 -2
  107. package/dist/core/workflow/types.d.ts +3 -3
  108. package/dist/core/workflow/types.d.ts.map +1 -1
  109. package/dist/core/workflow/workspaces/execution.d.ts +2 -2
  110. package/dist/core/workflow/workspaces/execution.d.ts.map +1 -1
  111. package/dist/core/workflow/workspaces/execution.js +5 -0
  112. package/dist/core/workflow/workspaces/index.d.ts +1 -1
  113. package/dist/core/workflow/workspaces/index.d.ts.map +1 -1
  114. package/dist/core/workflow/workspaces/local-git.d.ts.map +1 -1
  115. package/dist/core/workflow/workspaces/local-git.js +1 -2
  116. package/dist/core/workflow/workspaces/paths.d.ts +2 -2
  117. package/dist/core/workflow/workspaces/types.d.ts +0 -6
  118. package/dist/core/workflow/workspaces/types.d.ts.map +1 -1
  119. package/dist/core/workflow/workspaces/validate.d.ts +0 -2
  120. package/dist/core/workflow/workspaces/validate.d.ts.map +1 -1
  121. package/dist/core/workflow/workspaces/validate.js +0 -2
  122. package/dist/lib/browser/client.d.ts +118 -1
  123. package/dist/lib/browser/client.d.ts.map +1 -1
  124. package/dist/lib/browser/client.js +435 -6
  125. package/dist/lib/browser/geometry.d.ts.map +1 -1
  126. package/dist/lib/browser/geometry.js +180 -37
  127. package/dist/lib/browser/index.d.ts +5 -1
  128. package/dist/lib/browser/index.d.ts.map +1 -1
  129. package/dist/lib/browser/index.js +5 -1
  130. package/dist/lib/browser/netscape-cookies.d.ts +6 -0
  131. package/dist/lib/browser/netscape-cookies.d.ts.map +1 -0
  132. package/dist/lib/browser/netscape-cookies.js +31 -0
  133. package/dist/lib/browser/proxy.d.ts +24 -0
  134. package/dist/lib/browser/proxy.d.ts.map +1 -0
  135. package/dist/lib/browser/proxy.js +84 -0
  136. package/dist/lib/browser/runts.d.ts +6 -0
  137. package/dist/lib/browser/runts.d.ts.map +1 -1
  138. package/dist/lib/browser/runts.js +21 -4
  139. package/dist/lib/browser/session-control.d.ts +112 -0
  140. package/dist/lib/browser/session-control.d.ts.map +1 -0
  141. package/dist/lib/browser/session-control.js +670 -0
  142. package/dist/lib/docs-links.d.ts +108 -0
  143. package/dist/lib/docs-links.d.ts.map +1 -0
  144. package/dist/lib/docs-links.js +555 -0
  145. package/dist/lib/exec.d.ts +1 -1
  146. package/dist/lib/exec.js +1 -1
  147. package/dist/lib/identities/assume.d.ts +4 -2
  148. package/dist/lib/identities/assume.d.ts.map +1 -1
  149. package/dist/lib/identities/assume.js +15 -2
  150. package/dist/lib/instructions/git-hooks.d.ts +75 -0
  151. package/dist/lib/instructions/git-hooks.d.ts.map +1 -0
  152. package/dist/lib/instructions/git-hooks.js +238 -0
  153. package/dist/lib/instructions/splice.d.ts +10 -4
  154. package/dist/lib/instructions/splice.d.ts.map +1 -1
  155. package/dist/lib/instructions/splice.js +19 -11
  156. package/package.json +1 -1
  157. package/schemas/config.schema.json +32 -0
  158. package/src/commander.ts +2 -0
  159. package/src/commands/agents.ts +96 -115
  160. package/src/commands/browse-session.ts +245 -0
  161. package/src/commands/browse.ts +287 -44
  162. package/src/commands/checkpoint.ts +1 -1
  163. package/src/commands/deinit.ts +7 -1
  164. package/src/commands/docs.ts +56 -0
  165. package/src/commands/doctor.ts +100 -18
  166. package/src/commands/init.ts +17 -9
  167. package/src/commands/tunnel.ts +2 -5
  168. package/src/core/agents/canonical-emit.ts +1 -2
  169. package/src/core/agents/cli.ts +137 -88
  170. package/src/core/agents/coord-client.ts +10 -5
  171. package/src/core/agents/finalization.ts +595 -0
  172. package/src/core/agents/git-hook.ts +126 -0
  173. package/src/core/agents/render/prompt-context.ts +28 -13
  174. package/src/core/agents/render/session-context.ts +15 -2
  175. package/src/core/agents/rules/claim-conflict.ts +3 -3
  176. package/src/core/agents/rules/commit-conflict.ts +35 -8
  177. package/src/core/agents/rules/stop-hook.ts +71 -23
  178. package/src/core/agents/session-events.ts +14 -41
  179. package/src/core/agents/state/heartbeat-projector.ts +45 -1
  180. package/src/core/agents/state/heartbeat-writer.ts +78 -16
  181. package/src/core/agents/state/names.ts +54 -2
  182. package/src/core/config.ts +92 -12
  183. package/src/core/governor/planning.ts +17 -12
  184. package/src/core/hooks/adapter/detect.ts +4 -13
  185. package/src/core/hooks/adapter/output.ts +9 -4
  186. package/src/core/hooks/adapter/wiring.ts +43 -0
  187. package/src/core/hooks/cli.ts +201 -23
  188. package/src/core/hooks/codex-wsl-bridge.ts +188 -0
  189. package/src/core/hooks/effects/index.ts +5 -5
  190. package/src/core/hooks/events/schema.ts +27 -0
  191. package/src/core/hooks/resolve/owner.ts +22 -1
  192. package/src/core/hooks/resolve/transcript.ts +164 -1
  193. package/src/core/hooks/session-name-presence.ts +52 -0
  194. package/src/core/hooks/unsafe-cross-shell.ts +160 -0
  195. package/src/core/work/state.ts +8 -12
  196. package/src/core/workflow/engine.ts +2 -2
  197. package/src/core/workflow/index.ts +0 -1
  198. package/src/core/workflow/proof.ts +4 -4
  199. package/src/core/workflow/run-state.ts +5 -5
  200. package/src/core/workflow/types.ts +3 -3
  201. package/src/core/workflow/workspaces/execution.ts +11 -4
  202. package/src/core/workflow/workspaces/index.ts +0 -3
  203. package/src/core/workflow/workspaces/local-git.ts +1 -2
  204. package/src/core/workflow/workspaces/paths.ts +2 -2
  205. package/src/core/workflow/workspaces/types.ts +0 -9
  206. package/src/core/workflow/workspaces/validate.ts +1 -5
  207. package/src/lib/browser/client.ts +528 -6
  208. package/src/lib/browser/geometry.ts +197 -37
  209. package/src/lib/browser/index.ts +39 -0
  210. package/src/lib/browser/netscape-cookies.ts +39 -0
  211. package/src/lib/browser/proxy.ts +105 -0
  212. package/src/lib/browser/runts.ts +27 -3
  213. package/src/lib/browser/session-control.ts +892 -0
  214. package/src/lib/docs-links.ts +674 -0
  215. package/src/lib/exec.ts +1 -1
  216. package/src/lib/identities/assume.ts +22 -1
  217. package/src/lib/instructions/git-hooks.ts +259 -0
  218. package/src/lib/instructions/splice.ts +41 -11
@@ -1 +1 @@
1
- {"version":3,"file":"commander.d.ts","sourceRoot":"","sources":["../src/commander.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"commander.d.ts","sourceRoot":"","sources":["../src/commander.ts"],"names":[],"mappings":"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"}
package/dist/commander.js CHANGED
@@ -23,6 +23,7 @@ import { registerArtifactsCommand } from "./commands/artifacts.js";
23
23
  import { registerBackupCommand } from "./commands/backup.js";
24
24
  import { registerBrowseCommand } from "./commands/browse.js";
25
25
  import { registerBrowseAiCommand } from "./commands/browse-ai.js";
26
+ import { registerBrowseSessionCommand } from "./commands/browse-session.js";
26
27
  import { registerCallersCommand } from "./commands/callers.js";
27
28
  import { registerCheckpointCommand } from "./commands/checkpoint.js";
28
29
  import { registerClaudeDesktopCommand } from "./commands/claude-desktop.js";
@@ -117,6 +118,7 @@ export function createHarneryProgram(opts = {}) {
117
118
  registerFetchCommand(program, emit, opts.context);
118
119
  registerReadCommand(program, emit);
119
120
  registerBrowseCommand(program, emit, opts.context);
121
+ registerBrowseSessionCommand(program, emit);
120
122
  registerBrowseAiCommand(program, emit);
121
123
  registerCompletionCommand(program, emit, opts.context);
122
124
  registerCheckpointCommand(program, emit, opts.context);
@@ -31,13 +31,4 @@ export declare function coordHelperOpts(root: string): {
31
31
  };
32
32
  export declare function registerAgentsCommand(program: Command, emitParam: EmitContext, programContext?: HarneryProgramContext): void;
33
33
  export declare function registerCouncilCommands(parent: Command): void;
34
- /**
35
- * Build the copy-pasteable session name from the coord identity + the agent's
36
- * description parts. Pure (no coord-state reads) so it's unit-testable; collapses
37
- * internal whitespace and trims. Returns null when the description is empty.
38
- */
39
- export declare function buildSuggestedName(agentName: string, descriptionParts: string[]): {
40
- suggestedName: string;
41
- description: string;
42
- } | null;
43
34
  //# sourceMappingURL=agents.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/commands/agents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAeH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AA2E1E;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAA;CAAE,CAErF;AAsED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,WAAW,EACtB,cAAc,CAAC,EAAE,qBAAqB,GACrC,IAAI,CA+PN;AAyJD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAyO7D;AA2sBD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,gBAAgB,EAAE,MAAM,EAAE,GACzB;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAKvD"}
1
+ {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/commands/agents.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAeH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAkF1E;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAA;CAAE,CAErF;AAsED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,WAAW,EACtB,cAAc,CAAC,EAAE,qBAAqB,GACrC,IAAI,CAmQN;AAsKD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAyO7D"}
@@ -18,7 +18,9 @@ import { homedir, tmpdir } from "node:os";
18
18
  import { basename, join, resolve } from "node:path";
19
19
  import { coordBinPath } from "../core/agents/coord-bin.js";
20
20
  import { readStreamTailBounded } from "../core/agents/events/consume.js";
21
+ import { checkGitFinalization, formatGitFinalizationFailure, readSessionWriteClaims, } from "../core/agents/finalization.js";
21
22
  import { emitCanonical, monorepoRoot, normalizeAdapter, readHeartbeat, resolveOwner, resolveOwnerBySessionEnv, resolveOwnerWithSource, } from "../core/agents/index.js";
23
+ import { buildSuggestedName } from "../core/agents/state/heartbeat-writer.js";
22
24
  import { coordFreshnessSeconds, resolveBinName } from "../core/config.js";
23
25
  import { readRemoteMachines } from "../core/presence/index.js";
24
26
  import { registerContextCommand } from "./context.js";
@@ -126,6 +128,7 @@ export function registerAgentsCommand(program, emitParam, programContext) {
126
128
  .command("status")
127
129
  .description("End-of-turn status box (name + session age + files held + peer count)")
128
130
  .option("--json", "JSON output instead of the box")
131
+ .option("--end-turn", "Treat this as the turn's closing status: issue the box only when this session's held paths are committed and their repositories are pushed")
129
132
  .option("--session-id <id>", "Lookup heartbeat by session_id directly, bypassing the ppid walk. " +
130
133
  "Use this when calling from a hook (the hook's process tree may not lead back to Claude Code's session pid). " +
131
134
  "The Stop hook payload includes session_id; pass it through.")
@@ -203,7 +206,7 @@ export function registerAgentsCommand(program, emitParam, programContext) {
203
206
  .command("wait <name>")
204
207
  .description(`Block until a peer agent releases files (their \`files_touched\` becomes empty, OR they exit). Pair with \`${resolveBinName()} agents ping\` to coordinate hand-offs.`)
205
208
  .option("--file <path>", "Wait only for these specific paths (repeatable)", collectPath, [])
206
- .option("--timeout <dur>", "Give up after this duration; suffix s/m/h/d (e.g. 30s, 5m, 1h). Bare integer = minutes. Default 60m.", "60m")
209
+ .option("--timeout <dur>", "Give up after this duration; suffix s/m/h/d is required (e.g. 30s, 5m, 1h). Default 60m.", "60m")
207
210
  .option("--poll-secs <n>", "Poll interval in seconds (default 5)", "5")
208
211
  .option("--quiet", "Suppress progress lines")
209
212
  .option("--json", "JSON output (terminal status, only printed at exit)")
@@ -223,8 +226,8 @@ export function registerAgentsCommand(program, emitParam, programContext) {
223
226
  });
224
227
  cmd
225
228
  .command("health")
226
- .description("One-screen coord-layer health rollup: heal events, schema validity, " +
227
- "commit-guard activity, council activity, anomalies. Designed for " +
229
+ .description("One-screen coord-layer health rollup: heal events, council activity, " +
230
+ "zombie detection, and anomalies. Designed for " +
228
231
  "daily glance + dashboard ingestion. Reads .harnery/.")
229
232
  .option("--since <window>", "Window (Nh | Nd). Default: 24h.", "24h")
230
233
  .option("--json", "JSON envelope output")
@@ -236,7 +239,7 @@ export function registerAgentsCommand(program, emitParam, programContext) {
236
239
  .description("Adapter wiring probe: ppid chain, comm names, pid-map anchor, sample payload paths. " +
237
240
  "With --replay-samples, also replays every checked-in sample payload against the live " +
238
241
  "adapter in an isolated sandbox to catch adapter / payload-shape drift. " +
239
- "Complements heal-events (drift telemetry). Id: claude_code | cursor.")
242
+ "Complements heal-events (drift telemetry). Id: claude-code | cursor.")
240
243
  .option("--json", "JSON envelope output")
241
244
  .option("--replay-samples", "Replay docs/api/<adapter>-hooks/samples/*.json against the live adapter in an isolated sandbox. " +
242
245
  "Exits non-zero if any sample crashes the adapter.")
@@ -359,6 +362,9 @@ function registerIdentityCommands(parent) {
359
362
  "the event ledger, and the heartbeat.")
360
363
  .option("--json", "JSON envelope output")
361
364
  .option("--session-id <id>", "Bind the heartbeat with this session_id directly, bypassing the ppid walk.")
365
+ .option("--force-ancestor", "Allow assuming a persona this session's fork lineage descends from " +
366
+ "(default: refused, because a fork's inherited transcript asserting that " +
367
+ "name is not a role handoff).")
362
368
  .action((target, opts) => {
363
369
  runIdentityAssume(target, opts);
364
370
  });
@@ -385,7 +391,9 @@ function runIdentityAssume(target, opts) {
385
391
  process.exit(1);
386
392
  }
387
393
  try {
388
- const result = assumeIdentity(root, owner, target);
394
+ const result = assumeIdentity(root, owner, target, {
395
+ forceAncestor: opts.forceAncestor ?? false,
396
+ });
389
397
  emit.data({
390
398
  ...result,
391
399
  display_name: displayAgentName(result.name),
@@ -592,7 +600,7 @@ function runWhoami(opts) {
592
600
  task: hb.task ?? null,
593
601
  turn_summary: hb.turn_summary ?? null,
594
602
  turn_summary_updated_at: hb.turn_summary_updated_at ?? null,
595
- platform: hb.platform ?? "claude_code",
603
+ platform: hb.platform ?? "claude-code",
596
604
  };
597
605
  emit.data({ ...row, resolution_source: resolved.source, note: SUBAGENT_NOTE });
598
606
  if (process.stdout.isTTY && !opts.json) {
@@ -681,7 +689,7 @@ function runList(opts) {
681
689
  task: h.task ?? null,
682
690
  turn_summary: h.turn_summary ?? null,
683
691
  turn_summary_updated_at: h.turn_summary_updated_at ?? null,
684
- platform: h.platform ?? "claude_code",
692
+ platform: h.platform ?? "claude-code",
685
693
  });
686
694
  continue;
687
695
  }
@@ -706,7 +714,7 @@ function runList(opts) {
706
714
  task: h.task ?? null,
707
715
  turn_summary: h.turn_summary ?? null,
708
716
  turn_summary_updated_at: h.turn_summary_updated_at ?? null,
709
- platform: h.platform ?? "claude_code",
717
+ platform: h.platform ?? "claude-code",
710
718
  });
711
719
  }
712
720
  // Guard missing started_at: a heartbeat seeded from a stray event can lack it
@@ -732,7 +740,7 @@ function runList(opts) {
732
740
  task: a.task ?? null,
733
741
  turn_summary: a.turn_summary ?? null,
734
742
  turn_summary_updated_at: null,
735
- platform: a.platform ?? "claude_code",
743
+ platform: a.platform ?? "claude-code",
736
744
  machine: rm.machine,
737
745
  });
738
746
  }
@@ -1168,15 +1176,13 @@ function runSetTask(task, opts) {
1168
1176
  });
1169
1177
  process.exit(1);
1170
1178
  }
1171
- // Snapshot BEFORE the mutation: a heartbeat that has never carried a task
1172
- // has no `task_updated_at` stamp (setTask always stamps it, even on a clear),
1173
- // so its absence is the "focus never declared this session" signal — i.e. the
1174
- // first set-task of the session. That's the natural moment to also hand the
1175
- // operator a session name built from the same declaration (one source of
1176
- // truth: the focus you declare names the session). Distinct from task===""
1177
- // (a deliberate clear), which carries a stamp and does NOT re-trigger.
1179
+ // Snapshot BEFORE the mutation: the writer stamps `suggested_session_name`
1180
+ // on the session's first NON-EMPTY declaration (one source of truth: the
1181
+ // focus you declare names the session). A bare clear never consumes the
1182
+ // naming window, and subagent/workflow kinds are never named — see
1183
+ // heartbeat-writer.setTask. This call is the naming call exactly when the
1184
+ // stamp appears across the mutation.
1178
1185
  const priorHb = readHeartbeat(myOwner);
1179
- const firstOfSession = !priorHb?.task_updated_at;
1180
1186
  // Heartbeat mutation goes through agent-coord (atomic temp+rename).
1181
1187
  const helper = agentCoordOrExit(root);
1182
1188
  const result = spawnSync(helper, ["set-task", myOwner, task], {
@@ -1191,39 +1197,42 @@ function runSetTask(task, opts) {
1191
1197
  process.exit(1);
1192
1198
  }
1193
1199
  const hb = readHeartbeat(myOwner);
1200
+ // The naming call: the mutation just stamped `suggested_session_name` for
1201
+ // the first time. `first_of_session: true` means exactly "this call produced
1202
+ // the session name" — it is never true with a null name (an empty first
1203
+ // declaration or a `--session-id` relay both keep the window open instead).
1204
+ const suggestedName = !priorHb?.suggested_session_name && hb?.suggested_session_name
1205
+ ? hb.suggested_session_name
1206
+ : null;
1207
+ const firstOfSession = suggestedName !== null;
1194
1208
  emitCanonical({
1195
1209
  type: "state.task_set",
1196
1210
  owner: myOwner,
1197
1211
  session: hb?.session_id ?? myOwner,
1198
1212
  adapter: normalizeAdapter(hb?.platform),
1199
- data: { task, cleared: !task || task.length === 0 },
1213
+ data: {
1214
+ task,
1215
+ cleared: !task || task.length === 0,
1216
+ first_of_session: firstOfSession,
1217
+ suggested_session_name: suggestedName,
1218
+ },
1200
1219
  });
1201
- // On the first focus declaration of a session, surface a suggested session
1202
- // name for the operator to set as their adapter tab title. Read the result
1203
- // (`suggested_session_name`) and reproduce it in a fenced code block so the
1204
- // UI's Copy button hands over the exact string. null on every later call.
1205
- const built = firstOfSession && !opts?.sessionId ? buildSuggestedName(hb?.name ?? "unknown", [task]) : null;
1206
1220
  emit.data({
1207
1221
  instance_id: myOwner,
1208
1222
  name: hb?.name ?? null,
1209
1223
  task: hb?.task ?? null,
1210
1224
  cleared: !task || task.length === 0,
1211
1225
  first_of_session: firstOfSession,
1212
- suggested_session_name: built?.suggestedName ?? null,
1226
+ suggested_session_name: suggestedName,
1227
+ // Right-time instruction: the UserPromptSubmit nudge fires before the name
1228
+ // exists; this result is the moment the model holds the string.
1229
+ ...(suggestedName
1230
+ ? {
1231
+ note: "Reproduce suggested_session_name verbatim, by itself, in a fenced code block at the top of your reply — the operator copies it as the session/tab title.",
1232
+ }
1233
+ : {}),
1213
1234
  });
1214
1235
  }
1215
- /**
1216
- * Build the copy-pasteable session name from the coord identity + the agent's
1217
- * description parts. Pure (no coord-state reads) so it's unit-testable; collapses
1218
- * internal whitespace and trims. Returns null when the description is empty.
1219
- */
1220
- export function buildSuggestedName(agentName, descriptionParts) {
1221
- const description = descriptionParts.join(" ").replace(/\s+/g, " ").trim();
1222
- if (!description)
1223
- return null;
1224
- const name = agentName?.trim() || "unknown";
1225
- return { suggestedName: `Agent ${name} - ${description}`, description };
1226
- }
1227
1236
  function runSuggestName(descriptionParts, opts) {
1228
1237
  const root = monorepoRoot();
1229
1238
  if (!root) {
@@ -1308,20 +1317,21 @@ function runStatus(opts) {
1308
1317
  });
1309
1318
  process.exit(1);
1310
1319
  }
1311
- // Stamp .last_status_at = NOW. The verdict path reads state.status_checked
1312
- // canonical events (emitted below), but the legacy heartbeat field is still
1313
- // populated for back-compat with consumers reading v1 directly. The stamp
1314
- // goes through agent-coord (atomic write).
1315
- try {
1316
- const helper = agentCoordOrExit(root);
1317
- spawnSync(helper, ["stamp-status-call", myOwner], {
1318
- encoding: "utf8",
1319
- timeout: 2000,
1320
- ...coordHelperOpts(root),
1320
+ let finalization = null;
1321
+ if (opts.endTurn) {
1322
+ const history = readSessionWriteClaims(root, hb.instance_id, hb.session_id ?? myOwner);
1323
+ const touchedPaths = [...new Set([...(hb.files_touched ?? []), ...history.paths])];
1324
+ finalization = checkGitFinalization(root, touchedPaths, {
1325
+ claimHistoryComplete: history.complete,
1321
1326
  });
1322
- }
1323
- catch {
1324
- /* non-fatal */
1327
+ if (!finalization.ok) {
1328
+ emit.error({
1329
+ code: "git_not_finalized",
1330
+ message: formatGitFinalizationFailure(finalization, resolveBinName(root)),
1331
+ });
1332
+ process.exitCode = 1;
1333
+ return;
1334
+ }
1325
1335
  }
1326
1336
  emitCanonical({
1327
1337
  type: "state.status_checked",
@@ -1330,6 +1340,7 @@ function runStatus(opts) {
1330
1340
  adapter: normalizeAdapter(hb.platform),
1331
1341
  data: {
1332
1342
  format: opts.json ? "json" : "box",
1343
+ git_finalization_checked: opts.endTurn === true,
1333
1344
  agent_count: 0, // computed below, not yet available here; Phase 5 verdict reads owner-scope only
1334
1345
  included_self: true,
1335
1346
  },
@@ -1432,6 +1443,7 @@ function runStatus(opts) {
1432
1443
  context_window: ctxUsage?.window ?? null,
1433
1444
  timestamp_iso: new Date().toISOString(),
1434
1445
  timestamp_local: timeStr,
1446
+ ...(finalization ? { finalization } : {}),
1435
1447
  };
1436
1448
  if (opts.json) {
1437
1449
  emit.config({ format: "json" });
@@ -1794,16 +1806,15 @@ function readCanonicalEventsInWindow(root, cutoffMs) {
1794
1806
  }
1795
1807
  return out;
1796
1808
  }
1797
- /** adapter ("claude-code") → legacy platform label ("claude_code") so the
1798
- * existing formatPlatformLabel rendering keeps working unchanged. */
1809
+ /** Normalize adapter event data into the heartbeat platform value. */
1799
1810
  function adapterToPlatform(adapter) {
1800
1811
  if (adapter === "claude-code")
1801
- return "claude_code";
1812
+ return "claude-code";
1802
1813
  if (adapter === "cursor")
1803
1814
  return "cursor";
1804
1815
  if (adapter === "codex")
1805
1816
  return "codex";
1806
- return "claude_code";
1817
+ return "claude-code";
1807
1818
  }
1808
1819
  /** Project a canonical health.* event into the HealEvent shape the aggregators
1809
1820
  * already consume. Returns null for non-heal events. instance_id → display name
@@ -2292,18 +2303,7 @@ function runHealth(opts) {
2292
2303
  const councilsDir = resolve(root, ".harnery/councils");
2293
2304
  // Coordination telemetry reads from the canonical events.ndjson stream.
2294
2305
  // Heals come from health.*; council window-activity from council.*. The
2295
- // commit-guard + schema-invalid counters below have NO canonical equivalent
2296
- // yet. Their future home is the decision.* events (defined in schema.ts, not
2297
- // yet wired). Until then they report 0 (fields kept for output-shape
2298
- // compatibility).
2299
2306
  const heal = [];
2300
- const schemaInvalid = 0;
2301
- const schemaSamples = [];
2302
- const commitBlocked = 0;
2303
- const commitBypassed = 0;
2304
- const commitSuppressed = 0;
2305
- const editBlocked = 0;
2306
- const shellCandidates = 0;
2307
2307
  let councilAdvanced = 0;
2308
2308
  let councilClosed = 0;
2309
2309
  let councilArchived = 0;
@@ -2420,10 +2420,6 @@ function runHealth(opts) {
2420
2420
  }
2421
2421
  // Anomaly detection.
2422
2422
  const anomalies = [];
2423
- if (schemaInvalid > 0) {
2424
- const sampleList = schemaSamples.slice(0, 3).join(", ");
2425
- anomalies.push(`HEARTBEAT_SCHEMA_INVALID fired ${schemaInvalid}x; heartbeat shape failed validation${sampleList ? ` (samples: ${sampleList})` : ""}`);
2426
- }
2427
2423
  for (const { agent, count } of healTopAgents) {
2428
2424
  if (count >= 5) {
2429
2425
  anomalies.push(`${agent} self-healed ${count}x in ${opts.since}; possible idle-prune loop or PID instability`);
@@ -2477,14 +2473,6 @@ function runHealth(opts) {
2477
2473
  by_platform: healByPlatform,
2478
2474
  top_agents: healTopAgents,
2479
2475
  },
2480
- schema_invalid: { count: schemaInvalid, samples: schemaSamples },
2481
- commit_guards: {
2482
- blocked: commitBlocked,
2483
- bypassed: commitBypassed,
2484
- suppressed: commitSuppressed,
2485
- edit_blocked: editBlocked,
2486
- shell_candidates: shellCandidates,
2487
- },
2488
2476
  councils: {
2489
2477
  active: activeCouncils,
2490
2478
  archived_in_window: councilArchived,
@@ -2523,17 +2511,6 @@ function renderHealthBox(report) {
2523
2511
  }
2524
2512
  const topHealer = report.heal_events.top_agents[0];
2525
2513
  const topHealerStr = topHealer ? `${topHealer.agent} x${topHealer.count}` : "(none)";
2526
- const guardParts = [];
2527
- if (report.commit_guards.blocked > 0)
2528
- guardParts.push(`blocked ${report.commit_guards.blocked}`);
2529
- if (report.commit_guards.bypassed > 0)
2530
- guardParts.push(`bypassed ${report.commit_guards.bypassed}`);
2531
- if (report.commit_guards.suppressed > 0)
2532
- guardParts.push(`suppressed ${report.commit_guards.suppressed}`);
2533
- if (report.commit_guards.edit_blocked > 0)
2534
- guardParts.push(`edit-blocked ${report.commit_guards.edit_blocked}`);
2535
- if (report.commit_guards.shell_candidates > 0)
2536
- guardParts.push(`shell ${report.commit_guards.shell_candidates}`);
2537
2514
  const councilParts = [`${report.councils.active} active`];
2538
2515
  if (report.councils.advanced_in_window > 0)
2539
2516
  councilParts.push(`${report.councils.advanced_in_window} advanced`);
@@ -2566,8 +2543,6 @@ function renderHealthBox(report) {
2566
2543
  ? "0"
2567
2544
  : `${report.zombies.count} (${report.zombies.samples.join(", ")})`,
2568
2545
  ],
2569
- ["schema invalid", String(report.schema_invalid.count)],
2570
- ["commit guards", guardParts.length ? guardParts.join(", ") : "0"],
2571
2546
  ["councils", councilParts.join(", ")],
2572
2547
  ["anomalies", report.anomalies.length === 0 ? "(clean)" : `${report.anomalies.length} flagged`],
2573
2548
  ];
@@ -2585,10 +2560,10 @@ function runAdapterProbe(id, opts) {
2585
2560
  if (opts.json)
2586
2561
  emit.config({ format: "json" });
2587
2562
  const adapter = id.trim();
2588
- if (adapter !== "claude_code" && adapter !== "cursor") {
2563
+ if (adapter !== "claude-code" && adapter !== "cursor") {
2589
2564
  emit.error({
2590
2565
  code: "bad_adapter",
2591
- message: "adapter id must be claude_code or cursor",
2566
+ message: "adapter id must be claude-code or cursor",
2592
2567
  });
2593
2568
  process.exit(1);
2594
2569
  }
@@ -2784,7 +2759,7 @@ function replayAdapterSamples(adapter, root, relativeSampleDir, filter) {
2784
2759
  stopFailure: "stop-failure",
2785
2760
  StopFailure: "stop-failure",
2786
2761
  };
2787
- const adapterFlag = adapter === "claude_code" ? "claude-code" : adapter;
2762
+ const adapterFlag = adapter;
2788
2763
  const sandbox = mkdtempSync(join(tmpdir(), "harn-adapter-probe-"));
2789
2764
  const results = [];
2790
2765
  try {
@@ -2909,15 +2884,15 @@ function extractEventAndPayload(parsed, filename) {
2909
2884
  function collectPath(value, prev) {
2910
2885
  return [...prev, value];
2911
2886
  }
2912
- /** Parse "30", "30s", "5m", "1h", "2d" → ms. Bare integer defaults to minutes (back-compat). */
2887
+ /** Parse "30s", "5m", "1h", "2d" into milliseconds. */
2913
2888
  function parseDurationToMs(input) {
2914
- const match = input.trim().match(/^(\d+)([smhd]?)$/i);
2889
+ const match = input.trim().match(/^(\d+)([smhd])$/i);
2915
2890
  if (!match)
2916
2891
  return null;
2917
2892
  const n = Number.parseInt(match[1], 10);
2918
2893
  if (!Number.isFinite(n) || n <= 0)
2919
2894
  return null;
2920
- const unit = (match[2] || "m").toLowerCase();
2895
+ const unit = match[2].toLowerCase();
2921
2896
  const mult = { s: 1000, m: 60_000, h: 3_600_000, d: 86_400_000 };
2922
2897
  return n * mult[unit];
2923
2898
  }
@@ -0,0 +1,21 @@
1
+ import type { Readable } from "node:stream";
2
+ import type { Command } from "commander";
3
+ import type { EmitContext } from "../commander.js";
4
+ import type { BrowserSessionLocator } from "../lib/browser/client.js";
5
+ interface ControlFileOpts {
6
+ controlFile: string;
7
+ }
8
+ interface LocatorOpts extends ControlFileOpts {
9
+ selector?: string;
10
+ role?: string;
11
+ name?: string;
12
+ label?: string;
13
+ text?: string;
14
+ partial?: boolean;
15
+ }
16
+ export declare function registerBrowseSessionCommand(program: Command, emit: EmitContext): void;
17
+ export declare function parseLocatorOptions(opts: LocatorOpts, required: true): BrowserSessionLocator;
18
+ export declare function parseLocatorOptions(opts: LocatorOpts, required: false): BrowserSessionLocator | undefined;
19
+ export declare function readFillValue(input: Readable): Promise<string>;
20
+ export {};
21
+ //# sourceMappingURL=browse-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browse-session.d.ts","sourceRoot":"","sources":["../../src/commands/browse-session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAOtE,UAAU,eAAe;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,WAAY,SAAQ,eAAe;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI,CA4GtF;AAYD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,GAAG,qBAAqB,CAAC;AAC9F,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,WAAW,EACjB,QAAQ,EAAE,KAAK,GACd,qBAAqB,GAAG,SAAS,CAAC;AAoDrC,wBAAsB,aAAa,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAkBpE"}
@@ -0,0 +1,157 @@
1
+ import { BROWSER_SESSION_MAX_FILL_BYTES, BrowserSessionError, sendBrowserSessionRequest, } from "../lib/browser/session-control.js";
2
+ export function registerBrowseSessionCommand(program, emit) {
3
+ const session = program
4
+ .command("browse-session")
5
+ .description("Control an opted-in headed browse session through an owner-only descriptor");
6
+ session
7
+ .command("status")
8
+ .requiredOption("--control-file <path>", "Owner-only session descriptor")
9
+ .action((opts) => runAction(emit, opts.controlFile, "status", {}));
10
+ addLocatorOptions(session
11
+ .command("inspect")
12
+ .description("Inspect sanitized text, controls, focus, and active-tab state")
13
+ .requiredOption("--control-file <path>", "Owner-only session descriptor")).action((opts) => {
14
+ const locator = parseLocatorOptions(opts, false);
15
+ return runAction(emit, opts.controlFile, "inspect", locator ? { locator } : {});
16
+ });
17
+ session
18
+ .command("screenshot")
19
+ .requiredOption("--control-file <path>", "Owner-only session descriptor")
20
+ .requiredOption("--out <path>", "New PNG path in an existing directory")
21
+ .action((opts) => runAction(emit, opts.controlFile, "screenshot", { out: opts.out }));
22
+ session
23
+ .command("tabs")
24
+ .requiredOption("--control-file <path>", "Owner-only session descriptor")
25
+ .action((opts) => runAction(emit, opts.controlFile, "tabs", {}));
26
+ session
27
+ .command("select-tab")
28
+ .requiredOption("--control-file <path>", "Owner-only session descriptor")
29
+ .requiredOption("--index <n>", "Stable session-local tab index", parseIndex)
30
+ .action((opts) => runAction(emit, opts.controlFile, "select_tab", { index: opts.index }));
31
+ session
32
+ .command("open-tab <url>")
33
+ .requiredOption("--control-file <path>", "Owner-only session descriptor")
34
+ .action((url, opts) => runAction(emit, opts.controlFile, "open_tab", { url }));
35
+ session
36
+ .command("close-tab")
37
+ .requiredOption("--control-file <path>", "Owner-only session descriptor")
38
+ .requiredOption("--index <n>", "Stable session-local tab index", parseIndex)
39
+ .action((opts) => runAction(emit, opts.controlFile, "close_tab", { index: opts.index }));
40
+ session
41
+ .command("goto <url>")
42
+ .requiredOption("--control-file <path>", "Owner-only session descriptor")
43
+ .action((url, opts) => runAction(emit, opts.controlFile, "goto", { url }));
44
+ session
45
+ .command("reload")
46
+ .requiredOption("--control-file <path>", "Owner-only session descriptor")
47
+ .action((opts) => runAction(emit, opts.controlFile, "reload", {}));
48
+ addLocatorOptions(session
49
+ .command("click")
50
+ .requiredOption("--control-file <path>", "Owner-only session descriptor")).action((opts) => runAction(emit, opts.controlFile, "click", { locator: parseLocatorOptions(opts, true) }));
51
+ addLocatorOptions(session
52
+ .command("fill")
53
+ .description("Fill one strict locator with a value read once from standard input")
54
+ .requiredOption("--control-file <path>", "Owner-only session descriptor")).action(async (opts) => {
55
+ const value = await readFillValue(process.stdin);
56
+ return runAction(emit, opts.controlFile, "fill", {
57
+ locator: parseLocatorOptions(opts, true),
58
+ value,
59
+ });
60
+ });
61
+ session
62
+ .command("press <key>")
63
+ .requiredOption("--control-file <path>", "Owner-only session descriptor")
64
+ .action((key, opts) => runAction(emit, opts.controlFile, "press", { key }));
65
+ addLocatorOptions(session
66
+ .command("wait")
67
+ .requiredOption("--control-file <path>", "Owner-only session descriptor")).action((opts) => runAction(emit, opts.controlFile, "wait", { locator: parseLocatorOptions(opts, true) }));
68
+ session
69
+ .command("close")
70
+ .requiredOption("--control-file <path>", "Owner-only session descriptor")
71
+ .action((opts) => runAction(emit, opts.controlFile, "close", {}));
72
+ }
73
+ function addLocatorOptions(command) {
74
+ return command
75
+ .option("--selector <css>", "CSS locator")
76
+ .option("--role <role>", "Accessible role locator")
77
+ .option("--name <name>", "Accessible name used with --role")
78
+ .option("--label <text>", "Associated label locator")
79
+ .option("--text <text>", "Visible text locator")
80
+ .option("--partial", "Allow partial accessible-name, label, or text matching");
81
+ }
82
+ export function parseLocatorOptions(opts, required) {
83
+ const forms = [opts.selector, opts.role, opts.label, opts.text].filter((value) => value !== undefined);
84
+ if (forms.length === 0) {
85
+ if (!required) {
86
+ if (opts.name !== undefined || opts.partial) {
87
+ throw new BrowserSessionError("invalid_locator", "--name and --partial require a locator form.");
88
+ }
89
+ return undefined;
90
+ }
91
+ throw new BrowserSessionError("invalid_locator", "Choose exactly one locator: --selector, --role, --label, or --text.");
92
+ }
93
+ if (forms.length !== 1) {
94
+ throw new BrowserSessionError("invalid_locator", "Choose exactly one locator: --selector, --role, --label, or --text.");
95
+ }
96
+ if (opts.name !== undefined && opts.role === undefined) {
97
+ throw new BrowserSessionError("invalid_locator", "--name is valid only with --role.");
98
+ }
99
+ if (opts.selector !== undefined) {
100
+ if (opts.partial) {
101
+ throw new BrowserSessionError("invalid_locator", "--partial is not valid with --selector.");
102
+ }
103
+ return { kind: "selector", value: opts.selector, partial: false };
104
+ }
105
+ if (opts.role !== undefined) {
106
+ return {
107
+ kind: "role",
108
+ value: opts.role,
109
+ ...(opts.name === undefined ? {} : { name: opts.name }),
110
+ partial: Boolean(opts.partial),
111
+ };
112
+ }
113
+ if (opts.label !== undefined) {
114
+ return { kind: "label", value: opts.label, partial: Boolean(opts.partial) };
115
+ }
116
+ return { kind: "text", value: opts.text, partial: Boolean(opts.partial) };
117
+ }
118
+ export async function readFillValue(input) {
119
+ const chunks = [];
120
+ let size = 0;
121
+ for await (const chunk of input) {
122
+ const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk));
123
+ size += bytes.length;
124
+ if (size > BROWSER_SESSION_MAX_FILL_BYTES) {
125
+ throw new BrowserSessionError("fill_too_large", "Fill input exceeds the 64 KiB limit.");
126
+ }
127
+ chunks.push(bytes);
128
+ }
129
+ const value = Buffer.concat(chunks)
130
+ .toString("utf8")
131
+ .replace(/\r?\n$/, "");
132
+ if (value.length === 0) {
133
+ throw new BrowserSessionError("fill_empty", "Fill input from standard input was empty.");
134
+ }
135
+ return value;
136
+ }
137
+ async function runAction(emit, controlFile, action, args) {
138
+ try {
139
+ emit.data(await sendBrowserSessionRequest(controlFile, action, args));
140
+ }
141
+ catch (error) {
142
+ if (error instanceof BrowserSessionError) {
143
+ emit.error({ code: error.code, message: error.message });
144
+ emit.setExitCode(1);
145
+ return;
146
+ }
147
+ emit.error({ code: "browser_session_failed", message: "Browser session command failed." });
148
+ emit.setExitCode(1);
149
+ }
150
+ }
151
+ function parseIndex(value) {
152
+ const parsed = Number(value);
153
+ if (!Number.isSafeInteger(parsed) || parsed < 0) {
154
+ throw new BrowserSessionError("invalid_index", "Tab index must be a non-negative integer.");
155
+ }
156
+ return parsed;
157
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"browse.d.ts","sourceRoot":"","sources":["../../src/commands/browse.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAuL1E,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,WAAW,EACtB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,IAAI,CAoWN"}
1
+ {"version":3,"file":"browse.d.ts","sourceRoot":"","sources":["../../src/commands/browse.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAmM1E,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,WAAW,EACtB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,IAAI,CAkZN"}