@llblab/pi-actors 0.42.3 → 0.43.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (279) hide show
  1. package/AGENTS.md +127 -175
  2. package/BACKLOG.md +189 -1
  3. package/CHANGELOG.md +183 -292
  4. package/README.md +115 -276
  5. package/dist/fixtures/protocol/control-endpoint.json +6 -0
  6. package/dist/fixtures/protocol/control-record.json +9 -0
  7. package/dist/fixtures/protocol/recipe-summary.json +4 -12
  8. package/dist/fixtures/protocol/trace-event.json +9 -0
  9. package/dist/index.js +1 -1
  10. package/dist/lib/async-runs.d.ts +15 -38
  11. package/dist/lib/async-runs.js +173 -111
  12. package/dist/lib/automatic-review-runtime.d.ts +1 -1
  13. package/dist/lib/automatic-review-runtime.js +5 -5
  14. package/dist/lib/command-templates.d.ts +2 -0
  15. package/dist/lib/command-templates.js +38 -4
  16. package/dist/lib/control-projection.d.ts +20 -0
  17. package/dist/lib/control-projection.js +66 -0
  18. package/dist/lib/control.d.ts +15 -0
  19. package/dist/lib/control.js +97 -0
  20. package/dist/lib/draft-sleep.js +3 -3
  21. package/dist/lib/execution-sessions.d.ts +17 -0
  22. package/dist/lib/execution-sessions.js +85 -0
  23. package/dist/lib/file-state.d.ts +2 -0
  24. package/dist/lib/file-state.js +114 -46
  25. package/dist/lib/inspector-actions.d.ts +2 -2
  26. package/dist/lib/inspector-actions.js +2 -2
  27. package/dist/lib/inspector-command.js +3 -3
  28. package/dist/lib/inspector-overlay.d.ts +54 -70
  29. package/dist/lib/inspector-overlay.js +576 -910
  30. package/dist/lib/inspector.d.ts +3 -71
  31. package/dist/lib/inspector.js +19 -665
  32. package/dist/lib/limits.d.ts +7 -3
  33. package/dist/lib/limits.js +7 -3
  34. package/dist/lib/observability.d.ts +16 -16
  35. package/dist/lib/observability.js +43 -82
  36. package/dist/lib/prompts.d.ts +1 -1
  37. package/dist/lib/prompts.js +3 -3
  38. package/dist/lib/recipe-control.d.ts +7 -0
  39. package/dist/lib/recipe-control.js +43 -0
  40. package/dist/lib/recipes-discovery.js +2 -0
  41. package/dist/lib/recipes-references.d.ts +1 -14
  42. package/dist/lib/recipes-references.js +6 -21
  43. package/dist/lib/review-control.d.ts +1 -1
  44. package/dist/lib/review-control.js +4 -5
  45. package/dist/lib/review-projection.js +1 -5
  46. package/dist/lib/run-ui-runtime.js +2 -2
  47. package/dist/lib/runs-control-delivery.d.ts +28 -0
  48. package/dist/lib/runs-control-delivery.js +150 -0
  49. package/dist/lib/runs-controls.d.ts +37 -0
  50. package/dist/lib/runs-controls.js +146 -0
  51. package/dist/lib/runs-retention.d.ts +7 -0
  52. package/dist/lib/runs-retention.js +27 -3
  53. package/dist/lib/runs-start.js +4 -2
  54. package/dist/lib/runs-status.js +11 -6
  55. package/dist/lib/runs-trace.d.ts +24 -0
  56. package/dist/lib/runs-trace.js +102 -0
  57. package/dist/lib/runtime-identity.d.ts +7 -0
  58. package/dist/lib/runtime-identity.js +35 -0
  59. package/dist/lib/runtime-notifier.d.ts +1 -1
  60. package/dist/lib/runtime-notifier.js +1 -1
  61. package/dist/lib/runtime-triage.d.ts +29 -0
  62. package/dist/lib/runtime-triage.js +76 -0
  63. package/dist/lib/tool-review-scheduler.js +7 -7
  64. package/dist/lib/tools-inspect.d.ts +3 -3
  65. package/dist/lib/tools-inspect.js +241 -707
  66. package/dist/lib/tools-local.js +2 -10
  67. package/dist/lib/tools-message.d.ts +6 -7
  68. package/dist/lib/tools-message.js +95 -396
  69. package/dist/lib/tools-response.d.ts +1 -5
  70. package/dist/lib/tools-response.js +5 -48
  71. package/dist/lib/tools-spawn.js +16 -28
  72. package/dist/lib/tools.d.ts +1 -1
  73. package/dist/lib/tools.js +2 -3
  74. package/dist/lib/trace-projection.d.ts +22 -0
  75. package/dist/lib/trace-projection.js +185 -0
  76. package/dist/recipes/draft-review.json +0 -10
  77. package/dist/recipes/lens-swarm.json +0 -14
  78. package/dist/recipes/music-player.json +10 -19
  79. package/dist/recipes/pipeline-architect-coordinator.json +0 -11
  80. package/dist/recipes/pipeline-artifact-bundle.json +1 -22
  81. package/dist/recipes/pipeline-artifact-report.json +1 -18
  82. package/dist/recipes/pipeline-artifact-write.json +1 -18
  83. package/dist/recipes/pipeline-async-run-ops.json +0 -12
  84. package/dist/recipes/pipeline-checkpoint-continuation.json +0 -14
  85. package/dist/recipes/pipeline-development-tasking.json +0 -12
  86. package/dist/recipes/pipeline-docs-maintenance.json +0 -12
  87. package/dist/recipes/pipeline-media-library.json +0 -12
  88. package/dist/recipes/pipeline-quorum-review.json +0 -12
  89. package/dist/recipes/pipeline-release-readiness.json +0 -12
  90. package/dist/recipes/pipeline-release-summary.json +0 -12
  91. package/dist/recipes/pipeline-repo-health.json +0 -12
  92. package/dist/recipes/pipeline-research-synthesis.json +0 -11
  93. package/dist/recipes/pipeline-review-readiness.json +0 -12
  94. package/dist/recipes/resource-locker.json +27 -0
  95. package/dist/recipes/subagent-artifact.json +0 -9
  96. package/dist/recipes/subagent-checkpoint.json +0 -10
  97. package/dist/recipes/subagent-conflict-report.json +0 -11
  98. package/dist/recipes/subagent-contradiction-map.json +0 -11
  99. package/dist/recipes/subagent-critic.json +0 -11
  100. package/dist/recipes/subagent-evidence-map.json +0 -11
  101. package/dist/recipes/subagent-followup.json +0 -10
  102. package/dist/recipes/subagent-judge.json +0 -11
  103. package/dist/recipes/subagent-merge.json +0 -11
  104. package/dist/recipes/subagent-normalize.json +0 -11
  105. package/dist/recipes/subagent-plan.json +0 -11
  106. package/dist/recipes/subagent-preflight.json +0 -11
  107. package/dist/recipes/subagent-prompt.json +0 -10
  108. package/dist/recipes/subagent-quorum.json +0 -10
  109. package/dist/recipes/subagent-review-coordinator.json +0 -14
  110. package/dist/recipes/subagent-review.json +0 -11
  111. package/dist/recipes/subagent-task-card.json +0 -11
  112. package/dist/recipes/subagent-tools.json +0 -10
  113. package/dist/recipes/subagent-verify.json +0 -11
  114. package/dist/recipes/subagents-prompts.json +0 -10
  115. package/dist/recipes/tool-review.json +0 -10
  116. package/dist/scripts/async-runner.mjs +25 -25
  117. package/dist/scripts/conformance.mjs +4 -2
  118. package/dist/scripts/locker.mjs +196 -69
  119. package/dist/scripts/music-player.mjs +162 -159
  120. package/dist/scripts/recipe-utils.mjs +6 -96
  121. package/dist/scripts/release-gates.mjs +91 -0
  122. package/dist/scripts/validate-recipe.mjs +8 -57
  123. package/dist/skills/actors/SKILL.md +57 -265
  124. package/dist/skills/swarm/SKILL.md +10 -34
  125. package/docs/0.43-baseline.md +39 -0
  126. package/docs/README.md +4 -6
  127. package/docs/actor-inspector.md +26 -64
  128. package/docs/async-runs.md +81 -328
  129. package/docs/command-templates.md +8 -118
  130. package/docs/recipe-library.md +55 -182
  131. package/docs/releasing.md +28 -0
  132. package/docs/template-recipes.md +76 -289
  133. package/docs/tool-registry.md +41 -161
  134. package/fixtures/protocol/control-endpoint.json +6 -0
  135. package/fixtures/protocol/control-record.json +9 -0
  136. package/fixtures/protocol/recipe-summary.json +4 -12
  137. package/fixtures/protocol/trace-event.json +9 -0
  138. package/index.ts +1 -1
  139. package/lib/async-runs.ts +218 -204
  140. package/lib/automatic-review-runtime.ts +7 -7
  141. package/lib/command-templates.ts +44 -4
  142. package/lib/control-projection.ts +105 -0
  143. package/lib/control.ts +117 -0
  144. package/lib/draft-sleep.ts +3 -3
  145. package/lib/execution-sessions.ts +111 -0
  146. package/lib/file-state.ts +84 -64
  147. package/lib/inspector-actions.ts +2 -2
  148. package/lib/inspector-command.ts +3 -3
  149. package/lib/inspector-overlay.ts +617 -1126
  150. package/lib/inspector.ts +46 -979
  151. package/lib/limits.ts +7 -3
  152. package/lib/observability.ts +60 -101
  153. package/lib/prompts.ts +3 -3
  154. package/lib/recipe-control.ts +52 -0
  155. package/lib/recipes-discovery.ts +2 -0
  156. package/lib/recipes-references.ts +9 -45
  157. package/lib/review-control.ts +4 -5
  158. package/lib/review-projection.ts +1 -5
  159. package/lib/run-ui-runtime.ts +2 -2
  160. package/lib/runs-control-delivery.ts +209 -0
  161. package/lib/runs-controls.ts +213 -0
  162. package/lib/runs-retention.ts +38 -3
  163. package/lib/runs-start.ts +4 -2
  164. package/lib/runs-status.ts +11 -6
  165. package/lib/runs-trace.ts +136 -0
  166. package/lib/runtime-identity.ts +39 -0
  167. package/lib/runtime-notifier.ts +1 -1
  168. package/lib/runtime-triage.ts +120 -0
  169. package/lib/tool-review-scheduler.ts +7 -7
  170. package/lib/tools-inspect.ts +283 -900
  171. package/lib/tools-local.ts +2 -12
  172. package/lib/tools-message.ts +112 -520
  173. package/lib/tools-response.ts +5 -64
  174. package/lib/tools-spawn.ts +16 -32
  175. package/lib/tools.ts +5 -6
  176. package/lib/trace-projection.ts +244 -0
  177. package/package.json +2 -1
  178. package/recipes/draft-review.json +0 -10
  179. package/recipes/lens-swarm.json +0 -14
  180. package/recipes/music-player.json +10 -19
  181. package/recipes/pipeline-architect-coordinator.json +0 -11
  182. package/recipes/pipeline-artifact-bundle.json +1 -22
  183. package/recipes/pipeline-artifact-report.json +1 -18
  184. package/recipes/pipeline-artifact-write.json +1 -18
  185. package/recipes/pipeline-async-run-ops.json +0 -12
  186. package/recipes/pipeline-checkpoint-continuation.json +0 -14
  187. package/recipes/pipeline-development-tasking.json +0 -12
  188. package/recipes/pipeline-docs-maintenance.json +0 -12
  189. package/recipes/pipeline-media-library.json +0 -12
  190. package/recipes/pipeline-quorum-review.json +0 -12
  191. package/recipes/pipeline-release-readiness.json +0 -12
  192. package/recipes/pipeline-release-summary.json +0 -12
  193. package/recipes/pipeline-repo-health.json +0 -12
  194. package/recipes/pipeline-research-synthesis.json +0 -11
  195. package/recipes/pipeline-review-readiness.json +0 -12
  196. package/recipes/resource-locker.json +27 -0
  197. package/recipes/subagent-artifact.json +0 -9
  198. package/recipes/subagent-checkpoint.json +0 -10
  199. package/recipes/subagent-conflict-report.json +0 -11
  200. package/recipes/subagent-contradiction-map.json +0 -11
  201. package/recipes/subagent-critic.json +0 -11
  202. package/recipes/subagent-evidence-map.json +0 -11
  203. package/recipes/subagent-followup.json +0 -10
  204. package/recipes/subagent-judge.json +0 -11
  205. package/recipes/subagent-merge.json +0 -11
  206. package/recipes/subagent-normalize.json +0 -11
  207. package/recipes/subagent-plan.json +0 -11
  208. package/recipes/subagent-preflight.json +0 -11
  209. package/recipes/subagent-prompt.json +0 -10
  210. package/recipes/subagent-quorum.json +0 -10
  211. package/recipes/subagent-review-coordinator.json +0 -14
  212. package/recipes/subagent-review.json +0 -11
  213. package/recipes/subagent-task-card.json +0 -11
  214. package/recipes/subagent-tools.json +0 -10
  215. package/recipes/subagent-verify.json +0 -11
  216. package/recipes/subagents-prompts.json +0 -10
  217. package/recipes/tool-review.json +0 -10
  218. package/scripts/async-runner.mjs +25 -25
  219. package/scripts/conformance.mjs +4 -2
  220. package/scripts/locker.mjs +196 -69
  221. package/scripts/music-player.mjs +162 -159
  222. package/scripts/recipe-utils.mjs +6 -96
  223. package/scripts/release-gates.mjs +91 -0
  224. package/scripts/validate-recipe.mjs +8 -57
  225. package/skills/actors/SKILL.md +57 -265
  226. package/skills/swarm/SKILL.md +10 -34
  227. package/dist/fixtures/protocol/actor-message-branch.json +0 -13
  228. package/dist/fixtures/protocol/mailbox-contract.json +0 -15
  229. package/dist/fixtures/protocol/room-message.json +0 -11
  230. package/dist/fixtures/protocol/room-roster.json +0 -11
  231. package/dist/fixtures/protocol/run-inbox-message.json +0 -9
  232. package/dist/fixtures/protocol/run-outbox-event.json +0 -9
  233. package/dist/lib/mailbox-loop.d.ts +0 -41
  234. package/dist/lib/mailbox-loop.js +0 -60
  235. package/dist/lib/messages.d.ts +0 -25
  236. package/dist/lib/messages.js +0 -122
  237. package/dist/lib/rooms.d.ts +0 -104
  238. package/dist/lib/rooms.js +0 -647
  239. package/dist/lib/runs-mailbox.d.ts +0 -25
  240. package/dist/lib/runs-mailbox.js +0 -146
  241. package/dist/lib/runs-messages.d.ts +0 -15
  242. package/dist/lib/runs-messages.js +0 -179
  243. package/dist/lib/runs-outbox.d.ts +0 -41
  244. package/dist/lib/runs-outbox.js +0 -87
  245. package/dist/lib/tools-mailbox.d.ts +0 -8
  246. package/dist/lib/tools-mailbox.js +0 -48
  247. package/dist/recipes/actor-worker.json +0 -39
  248. package/dist/recipes/coordinator-locker.json +0 -45
  249. package/dist/recipes/locker.json +0 -45
  250. package/dist/recipes/pipeline-room-swarm.json +0 -50
  251. package/dist/recipes/subagent-message.json +0 -32
  252. package/dist/recipes/utility-actor-message.json +0 -23
  253. package/dist/scripts/actor-worker.mjs +0 -214
  254. package/dist/scripts/coordinator.mjs +0 -799
  255. package/docs/actor-messages.md +0 -225
  256. package/docs/actors-deep-reference.md +0 -66
  257. package/docs/component-recipes.md +0 -148
  258. package/docs/task-first-recipes.md +0 -263
  259. package/fixtures/protocol/actor-message-branch.json +0 -13
  260. package/fixtures/protocol/mailbox-contract.json +0 -15
  261. package/fixtures/protocol/room-message.json +0 -11
  262. package/fixtures/protocol/room-roster.json +0 -11
  263. package/fixtures/protocol/run-inbox-message.json +0 -9
  264. package/fixtures/protocol/run-outbox-event.json +0 -9
  265. package/lib/mailbox-loop.ts +0 -144
  266. package/lib/messages.ts +0 -151
  267. package/lib/rooms.ts +0 -939
  268. package/lib/runs-mailbox.ts +0 -208
  269. package/lib/runs-messages.ts +0 -252
  270. package/lib/runs-outbox.ts +0 -144
  271. package/lib/tools-mailbox.ts +0 -56
  272. package/recipes/actor-worker.json +0 -39
  273. package/recipes/coordinator-locker.json +0 -45
  274. package/recipes/locker.json +0 -45
  275. package/recipes/pipeline-room-swarm.json +0 -50
  276. package/recipes/subagent-message.json +0 -32
  277. package/recipes/utility-actor-message.json +0 -23
  278. package/scripts/actor-worker.mjs +0 -214
  279. package/scripts/coordinator.mjs +0 -799
