@llblab/pi-actors 0.42.3 → 0.43.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 (252) hide show
  1. package/AGENTS.md +121 -175
  2. package/CHANGELOG.md +12 -0
  3. package/README.md +113 -276
  4. package/dist/fixtures/protocol/control-endpoint.json +6 -0
  5. package/dist/fixtures/protocol/control-record.json +9 -0
  6. package/dist/fixtures/protocol/recipe-summary.json +4 -12
  7. package/dist/fixtures/protocol/trace-event.json +9 -0
  8. package/dist/lib/async-runs.d.ts +14 -38
  9. package/dist/lib/async-runs.js +158 -108
  10. package/dist/lib/control.d.ts +12 -0
  11. package/dist/lib/control.js +84 -0
  12. package/dist/lib/execution-sessions.d.ts +17 -0
  13. package/dist/lib/execution-sessions.js +85 -0
  14. package/dist/lib/file-state.d.ts +1 -0
  15. package/dist/lib/file-state.js +17 -5
  16. package/dist/lib/inspector-actions.d.ts +2 -2
  17. package/dist/lib/inspector-actions.js +2 -2
  18. package/dist/lib/inspector-command.js +3 -3
  19. package/dist/lib/inspector-overlay.d.ts +52 -70
  20. package/dist/lib/inspector-overlay.js +532 -905
  21. package/dist/lib/inspector.d.ts +3 -71
  22. package/dist/lib/inspector.js +19 -665
  23. package/dist/lib/limits.d.ts +4 -2
  24. package/dist/lib/limits.js +4 -2
  25. package/dist/lib/observability.d.ts +16 -16
  26. package/dist/lib/observability.js +43 -82
  27. package/dist/lib/prompts.d.ts +1 -1
  28. package/dist/lib/prompts.js +2 -2
  29. package/dist/lib/recipe-control.d.ts +7 -0
  30. package/dist/lib/recipe-control.js +39 -0
  31. package/dist/lib/recipes-discovery.js +2 -0
  32. package/dist/lib/recipes-references.d.ts +1 -14
  33. package/dist/lib/recipes-references.js +6 -21
  34. package/dist/lib/review-projection.js +1 -5
  35. package/dist/lib/run-ui-runtime.js +2 -2
  36. package/dist/lib/runs-control-delivery.d.ts +21 -0
  37. package/dist/lib/runs-control-delivery.js +127 -0
  38. package/dist/lib/runs-controls.d.ts +35 -0
  39. package/dist/lib/runs-controls.js +144 -0
  40. package/dist/lib/runs-retention.d.ts +7 -0
  41. package/dist/lib/runs-retention.js +27 -3
  42. package/dist/lib/runs-start.js +4 -2
  43. package/dist/lib/runs-status.js +11 -6
  44. package/dist/lib/runs-trace.d.ts +24 -0
  45. package/dist/lib/runs-trace.js +98 -0
  46. package/dist/lib/runtime-notifier.d.ts +1 -1
  47. package/dist/lib/runtime-notifier.js +1 -1
  48. package/dist/lib/tools-inspect.d.ts +3 -3
  49. package/dist/lib/tools-inspect.js +203 -708
  50. package/dist/lib/tools-local.js +2 -10
  51. package/dist/lib/tools-message.d.ts +7 -7
  52. package/dist/lib/tools-message.js +95 -396
  53. package/dist/lib/tools-response.d.ts +1 -4
  54. package/dist/lib/tools-response.js +5 -39
  55. package/dist/lib/tools-spawn.js +16 -28
  56. package/dist/lib/tools.js +1 -2
  57. package/dist/lib/trace-projection.d.ts +22 -0
  58. package/dist/lib/trace-projection.js +165 -0
  59. package/dist/recipes/draft-review.json +0 -10
  60. package/dist/recipes/lens-swarm.json +0 -14
  61. package/dist/recipes/music-player.json +10 -19
  62. package/dist/recipes/pipeline-architect-coordinator.json +0 -11
  63. package/dist/recipes/pipeline-artifact-bundle.json +1 -22
  64. package/dist/recipes/pipeline-artifact-report.json +1 -18
  65. package/dist/recipes/pipeline-artifact-write.json +1 -18
  66. package/dist/recipes/pipeline-async-run-ops.json +0 -12
  67. package/dist/recipes/pipeline-checkpoint-continuation.json +0 -14
  68. package/dist/recipes/pipeline-development-tasking.json +0 -12
  69. package/dist/recipes/pipeline-docs-maintenance.json +0 -12
  70. package/dist/recipes/pipeline-media-library.json +0 -12
  71. package/dist/recipes/pipeline-quorum-review.json +0 -12
  72. package/dist/recipes/pipeline-release-readiness.json +0 -12
  73. package/dist/recipes/pipeline-release-summary.json +0 -12
  74. package/dist/recipes/pipeline-repo-health.json +0 -12
  75. package/dist/recipes/pipeline-research-synthesis.json +0 -11
  76. package/dist/recipes/pipeline-review-readiness.json +0 -12
  77. package/dist/recipes/resource-locker.json +27 -0
  78. package/dist/recipes/subagent-artifact.json +0 -9
  79. package/dist/recipes/subagent-checkpoint.json +0 -10
  80. package/dist/recipes/subagent-conflict-report.json +0 -11
  81. package/dist/recipes/subagent-contradiction-map.json +0 -11
  82. package/dist/recipes/subagent-critic.json +0 -11
  83. package/dist/recipes/subagent-evidence-map.json +0 -11
  84. package/dist/recipes/subagent-followup.json +0 -10
  85. package/dist/recipes/subagent-judge.json +0 -11
  86. package/dist/recipes/subagent-merge.json +0 -11
  87. package/dist/recipes/subagent-normalize.json +0 -11
  88. package/dist/recipes/subagent-plan.json +0 -11
  89. package/dist/recipes/subagent-preflight.json +0 -11
  90. package/dist/recipes/subagent-prompt.json +0 -10
  91. package/dist/recipes/subagent-quorum.json +0 -10
  92. package/dist/recipes/subagent-review-coordinator.json +0 -14
  93. package/dist/recipes/subagent-review.json +0 -11
  94. package/dist/recipes/subagent-task-card.json +0 -11
  95. package/dist/recipes/subagent-tools.json +0 -10
  96. package/dist/recipes/subagent-verify.json +0 -11
  97. package/dist/recipes/subagents-prompts.json +0 -10
  98. package/dist/recipes/tool-review.json +0 -10
  99. package/dist/scripts/async-runner.mjs +25 -25
  100. package/dist/scripts/conformance.mjs +4 -2
  101. package/dist/scripts/locker.mjs +200 -66
  102. package/dist/scripts/music-player.mjs +159 -150
  103. package/dist/scripts/recipe-utils.mjs +6 -96
  104. package/dist/scripts/release-gates.mjs +60 -0
  105. package/dist/scripts/validate-recipe.mjs +3 -53
  106. package/dist/skills/actors/SKILL.md +53 -266
  107. package/dist/skills/swarm/SKILL.md +11 -33
  108. package/docs/0.43-baseline.md +44 -0
  109. package/docs/README.md +3 -3
  110. package/docs/actor-inspector.md +26 -64
  111. package/docs/actors-deep-reference.md +92 -50
  112. package/docs/async-runs.md +81 -328
  113. package/docs/command-templates.md +2 -2
  114. package/docs/component-recipes.md +30 -133
  115. package/docs/recipe-library.md +57 -182
  116. package/docs/task-first-recipes.md +10 -12
  117. package/docs/template-recipes.md +76 -289
  118. package/docs/tool-registry.md +41 -161
  119. package/fixtures/protocol/control-endpoint.json +6 -0
  120. package/fixtures/protocol/control-record.json +9 -0
  121. package/fixtures/protocol/recipe-summary.json +4 -12
  122. package/fixtures/protocol/trace-event.json +9 -0
  123. package/lib/async-runs.ts +202 -201
  124. package/lib/control.ts +102 -0
  125. package/lib/execution-sessions.ts +111 -0
  126. package/lib/file-state.ts +17 -4
  127. package/lib/inspector-actions.ts +2 -2
  128. package/lib/inspector-command.ts +3 -3
  129. package/lib/inspector-overlay.ts +577 -1121
  130. package/lib/inspector.ts +46 -979
  131. package/lib/limits.ts +4 -2
  132. package/lib/observability.ts +60 -101
  133. package/lib/prompts.ts +2 -2
  134. package/lib/recipe-control.ts +45 -0
  135. package/lib/recipes-discovery.ts +2 -0
  136. package/lib/recipes-references.ts +9 -45
  137. package/lib/review-projection.ts +1 -5
  138. package/lib/run-ui-runtime.ts +2 -2
  139. package/lib/runs-control-delivery.ts +181 -0
  140. package/lib/runs-controls.ts +204 -0
  141. package/lib/runs-retention.ts +38 -3
  142. package/lib/runs-start.ts +4 -2
  143. package/lib/runs-status.ts +11 -6
  144. package/lib/runs-trace.ts +132 -0
  145. package/lib/runtime-notifier.ts +1 -1
  146. package/lib/tools-inspect.ts +240 -901
  147. package/lib/tools-local.ts +2 -12
  148. package/lib/tools-message.ts +112 -519
  149. package/lib/tools-response.ts +5 -52
  150. package/lib/tools-spawn.ts +16 -32
  151. package/lib/tools.ts +1 -2
  152. package/lib/trace-projection.ts +221 -0
  153. package/package.json +2 -1
  154. package/recipes/draft-review.json +0 -10
  155. package/recipes/lens-swarm.json +0 -14
  156. package/recipes/music-player.json +10 -19
  157. package/recipes/pipeline-architect-coordinator.json +0 -11
  158. package/recipes/pipeline-artifact-bundle.json +1 -22
  159. package/recipes/pipeline-artifact-report.json +1 -18
  160. package/recipes/pipeline-artifact-write.json +1 -18
  161. package/recipes/pipeline-async-run-ops.json +0 -12
  162. package/recipes/pipeline-checkpoint-continuation.json +0 -14
  163. package/recipes/pipeline-development-tasking.json +0 -12
  164. package/recipes/pipeline-docs-maintenance.json +0 -12
  165. package/recipes/pipeline-media-library.json +0 -12
  166. package/recipes/pipeline-quorum-review.json +0 -12
  167. package/recipes/pipeline-release-readiness.json +0 -12
  168. package/recipes/pipeline-release-summary.json +0 -12
  169. package/recipes/pipeline-repo-health.json +0 -12
  170. package/recipes/pipeline-research-synthesis.json +0 -11
  171. package/recipes/pipeline-review-readiness.json +0 -12
  172. package/recipes/resource-locker.json +27 -0
  173. package/recipes/subagent-artifact.json +0 -9
  174. package/recipes/subagent-checkpoint.json +0 -10
  175. package/recipes/subagent-conflict-report.json +0 -11
  176. package/recipes/subagent-contradiction-map.json +0 -11
  177. package/recipes/subagent-critic.json +0 -11
  178. package/recipes/subagent-evidence-map.json +0 -11
  179. package/recipes/subagent-followup.json +0 -10
  180. package/recipes/subagent-judge.json +0 -11
  181. package/recipes/subagent-merge.json +0 -11
  182. package/recipes/subagent-normalize.json +0 -11
  183. package/recipes/subagent-plan.json +0 -11
  184. package/recipes/subagent-preflight.json +0 -11
  185. package/recipes/subagent-prompt.json +0 -10
  186. package/recipes/subagent-quorum.json +0 -10
  187. package/recipes/subagent-review-coordinator.json +0 -14
  188. package/recipes/subagent-review.json +0 -11
  189. package/recipes/subagent-task-card.json +0 -11
  190. package/recipes/subagent-tools.json +0 -10
  191. package/recipes/subagent-verify.json +0 -11
  192. package/recipes/subagents-prompts.json +0 -10
  193. package/recipes/tool-review.json +0 -10
  194. package/scripts/async-runner.mjs +25 -25
  195. package/scripts/conformance.mjs +4 -2
  196. package/scripts/locker.mjs +200 -66
  197. package/scripts/music-player.mjs +159 -150
  198. package/scripts/recipe-utils.mjs +6 -96
  199. package/scripts/release-gates.mjs +60 -0
  200. package/scripts/validate-recipe.mjs +3 -53
  201. package/skills/actors/SKILL.md +53 -266
  202. package/skills/swarm/SKILL.md +11 -33
  203. package/dist/fixtures/protocol/actor-message-branch.json +0 -13
  204. package/dist/fixtures/protocol/mailbox-contract.json +0 -15
  205. package/dist/fixtures/protocol/room-message.json +0 -11
  206. package/dist/fixtures/protocol/room-roster.json +0 -11
  207. package/dist/fixtures/protocol/run-inbox-message.json +0 -9
  208. package/dist/fixtures/protocol/run-outbox-event.json +0 -9
  209. package/dist/lib/mailbox-loop.d.ts +0 -41
  210. package/dist/lib/mailbox-loop.js +0 -60
  211. package/dist/lib/messages.d.ts +0 -25
  212. package/dist/lib/messages.js +0 -122
  213. package/dist/lib/rooms.d.ts +0 -104
  214. package/dist/lib/rooms.js +0 -647
  215. package/dist/lib/runs-mailbox.d.ts +0 -25
  216. package/dist/lib/runs-mailbox.js +0 -146
  217. package/dist/lib/runs-messages.d.ts +0 -15
  218. package/dist/lib/runs-messages.js +0 -179
  219. package/dist/lib/runs-outbox.d.ts +0 -41
  220. package/dist/lib/runs-outbox.js +0 -87
  221. package/dist/lib/tools-mailbox.d.ts +0 -8
  222. package/dist/lib/tools-mailbox.js +0 -48
  223. package/dist/recipes/actor-worker.json +0 -39
  224. package/dist/recipes/coordinator-locker.json +0 -45
  225. package/dist/recipes/locker.json +0 -45
  226. package/dist/recipes/pipeline-room-swarm.json +0 -50
  227. package/dist/recipes/subagent-message.json +0 -32
  228. package/dist/recipes/utility-actor-message.json +0 -23
  229. package/dist/scripts/actor-worker.mjs +0 -214
  230. package/dist/scripts/coordinator.mjs +0 -799
  231. package/docs/actor-messages.md +0 -225
  232. package/fixtures/protocol/actor-message-branch.json +0 -13
  233. package/fixtures/protocol/mailbox-contract.json +0 -15
  234. package/fixtures/protocol/room-message.json +0 -11
  235. package/fixtures/protocol/room-roster.json +0 -11
  236. package/fixtures/protocol/run-inbox-message.json +0 -9
  237. package/fixtures/protocol/run-outbox-event.json +0 -9
  238. package/lib/mailbox-loop.ts +0 -144
  239. package/lib/messages.ts +0 -151
  240. package/lib/rooms.ts +0 -939
  241. package/lib/runs-mailbox.ts +0 -208
  242. package/lib/runs-messages.ts +0 -252
  243. package/lib/runs-outbox.ts +0 -144
  244. package/lib/tools-mailbox.ts +0 -56
  245. package/recipes/actor-worker.json +0 -39
  246. package/recipes/coordinator-locker.json +0 -45
  247. package/recipes/locker.json +0 -45
  248. package/recipes/pipeline-room-swarm.json +0 -50
  249. package/recipes/subagent-message.json +0 -32
  250. package/recipes/utility-actor-message.json +0 -23
  251. package/scripts/actor-worker.mjs +0 -214
  252. package/scripts/coordinator.mjs +0 -799
