@osolmaz/pi-workflows 0.16.2 → 0.16.3

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 (315) hide show
  1. package/README.md +41 -41
  2. package/dist/builtins/monitor.workflow.d.ts +1 -1
  3. package/dist/builtins/monitor.workflow.js +8 -8
  4. package/dist/builtins/pi-agent-group.js +3 -3
  5. package/dist/builtins/pi-agent-group.js.map +1 -1
  6. package/dist/channels/adapter-entry.js +14 -14
  7. package/dist/channels/adapter-entry.js.map +1 -1
  8. package/dist/client/client.d.ts +6 -6
  9. package/dist/client/client.js +27 -27
  10. package/dist/client/client.js.map +1 -1
  11. package/dist/client/protocol.d.ts +4 -1
  12. package/dist/client/protocol.js +17 -11
  13. package/dist/client/protocol.js.map +1 -1
  14. package/dist/client/resolver.d.ts +4 -4
  15. package/dist/client/view.d.ts +1 -1
  16. package/dist/extension/index.d.ts +1 -1
  17. package/dist/extension/index.js +32 -32
  18. package/dist/extension/index.js.map +1 -1
  19. package/dist/extension/recorder.d.ts +1 -1
  20. package/dist/extension/recorder.js +1 -1
  21. package/dist/extension/recorder.js.map +1 -1
  22. package/dist/extension/remote-recorder-store.d.ts +1 -1
  23. package/dist/extension/remote-recorder-store.js +2 -2
  24. package/dist/extension/remote-recorder-store.js.map +1 -1
  25. package/dist/extension/{controller-command.d.ts → resource-manager-command.d.ts} +6 -6
  26. package/dist/extension/{controller-command.js → resource-manager-command.js} +7 -7
  27. package/dist/extension/resource-manager-command.js.map +1 -0
  28. package/dist/extension/session-delivery.d.ts +1 -1
  29. package/dist/extension/session-delivery.js +2 -2
  30. package/dist/extension/session-delivery.js.map +1 -1
  31. package/dist/extension/session-view.d.ts +1 -1
  32. package/dist/extension/session-view.js +1 -1
  33. package/dist/extension/session-view.js.map +1 -1
  34. package/dist/extension/workflow-message-coordinator.d.ts +1 -1
  35. package/dist/extension/workflow-message-coordinator.js +6 -6
  36. package/dist/extension/workflow-message-coordinator.js.map +1 -1
  37. package/dist/resource-managers/conditions.d.ts +6 -0
  38. package/dist/{controllers → resource-managers}/conditions.js +3 -3
  39. package/dist/resource-managers/conditions.js.map +1 -0
  40. package/dist/resource-managers/definition.d.ts +6 -0
  41. package/dist/resource-managers/definition.js +45 -0
  42. package/dist/resource-managers/definition.js.map +1 -0
  43. package/dist/resource-managers/effects.d.ts +15 -0
  44. package/dist/{controllers → resource-managers}/effects.js +2 -2
  45. package/dist/resource-managers/effects.js.map +1 -0
  46. package/dist/resource-managers/errors.d.ts +12 -0
  47. package/dist/resource-managers/errors.js +25 -0
  48. package/dist/resource-managers/errors.js.map +1 -0
  49. package/dist/resource-managers/index.d.ts +12 -0
  50. package/dist/resource-managers/index.js +12 -0
  51. package/dist/resource-managers/index.js.map +1 -0
  52. package/dist/resource-managers/json.js.map +1 -0
  53. package/dist/resource-managers/loader.d.ts +23 -0
  54. package/dist/resource-managers/loader.js +75 -0
  55. package/dist/resource-managers/loader.js.map +1 -0
  56. package/dist/resource-managers/results.d.ts +5 -0
  57. package/dist/resource-managers/results.js.map +1 -0
  58. package/dist/resource-managers/runtime.d.ts +59 -0
  59. package/dist/{controllers/manager.js → resource-managers/runtime.js} +57 -57
  60. package/dist/resource-managers/runtime.js.map +1 -0
  61. package/dist/{controllers → resource-managers}/sqlite.d.ts +44 -44
  62. package/dist/{controllers → resource-managers}/sqlite.js +139 -130
  63. package/dist/resource-managers/sqlite.js.map +1 -0
  64. package/dist/{controllers → resource-managers}/store.d.ts +33 -33
  65. package/dist/{controllers → resource-managers}/store.js.map +1 -1
  66. package/dist/{controllers → resource-managers}/types.d.ts +41 -41
  67. package/dist/{controllers → resource-managers}/types.js.map +1 -1
  68. package/dist/resource-managers/workflows.d.ts +34 -0
  69. package/dist/{controllers → resource-managers}/workflows.js +15 -15
  70. package/dist/resource-managers/workflows.js.map +1 -0
  71. package/dist/server/channel-effects.js.map +1 -0
  72. package/dist/{host → server}/channel-supervisor.d.ts +6 -6
  73. package/dist/{host → server}/channel-supervisor.js +3 -3
  74. package/dist/server/channel-supervisor.js.map +1 -0
  75. package/dist/{host/child-worker-supervisor.d.ts → server/child-runner-supervisor.d.ts} +15 -13
  76. package/dist/{host/child-worker-supervisor.js → server/child-runner-supervisor.js} +6 -5
  77. package/dist/server/child-runner-supervisor.js.map +1 -0
  78. package/dist/{host → server}/processes.d.ts +3 -3
  79. package/dist/{host → server}/processes.js +3 -3
  80. package/dist/server/processes.js.map +1 -0
  81. package/dist/{host → server}/resolver-entry.d.ts +6 -6
  82. package/dist/{host → server}/resolver-entry.js +14 -14
  83. package/dist/server/resolver-entry.js.map +1 -0
  84. package/dist/server/resource-runner-entry.d.ts +2 -0
  85. package/dist/{host/controller-worker-entry.js → server/resource-runner-entry.js} +33 -33
  86. package/dist/server/resource-runner-entry.js.map +1 -0
  87. package/dist/server/resource-runner-protocol.d.ts +36 -0
  88. package/dist/server/resource-runner-protocol.js +49 -0
  89. package/dist/server/resource-runner-protocol.js.map +1 -0
  90. package/dist/server/resource-runner-supervisor.d.ts +21 -0
  91. package/dist/{host/worker-supervisor.js → server/resource-runner-supervisor.js} +17 -17
  92. package/dist/server/resource-runner-supervisor.js.map +1 -0
  93. package/dist/{host → server}/rpc-bridge.d.ts +3 -3
  94. package/dist/{host → server}/rpc-bridge.js +3 -3
  95. package/dist/server/rpc-bridge.js.map +1 -0
  96. package/dist/{host → server}/rpc-executor.d.ts +1 -1
  97. package/dist/{host → server}/rpc-executor.js +3 -3
  98. package/dist/server/rpc-executor.js.map +1 -0
  99. package/dist/{host/host-entry.js → server/server-entry.js} +6 -6
  100. package/dist/server/server-entry.js.map +1 -0
  101. package/dist/{host/runner.d.ts → server/server.d.ts} +39 -38
  102. package/dist/{host/runner.js → server/server.js} +408 -374
  103. package/dist/server/server.js.map +1 -0
  104. package/dist/{host → server}/state.d.ts +25 -25
  105. package/dist/{host → server}/state.js +49 -49
  106. package/dist/server/state.js.map +1 -0
  107. package/dist/{host → server}/view.d.ts +7 -7
  108. package/dist/{host → server}/view.js +13 -13
  109. package/dist/server/view.js.map +1 -0
  110. package/dist/server/workflow-runner-content.d.ts +6 -0
  111. package/dist/server/workflow-runner-content.js +96 -0
  112. package/dist/server/workflow-runner-content.js.map +1 -0
  113. package/dist/{host/worker-entry.d.ts → server/workflow-runner-entry.d.ts} +3 -3
  114. package/dist/{host/worker-entry.js → server/workflow-runner-entry.js} +68 -35
  115. package/dist/server/workflow-runner-entry.js.map +1 -0
  116. package/dist/server/workflow-runner-protocol.d.ts +69 -0
  117. package/dist/server/workflow-runner-protocol.js +176 -0
  118. package/dist/server/workflow-runner-protocol.js.map +1 -0
  119. package/dist/{host/worker-store.d.ts → server/workflow-runner-store.d.ts} +11 -11
  120. package/dist/{host/worker-store.js → server/workflow-runner-store.js} +8 -8
  121. package/dist/server/workflow-runner-store.js.map +1 -0
  122. package/dist/server/workflow-runner-supervisor.d.ts +22 -0
  123. package/dist/server/workflow-runner-supervisor.js +56 -0
  124. package/dist/server/workflow-runner-supervisor.js.map +1 -0
  125. package/dist/state/prune.d.ts +1 -1
  126. package/dist/state/prune.js +17 -10
  127. package/dist/state/prune.js.map +1 -1
  128. package/dist/state/schema.js +2 -2
  129. package/dist/state/workflow-messages.d.ts +1 -1
  130. package/dist/state/workflow-messages.js +1 -1
  131. package/dist/state/workflow-messages.js.map +1 -1
  132. package/dist/viewer/backup.js +1 -1
  133. package/dist/viewer/backup.js.map +1 -1
  134. package/dist/viewer/cli.d.ts +2 -2
  135. package/dist/viewer/cli.js +46 -32
  136. package/dist/viewer/cli.js.map +1 -1
  137. package/dist/viewer/tui.d.ts +1 -1
  138. package/dist/viewer/tui.js +1 -1
  139. package/dist/viewer/tui.js.map +1 -1
  140. package/dist/workflows/command-batch.js +2 -2
  141. package/dist/workflows/engine.js +14 -15
  142. package/dist/workflows/engine.js.map +1 -1
  143. package/dist/workflows/store.d.ts +12 -11
  144. package/dist/workflows/store.js +24 -18
  145. package/dist/workflows/store.js.map +1 -1
  146. package/dist/workflows/types.d.ts +2 -2
  147. package/docs/2026-08-20-durable-workflow-launch-plan.md +12 -12
  148. package/docs/2026-08-25-workflow-follow-ups.md +7 -7
  149. package/docs/2026-08-25-workflow-settings.md +3 -3
  150. package/docs/2026-08-30-out-of-process-workflow-host-plan.md +3 -3
  151. package/docs/2026-09-01-restore-session-delivery-controls-plan.md +5 -5
  152. package/docs/2026-09-01-unified-workflow-client-plan.md +6 -6
  153. package/docs/2026-09-02-installed-live-e2e-plan.md +3 -3
  154. package/docs/2026-09-02-unify-workflow-messages-plan.md +8 -8
  155. package/docs/2026-09-04-workflow-run-state-plan.md +6 -6
  156. package/docs/DEFERRED_TURNS.md +7 -7
  157. package/docs/DESIGN_PHILOSOPHY.md +1 -1
  158. package/docs/HUMAN_DECISIONS.md +11 -11
  159. package/docs/HUMAN_DECISION_PRESENTATIONS.md +4 -4
  160. package/docs/MONITOR.md +1 -1
  161. package/docs/RESOURCE_MANAGERS.md +221 -0
  162. package/docs/SQLITE_STATE.md +35 -33
  163. package/docs/WORKFLOW_COMPOSITION.md +1 -1
  164. package/docs/{WORKFLOW_HOST.md → WORKFLOW_SERVER.md} +125 -119
  165. package/docs/WORKFLOW_STEP_MESSAGES.md +18 -18
  166. package/docs/WORKFLOW_UPDATES.md +16 -16
  167. package/docs/development.md +15 -14
  168. package/docs/live-replay-protocol.md +20 -20
  169. package/docs/plans/2026-08-04-controller-runtime-plan.md +25 -25
  170. package/docs/plans/2026-08-05-always-on-workflows-plan.md +8 -8
  171. package/docs/plans/2026-08-10-agent-managed-monitor-workflows-plan.md +2 -2
  172. package/docs/plans/2026-08-13-session-addressed-workflow-notifications-plan.md +1 -1
  173. package/docs/plans/2026-08-16-workflow-updates-plan.md +5 -5
  174. package/docs/plans/2026-08-19-human-decision-gates-plan.md +1 -1
  175. package/docs/plans/2026-08-20-bounded-command-batches-plan.md +1 -1
  176. package/docs/plans/2026-08-21-deferred-turn-intents-plan.md +3 -3
  177. package/docs/plans/2026-08-21-sanity-check-plan.md +2 -2
  178. package/docs/plans/2026-08-23-assistant-agent-completion-plan.md +5 -5
  179. package/docs/plans/2026-08-23-sqlite-state-plan.md +25 -25
  180. package/docs/plans/2026-08-25-live-workflow-settings-plan.md +4 -4
  181. package/docs/plans/2026-08-27-workflow-terminal-restart-plan.md +3 -3
  182. package/docs/plans/2026-09-04-workflow-runner-resume-state-plan.md +318 -0
  183. package/docs/plans/piw-viewer-experience-implementation-plan.md +1 -1
  184. package/docs/tui-viewer.md +9 -9
  185. package/docs/workflows.md +72 -66
  186. package/examples/{controllers/pull-request.controller.ts → resource-managers/pull-request.resource-manager.ts} +12 -12
  187. package/herdr-plugin.toml +1 -1
  188. package/package.json +5 -5
  189. package/protocol/client.v1.schema.json +7 -7
  190. package/protocol/fixtures/client-v1.json +1 -1
  191. package/src/builtins/monitor.workflow.ts +9 -9
  192. package/src/builtins/pi-agent-group.ts +3 -3
  193. package/src/channels/adapter-entry.ts +14 -14
  194. package/src/client/client.ts +33 -32
  195. package/src/client/protocol.ts +16 -11
  196. package/src/client/resolver.ts +4 -4
  197. package/src/client/view.ts +1 -1
  198. package/src/extension/index.ts +44 -34
  199. package/src/extension/recorder.ts +1 -1
  200. package/src/extension/remote-recorder-store.ts +2 -2
  201. package/src/extension/resource-manager-command.ts +45 -0
  202. package/src/extension/session-delivery.ts +2 -2
  203. package/src/extension/session-view.ts +1 -1
  204. package/src/extension/workflow-message-coordinator.ts +6 -6
  205. package/src/{controllers → resource-managers}/conditions.ts +23 -23
  206. package/src/resource-managers/definition.ts +71 -0
  207. package/src/{controllers → resource-managers}/effects.ts +9 -9
  208. package/src/resource-managers/errors.ts +27 -0
  209. package/src/resource-managers/index.ts +88 -0
  210. package/src/resource-managers/loader.ts +111 -0
  211. package/src/{controllers → resource-managers}/results.ts +4 -4
  212. package/src/{controllers/manager.ts → resource-managers/runtime.ts} +95 -92
  213. package/src/{controllers → resource-managers}/sqlite.ts +198 -186
  214. package/src/{controllers → resource-managers}/store.ts +46 -38
  215. package/src/{controllers → resource-managers}/types.ts +50 -41
  216. package/src/{controllers → resource-managers}/workflows.ts +43 -41
  217. package/src/{host → server}/channel-supervisor.ts +8 -8
  218. package/src/{host/child-worker-supervisor.ts → server/child-runner-supervisor.ts} +22 -18
  219. package/src/{host → server}/processes.ts +3 -3
  220. package/src/{host → server}/resolver-entry.ts +28 -25
  221. package/src/{host/controller-worker-entry.ts → server/resource-runner-entry.ts} +67 -65
  222. package/src/server/resource-runner-protocol.ts +103 -0
  223. package/src/server/resource-runner-supervisor.ts +76 -0
  224. package/src/{host → server}/rpc-bridge.ts +3 -3
  225. package/src/{host → server}/rpc-executor.ts +4 -4
  226. package/src/{host/host-entry.ts → server/server-entry.ts} +5 -5
  227. package/src/{host/runner.ts → server/server.ts} +526 -461
  228. package/src/{host → server}/state.ts +78 -67
  229. package/src/{host → server}/view.ts +15 -15
  230. package/src/server/workflow-runner-content.ts +119 -0
  231. package/src/{host/worker-entry.ts → server/workflow-runner-entry.ts} +98 -57
  232. package/src/server/workflow-runner-protocol.ts +241 -0
  233. package/src/{host/worker-store.ts → server/workflow-runner-store.ts} +18 -20
  234. package/src/server/workflow-runner-supervisor.ts +79 -0
  235. package/src/state/prune.ts +27 -9
  236. package/src/state/schema.ts +2 -2
  237. package/src/state/workflow-messages.ts +1 -1
  238. package/src/viewer/backup.ts +1 -1
  239. package/src/viewer/cli.ts +50 -36
  240. package/src/viewer/tui.ts +1 -1
  241. package/src/workflows/command-batch.ts +2 -2
  242. package/src/workflows/engine.ts +14 -15
  243. package/src/workflows/store.ts +31 -28
  244. package/src/workflows/types.ts +2 -2
  245. package/dist/controllers/conditions.d.ts +0 -6
  246. package/dist/controllers/conditions.js.map +0 -1
  247. package/dist/controllers/definition.d.ts +0 -6
  248. package/dist/controllers/definition.js +0 -45
  249. package/dist/controllers/definition.js.map +0 -1
  250. package/dist/controllers/effects.d.ts +0 -15
  251. package/dist/controllers/effects.js.map +0 -1
  252. package/dist/controllers/errors.d.ts +0 -12
  253. package/dist/controllers/errors.js +0 -25
  254. package/dist/controllers/errors.js.map +0 -1
  255. package/dist/controllers/index.d.ts +0 -12
  256. package/dist/controllers/index.js +0 -12
  257. package/dist/controllers/index.js.map +0 -1
  258. package/dist/controllers/json.js.map +0 -1
  259. package/dist/controllers/loader.d.ts +0 -23
  260. package/dist/controllers/loader.js +0 -74
  261. package/dist/controllers/loader.js.map +0 -1
  262. package/dist/controllers/manager.d.ts +0 -59
  263. package/dist/controllers/manager.js.map +0 -1
  264. package/dist/controllers/results.d.ts +0 -5
  265. package/dist/controllers/results.js.map +0 -1
  266. package/dist/controllers/sqlite.js.map +0 -1
  267. package/dist/controllers/workflows.d.ts +0 -34
  268. package/dist/controllers/workflows.js.map +0 -1
  269. package/dist/extension/controller-command.js.map +0 -1
  270. package/dist/host/channel-effects.js.map +0 -1
  271. package/dist/host/channel-supervisor.js.map +0 -1
  272. package/dist/host/child-worker-supervisor.js.map +0 -1
  273. package/dist/host/controller-worker-entry.d.ts +0 -2
  274. package/dist/host/controller-worker-entry.js.map +0 -1
  275. package/dist/host/controller-worker-protocol.d.ts +0 -36
  276. package/dist/host/controller-worker-protocol.js +0 -49
  277. package/dist/host/controller-worker-protocol.js.map +0 -1
  278. package/dist/host/controller-worker-supervisor.d.ts +0 -21
  279. package/dist/host/controller-worker-supervisor.js +0 -54
  280. package/dist/host/controller-worker-supervisor.js.map +0 -1
  281. package/dist/host/host-entry.js.map +0 -1
  282. package/dist/host/processes.js.map +0 -1
  283. package/dist/host/resolver-entry.js.map +0 -1
  284. package/dist/host/rpc-bridge.js.map +0 -1
  285. package/dist/host/rpc-executor.js.map +0 -1
  286. package/dist/host/runner.js.map +0 -1
  287. package/dist/host/state.js.map +0 -1
  288. package/dist/host/view.js.map +0 -1
  289. package/dist/host/worker-entry.js.map +0 -1
  290. package/dist/host/worker-protocol.d.ts +0 -46
  291. package/dist/host/worker-protocol.js +0 -122
  292. package/dist/host/worker-protocol.js.map +0 -1
  293. package/dist/host/worker-store.js.map +0 -1
  294. package/dist/host/worker-supervisor.d.ts +0 -22
  295. package/dist/host/worker-supervisor.js.map +0 -1
  296. package/docs/CONTROLLERS.md +0 -217
  297. package/src/controllers/definition.ts +0 -65
  298. package/src/controllers/errors.ts +0 -27
  299. package/src/controllers/index.ts +0 -88
  300. package/src/controllers/loader.ts +0 -104
  301. package/src/extension/controller-command.ts +0 -45
  302. package/src/host/controller-worker-protocol.ts +0 -104
  303. package/src/host/controller-worker-supervisor.ts +0 -79
  304. package/src/host/worker-protocol.ts +0 -176
  305. package/src/host/worker-supervisor.ts +0 -74
  306. /package/dist/{controllers → resource-managers}/json.d.ts +0 -0
  307. /package/dist/{controllers → resource-managers}/json.js +0 -0
  308. /package/dist/{controllers → resource-managers}/results.js +0 -0
  309. /package/dist/{controllers → resource-managers}/store.js +0 -0
  310. /package/dist/{controllers → resource-managers}/types.js +0 -0
  311. /package/dist/{host → server}/channel-effects.d.ts +0 -0
  312. /package/dist/{host → server}/channel-effects.js +0 -0
  313. /package/dist/{host/host-entry.d.ts → server/server-entry.d.ts} +0 -0
  314. /package/src/{controllers → resource-managers}/json.ts +0 -0
  315. /package/src/{host → server}/channel-effects.ts +0 -0
