@acpus/runtime 0.8.0 → 0.9.0-alpha.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 (289) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/admission/input.d.ts +5 -0
  3. package/dist/admission/input.d.ts.map +1 -0
  4. package/dist/admission/input.js +17 -0
  5. package/dist/admission/input.js.map +1 -0
  6. package/dist/artifacts/rewrite.d.ts +7 -0
  7. package/dist/artifacts/rewrite.d.ts.map +1 -0
  8. package/dist/artifacts/rewrite.js +28 -0
  9. package/dist/artifacts/rewrite.js.map +1 -0
  10. package/dist/control/agent-overrides.d.ts +4 -0
  11. package/dist/control/agent-overrides.d.ts.map +1 -0
  12. package/dist/control/agent-overrides.js +40 -0
  13. package/dist/control/agent-overrides.js.map +1 -0
  14. package/dist/daemon/loop.d.ts +16 -0
  15. package/dist/daemon/loop.d.ts.map +1 -0
  16. package/dist/daemon/loop.js +191 -0
  17. package/dist/daemon/loop.js.map +1 -0
  18. package/dist/daemon/sessions.d.ts +23 -0
  19. package/dist/daemon/sessions.d.ts.map +1 -0
  20. package/dist/daemon/sessions.js +190 -0
  21. package/dist/daemon/sessions.js.map +1 -0
  22. package/dist/daemon/socket.d.ts +82 -0
  23. package/dist/daemon/socket.d.ts.map +1 -0
  24. package/dist/daemon/socket.js +341 -0
  25. package/dist/daemon/socket.js.map +1 -0
  26. package/dist/daemon/tick.d.ts +9 -0
  27. package/dist/daemon/tick.d.ts.map +1 -0
  28. package/dist/daemon/tick.js +18 -0
  29. package/dist/daemon/tick.js.map +1 -0
  30. package/dist/evaluation/admissible.d.ts +2 -0
  31. package/dist/evaluation/admissible.d.ts.map +1 -0
  32. package/dist/evaluation/admissible.js +50 -0
  33. package/dist/evaluation/admissible.js.map +1 -0
  34. package/dist/evaluation/evaluator.d.ts +14 -0
  35. package/dist/evaluation/evaluator.d.ts.map +1 -0
  36. package/dist/evaluation/evaluator.js +34 -0
  37. package/dist/evaluation/evaluator.js.map +1 -0
  38. package/dist/evaluation/loop-limit.d.ts +4 -0
  39. package/dist/evaluation/loop-limit.d.ts.map +1 -0
  40. package/dist/evaluation/loop-limit.js +9 -0
  41. package/dist/evaluation/loop-limit.js.map +1 -0
  42. package/dist/evaluation/schema.d.ts +4 -0
  43. package/dist/evaluation/schema.d.ts.map +1 -0
  44. package/dist/evaluation/schema.js +92 -0
  45. package/dist/evaluation/schema.js.map +1 -0
  46. package/dist/execution/advance.d.ts +18 -0
  47. package/dist/execution/advance.d.ts.map +1 -0
  48. package/dist/execution/advance.js +57 -0
  49. package/dist/execution/advance.js.map +1 -0
  50. package/dist/execution/agent-node.d.ts +23 -0
  51. package/dist/execution/agent-node.d.ts.map +1 -0
  52. package/dist/execution/agent-node.js +512 -0
  53. package/dist/execution/agent-node.js.map +1 -0
  54. package/dist/execution/duration.d.ts +2 -0
  55. package/dist/execution/duration.d.ts.map +1 -0
  56. package/dist/execution/duration.js +15 -0
  57. package/dist/execution/duration.js.map +1 -0
  58. package/dist/execution/ir.d.ts +3 -0
  59. package/dist/execution/ir.d.ts.map +1 -0
  60. package/dist/execution/ir.js +46 -0
  61. package/dist/execution/ir.js.map +1 -0
  62. package/dist/execution/scheduler.d.ts +59 -0
  63. package/dist/execution/scheduler.d.ts.map +1 -0
  64. package/dist/execution/scheduler.js +306 -0
  65. package/dist/execution/scheduler.js.map +1 -0
  66. package/dist/execution/task-executor.d.ts +14 -0
  67. package/dist/execution/task-executor.d.ts.map +1 -0
  68. package/dist/execution/task-executor.js +186 -0
  69. package/dist/execution/task-executor.js.map +1 -0
  70. package/dist/hooks/config.d.ts +32 -0
  71. package/dist/hooks/config.d.ts.map +1 -0
  72. package/dist/hooks/config.js +112 -0
  73. package/dist/hooks/config.js.map +1 -0
  74. package/dist/hooks/context.d.ts +50 -0
  75. package/dist/hooks/context.d.ts.map +1 -0
  76. package/dist/hooks/context.js +116 -0
  77. package/dist/hooks/context.js.map +1 -0
  78. package/dist/hooks/events.d.ts +22 -0
  79. package/dist/hooks/events.d.ts.map +1 -0
  80. package/dist/hooks/events.js +41 -0
  81. package/dist/hooks/events.js.map +1 -0
  82. package/dist/hooks/journal.d.ts +21 -19
  83. package/dist/hooks/journal.d.ts.map +1 -1
  84. package/dist/hooks/journal.js +1 -48
  85. package/dist/hooks/journal.js.map +1 -1
  86. package/dist/hooks/loader.d.ts +33 -39
  87. package/dist/hooks/loader.d.ts.map +1 -1
  88. package/dist/hooks/loader.js +79 -95
  89. package/dist/hooks/loader.js.map +1 -1
  90. package/dist/hooks/runner.d.ts +14 -41
  91. package/dist/hooks/runner.d.ts.map +1 -1
  92. package/dist/hooks/runner.js +177 -145
  93. package/dist/hooks/runner.js.map +1 -1
  94. package/dist/index.d.ts +13 -28
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/index.js +13 -33
  97. package/dist/index.js.map +1 -1
  98. package/dist/runs/advance-runtime.d.ts +50 -0
  99. package/dist/runs/advance-runtime.d.ts.map +1 -0
  100. package/dist/runs/advance-runtime.js +82 -0
  101. package/dist/runs/advance-runtime.js.map +1 -0
  102. package/dist/runs/use-cases.d.ts +111 -0
  103. package/dist/runs/use-cases.d.ts.map +1 -0
  104. package/dist/runs/use-cases.js +539 -0
  105. package/dist/runs/use-cases.js.map +1 -0
  106. package/dist/scheduler/advance.d.ts +65 -0
  107. package/dist/scheduler/advance.d.ts.map +1 -0
  108. package/dist/scheduler/advance.js +435 -0
  109. package/dist/scheduler/advance.js.map +1 -0
  110. package/dist/scheduler/control.d.ts +49 -0
  111. package/dist/scheduler/control.d.ts.map +1 -0
  112. package/dist/scheduler/control.js +212 -0
  113. package/dist/scheduler/control.js.map +1 -0
  114. package/dist/scheduler/event-codec.d.ts +4 -0
  115. package/dist/scheduler/event-codec.d.ts.map +1 -0
  116. package/dist/scheduler/event-codec.js +57 -0
  117. package/dist/scheduler/event-codec.js.map +1 -0
  118. package/dist/scheduler/events.d.ts +193 -0
  119. package/dist/scheduler/events.d.ts.map +1 -0
  120. package/dist/scheduler/events.js +13 -0
  121. package/dist/scheduler/events.js.map +1 -0
  122. package/dist/scheduler/fork-seed.d.ts +38 -0
  123. package/dist/scheduler/fork-seed.d.ts.map +1 -0
  124. package/dist/scheduler/fork-seed.js +590 -0
  125. package/dist/scheduler/fork-seed.js.map +1 -0
  126. package/dist/scheduler/identity.d.ts +8 -0
  127. package/dist/scheduler/identity.d.ts.map +1 -0
  128. package/dist/scheduler/identity.js +49 -0
  129. package/dist/scheduler/identity.js.map +1 -0
  130. package/dist/scheduler/ir-walk.d.ts +3 -0
  131. package/dist/scheduler/ir-walk.d.ts.map +1 -0
  132. package/dist/scheduler/ir-walk.js +25 -0
  133. package/dist/scheduler/ir-walk.js.map +1 -0
  134. package/dist/scheduler/limiter.d.ts +7 -0
  135. package/dist/scheduler/limiter.d.ts.map +1 -0
  136. package/dist/scheduler/limiter.js +10 -0
  137. package/dist/scheduler/limiter.js.map +1 -0
  138. package/dist/scheduler/materialize.d.ts +7 -0
  139. package/dist/scheduler/materialize.d.ts.map +1 -0
  140. package/dist/scheduler/materialize.js +756 -0
  141. package/dist/scheduler/materialize.js.map +1 -0
  142. package/dist/scheduler/membership.d.ts +12 -0
  143. package/dist/scheduler/membership.d.ts.map +1 -0
  144. package/dist/scheduler/membership.js +74 -0
  145. package/dist/scheduler/membership.js.map +1 -0
  146. package/dist/scheduler/node-executor.d.ts +15 -0
  147. package/dist/scheduler/node-executor.d.ts.map +1 -0
  148. package/dist/scheduler/node-executor.js +69 -0
  149. package/dist/scheduler/node-executor.js.map +1 -0
  150. package/dist/scheduler/runtime-runner.d.ts +44 -0
  151. package/dist/scheduler/runtime-runner.d.ts.map +1 -0
  152. package/dist/scheduler/runtime-runner.js +155 -0
  153. package/dist/scheduler/runtime-runner.js.map +1 -0
  154. package/dist/scheduler/scope.d.ts +6 -0
  155. package/dist/scheduler/scope.d.ts.map +1 -0
  156. package/dist/scheduler/scope.js +56 -0
  157. package/dist/scheduler/scope.js.map +1 -0
  158. package/dist/scheduler/store-port.d.ts +211 -0
  159. package/dist/scheduler/store-port.d.ts.map +1 -0
  160. package/dist/scheduler/store-port.js +28 -0
  161. package/dist/scheduler/store-port.js.map +1 -0
  162. package/dist/scheduler/transitions.d.ts +89 -0
  163. package/dist/scheduler/transitions.d.ts.map +1 -0
  164. package/dist/scheduler/transitions.js +967 -0
  165. package/dist/scheduler/transitions.js.map +1 -0
  166. package/dist/scheduler/types.d.ts +146 -0
  167. package/dist/scheduler/types.d.ts.map +1 -0
  168. package/dist/{executors → scheduler}/types.js.map +1 -1
  169. package/dist/store/store.d.ts +390 -0
  170. package/dist/store/store.d.ts.map +1 -0
  171. package/dist/store/store.js +3053 -0
  172. package/dist/store/store.js.map +1 -0
  173. package/dist/visualization/overlay.d.ts +86 -0
  174. package/dist/visualization/overlay.d.ts.map +1 -0
  175. package/dist/visualization/overlay.js +161 -0
  176. package/dist/visualization/overlay.js.map +1 -0
  177. package/package.json +19 -37
  178. package/README.md +0 -7
  179. package/dist/agent-telemetry.d.ts +0 -56
  180. package/dist/agent-telemetry.d.ts.map +0 -1
  181. package/dist/agent-telemetry.js +0 -304
  182. package/dist/agent-telemetry.js.map +0 -1
  183. package/dist/artifacts.d.ts +0 -45
  184. package/dist/artifacts.d.ts.map +0 -1
  185. package/dist/artifacts.js +0 -163
  186. package/dist/artifacts.js.map +0 -1
  187. package/dist/attempt-artifacts.d.ts +0 -35
  188. package/dist/attempt-artifacts.d.ts.map +0 -1
  189. package/dist/attempt-artifacts.js +0 -90
  190. package/dist/attempt-artifacts.js.map +0 -1
  191. package/dist/client.d.ts +0 -82
  192. package/dist/client.d.ts.map +0 -1
  193. package/dist/client.js +0 -200
  194. package/dist/client.js.map +0 -1
  195. package/dist/evaluator.d.ts +0 -36
  196. package/dist/evaluator.d.ts.map +0 -1
  197. package/dist/evaluator.js +0 -101
  198. package/dist/evaluator.js.map +0 -1
  199. package/dist/executors/agent.d.ts +0 -103
  200. package/dist/executors/agent.d.ts.map +0 -1
  201. package/dist/executors/agent.js +0 -516
  202. package/dist/executors/agent.js.map +0 -1
  203. package/dist/executors/mock-program.d.ts +0 -26
  204. package/dist/executors/mock-program.d.ts.map +0 -1
  205. package/dist/executors/mock-program.js +0 -100
  206. package/dist/executors/mock-program.js.map +0 -1
  207. package/dist/executors/output-preview.d.ts +0 -2
  208. package/dist/executors/output-preview.d.ts.map +0 -1
  209. package/dist/executors/output-preview.js +0 -20
  210. package/dist/executors/output-preview.js.map +0 -1
  211. package/dist/executors/program.d.ts +0 -30
  212. package/dist/executors/program.d.ts.map +0 -1
  213. package/dist/executors/program.js +0 -230
  214. package/dist/executors/program.js.map +0 -1
  215. package/dist/executors/types.d.ts +0 -32
  216. package/dist/executors/types.d.ts.map +0 -1
  217. package/dist/fork.d.ts +0 -74
  218. package/dist/fork.d.ts.map +0 -1
  219. package/dist/fork.js +0 -278
  220. package/dist/fork.js.map +0 -1
  221. package/dist/hooks/payload.d.ts +0 -17
  222. package/dist/hooks/payload.d.ts.map +0 -1
  223. package/dist/hooks/payload.js +0 -45
  224. package/dist/hooks/payload.js.map +0 -1
  225. package/dist/interpreter.d.ts +0 -168
  226. package/dist/interpreter.d.ts.map +0 -1
  227. package/dist/interpreter.js +0 -1747
  228. package/dist/interpreter.js.map +0 -1
  229. package/dist/keys.d.ts +0 -77
  230. package/dist/keys.d.ts.map +0 -1
  231. package/dist/keys.js +0 -382
  232. package/dist/keys.js.map +0 -1
  233. package/dist/run-control.d.ts +0 -45
  234. package/dist/run-control.d.ts.map +0 -1
  235. package/dist/run-control.js +0 -255
  236. package/dist/run-control.js.map +0 -1
  237. package/dist/run-id.d.ts +0 -3
  238. package/dist/run-id.d.ts.map +0 -1
  239. package/dist/run-id.js +0 -10
  240. package/dist/run-id.js.map +0 -1
  241. package/dist/state-machine.d.ts +0 -31
  242. package/dist/state-machine.d.ts.map +0 -1
  243. package/dist/state-machine.js +0 -102
  244. package/dist/state-machine.js.map +0 -1
  245. package/dist/store.d.ts +0 -92
  246. package/dist/store.d.ts.map +0 -1
  247. package/dist/store.js +0 -420
  248. package/dist/store.js.map +0 -1
  249. package/dist/supervisor-app.d.ts +0 -27
  250. package/dist/supervisor-app.d.ts.map +0 -1
  251. package/dist/supervisor-app.js +0 -694
  252. package/dist/supervisor-app.js.map +0 -1
  253. package/dist/supervisor-discovery.d.ts +0 -18
  254. package/dist/supervisor-discovery.d.ts.map +0 -1
  255. package/dist/supervisor-discovery.js +0 -180
  256. package/dist/supervisor-discovery.js.map +0 -1
  257. package/dist/supervisor-entry.d.ts +0 -11
  258. package/dist/supervisor-entry.d.ts.map +0 -1
  259. package/dist/supervisor-entry.js +0 -50
  260. package/dist/supervisor-entry.js.map +0 -1
  261. package/dist/supervisor-lock.d.ts +0 -26
  262. package/dist/supervisor-lock.d.ts.map +0 -1
  263. package/dist/supervisor-lock.js +0 -49
  264. package/dist/supervisor-lock.js.map +0 -1
  265. package/dist/supervisor-runner.d.ts +0 -11
  266. package/dist/supervisor-runner.d.ts.map +0 -1
  267. package/dist/supervisor-runner.js +0 -128
  268. package/dist/supervisor-runner.js.map +0 -1
  269. package/dist/types.d.ts +0 -375
  270. package/dist/types.d.ts.map +0 -1
  271. package/dist/types.js +0 -7
  272. package/dist/types.js.map +0 -1
  273. package/dist/validate-input.d.ts +0 -27
  274. package/dist/validate-input.d.ts.map +0 -1
  275. package/dist/validate-input.js +0 -56
  276. package/dist/validate-input.js.map +0 -1
  277. package/dist/validate-signal.d.ts +0 -14
  278. package/dist/validate-signal.d.ts.map +0 -1
  279. package/dist/validate-signal.js +0 -31
  280. package/dist/validate-signal.js.map +0 -1
  281. package/dist/workflow-context.d.ts +0 -4
  282. package/dist/workflow-context.d.ts.map +0 -1
  283. package/dist/workflow-context.js +0 -11
  284. package/dist/workflow-context.js.map +0 -1
  285. package/dist/workflow-outputs.d.ts +0 -9
  286. package/dist/workflow-outputs.d.ts.map +0 -1
  287. package/dist/workflow-outputs.js +0 -60
  288. package/dist/workflow-outputs.js.map +0 -1
  289. /package/dist/{executors → scheduler}/types.js +0 -0
