harnery 0.9.0 → 0.10.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 (201) hide show
  1. package/README.md +1 -0
  2. package/dist/commander.d.ts.map +1 -1
  3. package/dist/commander.js +6 -0
  4. package/dist/commands/agents.d.ts +24 -0
  5. package/dist/commands/agents.d.ts.map +1 -1
  6. package/dist/commands/agents.js +244 -13
  7. package/dist/commands/backup.d.ts +5 -4
  8. package/dist/commands/backup.d.ts.map +1 -1
  9. package/dist/commands/backup.js +15 -14
  10. package/dist/commands/browse.d.ts.map +1 -1
  11. package/dist/commands/browse.js +27 -1
  12. package/dist/commands/claude-desktop.d.ts +19 -0
  13. package/dist/commands/claude-desktop.d.ts.map +1 -0
  14. package/dist/commands/claude-desktop.js +168 -0
  15. package/dist/commands/context.d.ts.map +1 -1
  16. package/dist/commands/context.js +149 -1
  17. package/dist/commands/doctor.d.ts.map +1 -1
  18. package/dist/commands/doctor.js +2 -3
  19. package/dist/commands/eml.d.ts +32 -0
  20. package/dist/commands/eml.d.ts.map +1 -1
  21. package/dist/commands/eml.js +16 -3
  22. package/dist/commands/harness.d.ts +11 -0
  23. package/dist/commands/harness.d.ts.map +1 -0
  24. package/dist/commands/harness.js +118 -0
  25. package/dist/commands/presence.d.ts +9 -4
  26. package/dist/commands/presence.d.ts.map +1 -1
  27. package/dist/commands/presence.js +88 -5
  28. package/dist/commands/relay.d.ts +9 -0
  29. package/dist/commands/relay.d.ts.map +1 -0
  30. package/dist/commands/relay.js +143 -0
  31. package/dist/commands/sync.d.ts.map +1 -1
  32. package/dist/commands/sync.js +5 -0
  33. package/dist/commands/workflow.d.ts.map +1 -1
  34. package/dist/commands/workflow.js +8 -15
  35. package/dist/core/agents/canonical-emit.d.ts +15 -0
  36. package/dist/core/agents/canonical-emit.d.ts.map +1 -1
  37. package/dist/core/agents/canonical-emit.js +41 -3
  38. package/dist/core/agents/cli.js +4 -2
  39. package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
  40. package/dist/core/agents/render/prompt-context.js +44 -3
  41. package/dist/core/agents/render/session-context.d.ts.map +1 -1
  42. package/dist/core/agents/render/session-context.js +26 -1
  43. package/dist/core/agents/rules/commit-conflict.d.ts.map +1 -1
  44. package/dist/core/agents/rules/commit-conflict.js +4 -37
  45. package/dist/core/agents/session-events.d.ts.map +1 -1
  46. package/dist/core/agents/session-events.js +16 -43
  47. package/dist/core/agents/state/heartbeat-projector.d.ts.map +1 -1
  48. package/dist/core/agents/state/heartbeat-projector.js +11 -2
  49. package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
  50. package/dist/core/agents/state/heartbeat-writer.js +3 -3
  51. package/dist/core/agents/state/names.d.ts +38 -3
  52. package/dist/core/agents/state/names.d.ts.map +1 -1
  53. package/dist/core/agents/state/names.js +46 -7
  54. package/dist/core/agents/state/pidmap.d.ts +5 -1
  55. package/dist/core/agents/state/pidmap.d.ts.map +1 -1
  56. package/dist/core/agents/state/pidmap.js +58 -2
  57. package/dist/core/agents/state/stale-sweep.d.ts +3 -2
  58. package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
  59. package/dist/core/agents/state/stale-sweep.js +6 -6
  60. package/dist/core/config.d.ts +68 -11
  61. package/dist/core/config.d.ts.map +1 -1
  62. package/dist/core/config.js +191 -25
  63. package/dist/core/context/index.d.ts +144 -0
  64. package/dist/core/context/index.d.ts.map +1 -0
  65. package/dist/core/context/index.js +380 -0
  66. package/dist/core/harnesses/bench.d.ts +29 -0
  67. package/dist/core/harnesses/bench.d.ts.map +1 -0
  68. package/dist/core/harnesses/bench.js +151 -0
  69. package/dist/core/harnesses/index.d.ts +9 -0
  70. package/dist/core/harnesses/index.d.ts.map +1 -0
  71. package/dist/core/harnesses/index.js +4 -0
  72. package/dist/core/harnesses/profiles.d.ts +62 -0
  73. package/dist/core/harnesses/profiles.d.ts.map +1 -0
  74. package/dist/core/harnesses/profiles.js +115 -0
  75. package/dist/core/harnesses/registry.d.ts +15 -0
  76. package/dist/core/harnesses/registry.d.ts.map +1 -0
  77. package/dist/core/harnesses/registry.js +113 -0
  78. package/dist/core/harnesses/types.d.ts +64 -0
  79. package/dist/core/harnesses/types.d.ts.map +1 -0
  80. package/dist/core/harnesses/types.js +20 -0
  81. package/dist/core/hooks/cli.js +280 -63
  82. package/dist/core/hooks/events/schema.d.ts +38 -1
  83. package/dist/core/hooks/events/schema.d.ts.map +1 -1
  84. package/dist/core/hooks/harness/events.d.ts.map +1 -1
  85. package/dist/core/hooks/harness/events.js +3 -0
  86. package/dist/core/hooks/harness/parse.d.ts +1 -1
  87. package/dist/core/hooks/harness/parse.d.ts.map +1 -1
  88. package/dist/core/hooks/harness/parse.js +4 -0
  89. package/dist/core/presence/blob.d.ts +40 -0
  90. package/dist/core/presence/blob.d.ts.map +1 -0
  91. package/dist/core/presence/blob.js +91 -0
  92. package/dist/core/presence/git.d.ts +68 -0
  93. package/dist/core/presence/git.d.ts.map +1 -0
  94. package/dist/core/presence/git.js +173 -0
  95. package/dist/core/presence/index.d.ts +74 -0
  96. package/dist/core/presence/index.d.ts.map +1 -0
  97. package/dist/core/presence/index.js +224 -0
  98. package/dist/core/presence/relay-client.d.ts +39 -0
  99. package/dist/core/presence/relay-client.d.ts.map +1 -0
  100. package/dist/core/presence/relay-client.js +295 -0
  101. package/dist/core/presence/relay-protocol.d.ts +94 -0
  102. package/dist/core/presence/relay-protocol.d.ts.map +1 -0
  103. package/dist/core/presence/relay-protocol.js +169 -0
  104. package/dist/core/workflow/billing.d.ts +1 -1
  105. package/dist/core/workflow/billing.d.ts.map +1 -1
  106. package/dist/core/workflow/billing.js +7 -1
  107. package/dist/core/workflow/engine.d.ts.map +1 -1
  108. package/dist/core/workflow/engine.js +11 -2
  109. package/dist/core/workflow/harnesses.d.ts +3 -3
  110. package/dist/core/workflow/harnesses.d.ts.map +1 -1
  111. package/dist/core/workflow/harnesses.js +8 -17
  112. package/dist/core/workflow/spawn-claude.d.ts +4 -1
  113. package/dist/core/workflow/spawn-claude.d.ts.map +1 -1
  114. package/dist/core/workflow/spawn-claude.js +39 -18
  115. package/dist/core/workflow/spawn-codex.d.ts +4 -1
  116. package/dist/core/workflow/spawn-codex.d.ts.map +1 -1
  117. package/dist/core/workflow/spawn-codex.js +44 -22
  118. package/dist/core/workflow/spawn-cursor.d.ts +4 -1
  119. package/dist/core/workflow/spawn-cursor.d.ts.map +1 -1
  120. package/dist/core/workflow/spawn-cursor.js +35 -16
  121. package/dist/core/workflow/types.d.ts +9 -2
  122. package/dist/core/workflow/types.d.ts.map +1 -1
  123. package/dist/lib/browser/client.d.ts +16 -0
  124. package/dist/lib/browser/client.d.ts.map +1 -1
  125. package/dist/lib/browser/client.js +22 -0
  126. package/dist/lib/browser/index.d.ts +1 -0
  127. package/dist/lib/browser/index.d.ts.map +1 -1
  128. package/dist/lib/browser/index.js +1 -0
  129. package/dist/lib/browser/launch-args.d.ts +21 -0
  130. package/dist/lib/browser/launch-args.d.ts.map +1 -0
  131. package/dist/lib/browser/launch-args.js +32 -0
  132. package/dist/lib/claude-desktop.d.ts +105 -0
  133. package/dist/lib/claude-desktop.d.ts.map +1 -0
  134. package/dist/lib/claude-desktop.js +217 -0
  135. package/dist/lib/docs-lint.d.ts.map +1 -1
  136. package/dist/lib/docs-lint.js +5 -2
  137. package/dist/lib/identities/assume.d.ts +51 -0
  138. package/dist/lib/identities/assume.d.ts.map +1 -0
  139. package/dist/lib/identities/assume.js +274 -0
  140. package/dist/lib/identities/index.d.ts +7 -7
  141. package/dist/lib/identities/index.d.ts.map +1 -1
  142. package/dist/lib/identities/index.js +24 -24
  143. package/dist/lib/instructions/templates.d.ts.map +1 -1
  144. package/dist/lib/instructions/templates.js +15 -2
  145. package/package.json +12 -1
  146. package/schemas/config.schema.json +88 -19
  147. package/src/commander.ts +6 -0
  148. package/src/commands/agents.ts +280 -14
  149. package/src/commands/backup.ts +17 -16
  150. package/src/commands/browse.ts +32 -0
  151. package/src/commands/claude-desktop.ts +215 -0
  152. package/src/commands/context.ts +174 -1
  153. package/src/commands/doctor.ts +2 -3
  154. package/src/commands/eml.ts +22 -4
  155. package/src/commands/harness.ts +147 -0
  156. package/src/commands/presence.ts +111 -5
  157. package/src/commands/relay.ts +160 -0
  158. package/src/commands/sync.ts +4 -0
  159. package/src/commands/workflow.ts +9 -18
  160. package/src/core/agents/canonical-emit.ts +41 -3
  161. package/src/core/agents/cli.ts +4 -2
  162. package/src/core/agents/render/prompt-context.ts +48 -3
  163. package/src/core/agents/render/session-context.ts +27 -1
  164. package/src/core/agents/rules/commit-conflict.ts +4 -33
  165. package/src/core/agents/session-events.ts +15 -39
  166. package/src/core/agents/state/heartbeat-projector.ts +10 -1
  167. package/src/core/agents/state/heartbeat-writer.ts +3 -2
  168. package/src/core/agents/state/names.ts +68 -9
  169. package/src/core/agents/state/pidmap.ts +59 -2
  170. package/src/core/agents/state/stale-sweep.ts +6 -11
  171. package/src/core/config.ts +248 -24
  172. package/src/core/context/index.ts +575 -0
  173. package/src/core/harnesses/bench.ts +214 -0
  174. package/src/core/harnesses/index.ts +31 -0
  175. package/src/core/harnesses/profiles.ts +141 -0
  176. package/src/core/harnesses/registry.ts +140 -0
  177. package/src/core/harnesses/types.ts +90 -0
  178. package/src/core/hooks/cli.ts +331 -62
  179. package/src/core/hooks/events/schema.ts +68 -0
  180. package/src/core/hooks/harness/events.ts +3 -0
  181. package/src/core/hooks/harness/parse.ts +7 -1
  182. package/src/core/presence/blob.ts +125 -0
  183. package/src/core/presence/git.ts +191 -0
  184. package/src/core/presence/index.ts +274 -0
  185. package/src/core/presence/relay-client.ts +322 -0
  186. package/src/core/presence/relay-protocol.ts +246 -0
  187. package/src/core/workflow/billing.ts +8 -2
  188. package/src/core/workflow/engine.ts +11 -2
  189. package/src/core/workflow/harnesses.ts +14 -19
  190. package/src/core/workflow/spawn-claude.ts +39 -20
  191. package/src/core/workflow/spawn-codex.ts +47 -28
  192. package/src/core/workflow/spawn-cursor.ts +37 -18
  193. package/src/core/workflow/types.ts +9 -2
  194. package/src/lib/browser/client.ts +37 -0
  195. package/src/lib/browser/index.ts +1 -0
  196. package/src/lib/browser/launch-args.ts +33 -0
  197. package/src/lib/claude-desktop.ts +293 -0
  198. package/src/lib/docs-lint.ts +5 -2
  199. package/src/lib/identities/assume.ts +363 -0
  200. package/src/lib/identities/index.ts +28 -24
  201. package/src/lib/instructions/templates.ts +16 -2