@@ -1,146 +0,0 @@
1
- /**
2
- * Async run mailbox state.
3
- * Owns: durable run inbox records, claim locks, and handler status transitions.
4
- */
5
- import { randomUUID } from "node:crypto";
6
- import { mkdirSync, rmSync, statSync, writeFileSync } from "node:fs";
7
- import { join } from "node:path";
8
- import { readJsonlFileResilient } from "./state-readers.js";
9
- const RUN_INBOX_LOCK_TIMEOUT_MS = 5000;
10
- const STALE_INBOX_LOCK_MAX_AGE_MS = 5 * 60 * 1000;
11
- export function runInboxFile(stateDir) {
12
- return join(stateDir, "inbox.jsonl");
13
- }
14
- export function parseRunInboxLine(line) {
15
- try {
16
- return JSON.parse(line);
17
- }
18
- catch {
19
- return undefined;
20
- }
21
- }
22
- export function readRunInboxMessagesFromStateDir(stateDir) {
23
- return readJsonlFileResilient(runInboxFile(stateDir))
24
- .records;
25
- }
26
- function sleepSync(ms) {
27
- Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
28
- }
29
- function acquireRunInboxLock(stateDir) {
30
- const lockDir = join(stateDir, ".inbox.lock");
31
- const started = Date.now();
32
- while (true) {
33
- try {
34
- mkdirSync(lockDir, { recursive: false });
35
- writeFileSync(join(lockDir, "owner.json"), `${JSON.stringify({ pid: process.pid, created_at: new Date().toISOString() })}\n`, "utf8");
36
- return () => rmSync(lockDir, { recursive: true, force: true });
37
- }
38
- catch (error) {
39
- try {
40
- const stat = statSync(lockDir);
41
- if (Date.now() - stat.mtimeMs > STALE_INBOX_LOCK_MAX_AGE_MS) {
42
- rmSync(lockDir, { recursive: true, force: true });
43
- continue;
44
- }
45
- }
46
- catch {
47
- continue;
48
- }
49
- if (Date.now() - started > RUN_INBOX_LOCK_TIMEOUT_MS) {
50
- throw new Error("Run inbox lock timed out.", { cause: error });
51
- }
52
- sleepSync(10);
53
- }
54
- }
55
- }
56
- function writeRunInboxMessages(stateDir, messages) {
57
- writeFileSync(runInboxFile(stateDir), messages.length
58
- ? `${messages.map((message) => JSON.stringify(message)).join("\n")}\n`
59
- : "", "utf8");
60
- }
61
- export function updateRunInboxMessageStatusInStateDir(stateDir, id, nextStatus, metadata = {}) {
62
- const releaseLock = acquireRunInboxLock(stateDir);
63
- try {
64
- const messages = readRunInboxMessagesFromStateDir(stateDir);
65
- const timestampKey = `${nextStatus}_at`;
66
- let changed = false;
67
- const updated = messages.map((message) => {
68
- if (message.id !== id)
69
- return message;
70
- changed = true;
71
- return {
72
- ...message,
73
- ...metadata,
74
- [timestampKey]: new Date().toISOString(),
75
- status: nextStatus,
76
- };
77
- });
78
- if (changed)
79
- writeRunInboxMessages(stateDir, updated);
80
- return changed;
81
- }
82
- finally {
83
- releaseLock();
84
- }
85
- }
86
- export function claimRunInboxMessageInStateDir(stateDir, owner = "runtime", statuses = ["queued"]) {
87
- const releaseLock = acquireRunInboxLock(stateDir);
88
- try {
89
- const messages = readRunInboxMessagesFromStateDir(stateDir);
90
- const index = messages.findIndex((message) => statuses.includes(String(message.status ?? "queued")));
91
- if (index < 0)
92
- return undefined;
93
- const claimed = {
94
- ...messages[index],
95
- claimed_at: new Date().toISOString(),
96
- claimed_by: owner,
97
- id: typeof messages[index].id === "string"
98
- ? messages[index].id
99
- : randomUUID(),
100
- status: "claimed",
101
- };
102
- messages[index] = claimed;
103
- writeRunInboxMessages(stateDir, messages);
104
- return claimed;
105
- }
106
- finally {
107
- releaseLock();
108
- }
109
- }
110
- export function appendRunInboxMessageInStateDir(stateDir, record) {
111
- const id = randomUUID();
112
- const ts = new Date().toISOString();
113
- const releaseLock = acquireRunInboxLock(stateDir);
114
- try {
115
- writeFileSync(runInboxFile(stateDir), `${JSON.stringify({ ...record, id, queued_at: ts, received_at: ts, status: "queued" })}\n`, { flag: "a" });
116
- }
117
- finally {
118
- releaseLock();
119
- }
120
- return id;
121
- }
122
- export async function processRunInboxMessagesInStateDir(stateDir, handler, options = {}) {
123
- const result = { claimed: 0, failed: 0, handled: 0 };
124
- const limit = Math.max(1, Number(options.limit ?? 1));
125
- const owner = options.owner ?? "runtime";
126
- for (let index = 0; index < limit; index += 1) {
127
- const message = claimRunInboxMessageInStateDir(stateDir, owner, options.statuses);
128
- if (!message?.id)
129
- break;
130
- result.claimed += 1;
131
- try {
132
- await handler(message);
133
- if (updateRunInboxMessageStatusInStateDir(stateDir, message.id, "handled")) {
134
- result.handled += 1;
135
- }
136
- }
137
- catch (error) {
138
- if (updateRunInboxMessageStatusInStateDir(stateDir, message.id, "failed", {
139
- error: error instanceof Error ? error.message : String(error),
140
- })) {
141
- result.failed += 1;
142
- }
143
- }
144
- }
145
- return result;
146
- }
@@ -1,15 +0,0 @@
1
- /**
2
- * Async run message delivery.
3
- * Owns: run control endpoint resolution, inbox enqueueing, wake notification,
4
- * transport writes, and delivery receipts.
5
- */
6
- export interface RunControlEndpoint {
7
- path: string;
8
- type: "fifo" | "mailbox" | "named-pipe";
9
- }
10
- export interface SendRunMessageOptions {
11
- namedPipeSend?: (path: string, payload: string) => Promise<number>;
12
- platform?: NodeJS.Platform;
13
- }
14
- export declare function getRunControlEndpoint(status: Record<string, unknown>, stateDir: string): RunControlEndpoint;
15
- export declare function deliverRunMessage(status: Record<string, unknown>, run: string, stateDir: string, message: string, options?: SendRunMessageOptions): Promise<Record<string, unknown>>;
@@ -1,179 +0,0 @@
1
- /**
2
- * Async run message delivery.
3
- * Owns: run control endpoint resolution, inbox enqueueing, wake notification,
4
- * transport writes, and delivery receipts.
5
- */
6
- import { closeSync, constants, existsSync, openSync, statSync, writeFileSync, writeSync, } from "node:fs";
7
- import { createConnection } from "node:net";
8
- import { join } from "node:path";
9
- import { markTerminalHandled } from "./runs-control.js";
10
- import { appendRunInboxMessageInStateDir, updateRunInboxMessageStatusInStateDir, } from "./runs-mailbox.js";
11
- import { notifyRuntimeWake } from "./runtime-notifier.js";
12
- export function getRunControlEndpoint(status, stateDir) {
13
- const control = status.control;
14
- if (control && typeof control === "object" && !Array.isArray(control)) {
15
- const record = control;
16
- if ((record.type === "fifo" ||
17
- record.type === "mailbox" ||
18
- record.type === "named-pipe") &&
19
- typeof record.path === "string" &&
20
- record.path.trim()) {
21
- return { path: record.path, type: record.type };
22
- }
23
- }
24
- return { path: join(stateDir, "control.fifo"), type: "fifo" };
25
- }
26
- function appendRunInboxMessage(stateDir, message) {
27
- let record;
28
- try {
29
- const parsed = JSON.parse(message);
30
- record =
31
- parsed && typeof parsed === "object" && !Array.isArray(parsed)
32
- ? parsed
33
- : { body: parsed, type: "run.message" };
34
- }
35
- catch {
36
- record = { body: message, type: "run.message" };
37
- }
38
- return appendRunInboxMessageInStateDir(stateDir, record);
39
- }
40
- function writeRunMessageReceipt(stateDir, message, bytes, inboxId) {
41
- const trimmedMessage = message.trim().toLowerCase();
42
- const terminalMessage = ["stop", "cancel", "quit", "exit"].includes(trimmedMessage);
43
- const ts = new Date().toISOString();
44
- writeFileSync(join(stateDir, "events.jsonl"), `${JSON.stringify({ bytes, event: "run.message", inbox_id: inboxId, terminal: terminalMessage || undefined, ts })}\n`, { flag: "a" });
45
- updateRunInboxMessageStatusInStateDir(stateDir, inboxId, "sent", { bytes });
46
- if (terminalMessage) {
47
- markTerminalHandled(stateDir, {
48
- event: "run.message",
49
- message: trimmedMessage,
50
- });
51
- }
52
- }
53
- function sendRunMessageToFifo(endpoint, payload) {
54
- if (!existsSync(endpoint.path))
55
- throw new Error(`Run control FIFO not found: ${endpoint.path}`);
56
- const stat = statSync(endpoint.path);
57
- if ((stat.mode & constants.S_IFMT) !== constants.S_IFIFO) {
58
- throw new Error(`Run control endpoint is not a FIFO: ${endpoint.path}`);
59
- }
60
- let fd;
61
- try {
62
- fd = openSync(endpoint.path, constants.O_WRONLY | constants.O_NONBLOCK);
63
- return writeSync(fd, payload);
64
- }
65
- finally {
66
- if (fd !== undefined)
67
- closeSync(fd);
68
- }
69
- }
70
- function notifyRunMessageWake(stateDir, run, bytes, endpoint, inboxId) {
71
- try {
72
- const event = notifyRuntimeWake(stateDir, {
73
- actor: `run:${run}`,
74
- metadata: { bytes, control_type: endpoint.type, inbox_id: inboxId },
75
- reason: "run.message",
76
- });
77
- return { wake: "wake.jsonl", wake_id: event.id };
78
- }
79
- catch {
80
- return undefined;
81
- }
82
- }
83
- function sendRunMessageToNamedPipe(endpoint, payload, send) {
84
- if (send)
85
- return send(endpoint.path, payload);
86
- return new Promise((resolve, reject) => {
87
- const socket = createConnection(endpoint.path);
88
- let settled = false;
89
- const timeout = setTimeout(() => {
90
- if (settled)
91
- return;
92
- settled = true;
93
- socket.destroy();
94
- reject(new Error("named pipe connection timed out"));
95
- }, 5000);
96
- const finish = (error) => {
97
- if (settled)
98
- return;
99
- settled = true;
100
- clearTimeout(timeout);
101
- if (error)
102
- reject(error);
103
- else
104
- resolve(Buffer.byteLength(payload));
105
- };
106
- socket.on("error", finish);
107
- socket.on("connect", () => {
108
- socket.end(payload, () => finish());
109
- });
110
- });
111
- }
112
- export async function deliverRunMessage(status, run, stateDir, message, options = {}) {
113
- const endpoint = getRunControlEndpoint(status, stateDir);
114
- const payload = message.endsWith("\n") ? message : `${message}\n`;
115
- const payloadBytes = Buffer.byteLength(payload);
116
- const inboxId = appendRunInboxMessage(stateDir, message);
117
- const wake = notifyRunMessageWake(stateDir, run, payloadBytes, endpoint, inboxId);
118
- const runtimePlatform = options.platform ?? process.platform;
119
- if (endpoint.type === "mailbox") {
120
- return {
121
- ...(wake ?? {}),
122
- bytes: payloadBytes,
123
- control: "inbox.jsonl",
124
- control_path: endpoint.path,
125
- control_type: endpoint.type,
126
- inbox_id: inboxId,
127
- queued: true,
128
- run,
129
- sent: true,
130
- state_dir: stateDir,
131
- };
132
- }
133
- try {
134
- if (endpoint.type === "fifo") {
135
- if (runtimePlatform === "win32") {
136
- throw new Error("run actor messages on native Windows require a named-pipe control endpoint; this recipe still exposes Unix FIFO control.");
137
- }
138
- const bytes = sendRunMessageToFifo(endpoint, payload);
139
- writeRunMessageReceipt(stateDir, message, bytes, inboxId);
140
- return {
141
- ...(wake ?? {}),
142
- bytes,
143
- control: "control.fifo",
144
- control_path: endpoint.path,
145
- control_type: endpoint.type,
146
- inbox_id: inboxId,
147
- run,
148
- sent: true,
149
- state_dir: stateDir,
150
- };
151
- }
152
- const bytes = await sendRunMessageToNamedPipe(endpoint, payload, options.namedPipeSend);
153
- writeRunMessageReceipt(stateDir, message, bytes, inboxId);
154
- return {
155
- ...(wake ?? {}),
156
- bytes,
157
- control: endpoint.path,
158
- control_path: endpoint.path,
159
- control_type: endpoint.type,
160
- inbox_id: inboxId,
161
- run,
162
- sent: true,
163
- state_dir: stateDir,
164
- };
165
- }
166
- catch (error) {
167
- const deliveryError = error instanceof Error ? error.message : String(error);
168
- throw Object.assign(new Error(`Run control endpoint is not ready: ${endpoint.path}: ${deliveryError}`), {
169
- control_path: endpoint.path,
170
- control_type: endpoint.type,
171
- delivery_error: deliveryError,
172
- inbox_id: inboxId,
173
- queued: true,
174
- run,
175
- sent: false,
176
- state_dir: stateDir,
177
- });
178
- }
179
- }
@@ -1,41 +0,0 @@
1
- /**
2
- * Async run outbox events.
3
- * Owns: outbox event normalization, parsing, and append payload formatting.
4
- */
5
- export type RunOutboxDelivery = "log" | "notify" | "followup";
6
- export type RunOutboxLevel = "info" | "warning" | "error";
7
- export interface RunOutboxEvent {
8
- body?: unknown;
9
- correlation_id?: string;
10
- data?: unknown;
11
- delivery: RunOutboxDelivery;
12
- event: string;
13
- from?: string;
14
- id: string;
15
- level: RunOutboxLevel;
16
- metadata?: Record<string, unknown>;
17
- reply_to?: string;
18
- run: string;
19
- state_dir: string;
20
- summary: string;
21
- to?: string;
22
- ts: string;
23
- type?: string;
24
- }
25
- export declare function normalizeRunOutboxDelivery(value: unknown): RunOutboxDelivery;
26
- export declare function normalizeRunOutboxLevel(value: unknown): RunOutboxLevel;
27
- export declare function parseRunOutboxEventLine(line: string, run: string, stateDir: string, index: number): RunOutboxEvent | undefined;
28
- export declare function buildRunOutboxEventPayload(run: string, event: {
29
- body?: unknown;
30
- correlation_id?: string;
31
- data?: unknown;
32
- delivery?: string;
33
- event?: string;
34
- from?: string;
35
- level?: string;
36
- metadata?: Record<string, unknown>;
37
- reply_to?: string;
38
- summary?: string;
39
- to?: string;
40
- type?: string;
41
- }): Record<string, unknown>;
@@ -1,87 +0,0 @@
1
- /**
2
- * Async run outbox events.
3
- * Owns: outbox event normalization, parsing, and append payload formatting.
4
- */
5
- export function normalizeRunOutboxDelivery(value) {
6
- return value === "notify" || value === "followup" ? value : "log";
7
- }
8
- export function normalizeRunOutboxLevel(value) {
9
- return value === "warning" || value === "error" ? value : "info";
10
- }
11
- function normalizeRunOutboxEvent(raw, run, stateDir, index) {
12
- if (!raw || typeof raw !== "object" || Array.isArray(raw))
13
- return undefined;
14
- const record = raw;
15
- const event = typeof record.event === "string" && record.event.trim()
16
- ? record.event.trim()
17
- : "run.event";
18
- const summary = typeof record.summary === "string" && record.summary.trim()
19
- ? record.summary.trim()
20
- : event;
21
- const ts = typeof record.ts === "string" && record.ts.trim()
22
- ? record.ts.trim()
23
- : new Date(0).toISOString();
24
- const id = typeof record.id === "string" && record.id.trim()
25
- ? record.id.trim()
26
- : `${run}:${index}`;
27
- return {
28
- ...(record.body !== undefined ? { body: record.body } : {}),
29
- ...(typeof record.correlation_id === "string"
30
- ? { correlation_id: record.correlation_id }
31
- : {}),
32
- ...(record.data !== undefined ? { data: record.data } : {}),
33
- delivery: normalizeRunOutboxDelivery(record.delivery),
34
- ...(record.metadata &&
35
- typeof record.metadata === "object" &&
36
- !Array.isArray(record.metadata)
37
- ? { metadata: record.metadata }
38
- : {}),
39
- event,
40
- ...(typeof record.from === "string" ? { from: record.from } : {}),
41
- id,
42
- level: normalizeRunOutboxLevel(record.level),
43
- ...(typeof record.reply_to === "string"
44
- ? { reply_to: record.reply_to }
45
- : {}),
46
- run,
47
- state_dir: stateDir,
48
- summary,
49
- ...(typeof record.to === "string" ? { to: record.to } : {}),
50
- ts,
51
- ...(typeof record.type === "string" ? { type: record.type } : {}),
52
- };
53
- }
54
- export function parseRunOutboxEventLine(line, run, stateDir, index) {
55
- try {
56
- return normalizeRunOutboxEvent(JSON.parse(line), run, stateDir, index);
57
- }
58
- catch {
59
- return undefined;
60
- }
61
- }
62
- export function buildRunOutboxEventPayload(run, event) {
63
- const type = event.type || event.event || "run.message";
64
- const to = event.to || "coordinator";
65
- const metadata = event.metadata ?? {};
66
- const requiresResponse = metadata.requires_response === true;
67
- return {
68
- ...(event.body !== undefined ? { body: event.body } : {}),
69
- ...(event.correlation_id ? { correlation_id: event.correlation_id } : {}),
70
- ...(event.data !== undefined ? { data: event.data } : {}),
71
- delivery: normalizeRunOutboxDelivery(event.delivery ??
72
- (requiresResponse
73
- ? "followup"
74
- : to === "coordinator"
75
- ? "notify"
76
- : "log")),
77
- event: type,
78
- from: event.from || `run:${run}`,
79
- level: normalizeRunOutboxLevel(event.level),
80
- ...(event.metadata ? { metadata: event.metadata } : {}),
81
- ...(event.reply_to ? { reply_to: event.reply_to } : {}),
82
- summary: event.summary || type,
83
- to,
84
- ts: new Date().toISOString(),
85
- type,
86
- };
87
- }
@@ -1,8 +0,0 @@
1
- /**
2
- * Public tool mailbox contract helpers
3
- * Zones: accepted/emitted message type declarations, contract normalization, compact type extraction
4
- * Owns mailbox metadata normalization for public message and inspect tool paths
5
- */
6
- export declare function normalizeMailboxEntry(value: unknown): Record<string, unknown> | undefined;
7
- export declare function normalizeMailboxContracts(mailbox: Record<string, unknown>): Record<string, unknown[]>;
8
- export declare function mailboxTypes(entries: unknown[]): string[];
@@ -1,48 +0,0 @@
1
- /**
2
- * Public tool mailbox contract helpers
3
- * Zones: accepted/emitted message type declarations, contract normalization, compact type extraction
4
- * Owns mailbox metadata normalization for public message and inspect tool paths
5
- */
6
- function asRecord(value) {
7
- return value && typeof value === "object" && !Array.isArray(value)
8
- ? value
9
- : {};
10
- }
11
- export function normalizeMailboxEntry(value) {
12
- if (typeof value === "string")
13
- return { type: value };
14
- const record = asRecord(value);
15
- if (typeof record.type !== "string" || !record.type.trim())
16
- return undefined;
17
- return {
18
- type: record.type.trim(),
19
- ...(record.body_schema !== undefined
20
- ? { body_schema: record.body_schema }
21
- : {}),
22
- ...(record.ack !== undefined ? { ack: record.ack } : {}),
23
- ...(typeof record.idempotency === "string"
24
- ? { idempotency: record.idempotency }
25
- : {}),
26
- ...(typeof record.level === "string" ? { level: record.level } : {}),
27
- ...(record.requires_response === true ? { requires_response: true } : {}),
28
- ...(typeof record.summary === "string" ? { summary: record.summary } : {}),
29
- };
30
- }
31
- export function normalizeMailboxContracts(mailbox) {
32
- const accepts = Array.isArray(mailbox.accepts)
33
- ? mailbox.accepts
34
- .map(normalizeMailboxEntry)
35
- .filter((entry) => Boolean(entry))
36
- : [];
37
- const emits = Array.isArray(mailbox.emits)
38
- ? mailbox.emits
39
- .map(normalizeMailboxEntry)
40
- .filter((entry) => Boolean(entry))
41
- : [];
42
- return { accepts, emits };
43
- }
44
- export function mailboxTypes(entries) {
45
- return entries.flatMap((entry) => typeof asRecord(entry).type === "string"
46
- ? [String(asRecord(entry).type)]
47
- : []);
48
- }
@@ -1,39 +0,0 @@
1
- {
2
- "async": true,
3
- "description": "Start a canonical mailbox-backed branch worker demo actor.",
4
- "args": [
5
- "repo:path",
6
- "branch:string",
7
- "poll_ms:int",
8
- "stale_claim_ms:int",
9
- "write_artifacts:bool"
10
- ],
11
- "defaults": {
12
- "repo": "~/.pi/agent/extensions/pi-actors",
13
- "branch": "worker",
14
- "poll_ms": "1000",
15
- "stale_claim_ms": "0",
16
- "write_artifacts": "true"
17
- },
18
- "mailbox": {
19
- "accepts": [
20
- "task.assign",
21
- "control.kill"
22
- ],
23
- "emits": [
24
- "actor.join",
25
- "task.claim",
26
- "task.result",
27
- "awaiting_assignment",
28
- "actor.leave",
29
- "run.done",
30
- "run.failed"
31
- ]
32
- },
33
- "artifacts": {
34
- "journal": "{state_dir}/worker-events.jsonl",
35
- "status": "{state_dir}/worker-status.json",
36
- "results": "{state_dir}/worker-artifacts"
37
- },
38
- "template": "{repo}/scripts/actor-worker.mjs --state-dir {state_dir} --run {run_id} --branch {branch} --poll-ms {poll_ms} --stale-claim-ms {stale_claim_ms} --write-artifacts {write_artifacts}"
39
- }
@@ -1,45 +0,0 @@
1
- {
2
- "async": true,
3
- "args": [
4
- "repo:path",
5
- "lease_ms:int"
6
- ],
7
- "defaults": {
8
- "repo": "~/.pi/agent/extensions/pi-actors",
9
- "lease_ms": "600000"
10
- },
11
- "mailbox": {
12
- "accepts": [
13
- "coord.enqueue",
14
- "coord.claim",
15
- "coord.complete",
16
- "coord.fail",
17
- "lock.acquire",
18
- "lock.renew",
19
- "lock.release",
20
- "control.stop",
21
- "control.cancel",
22
- "control.kill"
23
- ],
24
- "emits": [
25
- "coord.started",
26
- "coord.enqueued",
27
- "coord.assigned",
28
- "coord.empty",
29
- "coord.completed",
30
- "coord.failed",
31
- "lock.granted",
32
- "lock.denied",
33
- "lock.renewed",
34
- "lock.released",
35
- "run.done",
36
- "run.failed"
37
- ]
38
- },
39
- "artifacts": {
40
- "queue": "{state_dir}/queue.json",
41
- "locks": "{state_dir}/locks.json",
42
- "journal": "{state_dir}/journal.jsonl"
43
- },
44
- "template": "{repo}/scripts/locker.mjs serve --state-dir {state_dir} --lease-ms {lease_ms}"
45
- }
@@ -1,45 +0,0 @@
1
- {
2
- "async": true,
3
- "args": [
4
- "repo:path",
5
- "lease_ms:int"
6
- ],
7
- "defaults": {
8
- "repo": "~/.pi/agent/extensions/pi-actors",
9
- "lease_ms": "600000"
10
- },
11
- "mailbox": {
12
- "accepts": [
13
- "lock.enqueue",
14
- "lock.claim",
15
- "lock.complete",
16
- "lock.fail",
17
- "lock.acquire",
18
- "lock.renew",
19
- "lock.release",
20
- "control.stop",
21
- "control.cancel",
22
- "control.kill"
23
- ],
24
- "emits": [
25
- "lock.started",
26
- "lock.enqueued",
27
- "lock.assigned",
28
- "lock.empty",
29
- "lock.completed",
30
- "lock.failed",
31
- "lock.granted",
32
- "lock.denied",
33
- "lock.renewed",
34
- "lock.released",
35
- "run.done",
36
- "run.failed"
37
- ]
38
- },
39
- "artifacts": {
40
- "queue": "{state_dir}/queue.json",
41
- "locks": "{state_dir}/locks.json",
42
- "journal": "{state_dir}/journal.jsonl"
43
- },
44
- "template": "{repo}/scripts/locker.mjs serve --state-dir {state_dir} --lease-ms {lease_ms}"
45
- }