@@ -0,0 +1,79 @@
1
+ import fs from "node:fs";
2
+ import { createRequire } from "node:module";
3
+ import { fileURLToPath } from "node:url";
4
+ import { canonicalJson } from "../state/json.js";
5
+ import { ChildRunnerSupervisor, type SupervisedRunnerResult } from "./child-runner-supervisor.js";
6
+ import { ServerProcessRegistry, type ProcessIdentity } from "./processes.js";
7
+ import type { WorkflowRunnerLaunchEnvelope, RunnerOutcome } from "./state.js";
8
+ import {
9
+ MAX_WORKFLOW_RUNNER_PROTOCOL_MESSAGE_BYTES,
10
+ encodeRunnerLine,
11
+ parseRunnerMessage,
12
+ type WorkflowRunnerMessage,
13
+ type WorkflowRunnerResponse,
14
+ } from "./workflow-runner-protocol.js";
15
+
16
+ export type WorkflowRunnerResult = SupervisedRunnerResult;
17
+
18
+ export class WorkflowRunnerSupervisor {
19
+ private readonly supervisor: ChildRunnerSupervisor<WorkflowRunnerMessage, WorkflowRunnerResponse>;
20
+
21
+ constructor(
22
+ readonly envelope: WorkflowRunnerLaunchEnvelope,
23
+ private readonly options: {
24
+ registry: ServerProcessRegistry;
25
+ onMessage: (message: WorkflowRunnerMessage) => Promise<WorkflowRunnerResponse>;
26
+ env?: Record<string, string>;
27
+ startupTimeoutMs?: number;
28
+ runnerEntryPath?: string;
29
+ onSpawn?: (identity: ProcessIdentity) => void;
30
+ onDiagnostic?: (message: string) => void;
31
+ },
32
+ ) {
33
+ this.supervisor = new ChildRunnerSupervisor({
34
+ label: "Workflow runner",
35
+ registry: options.registry,
36
+ onMessage: options.onMessage,
37
+ parseMessage: parseRunnerMessage,
38
+ encodeResponse: encodeRunnerLine,
39
+ isReady: (message) => message.kind === "runner.ready",
40
+ isTerminal: (message) => message.kind === "runner.exiting",
41
+ maxMessageBytes: MAX_WORKFLOW_RUNNER_PROTOCOL_MESSAGE_BYTES,
42
+ oversizedMessage: "Runner protocol message exceeds 1 MiB",
43
+ ...(options.startupTimeoutMs === undefined
44
+ ? {}
45
+ : { startupTimeoutMs: options.startupTimeoutMs }),
46
+ ...(options.onSpawn === undefined ? {} : { onSpawn: options.onSpawn }),
47
+ ...(options.onDiagnostic === undefined ? {} : { onDiagnostic: options.onDiagnostic }),
48
+ });
49
+ }
50
+
51
+ async start(): Promise<void> {
52
+ const builtEntry = fileURLToPath(new URL("./workflow-runner-entry.js", import.meta.url));
53
+ const sourceEntry = fileURLToPath(new URL("./workflow-runner-entry.ts", import.meta.url));
54
+ const runnerEntry = this.options.runnerEntryPath ?? builtEntry;
55
+ const args =
56
+ this.options.runnerEntryPath === undefined && !fs.existsSync(builtEntry)
57
+ ? ["--import", createRequire(import.meta.url).resolve("tsx"), sourceEntry]
58
+ : [runnerEntry];
59
+ await this.supervisor.start({
60
+ args,
61
+ cwd: this.envelope.projectPath,
62
+ env: {
63
+ ...process.env,
64
+ ...this.options.env,
65
+ PI_WORKFLOWS_WORKFLOW_RUNNER_LAUNCH: Buffer.from(canonicalJson(this.envelope)).toString(
66
+ "base64url",
67
+ ),
68
+ },
69
+ });
70
+ }
71
+
72
+ async wait(): Promise<WorkflowRunnerResult> {
73
+ return await this.supervisor.wait();
74
+ }
75
+
76
+ async stop(outcome: RunnerOutcome = "cancelled"): Promise<void> {
77
+ await this.supervisor.stop(outcome);
78
+ }
79
+ }
@@ -48,6 +48,7 @@ export async function pruneState(
48
48
  state: StateDatabase,
49
49
  databasePath: string,
50
50
  options: StatePruneOptions,
51
+ activeBlobHashes: () => readonly Buffer[] = () => [],
51
52
  ): Promise<StatePruneReport> {
52
53
  validateStatePruneOptions(options);
53
54
  const cutoff = parseCutoff(options.before);
@@ -114,8 +115,9 @@ export async function pruneState(
114
115
  )`,
115
116
  )
116
117
  .run();
117
- const blobStats = unreferencedBlobStats(state.connection);
118
- deleteUnreferencedBlobs(state.connection);
118
+ const retainedBlobHashes = activeBlobHashes();
119
+ const blobStats = unreferencedBlobStats(state.connection, retainedBlobHashes);
120
+ deleteUnreferencedBlobs(state.connection, retainedBlobHashes);
119
121
  deletedRows = totalChanges(state.connection) - beforeChanges;
120
122
  deletedBlobs = blobStats.count;
121
123
  deletedBlobBytes = blobStats.bytes;
@@ -356,21 +358,31 @@ function selectionSignature(database: Database.Database, runIds: string[]): stri
356
358
  return JSON.stringify([resourceRows, queueRows]);
357
359
  }
358
360
 
359
- function unreferencedBlobStats(database: Database.Database): { count: number; bytes: number } {
360
- const predicate = blobReferencePredicate(database);
361
+ function unreferencedBlobStats(
362
+ database: Database.Database,
363
+ retainedBlobHashes: readonly Buffer[],
364
+ ): { count: number; bytes: number } {
365
+ const predicate = blobReferencePredicate(database, retainedBlobHashes.length);
361
366
  const row = database
362
367
  .prepare(
363
368
  `SELECT count(*) AS count, COALESCE(sum(byte_length), 0) AS bytes FROM blobs WHERE ${predicate}`,
364
369
  )
365
- .get();
370
+ .get(...retainedBlobHashes);
366
371
  return isBlobStatsRow(row) ? row : { count: 0, bytes: 0 };
367
372
  }
368
373
 
369
- function deleteUnreferencedBlobs(database: Database.Database): void {
370
- database.prepare(`DELETE FROM blobs WHERE ${blobReferencePredicate(database)}`).run();
374
+ function deleteUnreferencedBlobs(
375
+ database: Database.Database,
376
+ retainedBlobHashes: readonly Buffer[],
377
+ ): void {
378
+ database
379
+ .prepare(
380
+ `DELETE FROM blobs WHERE ${blobReferencePredicate(database, retainedBlobHashes.length)}`,
381
+ )
382
+ .run(...retainedBlobHashes);
371
383
  }
372
384
 
373
- function blobReferencePredicate(database: Database.Database): string {
385
+ function blobReferencePredicate(database: Database.Database, retainedBlobCount: number): string {
374
386
  const tables = database
375
387
  .prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'")
376
388
  .all()
@@ -387,7 +399,13 @@ function blobReferencePredicate(database: Database.Database): string {
387
399
  );
388
400
  }
389
401
  }
390
- return references.length === 0 ? "1 = 1" : `blob_hash NOT IN (${references.join(" UNION ")})`;
402
+ const unreferenced =
403
+ references.length === 0 ? "1 = 1" : `blob_hash NOT IN (${references.join(" UNION ")})`;
404
+ if (retainedBlobCount === 0) return unreferenced;
405
+ const retainedPlaceholders = placeholders(
406
+ Array.from({ length: retainedBlobCount }, () => undefined),
407
+ );
408
+ return `${unreferenced} AND blob_hash NOT IN (${retainedPlaceholders})`;
391
409
  }
392
410
 
393
411
  function descendants(root: string, children: Map<string, string[]>): string[] {
@@ -302,8 +302,8 @@ CREATE TABLE host_commands (
302
302
  'workflowMessage.reportBranch', 'workflowTurn.report', 'sessionView.clearTerminal',
303
303
  'run.restart', 'run.changeSettings', 'followUp.queue', 'followUp.remove', 'session.record',
304
304
  'channel.reload', 'channel.recover',
305
- 'controller.list', 'controller.get', 'controller.apply', 'controller.reconcile', 'controller.delete',
306
- 'host.status', 'host.stop', 'state.backup', 'state.prune'
305
+ 'resourceManager.list', 'resourceManager.get', 'resourceManager.apply', 'resourceManager.reconcile', 'resourceManager.delete',
306
+ 'server.status', 'server.stop', 'state.backup', 'state.prune'
307
307
  )),
308
308
  idempotency_key TEXT NOT NULL,
309
309
  request_fingerprint BLOB NOT NULL CHECK (length(request_fingerprint) = 32),
@@ -92,7 +92,7 @@ type WorkflowTurnRow = {
92
92
  endedAt: number | null;
93
93
  };
94
94
 
95
- /** Durable workflow content that the host requires Pi to add to one origin session. */
95
+ /** Durable workflow content that the server requires Pi to add to one origin session. */
96
96
  export class WorkflowMessageStore {
97
97
  constructor(readonly state: StateDatabase) {}
98
98
 
@@ -10,7 +10,7 @@ export function verifyInactiveBackup(
10
10
  const resolved = path.resolve(databasePath);
11
11
  const active = path.resolve(activeDatabasePath);
12
12
  if (sameFile(resolved, active)) {
13
- throw new Error("Active workflow state must be verified through the workflow host");
13
+ throw new Error("Active workflow state must be verified through the workflow server");
14
14
  }
15
15
  const state = new StateDatabase({ filePath: resolved, mode: "read-only" });
16
16
  try {
package/src/viewer/cli.ts CHANGED
@@ -12,35 +12,35 @@ import { renderClientView, runViewer } from "./tui.js";
12
12
 
13
13
  const CLI_CLIENT_ID = "pi-workflows-cli";
14
14
 
15
- const USAGE = `pi-workflows — workflow runs and controller resources
15
+ const USAGE = `pi-workflows — workflow runs and managed resources
16
16
 
17
17
  Usage:
18
18
  pi-workflows view [runId] [--once]
19
19
  pi-workflows runs
20
- pi-workflows controllers
21
- pi-workflows controller <controller> <key>
20
+ pi-workflows resource-managers
21
+ pi-workflows resource-manager <resource-manager> <key>
22
22
  pi-workflows state status
23
23
  pi-workflows state verify [inactive-backup]
24
24
  pi-workflows state backup <destination>
25
25
  pi-workflows state prune --before <timestamp> --dry-run
26
26
  pi-workflows state prune --before <timestamp> --backup <absolute-path> --apply
27
- pi-workflows host start
28
- pi-workflows host status
29
- pi-workflows host stop
30
- pi-workflows host run [-- <extra pi args>]
27
+ pi-workflows server start
28
+ pi-workflows server status
29
+ pi-workflows server stop
30
+ pi-workflows server run [-- <extra pi args>]
31
31
  pi-workflows herdr sync [--json]
32
32
  pi-workflows herdr setup [--json]
33
33
 
34
- Active state is available only through the package-owned workflow host.
34
+ Active state is available only through the package-owned workflow server.
35
35
  `;
36
36
 
37
37
  export type CliArgs = {
38
38
  command: string;
39
39
  runId?: string;
40
- controllerName?: string;
40
+ resourceManagerName?: string;
41
41
  resourceKey?: string;
42
42
  herdrAction?: string;
43
- hostAction?: "start" | "status" | "stop" | "run";
43
+ serverAction?: "start" | "status" | "stop" | "run";
44
44
  stateAction?: "status" | "verify" | "backup" | "prune";
45
45
  backupDestination?: string;
46
46
  verifyBackup?: string;
@@ -55,9 +55,16 @@ export function parseCliArgs(argv: string[]): CliArgs {
55
55
  const args = [...argv];
56
56
  const command = args[0] && !args[0].startsWith("-") ? (args.shift() as string) : "view";
57
57
  if (
58
- !["view", "runs", "controllers", "controller", "state", "host", "herdr", "help"].includes(
59
- command,
60
- )
58
+ ![
59
+ "view",
60
+ "runs",
61
+ "resource-managers",
62
+ "resource-manager",
63
+ "state",
64
+ "server",
65
+ "herdr",
66
+ "help",
67
+ ].includes(command)
61
68
  ) {
62
69
  throw new Error(`Unknown command: ${command}`);
63
70
  }
@@ -87,23 +94,24 @@ export function parseCliArgs(argv: string[]): CliArgs {
87
94
  }
88
95
 
89
96
  if (command !== "herdr" && json) throw new Error("--json is available only for herdr sync");
90
- if (command === "host") {
91
- if (project !== undefined) throw new Error("The global host does not accept --project");
97
+ if (command === "server") {
98
+ if (project !== undefined) throw new Error("The global server does not accept --project");
92
99
  const action = positionals[0];
93
100
  if (action !== "start" && action !== "status" && action !== "stop" && action !== "run") {
94
- throw new Error("host requires start, status, stop, or run");
101
+ throw new Error("server requires start, status, stop, or run");
95
102
  }
96
- if (positionals.length !== 1) throw new Error("host accepts one lifecycle action");
103
+ if (positionals.length !== 1) throw new Error("server accepts one lifecycle action");
97
104
  if (piArgs.length > 0 && action !== "run") {
98
- throw new Error("Extra Pi arguments are available only for host run");
105
+ throw new Error("Extra Pi arguments are available only for server run");
99
106
  }
100
- return { command, hostAction: action, once, json, piArgs };
107
+ return { command, serverAction: action, once, json, piArgs };
101
108
  }
102
- if (command === "controller") {
103
- if (positionals.length !== 2) throw new Error("controller requires <controller> and <key>");
109
+ if (command === "resource-manager") {
110
+ if (positionals.length !== 2)
111
+ throw new Error("resource-manager requires <resource-manager> and <key>");
104
112
  return {
105
113
  command,
106
- controllerName: positionals[0] as string,
114
+ resourceManagerName: positionals[0] as string,
107
115
  resourceKey: positionals[1] as string,
108
116
  once,
109
117
  json,
@@ -188,8 +196,8 @@ export async function main(argv = process.argv.slice(2)): Promise<number> {
188
196
  }
189
197
 
190
198
  try {
191
- if (args.command === "host") {
192
- return await runHost(args.hostAction as "start" | "status" | "stop" | "run", args.piArgs);
199
+ if (args.command === "server") {
200
+ return await runServer(args.serverAction as "start" | "status" | "stop" | "run", args.piArgs);
193
201
  }
194
202
  if (args.command === "herdr") {
195
203
  const result = syncHerdrPlugin(packageRoot());
@@ -223,13 +231,17 @@ export async function main(argv = process.argv.slice(2)): Promise<number> {
223
231
  printJsonLines(runs);
224
232
  return 0;
225
233
  }
226
- if (args.command === "controllers" || args.command === "controller") {
234
+ if (args.command === "resource-managers" || args.command === "resource-manager") {
227
235
  const response = await client.request({
228
- operation: args.command === "controllers" ? "controller.list" : "controller.get",
236
+ operation:
237
+ args.command === "resource-managers" ? "resourceManager.list" : "resourceManager.get",
229
238
  payload: {
230
239
  projectPath: process.cwd(),
231
- ...(args.command === "controller"
232
- ? { controller: args.controllerName as string, key: args.resourceKey as string }
240
+ ...(args.command === "resource-manager"
241
+ ? {
242
+ resourceManager: args.resourceManagerName as string,
243
+ key: args.resourceKey as string,
244
+ }
233
245
  : {}),
234
246
  },
235
247
  });
@@ -298,19 +310,19 @@ async function runStateCommand(client: WorkflowClient, args: CliArgs): Promise<v
298
310
  process.stdout.write(`${JSON.stringify(response.receipt ?? {})}\n`);
299
311
  }
300
312
 
301
- async function runHost(
313
+ async function runServer(
302
314
  action: "start" | "status" | "stop" | "run",
303
315
  piArgs: string[] | undefined,
304
316
  ): Promise<number> {
305
317
  if (action === "run") {
306
- const { WorkflowHost } = await import("../host/runner.js");
307
- const host = new WorkflowHost({
318
+ const { WorkflowServer } = await import("../server/server.js");
319
+ const server = new WorkflowServer({
308
320
  piArgs: piArgs ?? [],
309
- onLog: (message) => process.stdout.write(`[host] ${message}\n`),
321
+ onLog: (message) => process.stdout.write(`[server] ${message}\n`),
310
322
  });
311
- await host.start();
323
+ await server.start();
312
324
  await new Promise<void>((resolve) => {
313
- const shutdown = () => void host.stop().then(resolve);
325
+ const shutdown = () => void server.stop().then(resolve);
314
326
  process.once("SIGTERM", shutdown);
315
327
  process.once("SIGINT", shutdown);
316
328
  });
@@ -321,7 +333,9 @@ async function runHost(
321
333
  const response =
322
334
  action === "start"
323
335
  ? await client.ensureRunning()
324
- : await client.request({ operation: action === "status" ? "host.status" : "host.stop" });
336
+ : await client.request({
337
+ operation: action === "status" ? "server.status" : "server.stop",
338
+ });
325
339
  process.stdout.write(`${JSON.stringify(response.receipt ?? {})}\n`);
326
340
  return response.outcome === "accepted" || response.outcome === "adopted" ? 0 : 1;
327
341
  } finally {
@@ -364,7 +378,7 @@ function printJsonLines(value: JsonValue): void {
364
378
 
365
379
  function requireAccepted(response: { outcome: string; error?: string }): void {
366
380
  if (response.outcome !== "accepted" && response.outcome !== "adopted") {
367
- throw new Error(response.error ?? `Workflow host returned ${response.outcome}`);
381
+ throw new Error(response.error ?? `Workflow server returned ${response.outcome}`);
368
382
  }
369
383
  }
370
384
 
package/src/viewer/tui.ts CHANGED
@@ -13,7 +13,7 @@ export type ViewerOptions = {
13
13
  runId?: string | undefined;
14
14
  };
15
15
 
16
- /** Interactive client view. All durable reads stay in the workflow host. */
16
+ /** Interactive client view. All durable reads stay in the workflow server. */
17
17
  export async function runViewer(options: ViewerOptions): Promise<void> {
18
18
  let value: JsonValue = options.runId === undefined ? [] : null;
19
19
  let selected = 0;
@@ -117,8 +117,8 @@ export async function runCommandBatch(
117
117
  }
118
118
  };
119
119
 
120
- const workerCount = Math.min(request.maxConcurrency, total);
121
- await Promise.all(Array.from({ length: workerCount }, worker));
120
+ const runnerCount = Math.min(request.maxConcurrency, total);
121
+ await Promise.all(Array.from({ length: runnerCount }, worker));
122
122
 
123
123
  for (let index = 0; index < total; index += 1) {
124
124
  if (results[index] !== undefined) continue;
@@ -332,12 +332,11 @@ export class WorkflowEngine {
332
332
  validateWorkflowDefinition(workflow);
333
333
  this.presentationRequired = workflow.presentationPrompt !== undefined;
334
334
  // Reset before any await: a park or cancel landing during preparation
335
- // must survive, or a host drain would hang while the run executes.
335
+ // must survive, or a server drain would hang while the run executes.
336
336
  this.cancelled = false;
337
337
  this.paused = false;
338
338
  this.parked = false;
339
- const loaded = await this.store.prepareRunResume(runId);
340
- const state = loaded.state;
339
+ const state = await this.store.prepareRunResume(runId);
341
340
  const sourceMismatch = workflowIdentityMismatch(state, workflow, options.workflowSource);
342
341
  if (sourceMismatch && options.force !== true) {
343
342
  throw new WorkflowSourceChangedError(runId);
@@ -456,21 +455,21 @@ export class WorkflowEngine {
456
455
  this.cancelled = false;
457
456
  this.paused = false;
458
457
  this.parked = false;
459
- const parent = await this.store.readRun(parentRunId);
460
- if (parent === null) {
458
+ const parentState = await this.store.readRunState(parentRunId);
459
+ if (parentState === null) {
461
460
  throw new Error(`Cannot continue from unreadable workflow run: ${parentRunId}`);
462
461
  }
463
- if (parent.state.status !== "waiting" || parent.state.waitingOn === undefined) {
462
+ if (parentState.status !== "waiting" || parentState.waitingOn === undefined) {
464
463
  throw new Error(
465
- `Cannot continue workflow run ${parentRunId} with status ${parent.state.status}`,
464
+ `Cannot continue workflow run ${parentRunId} with status ${parentState.status}`,
466
465
  );
467
466
  }
468
- const sourceMismatch = workflowIdentityMismatch(parent.state, workflow, options.workflowSource);
467
+ const sourceMismatch = workflowIdentityMismatch(parentState, workflow, options.workflowSource);
469
468
  if (sourceMismatch && options.force !== true) {
470
469
  throw new WorkflowSourceChangedError(parentRunId);
471
470
  }
472
471
 
473
- const waitingNodeId = parent.state.waitingOn;
472
+ const waitingNodeId = parentState.waitingOn;
474
473
  const waitingNode = workflow.nodes[waitingNodeId];
475
474
  const humanContract =
476
475
  waitingNode?.nodeType === "checkpoint" ? waitingNode.humanDecision : undefined;
@@ -481,7 +480,7 @@ export class WorkflowEngine {
481
480
  if (options.humanDecision === undefined) {
482
481
  throw new Error(`Checkpoint ${waitingNodeId} requires an accepted verified human decision`);
483
482
  }
484
- const request = parent.state.finalOutput as HumanDecisionRequest;
483
+ const request = parentState.finalOutput as HumanDecisionRequest;
485
484
  if (
486
485
  request?.schema !== "pi-workflows.human-decision-request.v1" ||
487
486
  request.decisionId !== options.humanDecision.decisionId ||
@@ -495,7 +494,7 @@ export class WorkflowEngine {
495
494
  }
496
495
  acceptedResponse = validateHumanDecisionResponse(request, durableDecision.response);
497
496
  acceptedNodeId = request.nodeId;
498
- normalizedInput = structuredClone(parent.state.input);
497
+ normalizedInput = structuredClone(parentState.input);
499
498
  } else {
500
499
  const suppliedInput = input === undefined ? null : input;
501
500
  normalizedInput = workflow.input ? await workflow.input(suppliedInput) : suppliedInput;
@@ -512,9 +511,9 @@ export class WorkflowEngine {
512
511
  options.runId,
513
512
  );
514
513
  state.parentRunId = parentRunId;
515
- state.outputs = structuredClone(parent.state.outputs);
516
- state.results = structuredClone(parent.state.results);
517
- state.steps = structuredClone(parent.state.steps);
514
+ state.outputs = structuredClone(parentState.outputs);
515
+ state.results = structuredClone(parentState.results);
516
+ state.steps = structuredClone(parentState.steps);
518
517
  if (humanContract !== undefined && options.humanDecision !== undefined) {
519
518
  const receipt = {
520
519
  decisionId: options.humanDecision.decisionId,
@@ -557,7 +556,7 @@ export class WorkflowEngine {
557
556
  ...(state.runTitle ? { runTitle: state.runTitle } : {}),
558
557
  input: state.input,
559
558
  continuedFrom: parentRunId,
560
- checkpoint: parent.state.waitingOn,
559
+ checkpoint: parentState.waitingOn,
561
560
  carriedSteps: state.steps.length,
562
561
  },
563
562
  });
@@ -156,7 +156,7 @@ export type WorkflowRunTerminalData = {
156
156
 
157
157
  export type WorkflowRunStoreOptions = {
158
158
  authorityProvider?: (runId: string) => RunWriteAuthority | undefined;
159
- /** Host-owned projection updates that must commit with each run snapshot. */
159
+ /** Server-owned projection updates that must commit with each run snapshot. */
160
160
  snapshotLifecycle?: (context: {
161
161
  runId: string;
162
162
  state: WorkflowRunState;
@@ -164,13 +164,13 @@ export type WorkflowRunStoreOptions = {
164
164
  database: StateDatabase;
165
165
  now: number;
166
166
  }) => void;
167
- /** The global host may record an attested Pi session after the worker lease ends. */
168
- allowHostSessionRecording?: boolean;
167
+ /** The global server may record an attested Pi session after the runner lease ends. */
168
+ allowServerSessionRecording?: boolean;
169
169
  state?: StateDatabase;
170
170
  readOnly?: boolean;
171
171
  };
172
172
 
173
- /** The state boundary used by workflow code, including out-of-process workers. */
173
+ /** The state boundary used by workflow code, including out-of-process runners. */
174
174
  export interface WorkflowExecutionStore {
175
175
  readonly databasePath: string;
176
176
  initializeRun(
@@ -178,11 +178,8 @@ export interface WorkflowExecutionStore {
178
178
  state: WorkflowRunState,
179
179
  options?: InitializeWorkflowRunOptions,
180
180
  ): Promise<string>;
181
- prepareRunResume(runId: string): Promise<LoadedWorkflowRun>;
182
- readRun(
183
- runId: string,
184
- options?: ReadWorkflowRunOptions,
185
- ): LoadedWorkflowRun | null | Promise<LoadedWorkflowRun | null>;
181
+ prepareRunResume(runId: string): Promise<WorkflowRunState>;
182
+ readRunState(runId: string): WorkflowRunState | null | Promise<WorkflowRunState | null>;
186
183
  writeSnapshot(
187
184
  runId: string,
188
185
  state: WorkflowRunState,
@@ -499,7 +496,7 @@ export class WorkflowRunStore {
499
496
  | ((runId: string) => RunWriteAuthority | undefined)
500
497
  | undefined;
501
498
  private readonly snapshotLifecycle: WorkflowRunStoreOptions["snapshotLifecycle"];
502
- private readonly allowHostSessionRecording: boolean;
499
+ private readonly allowServerSessionRecording: boolean;
503
500
  private readonly contexts = new Map<string, RunContext>();
504
501
  private readonly ownsState: boolean;
505
502
  private readonly mutations: StateMutationStore;
@@ -508,7 +505,7 @@ export class WorkflowRunStore {
508
505
  constructor(databasePath: string = workflowStatePath(), options: WorkflowRunStoreOptions = {}) {
509
506
  this.authorityProvider = options.authorityProvider;
510
507
  this.snapshotLifecycle = options.snapshotLifecycle;
511
- this.allowHostSessionRecording = options.allowHostSessionRecording === true;
508
+ this.allowServerSessionRecording = options.allowServerSessionRecording === true;
512
509
  this.ownsState = options.state === undefined;
513
510
  this.state =
514
511
  options.state ??
@@ -526,7 +523,7 @@ export class WorkflowRunStore {
526
523
  if (this.ownsState) this.state.close();
527
524
  }
528
525
 
529
- /** Host-only synchronization after a queue lifecycle mutation on the run resource. */
526
+ /** Server-only synchronization after a queue lifecycle mutation on the run resource. */
530
527
  synchronizeRevision(runId: string): number {
531
528
  const revision = this.resourceRevision(runId);
532
529
  const context = this.contexts.get(runId);
@@ -1466,11 +1463,11 @@ export class WorkflowRunStore {
1466
1463
  return { runId, originSessionId, followUps };
1467
1464
  }
1468
1465
 
1469
- async prepareRunResume(runId: string): Promise<LoadedWorkflowRun> {
1470
- const loaded = this.readRun(runId, { includeTrace: true });
1471
- if (loaded === null) throw new Error(`Cannot resume unreadable workflow run: ${runId}`);
1472
- if (loaded.state.status !== "running") {
1473
- throw new Error(`Cannot resume workflow run ${runId} with status ${loaded.state.status}`);
1466
+ async prepareRunResume(runId: string): Promise<WorkflowRunState> {
1467
+ const state = this.readRunState(runId);
1468
+ if (state === null) throw new Error(`Cannot resume unreadable workflow run: ${runId}`);
1469
+ if (state.status !== "running") {
1470
+ throw new Error(`Cannot resume workflow run ${runId} with status ${state.status}`);
1474
1471
  }
1475
1472
  this.verifySettingsProjections(runId);
1476
1473
  const revision = this.resourceRevision(runId);
@@ -1498,20 +1495,20 @@ export class WorkflowRunStore {
1498
1495
  payload: {},
1499
1496
  };
1500
1497
  insertRunEvent(this.state, row.resourceId, nextRevision, at, traceEvent);
1501
- loaded.state.traceSeq = nextRevision;
1502
- loaded.state.updatedAt = at;
1503
- this.persistRunState(row, loaded.state, nextRevision, now);
1504
- recordViewerDeltas(this.state, runId, runViewerTargets(loaded.state, traceEvent), now);
1498
+ state.traceSeq = nextRevision;
1499
+ state.updatedAt = at;
1500
+ this.persistRunState(row, state, nextRevision, now);
1501
+ recordViewerDeltas(this.state, runId, runViewerTargets(state, traceEvent), now);
1505
1502
  context.revision = nextRevision;
1506
1503
  });
1507
- const prepared = this.readRun(runId, { includeTrace: true });
1504
+ const prepared = this.readRunState(runId);
1508
1505
  if (prepared === null) throw new Error(`Workflow run became unreadable: ${runId}`);
1509
1506
  return prepared;
1510
1507
  }
1511
1508
 
1512
1509
  async markRunInterrupted(
1513
1510
  runId: string,
1514
- reason = "Workflow host stopped before the run finished",
1511
+ reason = "Workflow server stopped before the run finished",
1515
1512
  ): Promise<LoadedWorkflowRun | null> {
1516
1513
  const loaded = this.readRun(runId);
1517
1514
  if (loaded === null || loaded.state.status !== "running") return loaded;
@@ -1549,7 +1546,7 @@ export class WorkflowRunStore {
1549
1546
  );
1550
1547
  }
1551
1548
 
1552
- /** Host-only synchronous form for an already serialized command transaction. */
1549
+ /** Server-only synchronous form for an already serialized command transaction. */
1553
1550
  publishUpdateSynchronous(
1554
1551
  runId: string,
1555
1552
  state: WorkflowRunState,
@@ -1765,7 +1762,7 @@ export class WorkflowRunStore {
1765
1762
  },
1766
1763
  };
1767
1764
  insertRunEvent(this.state, run.resourceId, revision, at, traceEvent);
1768
- const current = this.readRunState(run, this.readDefinition(run.definitionHash));
1765
+ const current = this.materializeRunState(run, this.readDefinition(run.definitionHash));
1769
1766
  current.traceSeq = revision;
1770
1767
  current.updatedAt = at;
1771
1768
  this.persistRunState(run, current, revision, now);
@@ -2246,11 +2243,17 @@ export class WorkflowRunStore {
2246
2243
  };
2247
2244
  }
2248
2245
 
2246
+ readRunState(runId: string): WorkflowRunState | null {
2247
+ const row = this.readRunRow(runId);
2248
+ if (row === undefined) return null;
2249
+ return this.materializeRunState(row, this.readDefinition(row.definitionHash));
2250
+ }
2251
+
2249
2252
  readRun(runId: string, options: ReadWorkflowRunOptions = {}): LoadedWorkflowRun | null {
2250
2253
  const row = this.readRunRow(runId);
2251
2254
  if (row === undefined) return null;
2252
2255
  const snapshot = this.readDefinition(row.definitionHash);
2253
- const state = this.readRunState(row, snapshot);
2256
+ const state = this.materializeRunState(row, snapshot);
2254
2257
  const segments = this.segmentRows(runId).map((segment) => this.loadSegment(segment, state));
2255
2258
  const flat = segments.find((segment) => segment.attemptId === "") ?? emptySegment();
2256
2259
  return {
@@ -2529,7 +2532,7 @@ export class WorkflowRunStore {
2529
2532
 
2530
2533
  private assertSessionWriteAuthority(runId: string): void {
2531
2534
  const run = this.requireRunRow(runId);
2532
- if (this.allowHostSessionRecording) return;
2535
+ if (this.allowServerSessionRecording) return;
2533
2536
  this.assertWriteAuthority(run, this.contextFor(runId).revision);
2534
2537
  }
2535
2538
 
@@ -3522,7 +3525,7 @@ export class WorkflowRunStore {
3522
3525
  return row;
3523
3526
  }
3524
3527
 
3525
- private readRunState(row: RunRow, snapshot: WorkflowDefinitionSnapshot): WorkflowRunState {
3528
+ private materializeRunState(row: RunRow, snapshot: WorkflowDefinitionSnapshot): WorkflowRunState {
3526
3529
  const steps = this.readSteps(row.runId);
3527
3530
  return this.buildRunState(
3528
3531
  row,
@@ -96,7 +96,7 @@ export type WorkflowProgressData = {
96
96
  export type WorkflowNodeCommon = {
97
97
  /**
98
98
  * Per-node active-execution timeout or a callback that derives it from the run context.
99
- * Waiting, paused, disconnected, and host-down origin-session time does not count.
99
+ * Waiting, paused, disconnected, and server-down origin-session time does not count.
100
100
  * Null disables the deadline. Omission falls back to the engine default (15 minutes).
101
101
  */
102
102
  timeoutMs?: number | null | ((context: WorkflowNodeContext) => MaybePromise<number | null>);
@@ -962,7 +962,7 @@ export type WorkflowEngineOptions = {
962
962
  notificationSink?: WorkflowNotificationSink;
963
963
  /** Canonical SQLite database. Defaults to `~/.pi/agent/workflows/state.sqlite`. */
964
964
  databasePath?: string;
965
- /** Durable execution store. Workers use a host-backed implementation. */
965
+ /** Durable execution store. Runners use a server-backed implementation. */
966
966
  store?: import("./store.js").WorkflowExecutionStore;
967
967
  /**
968
968
  * Awaited after `run_started` is persisted, before any node executes.
@@ -1,6 +0,0 @@
1
- import type { ControllerCondition, ControllerConditionInput, ControllerResourceStatus, ControllerStatusPatch } from "./types.js";
2
- export declare function conditionTrue(type: string, reason: string, message?: string): ControllerConditionInput;
3
- export declare function conditionFalse(type: string, reason: string, message?: string): ControllerConditionInput;
4
- export declare function conditionUnknown(type: string, reason: string, message?: string): ControllerConditionInput;
5
- export declare function applyStatusPatch<TStatus>(current: ControllerResourceStatus<TStatus>, patch: ControllerStatusPatch<TStatus> | undefined, generation: number, now: string): ControllerResourceStatus<TStatus>;
6
- export declare function mergeConditions(current: ControllerCondition[], updates: ControllerConditionInput[], generation: number, now: string): ControllerCondition[];