@@ -6,25 +6,16 @@
6
6
  * Install commands are the vendors' official one-liners; they drift rarely
7
7
  * but they do drift — keep this module the single place they live.
8
8
  */
9
- export const HARNESS_BINARIES = {
10
- "claude-code": "claude",
11
- codex: "codex",
12
- cursor: "cursor-agent",
13
- };
14
- export const HARNESS_INSTALL_HINTS = {
15
- "claude-code": "npm install -g @anthropic-ai/claude-code",
16
- codex: "npm install -g @openai/codex",
17
- cursor: "curl https://cursor.com/install -fsS | bash",
18
- };
9
+ import { BUILTIN_HARNESS_PROFILES } from "../harnesses/profiles.js";
10
+ export const HARNESS_BINARIES = Object.fromEntries(Object.values(BUILTIN_HARNESS_PROFILES).map((profile) => [profile.id, profile.binary]));
11
+ export const HARNESS_INSTALL_HINTS = Object.fromEntries(Object.values(BUILTIN_HARNESS_PROFILES).map((profile) => [profile.id, profile.installHint]));
19
12
  /** How to authenticate each CLI with a subscription login (the billing
20
13
  * default — see billing.ts). */
21
- export const HARNESS_LOGIN_HINTS = {
22
- "claude-code": "run `claude` and use /login",
23
- codex: "codex login",
24
- cursor: "cursor-agent login",
25
- };
14
+ export const HARNESS_LOGIN_HINTS = Object.fromEntries(Object.values(BUILTIN_HARNESS_PROFILES).map((profile) => [profile.id, profile.loginHint]));
26
15
  /** One-line "it's missing, here's the fix" string for spawn adapters. */