@@ -0,0 +1,23 @@
1
+ import { type RuntimeAdvanceResult } from "../runs/advance-runtime.js";
2
+ import type { RuntimeMutationResult } from "../runs/use-cases.js";
3
+ import type { HookRunner } from "../hooks/runner.js";
4
+ import type { RunDetails, RuntimeStore } from "../store/store.js";
5
+ import { type DaemonControlIntent } from "./socket.js";
6
+ export declare class RunExecutionSessions {
7
+ private readonly cwd;
8
+ private readonly store;
9
+ private readonly hookRunner?;
10
+ private readonly sessions;
11
+ constructor(cwd: string, store: RuntimeStore, hookRunner?: HookRunner | undefined);
12
+ activeCount(): number;
13
+ hookActiveCount(): number;
14
+ drainHooks(): Promise<void>;
15
+ start(runId: string): RunDetails;
16
+ observe(runId: string): Promise<RuntimeAdvanceResult>;
17
+ control(intent: DaemonControlIntent): Promise<RuntimeMutationResult | undefined>;
18
+ private controlWithShortSession;
19
+ private fork;
20
+ private triggerHooks;
21
+ private run;
22
+ }
23
+ //# sourceMappingURL=sessions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/daemon/sessions.ts"],"names":[],"mappings":"AACA,OAAO,EAA2C,KAAK,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAChH,OAAO,KAAK,EAAwB,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAGxF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAsB,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAS3E,qBAAa,oBAAoB;IAGnB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAAU,OAAO,CAAC,QAAQ,CAAC,KAAK;IAAgB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;IAF5G,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuC;gBAEnC,GAAG,EAAE,MAAM,EAAmB,KAAK,EAAE,YAAY,EAAmB,UAAU,CAAC,EAAE,UAAU,YAAA;IAExH,WAAW,IAAI,MAAM;IAIrB,eAAe,IAAI,MAAM;IAInB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU;IAW1B,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAOrD,OAAO,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC;YAmBxE,uBAAuB;YAsBvB,IAAI;IAQlB,OAAO,CAAC,YAAY;YAUN,GAAG;CAwBlB"}
@@ -0,0 +1,190 @@
1
+ import { advanceRuntimeRun, runtimeAdvanceResult } from "../runs/advance-runtime.js";
2
+ import { applySchedulerControlIntentWithOwnerEpoch } from "../scheduler/control.js";
3
+ import { triggerHooksForCommittedRowsForRun } from "../scheduler/runtime-runner.js";
4
+ import { DaemonRequestError } from "./socket.js";
5
+ export class RunExecutionSessions {
6
+ cwd;
7
+ store;
8
+ hookRunner;
9
+ sessions = new Map();
10
+ constructor(cwd, store, hookRunner) {
11
+ this.cwd = cwd;
12
+ this.store = store;
13
+ this.hookRunner = hookRunner;
14
+ }
15
+ activeCount() {
16
+ return this.sessions.size;
17
+ }
18
+ hookActiveCount() {
19
+ return this.hookRunner?.activeCount() ?? 0;
20
+ }
21
+ async drainHooks() {
22
+ await this.hookRunner?.drain();
23
+ }
24
+ start(runId) {
25
+ const existing = this.store.getRun(runId);
26
+ if (!existing)
27
+ throw new DaemonRequestError("RUN_NOT_FOUND", `Run '${runId}' was not found.`);
28
+ if (!this.sessions.has(runId) && !isTerminal(existing.status)) {
29
+ const session = createSession();
30
+ this.sessions.set(runId, session);
31
+ session.promise = this.run(runId);
32
+ }
33
+ return existing;
34
+ }
35
+ async observe(runId) {
36
+ const run = this.start(runId);
37
+ const session = this.sessions.get(runId);
38
+ if (!session?.promise)
39
+ return runtimeAdvanceResult(this.store, runId, { status: terminalSummaryStatus(run.status) ?? "idle", runId, started: 0, completed: 0, failed: 0, cancelled: 0, active: 0 });
40
+ return session.promise;
41
+ }
42
+ async control(intent) {
43
+ const session = this.sessions.get(intent.runId);
44
+ if (!session)
45
+ return this.controlWithShortSession(intent);
46
+ if (intent.type === "fork")
47
+ return await this.fork(intent);
48
+ if (!session.ownerEpoch) {
49
+ await Promise.race([waitForOwnerEpoch(session), session.promise]);
50
+ if (!session.ownerEpoch)
51
+ return undefined;
52
+ }
53
+ const eventCursor = this.store.getLastRunEventSequence(intent.runId);
54
+ const result = applySchedulerControlIntentWithOwnerEpoch(this.store, controlIntent(intent), session.ownerEpoch);
55
+ this.triggerHooks(intent.runId, eventCursor);
56
+ if (intent.type === "pause" || intent.type === "cancel") {
57
+ for (const controller of session.activeAttempts.values())
58
+ controller.abort();
59
+ }
60
+ const run = this.store.getRun(result.runId);
61
+ if (!run)
62
+ throw new DaemonRequestError("RUN_NOT_FOUND", `Run '${result.runId}' was not found.`);
63
+ return { run };
64
+ }
65
+ async controlWithShortSession(intent) {
66
+ const existing = this.store.getRun(intent.runId);
67
+ if (!existing)
68
+ throw new DaemonRequestError("RUN_NOT_FOUND", `Run '${intent.runId}' was not found.`);
69
+ const claim = this.store.scheduler.claimRun(intent.runId, `daemon:${process.pid}:${intent.runId}:control`, 30_000);
70
+ if (!claim)
71
+ throw new DaemonRequestError("CONTROL_CONFLICT", `Run '${intent.runId}' is currently controlled by another owner.`);
72
+ const session = createSession();
73
+ session.ownerEpoch = claim.ownerEpoch;
74
+ this.sessions.set(intent.runId, session);
75
+ try {
76
+ if (intent.type === "fork")
77
+ return await this.fork(intent);
78
+ const eventCursor = this.store.getLastRunEventSequence(intent.runId);
79
+ const result = applySchedulerControlIntentWithOwnerEpoch(this.store, controlIntent(intent), claim.ownerEpoch);
80
+ this.triggerHooks(intent.runId, eventCursor);
81
+ const run = this.store.getRun(result.runId);
82
+ if (!run)
83
+ throw new DaemonRequestError("RUN_NOT_FOUND", `Run '${result.runId}' was not found.`);
84
+ return { run };
85
+ }
86
+ finally {
87
+ this.store.scheduler.releaseRun(claim);
88
+ if (this.sessions.get(intent.runId) === session)
89
+ this.sessions.delete(intent.runId);
90
+ }
91
+ }
92
+ async fork(intent) {
93
+ const fork = await this.store.forkRun(intent.runId, { ...(intent.input ?? {}), requestId: intent.requestId });
94
+ if (fork.forkCreated)
95
+ this.triggerHooks(fork.id, 0);
96
+ const run = this.store.getRun(intent.runId);
97
+ if (!run)
98
+ throw new DaemonRequestError("RUN_NOT_FOUND", `Run '${intent.runId}' was not found.`);
99
+ return { run, forkRunId: fork.id };
100
+ }
101
+ triggerHooks(runId, afterSequence) {
102
+ triggerHooksForCommittedRowsForRun({
103
+ cwd: this.cwd,
104
+ store: this.store,
105
+ runId,
106
+ ...(this.hookRunner === undefined ? {} : { hookRunner: this.hookRunner }),
107
+ afterSequence,
108
+ });
109
+ }
110
+ async run(runId) {
111
+ const session = this.sessions.get(runId);
112
+ try {
113
+ return await advanceRuntimeRun(this.cwd, this.store, runId, `daemon:${process.pid}:${runId}`, undefined, {
114
+ onClaim: claim => {
115
+ if (claim.runId === runId && session) {
116
+ session.ownerEpoch = claim.ownerEpoch;
117
+ resolveOwnerEpochWaiters(session);
118
+ }
119
+ },
120
+ onRelease: claim => {
121
+ if (claim.runId === runId && session?.ownerEpoch === claim.ownerEpoch)
122
+ delete session.ownerEpoch;
123
+ },
124
+ onActiveAttempt: attempt => {
125
+ if (attempt.runId !== runId || !session)
126
+ return undefined;
127
+ return trackActiveAttempt(session, attempt);
128
+ },
129
+ ...(this.hookRunner === undefined ? {} : { hookRunner: this.hookRunner }),
130
+ });
131
+ }
132
+ finally {
133
+ if (session)
134
+ resolveOwnerEpochWaiters(session);
135
+ if (this.sessions.get(runId) === session)
136
+ this.sessions.delete(runId);
137
+ }
138
+ }
139
+ }
140
+ function createSession() {
141
+ return { ownerEpochWaiters: [], activeAttempts: new Map() };
142
+ }
143
+ function waitForOwnerEpoch(session) {
144
+ if (session.ownerEpoch)
145
+ return Promise.resolve();
146
+ return new Promise(resolve => session.ownerEpochWaiters.push(resolve));
147
+ }
148
+ function resolveOwnerEpochWaiters(session) {
149
+ const waiters = session.ownerEpochWaiters.splice(0);
150
+ for (const resolve of waiters)
151
+ resolve();
152
+ }
153
+ function trackActiveAttempt(session, attempt) {
154
+ session.activeAttempts.set(attempt.nodeKey, attempt.controller);
155
+ return () => {
156
+ if (session.activeAttempts.get(attempt.nodeKey) === attempt.controller)
157
+ session.activeAttempts.delete(attempt.nodeKey);
158
+ };
159
+ }
160
+ function controlIntent(intent) {
161
+ if (intent.type === "signal") {
162
+ return {
163
+ requestId: intent.requestId,
164
+ runId: intent.runId,
165
+ type: "signal",
166
+ node: intent.nodeId,
167
+ payload: intent.payload,
168
+ commandIdempotencyKey: intent.requestId,
169
+ };
170
+ }
171
+ const input = intent.input;
172
+ if (intent.type === "pause")
173
+ return { requestId: intent.requestId, runId: intent.runId, type: "pause" };
174
+ if (intent.type === "resume")
175
+ return { requestId: intent.requestId, runId: intent.runId, type: "resume" };
176
+ if (intent.type === "retry")
177
+ return { requestId: intent.requestId, runId: intent.runId, type: "retry", ...(input?.target ? { target: input.target } : {}) };
178
+ if (intent.type === "cancel")
179
+ return { requestId: intent.requestId, runId: intent.runId, type: "cancel", ...(input?.target ? { target: input.target } : {}) };
180
+ throw new Error(`Unsupported active control '${intent.type}'.`);
181
+ }
182
+ function isTerminal(status) {
183
+ return status === "completed" || status === "failed" || status === "canceled";
184
+ }
185
+ function terminalSummaryStatus(status) {
186
+ if (status === "completed" || status === "failed" || status === "canceled")
187
+ return status;
188
+ return undefined;
189
+ }
190
+ //# sourceMappingURL=sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/daemon/sessions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ import { type RuntimeAdvanceResult } from "../runs/advance-runtime.js";
2
+ import { type RuntimeMutationAction, type RuntimeMutationInput, type RuntimeMutationResult } from "../runs/use-cases.js";
3
+ import type { RunDetails } from "../store/store.js";
4
+ export type DaemonStatus = {
5
+ status: "ok";
6
+ pid: number;
7
+ generation?: number;
8
+ protocolVersion: number;
9
+ packageVersion: string;
10
+ };
11
+ export type DaemonRequest = {
12
+ id?: string;
13
+ method: "status";
14
+ } | {
15
+ id?: string;
16
+ method: "shutdown";
17
+ } | {
18
+ id?: string;
19
+ method: "control";
20
+ control: DaemonControlIntent;
21
+ } | {
22
+ id?: string;
23
+ method: "startRun" | "observeRun";
24
+ runId: string;
25
+ };
26
+ export type DaemonControlIntent = {
27
+ requestId: string;
28
+ type: Exclude<RuntimeMutationAction, "fork">;
29
+ runId: string;
30
+ input?: RuntimeMutationInput;
31
+ } | {
32
+ requestId: string;
33
+ type: "fork";
34
+ runId: string;
35
+ input?: RuntimeMutationInput;
36
+ } | {
37
+ requestId: string;
38
+ type: "signal";
39
+ runId: string;
40
+ nodeId: string;
41
+ payload: unknown;
42
+ };
43
+ export type DaemonResponse = {
44
+ id?: string;
45
+ ok: true;
46
+ outcome: "applied";
47
+ result: DaemonStatus | DaemonShutdownResult | RunDetails | RuntimeAdvanceResult | RuntimeMutationResult;
48
+ } | {
49
+ id?: string;
50
+ ok: false;
51
+ outcome: "failed";
52
+ error: {
53
+ code: DaemonErrorCode;
54
+ message: string;
55
+ };
56
+ };
57
+ export type DaemonErrorCode = "INVALID_CONTROL" | "RUN_NOT_FOUND" | "RUN_TERMINAL" | "RUN_NOT_CONTROLLABLE" | "CONTROL_CONFLICT" | "EXECUTION_UNAVAILABLE" | "STORE_ERROR" | "INTERNAL_ERROR";
58
+ export type DaemonShutdownResult = {
59
+ status: "shutdown";
60
+ };
61
+ export declare class DaemonRequestError extends Error {
62
+ readonly code: DaemonErrorCode;
63
+ constructor(code: DaemonErrorCode, message: string);
64
+ }
65
+ export type DaemonServerHandle = {
66
+ endpoint: string;
67
+ close(): Promise<void>;
68
+ };
69
+ export declare function daemonEndpoint(cwd: string): string;
70
+ export declare function startDaemonServer(cwd: string, handlers: {
71
+ status(): DaemonStatus;
72
+ control(intent: DaemonControlIntent): Promise<RuntimeMutationResult>;
73
+ startRun(runId: string): Promise<RunDetails> | RunDetails;
74
+ observeRun(runId: string): Promise<RuntimeAdvanceResult>;
75
+ shutdown(): Promise<DaemonShutdownResult> | DaemonShutdownResult;
76
+ }): Promise<DaemonServerHandle>;
77
+ export declare function requestDaemonStatus(cwd: string): Promise<DaemonStatus>;
78
+ export declare function requestDaemonControl(cwd: string, control: DaemonControlIntent): Promise<RuntimeMutationResult>;
79
+ export declare function requestDaemonStartRun(cwd: string, runId: string): Promise<RunDetails>;
80
+ export declare function requestDaemonObserveRun(cwd: string, runId: string): Promise<RuntimeAdvanceResult>;
81
+ export declare function requestDaemonShutdown(cwd: string): Promise<DaemonShutdownResult>;
82
+ //# sourceMappingURL=socket.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"socket.d.ts","sourceRoot":"","sources":["../../src/daemon/socket.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EAA2B,KAAK,qBAAqB,EAAE,KAAK,oBAAoB,EAAE,KAAK,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClJ,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,IAAI,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,QAAQ,CAAC;CAClB,GAAG;IACF,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,UAAU,CAAC;CACpB,GAAG;IACF,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,SAAS,CAAC;IAClB,OAAO,EAAE,mBAAmB,CAAC;CAC9B,GAAG;IACF,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,UAAU,GAAG,YAAY,CAAC;IAClC,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAC3B;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,oBAAoB,CAAA;CAAE,GAChH;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,oBAAoB,CAAA;CAAE,GAChF;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAE3F,MAAM,MAAM,cAAc,GACtB;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,YAAY,GAAG,oBAAoB,GAAG,UAAU,GAAG,oBAAoB,GAAG,qBAAqB,CAAA;CAAE,GACtJ;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE;QAAE,IAAI,EAAE,eAAe,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC;AAErG,MAAM,MAAM,eAAe,GAAG,iBAAiB,GAAG,eAAe,GAAG,cAAc,GAAG,sBAAsB,GAAG,kBAAkB,GAAG,uBAAuB,GAAG,aAAa,GAAG,gBAAgB,CAAC;AAE9L,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,EAAE,UAAU,CAAC;CACpB,CAAC;AAEF,qBAAa,kBAAmB,SAAQ,KAAK;IAC/B,QAAQ,CAAC,IAAI,EAAE,eAAe;gBAArB,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM;CAG5D;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB,CAAC;AAEF,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAUlD;AAED,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE;IAAE,MAAM,IAAI,YAAY,CAAC;IAAC,OAAO,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG,UAAU,CAAC;IAAC,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAAC,QAAQ,IAAI,OAAO,CAAC,oBAAoB,CAAC,GAAG,oBAAoB,CAAA;CAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAiCnX;AA8CD,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAK5E;AAED,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAKpH;AAED,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAK3F;AAED,wBAAsB,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAKvG;AAED,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAKtF"}
@@ -0,0 +1,341 @@
1
+ import { createHash } from "node:crypto";
2
+ import { mkdir, open, rm } from "node:fs/promises";
3
+ import { createServer, connect } from "node:net";
4
+ import { tmpdir } from "node:os";
5
+ import { dirname, join, resolve } from "node:path";
6
+ import { openExistingRuntimeStore } from "../store/store.js";
7
+ import {} from "../runs/advance-runtime.js";
8
+ import { RuntimeUseCaseException } from "../runs/use-cases.js";
9
+ export class DaemonRequestError extends Error {
10
+ code;
11
+ constructor(code, message) {
12
+ super(message);
13
+ this.code = code;
14
+ }
15
+ }
16
+ export function daemonEndpoint(cwd) {
17
+ const workspace = resolve(cwd);
18
+ const digest = createHash("sha256").update(workspace).digest("hex").slice(0, 24);
19
+ if (process.platform === "win32") {
20
+ return `\\\\.\\pipe\\acpus-daemon-${digest}`;
21
+ }
22
+ const workspaceEndpoint = join(workspace, ".acpus", ".local", "daemon.sock");
23
+ if (Buffer.byteLength(workspaceEndpoint) < 100)
24
+ return workspaceEndpoint;
25
+ if (process.platform === "linux")
26
+ return `\0acpus-daemon-${digest}`;
27
+ return join(tmpdir(), `acpus-daemon-${digest}.sock`);
28
+ }
29
+ export async function startDaemonServer(cwd, handlers) {
30
+ const endpoint = daemonEndpoint(cwd);
31
+ if (isFilesystemSocket(endpoint)) {
32
+ await mkdir(dirname(endpoint), { recursive: true });
33
+ }
34
+ const sockets = new Set();
35
+ const server = createServer({ allowHalfOpen: true }, socket => {
36
+ sockets.add(socket);
37
+ socket.once("close", () => sockets.delete(socket));
38
+ void handleSocket(socket, handlers);
39
+ });
40
+ try {
41
+ await listen(server, endpoint);
42
+ }
43
+ catch (error) {
44
+ if (!isFilesystemSocket(endpoint) || !isAddressInUse(error))
45
+ throw error;
46
+ await recoverStaleFilesystemSocket(cwd, endpoint, server, error);
47
+ }
48
+ return {
49
+ endpoint,
50
+ close: async () => {
51
+ for (const socket of sockets)
52
+ socket.destroy();
53
+ await new Promise((resolveClose, rejectClose) => {
54
+ server.close(error => {
55
+ if (error)
56
+ rejectClose(error);
57
+ else
58
+ resolveClose();
59
+ });
60
+ });
61
+ if (isFilesystemSocket(endpoint))
62
+ await rm(endpoint, { force: true });
63
+ },
64
+ };
65
+ }
66
+ async function recoverStaleFilesystemSocket(cwd, endpoint, server, originalError) {
67
+ const lock = await acquireStaleSocketLock(endpoint);
68
+ if (!lock)
69
+ throw originalError;
70
+ try {
71
+ if (await hasLiveDaemon(cwd))
72
+ throw originalError;
73
+ if (!await hasStaleDaemonEvidence(cwd))
74
+ throw originalError;
75
+ await rm(endpoint, { force: true });
76
+ try {
77
+ await listen(server, endpoint);
78
+ }
79
+ catch (retryError) {
80
+ if (isAddressInUse(retryError))
81
+ throw originalError;
82
+ throw retryError;
83
+ }
84
+ }
85
+ finally {
86
+ await lock.release();
87
+ }
88
+ }
89
+ async function acquireStaleSocketLock(endpoint) {
90
+ const lockPath = `${endpoint}.lock`;
91
+ try {
92
+ const file = await open(lockPath, "wx");
93
+ return {
94
+ release: async () => {
95
+ await file.close();
96
+ await rm(lockPath, { force: true });
97
+ },
98
+ };
99
+ }
100
+ catch (error) {
101
+ if (isFileExists(error))
102
+ return undefined;
103
+ throw error;
104
+ }
105
+ }
106
+ async function listen(server, endpoint) {
107
+ await new Promise((resolveListen, rejectListen) => {
108
+ server.once("error", rejectListen);
109
+ server.listen(endpoint, () => {
110
+ server.off("error", rejectListen);
111
+ resolveListen();
112
+ });
113
+ });
114
+ }
115
+ export async function requestDaemonStatus(cwd) {
116
+ const response = await requestDaemon(cwd, { method: "status" });
117
+ if (!response.ok)
118
+ throw new DaemonRequestError(response.error.code, response.error.message);
119
+ if (!isDaemonStatus(response.result))
120
+ throw new Error("Daemon returned an invalid status response.");
121
+ return response.result;
122
+ }
123
+ export async function requestDaemonControl(cwd, control) {
124
+ const response = await requestDaemon(cwd, { method: "control", control });
125
+ if (!response.ok)
126
+ throw new DaemonRequestError(response.error.code, response.error.message);
127
+ if (isDaemonStatus(response.result) || isDaemonShutdownResult(response.result) || isRunDetails(response.result) || isRuntimeAdvanceResult(response.result))
128
+ throw new Error("Daemon returned an invalid control response.");
129
+ return response.result;
130
+ }
131
+ export async function requestDaemonStartRun(cwd, runId) {
132
+ const response = await requestDaemon(cwd, { method: "startRun", runId });
133
+ if (!response.ok)
134
+ throw new DaemonRequestError(response.error.code, response.error.message);
135
+ if (isDaemonStatus(response.result) || isRuntimeAdvanceResult(response.result) || !isRunDetails(response.result))
136
+ throw new Error("Daemon returned an invalid startRun response.");
137
+ return response.result;
138
+ }
139
+ export async function requestDaemonObserveRun(cwd, runId) {
140
+ const response = await requestDaemon(cwd, { method: "observeRun", runId });
141
+ if (!response.ok)
142
+ throw new DaemonRequestError(response.error.code, response.error.message);
143
+ if (!isRuntimeAdvanceResult(response.result))
144
+ throw new Error("Daemon returned an invalid observeRun response.");
145
+ return response.result;
146
+ }
147
+ export async function requestDaemonShutdown(cwd) {
148
+ const response = await requestDaemon(cwd, { method: "shutdown" });
149
+ if (!response.ok)
150
+ throw new DaemonRequestError(response.error.code, response.error.message);
151
+ if (!isDaemonShutdownResult(response.result))
152
+ throw new Error("Daemon returned an invalid shutdown response.");
153
+ return response.result;
154
+ }
155
+ async function requestDaemon(cwd, request) {
156
+ const endpoint = daemonEndpoint(cwd);
157
+ return new Promise((resolveRequest, rejectRequest) => {
158
+ const socket = connect(endpoint);
159
+ const chunks = [];
160
+ const timeoutMs = request.method === "observeRun" ? undefined : request.method === "control" ? 30_000 : 1_000;
161
+ const timeout = timeoutMs === undefined ? undefined : setTimeout(() => {
162
+ socket.destroy();
163
+ rejectRequest(new DaemonRequestError("EXECUTION_UNAVAILABLE", `Timed out waiting for daemon ${describeRequest(request)} response.`));
164
+ }, timeoutMs);
165
+ socket.once("error", error => {
166
+ if (timeout)
167
+ clearTimeout(timeout);
168
+ rejectRequest(error);
169
+ });
170
+ socket.on("data", chunk => chunks.push(Buffer.from(chunk)));
171
+ socket.once("end", () => {
172
+ if (timeout)
173
+ clearTimeout(timeout);
174
+ try {
175
+ resolveRequest(JSON.parse(Buffer.concat(chunks).toString("utf8")));
176
+ }
177
+ catch (error) {
178
+ rejectRequest(error);
179
+ }
180
+ });
181
+ socket.once("connect", () => {
182
+ socket.end(JSON.stringify(request));
183
+ });
184
+ });
185
+ }
186
+ async function handleSocket(socket, handlers) {
187
+ const chunks = [];
188
+ socket.setTimeout(5_000, () => socket.destroy());
189
+ socket.on("data", chunk => chunks.push(Buffer.from(chunk)));
190
+ socket.once("end", () => {
191
+ socket.setTimeout(0);
192
+ void (async () => {
193
+ const request = parseRequest(Buffer.concat(chunks).toString("utf8"));
194
+ const response = request.ok ? await dispatchRequest(request.value, handlers) : request.response;
195
+ socket.end(JSON.stringify(response));
196
+ })();
197
+ });
198
+ }
199
+ function parseRequest(raw) {
200
+ try {
201
+ const value = JSON.parse(raw);
202
+ if (value.method !== "status") {
203
+ if (value.method === "shutdown")
204
+ return { ok: true, value: { ...(value.id === undefined ? {} : { id: value.id }), method: value.method } };
205
+ if (value.method === "startRun" || value.method === "observeRun") {
206
+ if (typeof value.runId !== "string")
207
+ return { ok: false, response: failedResponse(value.id, "INVALID_CONTROL", "Invalid daemon run request.") };
208
+ return { ok: true, value: { ...(value.id === undefined ? {} : { id: value.id }), method: value.method, runId: value.runId } };
209
+ }
210
+ if (value.method !== "control" || !isControlIntent(value.control)) {
211
+ return { ok: false, response: failedResponse(value.id, "INVALID_CONTROL", "Unsupported daemon method.") };
212
+ }
213
+ return { ok: true, value: { ...(value.id === undefined ? {} : { id: value.id }), method: "control", control: value.control } };
214
+ }
215
+ return { ok: true, value: { ...(value.id === undefined ? {} : { id: value.id }), method: value.method } };
216
+ }
217
+ catch {
218
+ return { ok: false, response: failedResponse(undefined, "INVALID_CONTROL", "Invalid daemon request JSON.") };
219
+ }
220
+ }
221
+ async function dispatchRequest(request, handlers) {
222
+ try {
223
+ if (request.method === "control")
224
+ return appliedResponse(request.id, await handlers.control(request.control));
225
+ if (request.method === "startRun")
226
+ return appliedResponse(request.id, await handlers.startRun(request.runId));
227
+ if (request.method === "observeRun")
228
+ return appliedResponse(request.id, await handlers.observeRun(request.runId));
229
+ if (request.method === "shutdown")
230
+ return appliedResponse(request.id, await handlers.shutdown());
231
+ return appliedResponse(request.id, handlers.status());
232
+ }
233
+ catch (error) {
234
+ return failedResponse(request.id, request.method === "status" ? "INTERNAL_ERROR" : daemonControlErrorCode(error), error instanceof Error ? error.message : String(error));
235
+ }
236
+ }
237
+ function responseId(id) {
238
+ return id === undefined ? {} : { id };
239
+ }
240
+ function appliedResponse(id, result) {
241
+ return { ...responseId(id), ok: true, outcome: "applied", result };
242
+ }
243
+ function failedResponse(id, code, message) {
244
+ return { ...responseId(id), ok: false, outcome: "failed", error: { code, message } };
245
+ }
246
+ function describeRequest(request) {
247
+ if (request.method === "control")
248
+ return `${request.control.type} control for run '${request.control.runId}'`;
249
+ if (request.method === "startRun" || request.method === "observeRun")
250
+ return `${request.method} for run '${request.runId}'`;
251
+ return request.method;
252
+ }
253
+ function daemonControlErrorCode(error) {
254
+ if (error instanceof DaemonRequestError)
255
+ return error.code;
256
+ const failure = runtimeFailure(error);
257
+ if (failure) {
258
+ if (failure.type === "run-not-found" || failure.type === "runtime-store-not-found")
259
+ return "RUN_NOT_FOUND";
260
+ if (failure.type === "scheduler-store-failed")
261
+ return "STORE_ERROR";
262
+ if (failure.type === "run-control-failed" && error instanceof Error && error.message.includes("currently controlled by another owner"))
263
+ return "CONTROL_CONFLICT";
264
+ return "RUN_NOT_CONTROLLABLE";
265
+ }
266
+ return "RUN_NOT_CONTROLLABLE";
267
+ }
268
+ function runtimeFailure(error) {
269
+ if (error instanceof RuntimeUseCaseException)
270
+ return error.failure;
271
+ if (typeof error !== "object" || error === null || !("failure" in error))
272
+ return undefined;
273
+ const failure = error.failure;
274
+ if (typeof failure !== "object" || failure === null || !("type" in failure))
275
+ return undefined;
276
+ return failure;
277
+ }
278
+ function isFilesystemSocket(endpoint) {
279
+ return process.platform !== "win32" && !endpoint.startsWith("\0");
280
+ }
281
+ function isDaemonStatus(value) {
282
+ return typeof value === "object" && value !== null && value.status === "ok";
283
+ }
284
+ function isDaemonShutdownResult(value) {
285
+ return typeof value === "object" && value !== null && value.status === "shutdown";
286
+ }
287
+ function isRunDetails(value) {
288
+ return typeof value === "object" && value !== null && typeof value.id === "string" && typeof value.status === "string";
289
+ }
290
+ function isRuntimeAdvanceResult(value) {
291
+ return typeof value === "object" && value !== null && "summary" in value && "run" in value;
292
+ }
293
+ function isControlIntent(value) {
294
+ if (typeof value !== "object" || value === null)
295
+ return false;
296
+ const intent = value;
297
+ if (typeof intent.requestId !== "string" || typeof intent.type !== "string" || typeof intent.runId !== "string")
298
+ return false;
299
+ return intent.type === "signal" ? typeof intent.nodeId === "string" : ["pause", "resume", "retry", "cancel", "fork"].includes(intent.type);
300
+ }
301
+ async function hasLiveDaemon(cwd) {
302
+ try {
303
+ await requestDaemonStatus(cwd);
304
+ return true;
305
+ }
306
+ catch {
307
+ return false;
308
+ }
309
+ }
310
+ function isAddressInUse(error) {
311
+ return typeof error === "object" && error !== null && "code" in error && error.code === "EADDRINUSE";
312
+ }
313
+ function isFileExists(error) {
314
+ return typeof error === "object" && error !== null && "code" in error && error.code === "EEXIST";
315
+ }
316
+ async function hasStaleDaemonEvidence(cwd) {
317
+ const store = await openExistingRuntimeStore(cwd);
318
+ if (!store)
319
+ return true;
320
+ try {
321
+ const daemon = store.getRuntimeDiagnostics().daemon;
322
+ if (!daemon)
323
+ return true;
324
+ if (daemon.heartbeatAt && Date.now() - Date.parse(daemon.heartbeatAt) > 5_000)
325
+ return true;
326
+ return daemon.pid !== undefined && !isProcessAlive(daemon.pid);
327
+ }
328
+ finally {
329
+ store.close();
330
+ }
331
+ }
332
+ function isProcessAlive(pid) {
333
+ try {
334
+ process.kill(pid, 0);
335
+ return true;
336
+ }
337
+ catch (error) {
338
+ return typeof error === "object" && error !== null && "code" in error && error.code === "EPERM";
339
+ }
340
+ }
341
+ //# sourceMappingURL=socket.js.map