@@ -1,50 +0,0 @@
1
- {
2
- "async": true,
3
- "args": [
4
- "mode:enum(consensus,pipeline,fanout,pool)",
5
- "mission:string",
6
- "model:string",
7
- "thinking:string",
8
- "roles:string",
9
- "roles_path:path",
10
- "rounds:int",
11
- "delay:int",
12
- "locker:bool",
13
- "locker_lease_ms:int",
14
- "subagent_ttl_ms:int",
15
- "artifact_path:path",
16
- "repo:path"
17
- ],
18
- "defaults": {
19
- "mode": "consensus",
20
- "thinking": "off",
21
- "roles": "",
22
- "roles_path": "",
23
- "rounds": "4",
24
- "delay": "10",
25
- "locker": "false",
26
- "locker_lease_ms": "600000",
27
- "subagent_ttl_ms": "0",
28
- "artifact_path": "{state_dir}/room-swarm-artifact.md",
29
- "repo": "~/.pi/agent/extensions/pi-actors"
30
- },
31
- "artifacts": {
32
- "artifact": "{artifact_path}",
33
- "locker_journal": "{state_dir}/locker/journal.jsonl",
34
- "locker_locks": "{state_dir}/locker/locks.json",
35
- "locker_queue": "{state_dir}/locker/queue.json"
36
- },
37
- "mailbox": {
38
- "accepts": [
39
- "control.kill"
40
- ],
41
- "emits": [
42
- "chat.message",
43
- "actor.join",
44
- "actor.leave",
45
- "run.done",
46
- "run.failed"
47
- ]
48
- },
49
- "template": "{repo}/scripts/coordinator.mjs --run-id={run_id} --mode={mode} --mission={mission} --model={model} --thinking={thinking} --roles={roles} --roles-path={roles_path} --rounds={rounds} --delay={delay} --locker={locker} --locker-lease-ms={locker_lease_ms} --subagent-ttl-ms={subagent_ttl_ms} --artifact-path={artifact_path}"
50
- }
@@ -1,32 +0,0 @@
1
- {
2
- "async": true,
3
- "args": [
4
- "type:string",
5
- "payload:string",
6
- "to:string",
7
- "from:string",
8
- "message_policy:string",
9
- "output_format:string",
10
- "model:string",
11
- "thinking:string",
12
- "tools:string"
13
- ],
14
- "defaults": {
15
- "type": "component.update",
16
- "to": "coordinator",
17
- "from": "run:{run_id}",
18
- "message_policy": "Emit an actor-message envelope-shaped JSON object for the coordinator; do not call transport tools directly.",
19
- "output_format": "JSON object with to, from, type, summary, body, metadata, confidence, and next_action.",
20
- "thinking": "off",
21
- "tools": ""
22
- },
23
- "mailbox": {
24
- "accepts": [
25
- "control.kill"
26
- ],
27
- "emits": [
28
- "component.*"
29
- ]
30
- },
31
- "template": "pi -p --model {model} --thinking {thinking} {tools?--tools:--no-tools} {tools} Create an actor-message envelope-shaped record. To: {to}. From: {from}. Type: {type}. Message policy: {message_policy}. Payload/body: {payload}. Output format: {output_format}"
32
- }
@@ -1,23 +0,0 @@
1
- {
2
- "async": false,
3
- "args": [
4
- "type:string",
5
- "to:string",
6
- "from:string",
7
- "summary:string",
8
- "metadata:string",
9
- "correlation_id:string",
10
- "reply_to:string",
11
- "repo:path"
12
- ],
13
- "defaults": {
14
- "to": "coordinator",
15
- "from": "run:{run_id}",
16
- "summary": "",
17
- "metadata": "{}",
18
- "correlation_id": "",
19
- "reply_to": "",
20
- "repo": "~/.pi/agent/extensions/pi-actors"
21
- },
22
- "template": "node {repo}/scripts/recipe-utils.mjs actor-message {type} {to} {from} {summary} {metadata} {correlation_id} {reply_to}"
23
- }
@@ -1,214 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Canonical mailbox-backed actor worker demo.
5
- *
6
- * Owns the worker argument parsing and control loop directly. Reusable room and
7
- * mailbox primitives stay in lib/; this script remains the public executable.
8
- */
9
-
10
- import { appendFileSync, existsSync, mkdirSync, writeFileSync } from "node:fs";
11
- import { dirname, join } from "node:path";
12
- import { fileURLToPath, pathToFileURL } from "node:url";
13
-
14
- function packageRoot() {
15
- return dirname(dirname(fileURLToPath(import.meta.url)));
16
- }
17
-
18
- async function importRuntimeModule(name) {
19
- const root = packageRoot();
20
- const compiled = join(root, "dist", "lib", `${name}.js`);
21
- const source = join(root, "lib", `${name}.ts`);
22
- return await import(
23
- pathToFileURL(existsSync(compiled) ? compiled : source).href
24
- );
25
- }
26
-
27
- const { appendRoomMessage, ensureRoomMember, readBranchInboxMessages } =
28
- await importRuntimeModule("rooms");
29
- const { handleMailboxLoopOnce, isMailboxLoopStopMessage } =
30
- await importRuntimeModule("mailbox-loop");
31
-
32
- export function parseActorWorkerArgs(argv) {
33
- const args = {};
34
- for (let index = 0; index < argv.length; index += 1) {
35
- const token = argv[index];
36
- if (!token.startsWith("--")) continue;
37
- const key = token.slice(2).replaceAll("-", "_");
38
- const next = argv[index + 1];
39
- if (!next || next.startsWith("--")) {
40
- args[key] = true;
41
- continue;
42
- }
43
- args[key] = next;
44
- index += 1;
45
- }
46
- return args;
47
- }
48
-
49
- function sleep(ms) {
50
- return new Promise((resolve) => setTimeout(resolve, ms));
51
- }
52
-
53
- function text(value) {
54
- return typeof value === "string" ? value : JSON.stringify(value);
55
- }
56
-
57
- function enabled(value) {
58
- return value !== false && value !== "false" && value !== "0";
59
- }
60
-
61
- function safeName(value) {
62
- return String(value ?? "unknown").replaceAll(/[^A-Za-z0-9_.-]+/g, "_");
63
- }
64
-
65
- export async function runActorWorker(argv = process.argv.slice(2)) {
66
- const args = parseActorWorkerArgs(argv);
67
- const stateDir = String(args.state_dir ?? "");
68
- const run = String(args.run ?? "");
69
- const branch = String(args.branch ?? "worker");
70
- const pollMs = Math.max(50, Number(args.poll_ms ?? 1000));
71
- const staleClaimMs = Math.max(0, Number(args.stale_claim_ms ?? 0));
72
- const artifactDir = String(
73
- args.artifact_dir ?? join(stateDir, "worker-artifacts"),
74
- );
75
- const writeArtifacts = enabled(args.write_artifacts ?? true);
76
-
77
- if (!stateDir || !run) {
78
- throw new Error(
79
- "usage: actor-worker.mjs --state-dir <dir> --run <id> [--branch worker] [--poll-ms 1000]",
80
- );
81
- }
82
-
83
- const branchAddress = `branch:${run}/${branch}`;
84
- const roomAddress = `room:${run}`;
85
- const journalPath = join(stateDir, "worker-events.jsonl");
86
- const statusPath = join(stateDir, "worker-status.json");
87
- if (writeArtifacts) mkdirSync(artifactDir, { recursive: true });
88
-
89
- function journal(event, data = {}) {
90
- appendFileSync(
91
- journalPath,
92
- `${JSON.stringify({ event, ts: new Date().toISOString(), ...data })}\n`,
93
- );
94
- }
95
-
96
- function staleClaims() {
97
- if (staleClaimMs <= 0) return 0;
98
- const cutoff = Date.now() - staleClaimMs;
99
- return readBranchInboxMessages(stateDir, run, branchAddress).filter(
100
- (record) => {
101
- if (record.status !== "claimed" || !record.claimed_at) return false;
102
- const claimedAt = Date.parse(record.claimed_at);
103
- return Number.isFinite(claimedAt) && claimedAt < cutoff;
104
- },
105
- ).length;
106
- }
107
-
108
- function status(state, data = {}) {
109
- writeFileSync(
110
- statusPath,
111
- `${JSON.stringify({ artifact_dir: artifactDir, branch, run, stale_claims: staleClaims(), state, ts: new Date().toISOString(), ...data }, null, 2)}\n`,
112
- );
113
- }
114
-
115
- function writeResultArtifact(id, result) {
116
- if (!writeArtifacts) return undefined;
117
- const path = join(artifactDir, `${safeName(id)}.txt`);
118
- writeFileSync(path, `${result}\n`);
119
- return path;
120
- }
121
-
122
- function room(type, summary, body = {}) {
123
- appendRoomMessage(stateDir, "main", {
124
- body,
125
- from: branchAddress,
126
- summary,
127
- to: roomAddress,
128
- type,
129
- });
130
- }
131
-
132
- ensureRoomMember(
133
- stateDir,
134
- run,
135
- "main",
136
- branchAddress,
137
- { display: branch, role: "worker", status: "present" },
138
- `${branch} joined as mailbox worker`,
139
- );
140
- room("awaiting_assignment", `${branch} awaiting assignment`, {
141
- branch,
142
- stale_claim_ms: staleClaimMs,
143
- stale_claims: staleClaims(),
144
- });
145
- journal("worker.started", {
146
- artifact_dir: artifactDir,
147
- branch,
148
- run,
149
- stale_claim_ms: staleClaimMs,
150
- });
151
- status("awaiting_assignment", { handled: 0, stale_claim_ms: staleClaimMs });
152
-
153
- let handled = 0;
154
- let stopping = false;
155
- while (!stopping) {
156
- const result = await handleMailboxLoopOnce(
157
- { address: branchAddress, kind: "branch", run, stateDir },
158
- (message) => {
159
- if (isMailboxLoopStopMessage(message)) {
160
- stopping = true;
161
- room("actor.leave", `${branch} stopping`, {
162
- branch,
163
- reason: message.type,
164
- });
165
- journal("worker.stopping", { id: message.id, type: message.type });
166
- status("stopping", { handled, reason: message.type });
167
- return;
168
- }
169
- room("task.claim", `${branch} claimed ${message.type}`, {
170
- branch,
171
- id: message.id,
172
- type: message.type,
173
- });
174
- const result = text(message.body);
175
- const artifact = writeResultArtifact(message.id, result);
176
- handled += 1;
177
- room("task.result", `${branch} handled ${message.type}`, {
178
- artifact,
179
- branch,
180
- id: message.id,
181
- result,
182
- type: message.type,
183
- });
184
- room("awaiting_assignment", `${branch} awaiting assignment`, {
185
- branch,
186
- });
187
- journal("task.handled", {
188
- artifact,
189
- id: message.id,
190
- type: message.type,
191
- });
192
- status("awaiting_assignment", {
193
- handled,
194
- last_artifact: artifact,
195
- last_id: message.id,
196
- last_type: message.type,
197
- stale_claim_ms: staleClaimMs,
198
- });
199
- },
200
- { owner: branchAddress },
201
- );
202
- if (!result.handled) await sleep(pollMs);
203
- }
204
-
205
- journal("worker.done", { branch, handled, run });
206
- status("done", { handled });
207
- }
208
-
209
- try {
210
- await runActorWorker(process.argv.slice(2));
211
- } catch (error) {
212
- console.error(error instanceof Error ? error.message : String(error));
213
- process.exit(2);
214
- }