27
16
  export function notFoundError(harness) {
28
- return (`${HARNESS_BINARIES[harness]} CLI not found on PATH; ` +
29
- `install: ${HARNESS_INSTALL_HINTS[harness]} then authenticate: ${HARNESS_LOGIN_HINTS[harness]}`);
17
+ const binary = HARNESS_BINARIES[harness] ?? harness;
18
+ const install = HARNESS_INSTALL_HINTS[harness] ?? "install the harness CLI";
19
+ const login = HARNESS_LOGIN_HINTS[harness] ?? "authenticate the harness CLI";
20
+ return `${binary} CLI not found on PATH; ` + `install: ${install} then authenticate: ${login}`;
30
21
  }
@@ -17,6 +17,9 @@
17
17
  * gets HARNERY_WORKFLOW_CHILD=1 and the stop-hook rule exempts it
18
18
  * (stop-hook.ts), keeping heartbeats + events on.
19
19
  */
20
- import type { Spawner } from "./types.js";
20
+ import type { HarnessInvocation, HarnessRawResult } from "../harnesses/types.js";
21
+ import type { Spawner, SpawnRequest, SpawnResult } from "./types.js";
22
+ export declare function buildClaudeInvocation(req: SpawnRequest): HarnessInvocation;
23
+ export declare function normalizeClaudeResult(raw: HarnessRawResult): SpawnResult;
21
24
  export declare const claudeCodeSpawner: Spawner;
22
25
  //# sourceMappingURL=spawn-claude.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"spawn-claude.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/spawn-claude.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,KAAK,EAAE,OAAO,EAA6B,MAAM,YAAY,CAAC;AAYrE,eAAO,MAAM,iBAAiB,EAAE,OA+D/B,CAAC"}
1
+ {"version":3,"file":"spawn-claude.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/spawn-claude.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGjF,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAYrE,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,YAAY,GAAG,iBAAiB,CAc1E;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,gBAAgB,GAAG,WAAW,CAgDxE;AAED,eAAO,MAAM,iBAAiB,EAAE,OAc/B,CAAC"}
@@ -18,10 +18,11 @@
18
18
  * (stop-hook.ts), keeping heartbeats + events on.
19
19
  */
20
20
  import { exec } from "../../lib/exec.js";
21
+ import { validateHarnessEffort } from "../harnesses/profiles.js";
21
22
  import { buildChildEnv } from "./child-env.js";
22
23
  import { notFoundError } from "./harnesses.js";
23
- export const claudeCodeSpawner = async (req) => {
24
- const t0 = Date.now();
24
+ export function buildClaudeInvocation(req) {
25
+ validateHarnessEffort("claude-code", req.effort);
25
26
  const argv = [
26
27
  "claude",
27
28
  "-p",
@@ -33,33 +34,37 @@ export const claudeCodeSpawner = async (req) => {
33
34
  ];
34
35
  if (req.model)
35
36
  argv.push("--model", req.model);
36
- const r = await exec(argv, {
37
- cwd: req.cwd,
38
- env: buildChildEnv(req.runId, { subscriptionOnly: req.subscriptionOnly }),
39
- timeout: req.timeoutMs,
40
- });
41
- const durationMs = Date.now() - t0;
42
- if (r.exitCode === 127) {
43
- return { ok: false, text: "", durationMs, error: notFoundError("claude-code") };
37
+ if (req.effort)
38
+ argv.push("--effort", req.effort);
39
+ return { argv };
40
+ }
41
+ export function normalizeClaudeResult(raw) {
42
+ if (raw.exitCode === 127) {
43
+ return {
44
+ ok: false,
45
+ text: "",
46
+ durationMs: raw.durationMs,
47
+ error: notFoundError("claude-code"),
48
+ };
44
49
  }
45
- if (r.exitCode !== 0) {
50
+ if (raw.exitCode !== 0) {
46
51
  return {
47
52
  ok: false,
48
53
  text: "",
49
- durationMs,
50
- error: `claude exited ${r.exitCode}: ${(r.stderr || r.stdout).slice(0, 500)}`,
54
+ durationMs: raw.durationMs,
55
+ error: `claude exited ${raw.exitCode}: ${(raw.stderr || raw.stdout).slice(0, 500)}`,
51
56
  };
52
57
  }
53
58
  let envelope;
54
59
  try {
55
- envelope = JSON.parse(r.stdout);
60
+ envelope = JSON.parse(raw.stdout);
56
61
  }
57
62
  catch {
58
63
  return {
59
64
  ok: false,
60
65
  text: "",
61
- durationMs,
62
- error: `result envelope was not JSON: ${r.stdout.slice(0, 300)}`,
66
+ durationMs: raw.durationMs,
67
+ error: `result envelope was not JSON: ${raw.stdout.slice(0, 300)}`,
63
68
  };
64
69
  }
65
70
  if (envelope.is_error) {
@@ -68,7 +73,7 @@ export const claudeCodeSpawner = async (req) => {
68
73
  text: String(envelope.result ?? ""),
69
74
  sessionId: envelope.session_id,
70
75
  costUsd: envelope.total_cost_usd,
71
- durationMs,
76
+ durationMs: raw.durationMs,
72
77
  error: `harness error (${envelope.subtype ?? "unknown"}): ${(envelope.errors ?? []).join("; ") || "see envelope"}`,
73
78
  };
74
79
  }
@@ -77,6 +82,22 @@ export const claudeCodeSpawner = async (req) => {
77
82
  text: String(envelope.result ?? ""),
78
83
  sessionId: envelope.session_id,
79
84
  costUsd: envelope.total_cost_usd,
80
- durationMs,
85
+ durationMs: raw.durationMs,
81
86
  };
87
+ }
88
+ export const claudeCodeSpawner = async (req) => {
89
+ const t0 = Date.now();
90
+ let invocation;
91
+ try {
92
+ invocation = buildClaudeInvocation(req);
93
+ }
94
+ catch (error) {
95
+ return { ok: false, text: "", durationMs: 0, error: error.message };
96
+ }
97
+ const r = await exec(invocation.argv, {
98
+ cwd: req.cwd,
99
+ env: buildChildEnv(req.runId, { subscriptionOnly: req.subscriptionOnly }),
100
+ timeout: req.timeoutMs,
101
+ });
102
+ return normalizeClaudeResult({ ...r, durationMs: Date.now() - t0 });
82
103
  };
@@ -14,6 +14,9 @@
14
14
  * - No max-turns equivalent → `maxTurns` is accepted and ignored (documented
15
15
  * in the CLI docs page).
16
16
  */
17
- import type { Spawner } from "./types.js";
17
+ import type { HarnessInvocation, HarnessRawResult } from "../harnesses/types.js";
18
+ import type { Spawner, SpawnRequest, SpawnResult } from "./types.js";
19
+ export declare function buildCodexInvocation(req: SpawnRequest, resultFile?: string): HarnessInvocation;
20
+ export declare function normalizeCodexResult(raw: HarnessRawResult): SpawnResult;
18
21
  export declare const codexSpawner: Spawner;
19
22
  //# sourceMappingURL=spawn-codex.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"spawn-codex.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/spawn-codex.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AASH,OAAO,KAAK,EAAE,OAAO,EAA6B,MAAM,YAAY,CAAC;AAErE,eAAO,MAAM,YAAY,EAAE,OA+C1B,CAAC"}
1
+ {"version":3,"file":"spawn-codex.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/spawn-codex.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAQH,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGjF,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAErE,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,YAAY,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAgB9F;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,gBAAgB,GAAG,WAAW,CAiBvE;AAED,eAAO,MAAM,YAAY,EAAE,OA2B1B,CAAC"}
@@ -19,46 +19,68 @@ import { existsSync, readFileSync, rmSync } from "node:fs";
19
19
  import { tmpdir } from "node:os";
20
20
  import { join } from "node:path";
21
21
  import { exec } from "../../lib/exec.js";
22
+ import { validateHarnessEffort } from "../harnesses/profiles.js";
22
23
  import { buildChildEnv } from "./child-env.js";
23
24
  import { notFoundError } from "./harnesses.js";
24
- export const codexSpawner = async (req) => {
25
- const t0 = Date.now();
26
- const outFile = join(tmpdir(), `harnery-codex-${process.pid}-${randomBytes(4).toString("hex")}.txt`);
25
+ export function buildCodexInvocation(req, resultFile) {
26
+ validateHarnessEffort("codex", req.effort);
27
+ if (!resultFile)
28
+ throw new Error("codex adapter requires a final-message result file");
27
29
  const argv = [
28
30
  "codex",
29
31
  "exec",
30
32
  req.prompt,
31
33
  "--output-last-message",
32
- outFile,
34
+ resultFile,
33
35
  "--skip-git-repo-check",
34
36
  "--sandbox",
35
37
  "workspace-write",
36
38
  ];
37
39
  if (req.model)
38
40
  argv.push("--model", req.model);
41
+ if (req.effort)
42
+ argv.push("-c", `model_reasoning_effort=${JSON.stringify(req.effort)}`);
43
+ return { argv, resultFile };
44
+ }
45
+ export function normalizeCodexResult(raw) {
46
+ if (raw.exitCode === 127) {
47
+ return { ok: false, text: "", durationMs: raw.durationMs, error: notFoundError("codex") };
48
+ }
49
+ if (raw.exitCode !== 0) {
50
+ return {
51
+ ok: false,
52
+ text: "",
53
+ durationMs: raw.durationMs,
54
+ error: `codex exited ${raw.exitCode}: ${(raw.stderr || raw.stdout).slice(0, 500)}`,
55
+ };
56
+ }
57
+ return {
58
+ ok: true,
59
+ text: (raw.resultFileText ?? raw.stdout).trim(),
60
+ durationMs: raw.durationMs,
61
+ };
62
+ }
63
+ export const codexSpawner = async (req) => {
64
+ const t0 = Date.now();
65
+ const outFile = join(tmpdir(), `harnery-codex-${process.pid}-${randomBytes(4).toString("hex")}.txt`);
39
66
  try {
40
- const r = await exec(argv, {
67
+ let invocation;
68
+ try {
69
+ invocation = buildCodexInvocation(req, outFile);
70
+ }
71
+ catch (error) {
72
+ return { ok: false, text: "", durationMs: 0, error: error.message };
73
+ }
74
+ const r = await exec(invocation.argv, {
41
75
  cwd: req.cwd,
42
76
  env: buildChildEnv(req.runId, { subscriptionOnly: req.subscriptionOnly }),
43
77
  timeout: req.timeoutMs,
44
78
  });
45
- const durationMs = Date.now() - t0;
46
- if (r.exitCode === 127) {
47
- return { ok: false, text: "", durationMs, error: notFoundError("codex") };
48
- }
49
- if (r.exitCode !== 0) {
50
- return {
51
- ok: false,
52
- text: "",
53
- durationMs,
54
- error: `codex exited ${r.exitCode}: ${(r.stderr || r.stdout).slice(0, 500)}`,
55
- };
56
- }
57
- if (!existsSync(outFile)) {
58
- // Exit 0 but no last-message file: fall back to stdout (contract drift guard).
59
- return { ok: true, text: r.stdout, durationMs };
60
- }
61
- return { ok: true, text: readFileSync(outFile, "utf8").trim(), durationMs };
79
+ return normalizeCodexResult({
80
+ ...r,
81
+ durationMs: Date.now() - t0,
82
+ resultFileText: existsSync(outFile) ? readFileSync(outFile, "utf8") : undefined,
83
+ });
62
84
  }
63
85
  finally {
64
86
  rmSync(outFile, { force: true });
@@ -15,12 +15,15 @@
15
15
  * - No per-run cost surface → undefined. No max-turns equivalent → `maxTurns`
16
16
  * accepted and ignored (documented in the CLI docs page).
17
17
  */
18
- import type { Spawner } from "./types.js";
18
+ import type { HarnessInvocation, HarnessRawResult } from "../harnesses/types.js";
19
+ import type { Spawner, SpawnRequest, SpawnResult } from "./types.js";
19
20
  /** Exported for unit tests (no live binary to test against). */
20
21
  export declare function parseCursorOutput(stdout: string): {
21
22
  text: string;
22
23
  sessionId?: string;
23
24
  isError: boolean;
24
25
  };
26
+ export declare function buildCursorInvocation(req: SpawnRequest): HarnessInvocation;
27
+ export declare function normalizeCursorResult(raw: HarnessRawResult): SpawnResult;
25
28
  export declare const cursorSpawner: Spawner;
26
29
  //# sourceMappingURL=spawn-cursor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"spawn-cursor.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/spawn-cursor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,OAAO,KAAK,EAAE,OAAO,EAA6B,MAAM,YAAY,CAAC;AASrE,gEAAgE;AAChE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CAClB,CAWA;AAED,eAAO,MAAM,aAAa,EAAE,OAwC3B,CAAC"}
1
+ {"version":3,"file":"spawn-cursor.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/spawn-cursor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGjF,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AASrE,gEAAgE;AAChE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CAClB,CAWA;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,YAAY,GAAG,iBAAiB,CAS1E;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,gBAAgB,GAAG,WAAW,CA6BxE;AAED,eAAO,MAAM,aAAa,EAAE,OAe3B,CAAC"}
@@ -16,6 +16,7 @@
16
16
  * accepted and ignored (documented in the CLI docs page).
17
17
  */
18
18
  import { exec } from "../../lib/exec.js";
19
+ import { validateHarnessEffort } from "../harnesses/profiles.js";
19
20
  import { buildChildEnv } from "./child-env.js";
20
21
  import { notFoundError } from "./harnesses.js";
21
22
  /** Exported for unit tests (no live binary to test against). */
@@ -32,8 +33,8 @@ export function parseCursorOutput(stdout) {
32
33
  return { text: stdout, isError: false };
33
34
  }
34
35
  }
35
- export const cursorSpawner = async (req) => {
36
- const t0 = Date.now();
36
+ export function buildCursorInvocation(req) {
37
+ validateHarnessEffort("cursor", req.effort);
37
38
  // --trust: headless cursor-agent refuses untrusted workspaces (exit 1,
38
39
  // "Workspace Trust Required"). Workflow children run in the engine's cwd
39
40
  // deliberately and may edit files — the same posture as the codex adapter's
@@ -41,32 +42,50 @@ export const cursorSpawner = async (req) => {
41
42
  const argv = ["cursor-agent", "-p", req.prompt, "--output-format", "json", "--trust"];
42
43
  if (req.model)
43
44
  argv.push("--model", req.model);
44
- const r = await exec(argv, {
45
- cwd: req.cwd,
46
- env: buildChildEnv(req.runId, { subscriptionOnly: req.subscriptionOnly }),
47
- timeout: req.timeoutMs,
48
- });
49
- const durationMs = Date.now() - t0;
50
- if (r.exitCode === 127) {
51
- return { ok: false, text: "", durationMs, error: notFoundError("cursor") };
45
+ return { argv };
46
+ }
47
+ export function normalizeCursorResult(raw) {
48
+ if (raw.exitCode === 127) {
49
+ return { ok: false, text: "", durationMs: raw.durationMs, error: notFoundError("cursor") };
52
50
  }
53
- if (r.exitCode !== 0) {
51
+ if (raw.exitCode !== 0) {
54
52
  return {
55
53
  ok: false,
56
54
  text: "",
57
- durationMs,
58
- error: `cursor-agent exited ${r.exitCode}: ${(r.stderr || r.stdout).slice(0, 500)}`,
55
+ durationMs: raw.durationMs,
56
+ error: `cursor-agent exited ${raw.exitCode}: ${(raw.stderr || raw.stdout).slice(0, 500)}`,
59
57
  };
60
58
  }
61
- const parsed = parseCursorOutput(r.stdout);
59
+ const parsed = parseCursorOutput(raw.stdout);
62
60
  if (parsed.isError) {
63
61
  return {
64
62
  ok: false,
65
63
  text: parsed.text,
66
64
  sessionId: parsed.sessionId,
67
- durationMs,
65
+ durationMs: raw.durationMs,
68
66
  error: `cursor-agent reported is_error: ${parsed.text.slice(0, 300)}`,
69
67
  };
70
68
  }
71
- return { ok: true, text: parsed.text, sessionId: parsed.sessionId, durationMs };
69
+ return {
70
+ ok: true,
71
+ text: parsed.text,
72
+ sessionId: parsed.sessionId,
73
+ durationMs: raw.durationMs,
74
+ };
75
+ }
76
+ export const cursorSpawner = async (req) => {
77
+ const t0 = Date.now();
78
+ let invocation;
79
+ try {
80
+ invocation = buildCursorInvocation(req);
81
+ }
82
+ catch (error) {
83
+ return { ok: false, text: "", durationMs: 0, error: error.message };
84
+ }
85
+ const r = await exec(invocation.argv, {
86
+ cwd: req.cwd,
87
+ env: buildChildEnv(req.runId, { subscriptionOnly: req.subscriptionOnly }),
88
+ timeout: req.timeoutMs,
89
+ });
90
+ return normalizeCursorResult({ ...r, durationMs: Date.now() - t0 });
72
91
  };
@@ -25,6 +25,9 @@ export interface AgentOpts {
25
25
  schema?: StageSchema;
26
26
  /** Model slug passed through to the harness CLI (default: the CLI's default). */
27
27
  model?: string;
28
+ /** Reasoning effort mapped through the selected harness profile. Unsupported
29
+ * values fail before the vendor process starts. */
30
+ effort?: string;
28
31
  /** Attempt ceiling for the schema-retry loop (default 2). */
29
32
  maxAttempts?: number;
30
33
  /** Subprocess timeout ms (default 300_000). */
@@ -39,7 +42,10 @@ export interface AgentOpts {
39
42
  * another. */
40
43
  harness?: HarnessName;
41
44
  }
42
- export type HarnessName = "claude-code" | "codex" | "cursor";
45
+ /** Open registry key. The built-in catalog currently contains Claude Code,
46
+ * Codex, and Cursor; consumers may register another adapter without widening
47
+ * a package-owned union first. */
48
+ export type HarnessName = string;
43
49
  /** What a spawn adapter returns for one subagent run. */
44
50
  export interface SpawnResult {
45
51
  ok: boolean;
@@ -55,6 +61,7 @@ export interface SpawnResult {
55
61
  export interface SpawnRequest {
56
62
  prompt: string;
57
63
  model?: string;
64
+ effort?: string;
58
65
  timeoutMs: number;
59
66
  maxTurns: number;
60
67
  cwd: string;
@@ -94,7 +101,7 @@ export interface EngineOpts {
94
101
  coordRoot: string;
95
102
  /** Spawner registry keyed by harness. A single-harness caller registers one
96
103
  * entry and names it in `defaultHarness`. */
97
- spawners: Partial<Record<HarnessName, Spawner>>;
104
+ spawners: Readonly<Record<HarnessName, Spawner | undefined>>;
98
105
  /** Harness used when an agent() call doesn't name one (default "claude-code"). */
99
106
  defaultHarness?: HarnessName;
100
107
  /** Resume: run id of a prior run whose journal supplies cached results.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/workflow/types.ts"],"names":[],"mappings":"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"}
@@ -47,6 +47,14 @@ export interface BrowserOptions {
47
47
  * via this callback (e.g., a Cloudflare-bypass header for specific zones).
48
48
  */
49
49
  extraHeaders?: (url: string) => Record<string, string>;
50
+ /**
51
+ * Extra Chromium command-line flags, passed through to Playwright's
52
+ * `launchPersistentContext` `args`. Used for environment-specific
53
+ * workarounds — most notably `--disable-gpu` for headed windows under
54
+ * WSLg (see `./launch-args.ts`). Empty/undefined means Playwright's
55
+ * defaults only.
56
+ */
57
+ launchArgs?: string[];
50
58
  }
51
59
  export interface NavigateResult {
52
60
  url: string;
@@ -71,6 +79,14 @@ export interface FailedRequest {
71
79
  method: string;
72
80
  failure: string;
73
81
  resourceType: string;
82
+ /** HTTP status for kind "http" entries; null for network-level failures. */
83
+ status: number | null;
84
+ /** "http" = request completed with a >=400 response; "network" = never completed (DNS, TLS, aborts, tunnel). */
85
+ kind: "http" | "network";
86
+ /** True when the entry is the main frame's document response — lets consumers
87
+ * distinguish an expected error-page status (a 404 route under test) from a
88
+ * broken subresource. */
89
+ document?: boolean;
74
90
  }
75
91
  export interface Diagnostics {
76
92
  consoleEvents: ConsoleEvent[];
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/lib/browser/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/lib/browser/client.ts"],"names":[],"mappings":"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"}
@@ -32,6 +32,9 @@ export class Browser {
32
32
  this.context = await chromium.launchPersistentContext(this.profileDir, {
33
33
  headless: !this.opts.headed,
34
34
  viewport: this.opts.viewport ?? { width: 1280, height: 800 },
35
+ ...(this.opts.launchArgs && this.opts.launchArgs.length > 0
36
+ ? { args: this.opts.launchArgs }
37
+ : {}),
35
38
  ...(this.opts.recordHarPath
36
39
  ? { recordHar: { path: this.opts.recordHarPath, mode: "full" } }
37
40
  : {}),
@@ -84,6 +87,25 @@ export class Browser {
84
87
  method: req.method(),
85
88
  failure: req.failure()?.errorText ?? "unknown",
86
89
  resourceType: req.resourceType(),
90
+ status: null,
91
+ kind: "network",
92
+ });
93
+ });
94
+ // HTTP-level failures: `requestfailed` only fires for requests that never
95
+ // complete (DNS, TLS, aborts), so a script/stylesheet answered with a
96
+ // 4xx/5xx would otherwise be invisible to failedRequests-based gates.
97
+ page.on("response", (res) => {
98
+ if (res.status() < 400)
99
+ return;
100
+ const req = res.request();
101
+ this.failedRequests.push({
102
+ url: res.url(),
103
+ method: req.method(),
104
+ failure: `HTTP ${res.status()}`,
105
+ resourceType: req.resourceType(),
106
+ status: res.status(),
107
+ kind: "http",
108
+ document: req.resourceType() === "document" && res.frame() === page.mainFrame(),
87
109
  });
88
110
  });
89
111
  }
@@ -1,5 +1,6 @@
1
1
  export { Browser, type BrowserOptions, type ConsoleEvent, type Diagnostics, type FailedRequest, type NavigateResult, type PageErrorEvent, } from "./client.js";
2
2
  export { captureDevOverlay, type DevOverlayError, type DevOverlayResult, } from "./dev-overlay.js";
3
+ export { isWSL, wslHeadedLaunchArgs } from "./launch-args.js";
3
4
  export type { OverflowElement, OverflowResult, WidthResult, } from "./layout.js";
4
5
  export type { RuntHit, RuntsResult, } from "./runts.js";
5
6
  export type { CheckVisibilityOptions, VisibilityResult, VisibilitySample, } from "./visibility.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/browser/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,cAAc,GACpB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,iBAAiB,EACjB,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,eAAe,EACf,cAAc,EACd,WAAW,GACZ,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,OAAO,EACP,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,sBAAsB,EACtB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/browser/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,cAAc,GACpB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,iBAAiB,EACjB,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC9D,YAAY,EACV,eAAe,EACf,cAAc,EACd,WAAW,GACZ,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,OAAO,EACP,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,sBAAsB,EACtB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,iBAAiB,CAAC"}
@@ -1,2 +1,3 @@
1
1
  export { Browser, } from "./client.js";
2
2
  export { captureDevOverlay, } from "./dev-overlay.js";
3
+ export { isWSL, wslHeadedLaunchArgs } from "./launch-args.js";
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Chromium launch-arg helpers for environment-specific workarounds.
3
+ *
4
+ * The one that matters today is WSLg: a headed Chromium window renders its
5
+ * page to a GPU-backed surface that WSLg composites over an RDP stream to the
6
+ * Windows host. On a range of Windows / GPU-driver / WSLg combinations that
7
+ * GPU-composited surface never presents, so the window shows in the taskbar
8
+ * but paints blank — even though the page itself runs fine (JS, navigation,
9
+ * and DOM all work). Forcing Chromium onto its software compositor with
10
+ * `--disable-gpu` restores on-screen paint. It only matters for headed mode
11
+ * (headless never composites to a display) and only under WSL.
12
+ */
13
+ /** True when running under WSL (WSL1 or WSL2). */
14
+ export declare function isWSL(): boolean;
15
+ /**
16
+ * Chromium launch flags to make a headed window paint under WSLg. Returns
17
+ * `["--disable-gpu"]` on WSL, `[]` elsewhere. Callers apply these only for
18
+ * headed launches. See the module doc for the failure mode.
19
+ */
20
+ export declare function wslHeadedLaunchArgs(): string[];
21
+ //# sourceMappingURL=launch-args.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launch-args.d.ts","sourceRoot":"","sources":["../../../src/lib/browser/launch-args.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AAEH,kDAAkD;AAClD,wBAAgB,KAAK,IAAI,OAAO,CAO/B;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CAE9C"}
@@ -0,0 +1,32 @@
1
+ import { readFileSync } from "node:fs";
2
+ /**
3
+ * Chromium launch-arg helpers for environment-specific workarounds.
4
+ *
5
+ * The one that matters today is WSLg: a headed Chromium window renders its
6
+ * page to a GPU-backed surface that WSLg composites over an RDP stream to the
7
+ * Windows host. On a range of Windows / GPU-driver / WSLg combinations that
8
+ * GPU-composited surface never presents, so the window shows in the taskbar
9
+ * but paints blank — even though the page itself runs fine (JS, navigation,
10
+ * and DOM all work). Forcing Chromium onto its software compositor with
11
+ * `--disable-gpu` restores on-screen paint. It only matters for headed mode
12
+ * (headless never composites to a display) and only under WSL.
13
+ */
14
+ /** True when running under WSL (WSL1 or WSL2). */
15
+ export function isWSL() {
16
+ if (process.env.WSL_DISTRO_NAME || process.env.WSL_INTEROP)
17
+ return true;
18
+ try {
19
+ return /microsoft|wsl/i.test(readFileSync("/proc/version", "utf8"));
20
+ }
21
+ catch {
22
+ return false;
23
+ }
24
+ }
25
+ /**
26
+ * Chromium launch flags to make a headed window paint under WSLg. Returns
27
+ * `["--disable-gpu"]` on WSL, `[]` elsewhere. Callers apply these only for
28
+ * headed launches. See the module doc for the failure mode.
29
+ */
30
+ export function wslHeadedLaunchArgs() {
31
+ return isWSL() ? ["--disable-gpu"] : [];
32
+ }