@osolmaz/pi-workflows 0.16.1 → 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 (327) 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 +7 -1
  16. package/dist/client/view.js +1 -0
  17. package/dist/client/view.js.map +1 -1
  18. package/dist/extension/index.d.ts +1 -1
  19. package/dist/extension/index.js +66 -47
  20. package/dist/extension/index.js.map +1 -1
  21. package/dist/extension/recorder.d.ts +1 -1
  22. package/dist/extension/recorder.js +1 -1
  23. package/dist/extension/recorder.js.map +1 -1
  24. package/dist/extension/remote-recorder-store.d.ts +1 -1
  25. package/dist/extension/remote-recorder-store.js +2 -2
  26. package/dist/extension/remote-recorder-store.js.map +1 -1
  27. package/dist/extension/{controller-command.d.ts → resource-manager-command.d.ts} +6 -6
  28. package/dist/extension/{controller-command.js → resource-manager-command.js} +7 -7
  29. package/dist/extension/resource-manager-command.js.map +1 -0
  30. package/dist/extension/session-delivery.d.ts +1 -1
  31. package/dist/extension/session-delivery.js +2 -2
  32. package/dist/extension/session-delivery.js.map +1 -1
  33. package/dist/extension/session-view.d.ts +1 -1
  34. package/dist/extension/session-view.js +1 -1
  35. package/dist/extension/session-view.js.map +1 -1
  36. package/dist/extension/workflow-message-coordinator.d.ts +4 -3
  37. package/dist/extension/workflow-message-coordinator.js +81 -29
  38. package/dist/extension/workflow-message-coordinator.js.map +1 -1
  39. package/dist/resource-managers/conditions.d.ts +6 -0
  40. package/dist/{controllers → resource-managers}/conditions.js +3 -3
  41. package/dist/resource-managers/conditions.js.map +1 -0
  42. package/dist/resource-managers/definition.d.ts +6 -0
  43. package/dist/resource-managers/definition.js +45 -0
  44. package/dist/resource-managers/definition.js.map +1 -0
  45. package/dist/resource-managers/effects.d.ts +15 -0
  46. package/dist/{controllers → resource-managers}/effects.js +2 -2
  47. package/dist/resource-managers/effects.js.map +1 -0
  48. package/dist/resource-managers/errors.d.ts +12 -0
  49. package/dist/resource-managers/errors.js +25 -0
  50. package/dist/resource-managers/errors.js.map +1 -0
  51. package/dist/resource-managers/index.d.ts +12 -0
  52. package/dist/resource-managers/index.js +12 -0
  53. package/dist/resource-managers/index.js.map +1 -0
  54. package/dist/resource-managers/json.js.map +1 -0
  55. package/dist/resource-managers/loader.d.ts +23 -0
  56. package/dist/resource-managers/loader.js +75 -0
  57. package/dist/resource-managers/loader.js.map +1 -0
  58. package/dist/resource-managers/results.d.ts +5 -0
  59. package/dist/resource-managers/results.js.map +1 -0
  60. package/dist/resource-managers/runtime.d.ts +59 -0
  61. package/dist/{controllers/manager.js → resource-managers/runtime.js} +57 -57
  62. package/dist/resource-managers/runtime.js.map +1 -0
  63. package/dist/{controllers → resource-managers}/sqlite.d.ts +51 -43
  64. package/dist/{controllers → resource-managers}/sqlite.js +187 -125
  65. package/dist/resource-managers/sqlite.js.map +1 -0
  66. package/dist/{controllers → resource-managers}/store.d.ts +33 -33
  67. package/dist/{controllers → resource-managers}/store.js.map +1 -1
  68. package/dist/{controllers → resource-managers}/types.d.ts +41 -41
  69. package/dist/{controllers → resource-managers}/types.js.map +1 -1
  70. package/dist/resource-managers/workflows.d.ts +34 -0
  71. package/dist/{controllers → resource-managers}/workflows.js +15 -15
  72. package/dist/resource-managers/workflows.js.map +1 -0
  73. package/dist/server/channel-effects.js.map +1 -0
  74. package/dist/{host → server}/channel-supervisor.d.ts +6 -6
  75. package/dist/{host → server}/channel-supervisor.js +3 -3
  76. package/dist/server/channel-supervisor.js.map +1 -0
  77. package/dist/{host/child-worker-supervisor.d.ts → server/child-runner-supervisor.d.ts} +15 -13
  78. package/dist/{host/child-worker-supervisor.js → server/child-runner-supervisor.js} +6 -5
  79. package/dist/server/child-runner-supervisor.js.map +1 -0
  80. package/dist/{host → server}/processes.d.ts +3 -3
  81. package/dist/{host → server}/processes.js +3 -3
  82. package/dist/server/processes.js.map +1 -0
  83. package/dist/{host → server}/resolver-entry.d.ts +6 -6
  84. package/dist/{host → server}/resolver-entry.js +14 -14
  85. package/dist/server/resolver-entry.js.map +1 -0
  86. package/dist/server/resource-runner-entry.d.ts +2 -0
  87. package/dist/{host/controller-worker-entry.js → server/resource-runner-entry.js} +33 -33
  88. package/dist/server/resource-runner-entry.js.map +1 -0
  89. package/dist/server/resource-runner-protocol.d.ts +36 -0
  90. package/dist/server/resource-runner-protocol.js +49 -0
  91. package/dist/server/resource-runner-protocol.js.map +1 -0
  92. package/dist/server/resource-runner-supervisor.d.ts +21 -0
  93. package/dist/{host/worker-supervisor.js → server/resource-runner-supervisor.js} +17 -17
  94. package/dist/server/resource-runner-supervisor.js.map +1 -0
  95. package/dist/{host → server}/rpc-bridge.d.ts +3 -3
  96. package/dist/{host → server}/rpc-bridge.js +3 -3
  97. package/dist/server/rpc-bridge.js.map +1 -0
  98. package/dist/{host → server}/rpc-executor.d.ts +1 -1
  99. package/dist/{host → server}/rpc-executor.js +3 -3
  100. package/dist/server/rpc-executor.js.map +1 -0
  101. package/dist/{host/host-entry.js → server/server-entry.js} +6 -6
  102. package/dist/server/server-entry.js.map +1 -0
  103. package/dist/{host/runner.d.ts → server/server.d.ts} +47 -39
  104. package/dist/{host/runner.js → server/server.js} +624 -535
  105. package/dist/server/server.js.map +1 -0
  106. package/dist/{host → server}/state.d.ts +25 -25
  107. package/dist/{host → server}/state.js +49 -49
  108. package/dist/server/state.js.map +1 -0
  109. package/dist/{host → server}/view.d.ts +7 -7
  110. package/dist/{host → server}/view.js +19 -15
  111. package/dist/server/view.js.map +1 -0
  112. package/dist/server/workflow-runner-content.d.ts +6 -0
  113. package/dist/server/workflow-runner-content.js +96 -0
  114. package/dist/server/workflow-runner-content.js.map +1 -0
  115. package/dist/server/workflow-runner-entry.d.ts +13 -0
  116. package/dist/{host/worker-entry.js → server/workflow-runner-entry.js} +89 -57
  117. package/dist/server/workflow-runner-entry.js.map +1 -0
  118. package/dist/server/workflow-runner-protocol.d.ts +69 -0
  119. package/dist/server/workflow-runner-protocol.js +176 -0
  120. package/dist/server/workflow-runner-protocol.js.map +1 -0
  121. package/dist/{host/worker-store.d.ts → server/workflow-runner-store.d.ts} +11 -11
  122. package/dist/{host/worker-store.js → server/workflow-runner-store.js} +8 -8
  123. package/dist/server/workflow-runner-store.js.map +1 -0
  124. package/dist/server/workflow-runner-supervisor.d.ts +22 -0
  125. package/dist/server/workflow-runner-supervisor.js +56 -0
  126. package/dist/server/workflow-runner-supervisor.js.map +1 -0
  127. package/dist/state/prune.d.ts +1 -1
  128. package/dist/state/prune.js +17 -10
  129. package/dist/state/prune.js.map +1 -1
  130. package/dist/state/schema.js +2 -2
  131. package/dist/state/workflow-messages.d.ts +3 -1
  132. package/dist/state/workflow-messages.js +32 -1
  133. package/dist/state/workflow-messages.js.map +1 -1
  134. package/dist/viewer/backup.js +1 -1
  135. package/dist/viewer/backup.js.map +1 -1
  136. package/dist/viewer/cli.d.ts +2 -2
  137. package/dist/viewer/cli.js +46 -32
  138. package/dist/viewer/cli.js.map +1 -1
  139. package/dist/viewer/tui.d.ts +1 -1
  140. package/dist/viewer/tui.js +1 -1
  141. package/dist/viewer/tui.js.map +1 -1
  142. package/dist/workflows/command-batch.js +2 -2
  143. package/dist/workflows/composition.js +0 -4
  144. package/dist/workflows/composition.js.map +1 -1
  145. package/dist/workflows/definition.js +0 -8
  146. package/dist/workflows/definition.js.map +1 -1
  147. package/dist/workflows/engine.js +18 -20
  148. package/dist/workflows/engine.js.map +1 -1
  149. package/dist/workflows/schema.js +0 -4
  150. package/dist/workflows/schema.js.map +1 -1
  151. package/dist/workflows/store.d.ts +27 -11
  152. package/dist/workflows/store.js +66 -18
  153. package/dist/workflows/store.js.map +1 -1
  154. package/dist/workflows/types.d.ts +3 -5
  155. package/docs/2026-08-20-durable-workflow-launch-plan.md +12 -12
  156. package/docs/2026-08-25-workflow-follow-ups.md +7 -7
  157. package/docs/2026-08-25-workflow-settings.md +3 -3
  158. package/docs/2026-08-30-out-of-process-workflow-host-plan.md +3 -3
  159. package/docs/2026-09-01-restore-session-delivery-controls-plan.md +5 -5
  160. package/docs/2026-09-01-unified-workflow-client-plan.md +6 -6
  161. package/docs/2026-09-02-installed-live-e2e-plan.md +3 -3
  162. package/docs/2026-09-02-unify-workflow-messages-plan.md +8 -8
  163. package/docs/2026-09-04-workflow-run-state-plan.md +363 -0
  164. package/docs/DEFERRED_TURNS.md +7 -7
  165. package/docs/DESIGN_PHILOSOPHY.md +1 -1
  166. package/docs/HUMAN_DECISIONS.md +11 -11
  167. package/docs/HUMAN_DECISION_PRESENTATIONS.md +4 -4
  168. package/docs/MONITOR.md +1 -1
  169. package/docs/RESOURCE_MANAGERS.md +221 -0
  170. package/docs/SQLITE_STATE.md +40 -34
  171. package/docs/WORKFLOW_COMPOSITION.md +1 -1
  172. package/docs/{WORKFLOW_HOST.md → WORKFLOW_SERVER.md} +131 -116
  173. package/docs/WORKFLOW_STEP_MESSAGES.md +18 -18
  174. package/docs/WORKFLOW_UPDATES.md +16 -16
  175. package/docs/development.md +15 -14
  176. package/docs/live-replay-protocol.md +20 -20
  177. package/docs/plans/2026-08-04-controller-runtime-plan.md +25 -25
  178. package/docs/plans/2026-08-05-always-on-workflows-plan.md +8 -8
  179. package/docs/plans/2026-08-10-agent-managed-monitor-workflows-plan.md +2 -2
  180. package/docs/plans/2026-08-13-session-addressed-workflow-notifications-plan.md +1 -1
  181. package/docs/plans/2026-08-16-workflow-updates-plan.md +5 -5
  182. package/docs/plans/2026-08-19-human-decision-gates-plan.md +1 -1
  183. package/docs/plans/2026-08-20-bounded-command-batches-plan.md +1 -1
  184. package/docs/plans/2026-08-21-deferred-turn-intents-plan.md +3 -3
  185. package/docs/plans/2026-08-21-sanity-check-plan.md +2 -2
  186. package/docs/plans/2026-08-23-assistant-agent-completion-plan.md +5 -5
  187. package/docs/plans/2026-08-23-sqlite-state-plan.md +25 -25
  188. package/docs/plans/2026-08-25-live-workflow-settings-plan.md +4 -4
  189. package/docs/plans/2026-08-27-workflow-terminal-restart-plan.md +3 -3
  190. package/docs/plans/2026-09-04-workflow-runner-resume-state-plan.md +318 -0
  191. package/docs/plans/piw-viewer-experience-implementation-plan.md +1 -1
  192. package/docs/tui-viewer.md +9 -9
  193. package/docs/workflows.md +78 -63
  194. package/examples/{controllers/pull-request.controller.ts → resource-managers/pull-request.resource-manager.ts} +12 -12
  195. package/herdr-plugin.toml +1 -1
  196. package/package.json +5 -5
  197. package/protocol/client.v1.schema.json +7 -7
  198. package/protocol/fixtures/client-v1.json +1 -1
  199. package/src/builtins/monitor.workflow.ts +9 -9
  200. package/src/builtins/pi-agent-group.ts +3 -3
  201. package/src/channels/adapter-entry.ts +14 -14
  202. package/src/client/client.ts +33 -32
  203. package/src/client/protocol.ts +16 -11
  204. package/src/client/resolver.ts +4 -4
  205. package/src/client/view.ts +9 -1
  206. package/src/extension/index.ts +81 -53
  207. package/src/extension/recorder.ts +1 -1
  208. package/src/extension/remote-recorder-store.ts +2 -2
  209. package/src/extension/resource-manager-command.ts +45 -0
  210. package/src/extension/session-delivery.ts +2 -2
  211. package/src/extension/session-view.ts +1 -1
  212. package/src/extension/workflow-message-coordinator.ts +94 -30
  213. package/src/{controllers → resource-managers}/conditions.ts +23 -23
  214. package/src/resource-managers/definition.ts +71 -0
  215. package/src/{controllers → resource-managers}/effects.ts +9 -9
  216. package/src/resource-managers/errors.ts +27 -0
  217. package/src/resource-managers/index.ts +88 -0
  218. package/src/resource-managers/loader.ts +111 -0
  219. package/src/{controllers → resource-managers}/results.ts +4 -4
  220. package/src/{controllers/manager.ts → resource-managers/runtime.ts} +95 -92
  221. package/src/{controllers → resource-managers}/sqlite.ts +275 -181
  222. package/src/{controllers → resource-managers}/store.ts +46 -38
  223. package/src/{controllers → resource-managers}/types.ts +50 -41
  224. package/src/{controllers → resource-managers}/workflows.ts +43 -41
  225. package/src/{host → server}/channel-supervisor.ts +8 -8
  226. package/src/{host/child-worker-supervisor.ts → server/child-runner-supervisor.ts} +22 -18
  227. package/src/{host → server}/processes.ts +3 -3
  228. package/src/{host → server}/resolver-entry.ts +28 -25
  229. package/src/{host/controller-worker-entry.ts → server/resource-runner-entry.ts} +67 -65
  230. package/src/server/resource-runner-protocol.ts +103 -0
  231. package/src/server/resource-runner-supervisor.ts +76 -0
  232. package/src/{host → server}/rpc-bridge.ts +3 -3
  233. package/src/{host → server}/rpc-executor.ts +4 -4
  234. package/src/{host/host-entry.ts → server/server-entry.ts} +5 -5
  235. package/src/{host/runner.ts → server/server.ts} +786 -672
  236. package/src/{host → server}/state.ts +78 -67
  237. package/src/{host → server}/view.ts +21 -17
  238. package/src/server/workflow-runner-content.ts +119 -0
  239. package/src/{host/worker-entry.ts → server/workflow-runner-entry.ts} +131 -82
  240. package/src/server/workflow-runner-protocol.ts +241 -0
  241. package/src/{host/worker-store.ts → server/workflow-runner-store.ts} +18 -20
  242. package/src/server/workflow-runner-supervisor.ts +79 -0
  243. package/src/state/prune.ts +27 -9
  244. package/src/state/schema.ts +2 -2
  245. package/src/state/workflow-messages.ts +52 -1
  246. package/src/viewer/backup.ts +1 -1
  247. package/src/viewer/cli.ts +50 -36
  248. package/src/viewer/tui.ts +1 -1
  249. package/src/workflows/command-batch.ts +2 -2
  250. package/src/workflows/composition.ts +0 -5
  251. package/src/workflows/definition.ts +0 -8
  252. package/src/workflows/engine.ts +18 -21
  253. package/src/workflows/schema.ts +0 -6
  254. package/src/workflows/store.ts +95 -28
  255. package/src/workflows/types.ts +3 -5
  256. package/dist/controllers/conditions.d.ts +0 -6
  257. package/dist/controllers/conditions.js.map +0 -1
  258. package/dist/controllers/definition.d.ts +0 -6
  259. package/dist/controllers/definition.js +0 -45
  260. package/dist/controllers/definition.js.map +0 -1
  261. package/dist/controllers/effects.d.ts +0 -15
  262. package/dist/controllers/effects.js.map +0 -1
  263. package/dist/controllers/errors.d.ts +0 -12
  264. package/dist/controllers/errors.js +0 -25
  265. package/dist/controllers/errors.js.map +0 -1
  266. package/dist/controllers/index.d.ts +0 -12
  267. package/dist/controllers/index.js +0 -12
  268. package/dist/controllers/index.js.map +0 -1
  269. package/dist/controllers/json.js.map +0 -1
  270. package/dist/controllers/loader.d.ts +0 -23
  271. package/dist/controllers/loader.js +0 -74
  272. package/dist/controllers/loader.js.map +0 -1
  273. package/dist/controllers/manager.d.ts +0 -59
  274. package/dist/controllers/manager.js.map +0 -1
  275. package/dist/controllers/results.d.ts +0 -5
  276. package/dist/controllers/results.js.map +0 -1
  277. package/dist/controllers/sqlite.js.map +0 -1
  278. package/dist/controllers/workflows.d.ts +0 -34
  279. package/dist/controllers/workflows.js.map +0 -1
  280. package/dist/extension/controller-command.js.map +0 -1
  281. package/dist/host/channel-effects.js.map +0 -1
  282. package/dist/host/channel-supervisor.js.map +0 -1
  283. package/dist/host/child-worker-supervisor.js.map +0 -1
  284. package/dist/host/controller-worker-entry.d.ts +0 -2
  285. package/dist/host/controller-worker-entry.js.map +0 -1
  286. package/dist/host/controller-worker-protocol.d.ts +0 -36
  287. package/dist/host/controller-worker-protocol.js +0 -49
  288. package/dist/host/controller-worker-protocol.js.map +0 -1
  289. package/dist/host/controller-worker-supervisor.d.ts +0 -21
  290. package/dist/host/controller-worker-supervisor.js +0 -54
  291. package/dist/host/controller-worker-supervisor.js.map +0 -1
  292. package/dist/host/host-entry.js.map +0 -1
  293. package/dist/host/processes.js.map +0 -1
  294. package/dist/host/resolver-entry.js.map +0 -1
  295. package/dist/host/rpc-bridge.js.map +0 -1
  296. package/dist/host/rpc-executor.js.map +0 -1
  297. package/dist/host/runner.js.map +0 -1
  298. package/dist/host/state.js.map +0 -1
  299. package/dist/host/view.js.map +0 -1
  300. package/dist/host/worker-entry.d.ts +0 -10
  301. package/dist/host/worker-entry.js.map +0 -1
  302. package/dist/host/worker-protocol.d.ts +0 -31
  303. package/dist/host/worker-protocol.js +0 -122
  304. package/dist/host/worker-protocol.js.map +0 -1
  305. package/dist/host/worker-store.js.map +0 -1
  306. package/dist/host/worker-supervisor.d.ts +0 -22
  307. package/dist/host/worker-supervisor.js.map +0 -1
  308. package/docs/CONTROLLERS.md +0 -217
  309. package/src/controllers/definition.ts +0 -65
  310. package/src/controllers/errors.ts +0 -27
  311. package/src/controllers/index.ts +0 -88
  312. package/src/controllers/loader.ts +0 -104
  313. package/src/extension/controller-command.ts +0 -45
  314. package/src/host/controller-worker-protocol.ts +0 -104
  315. package/src/host/controller-worker-supervisor.ts +0 -79
  316. package/src/host/worker-protocol.ts +0 -165
  317. package/src/host/worker-supervisor.ts +0 -74
  318. /package/dist/{controllers → resource-managers}/json.d.ts +0 -0
  319. /package/dist/{controllers → resource-managers}/json.js +0 -0
  320. /package/dist/{controllers → resource-managers}/results.js +0 -0
  321. /package/dist/{controllers → resource-managers}/store.js +0 -0
  322. /package/dist/{controllers → resource-managers}/types.js +0 -0
  323. /package/dist/{host → server}/channel-effects.d.ts +0 -0
  324. /package/dist/{host → server}/channel-effects.js +0 -0
  325. /package/dist/{host/host-entry.d.ts → server/server-entry.d.ts} +0 -0
  326. /package/src/{controllers → resource-managers}/json.ts +0 -0
  327. /package/src/{host → server}/channel-effects.ts +0 -0
@@ -1,16 +1,16 @@
1
1
  import type {
2
- ControllerCondition,
3
- ControllerConditionInput,
4
- ControllerConditionStatus,
5
- ControllerResourceStatus,
6
- ControllerStatusPatch,
2
+ ManagedResourceCondition,
3
+ ManagedResourceConditionInput,
4
+ ManagedResourceConditionStatus,
5
+ ManagedResourceStatus,
6
+ ResourceManagerStatusPatch,
7
7
  } from "./types.js";
8
8
 
9
9
  export function conditionTrue(
10
10
  type: string,
11
11
  reason: string,
12
12
  message?: string,
13
- ): ControllerConditionInput {
13
+ ): ManagedResourceConditionInput {
14
14
  return condition(type, true, reason, message);
15
15
  }
16
16
 
@@ -18,7 +18,7 @@ export function conditionFalse(
18
18
  type: string,
19
19
  reason: string,
20
20
  message?: string,
21
- ): ControllerConditionInput {
21
+ ): ManagedResourceConditionInput {
22
22
  return condition(type, false, reason, message);
23
23
  }
24
24
 
@@ -26,23 +26,23 @@ export function conditionUnknown(
26
26
  type: string,
27
27
  reason: string,
28
28
  message?: string,
29
- ): ControllerConditionInput {
29
+ ): ManagedResourceConditionInput {
30
30
  return condition(type, "unknown", reason, message);
31
31
  }
32
32
 
33
33
  export function applyStatusPatch<TStatus>(
34
- current: ControllerResourceStatus<TStatus>,
35
- patch: ControllerStatusPatch<TStatus> | undefined,
34
+ current: ManagedResourceStatus<TStatus>,
35
+ patch: ResourceManagerStatusPatch<TStatus> | undefined,
36
36
  generation: number,
37
37
  now: string,
38
- ): ControllerResourceStatus<TStatus> {
38
+ ): ManagedResourceStatus<TStatus> {
39
39
  return {
40
40
  observedGeneration: generation,
41
41
  conditions: mergeConditions(current.conditions, patch?.conditions ?? [], generation, now),
42
- controllerStatus:
43
- patch !== undefined && Object.hasOwn(patch, "controllerStatus")
44
- ? (patch.controllerStatus as TStatus)
45
- : current.controllerStatus,
42
+ resourceManagerStatus:
43
+ patch !== undefined && Object.hasOwn(patch, "resourceManagerStatus")
44
+ ? (patch.resourceManagerStatus as TStatus)
45
+ : current.resourceManagerStatus,
46
46
  ...(patch?.workflowRun === null
47
47
  ? {}
48
48
  : patch?.workflowRun !== undefined
@@ -54,11 +54,11 @@ export function applyStatusPatch<TStatus>(
54
54
  }
55
55
 
56
56
  export function mergeConditions(
57
- current: ControllerCondition[],
58
- updates: ControllerConditionInput[],
57
+ current: ManagedResourceCondition[],
58
+ updates: ManagedResourceConditionInput[],
59
59
  generation: number,
60
60
  now: string,
61
- ): ControllerCondition[] {
61
+ ): ManagedResourceCondition[] {
62
62
  const byType = new Map(current.map((item) => [item.type, item]));
63
63
  const seen = new Set<string>();
64
64
  for (const update of updates) {
@@ -68,7 +68,7 @@ export function mergeConditions(
68
68
  }
69
69
  seen.add(update.type);
70
70
  const previous = byType.get(update.type);
71
- const next: ControllerCondition = {
71
+ const next: ManagedResourceCondition = {
72
72
  ...update,
73
73
  observedGeneration: generation,
74
74
  lastTransitionTime:
@@ -83,11 +83,11 @@ export function mergeConditions(
83
83
 
84
84
  function condition(
85
85
  type: string,
86
- status: ControllerConditionStatus,
86
+ status: ManagedResourceConditionStatus,
87
87
  reason: string,
88
88
  message: string | undefined,
89
- ): ControllerConditionInput {
90
- const value: ControllerConditionInput = {
89
+ ): ManagedResourceConditionInput {
90
+ const value: ManagedResourceConditionInput = {
91
91
  type,
92
92
  status,
93
93
  reason,
@@ -97,7 +97,7 @@ function condition(
97
97
  return value;
98
98
  }
99
99
 
100
- function validateCondition(value: ControllerConditionInput): void {
100
+ function validateCondition(value: ManagedResourceConditionInput): void {
101
101
  if (value.type.trim().length === 0) {
102
102
  throw new Error("Condition type must not be empty");
103
103
  }
@@ -0,0 +1,71 @@
1
+ import type {
2
+ AnyResourceManagerDefinition,
3
+ ResourceManagerDefinition,
4
+ ManagedResource,
5
+ } from "./types.js";
6
+
7
+ const RESOURCE_MANAGER_DEFINITION_BRAND = Symbol.for("pi-workflows.resource-manager-definition");
8
+ const RESOURCE_MANAGER_NAME_PATTERN = /^[a-z][a-z0-9-]*$/;
9
+
10
+ export function defineResourceManager<TSpec, TStatus>(
11
+ definition: ResourceManagerDefinition<TSpec, TStatus>,
12
+ ): ResourceManagerDefinition<TSpec, TStatus> {
13
+ assertValidResourceManagerDefinition(definition);
14
+ if (isResourceManagerDefinition(definition)) {
15
+ return definition;
16
+ }
17
+ Object.defineProperty(definition, RESOURCE_MANAGER_DEFINITION_BRAND, {
18
+ value: true,
19
+ enumerable: false,
20
+ configurable: false,
21
+ writable: false,
22
+ });
23
+ return definition;
24
+ }
25
+
26
+ export function isResourceManagerDefinition(value: unknown): value is AnyResourceManagerDefinition {
27
+ return (
28
+ value !== null &&
29
+ typeof value === "object" &&
30
+ (value as Record<PropertyKey, unknown>)[RESOURCE_MANAGER_DEFINITION_BRAND] === true
31
+ );
32
+ }
33
+
34
+ export function assertValidResourceManagerDefinition<TSpec, TStatus>(
35
+ definition: ResourceManagerDefinition<TSpec, TStatus>,
36
+ ): void {
37
+ if (definition === null || typeof definition !== "object") {
38
+ throw new Error("Invalid resource manager definition: expected an object");
39
+ }
40
+ if (!RESOURCE_MANAGER_NAME_PATTERN.test(definition.name)) {
41
+ throw new Error(
42
+ `Invalid resource manager definition: name ${JSON.stringify(definition.name)} must match ${RESOURCE_MANAGER_NAME_PATTERN.source}`,
43
+ );
44
+ }
45
+ if (typeof definition.initialStatus !== "function") {
46
+ throw new Error("Invalid resource manager definition: initialStatus must be a function");
47
+ }
48
+ if (typeof definition.reconcile !== "function") {
49
+ throw new Error("Invalid resource manager definition: reconcile must be a function");
50
+ }
51
+ if (
52
+ definition.timeoutMs !== undefined &&
53
+ (!Number.isSafeInteger(definition.timeoutMs) || definition.timeoutMs <= 0)
54
+ ) {
55
+ throw new Error(
56
+ "Invalid resource manager definition: timeoutMs must be a positive safe integer",
57
+ );
58
+ }
59
+ }
60
+
61
+ export function asAnyResourceManagerDefinition<TSpec, TStatus>(
62
+ definition: ResourceManagerDefinition<TSpec, TStatus>,
63
+ ): AnyResourceManagerDefinition {
64
+ return definition as unknown as ResourceManagerDefinition<unknown, unknown>;
65
+ }
66
+
67
+ export function asTypedResource<TSpec, TStatus>(
68
+ resource: ManagedResource,
69
+ ): ManagedResource<TSpec, TStatus> {
70
+ return resource as ManagedResource<TSpec, TStatus>;
71
+ }
@@ -1,9 +1,9 @@
1
1
  import { jsonFingerprint } from "./json.js";
2
- import type { ControllerStore } from "./store.js";
2
+ import type { ResourceManagerStore } from "./store.js";
3
3
  import type {
4
- ControllerEffects,
5
- ControllerQueueClaim,
6
- ControllerResource,
4
+ ResourceManagerEffects,
5
+ ResourceManagerQueueClaim,
6
+ ManagedResource,
7
7
  EffectApplication,
8
8
  EffectDefinition,
9
9
  EffectObservation,
@@ -11,13 +11,13 @@ import type {
11
11
  JsonObject,
12
12
  } from "./types.js";
13
13
 
14
- export class ControllerEffectService implements ControllerEffects {
14
+ export class ResourceManagerEffectService implements ResourceManagerEffects {
15
15
  private used = false;
16
16
 
17
17
  constructor(
18
- private readonly store: ControllerStore,
19
- private readonly resource: ControllerResource,
20
- private readonly claim: ControllerQueueClaim,
18
+ private readonly store: ResourceManagerStore,
19
+ private readonly resource: ManagedResource,
20
+ private readonly claim: ResourceManagerQueueClaim,
21
21
  private readonly signal: AbortSignal,
22
22
  ) {}
23
23
 
@@ -115,7 +115,7 @@ export class ControllerEffectService implements ControllerEffects {
115
115
 
116
116
  private recordEvent(type: string, effectKey: string, extra: JsonObject = {}): void {
117
117
  this.store.recordEvent({
118
- controller: this.resource.metadata.controller,
118
+ resourceManager: this.resource.metadata.resourceManager,
119
119
  key: this.resource.metadata.key,
120
120
  claim: this.claim,
121
121
  type,
@@ -0,0 +1,27 @@
1
+ export class ManagedResourceConflictError extends Error {
2
+ constructor(resourceManager: string, key: string) {
3
+ super(`Managed resource ${resourceManager}/${key} changed during reconciliation`);
4
+ this.name = "ManagedResourceConflictError";
5
+ }
6
+ }
7
+
8
+ export class ManagedResourceNotFoundError extends Error {
9
+ constructor(resourceManager: string, key: string) {
10
+ super(`Managed resource not found: ${resourceManager}/${key}`);
11
+ this.name = "ManagedResourceNotFoundError";
12
+ }
13
+ }
14
+
15
+ export class EffectRequestConflictError extends Error {
16
+ constructor(key: string) {
17
+ super(`Effect key ${JSON.stringify(key)} was reused with a different request`);
18
+ this.name = "EffectRequestConflictError";
19
+ }
20
+ }
21
+
22
+ export class WorkflowRequestConflictError extends Error {
23
+ constructor(key: string) {
24
+ super(`Workflow request key ${JSON.stringify(key)} was reused with different input`);
25
+ this.name = "WorkflowRequestConflictError";
26
+ }
27
+ }
@@ -0,0 +1,88 @@
1
+ export {
2
+ assertValidResourceManagerDefinition,
3
+ defineResourceManager,
4
+ isResourceManagerDefinition,
5
+ } from "./definition.js";
6
+ export {
7
+ applyStatusPatch,
8
+ conditionFalse,
9
+ conditionTrue,
10
+ conditionUnknown,
11
+ mergeConditions,
12
+ } from "./conditions.js";
13
+ export {
14
+ EffectRequestConflictError,
15
+ ManagedResourceConflictError,
16
+ ManagedResourceNotFoundError,
17
+ WorkflowRequestConflictError,
18
+ } from "./errors.js";
19
+ export { ResourceManagerEffectService } from "./effects.js";
20
+ export { canonicalJson, jsonFingerprint } from "./json.js";
21
+ export { ResourceManagerRuntime, type ResourceManagerRuntimeOptions } from "./runtime.js";
22
+ export { createResultHelpers, requeue, requeueAfter, settled } from "./results.js";
23
+ export {
24
+ SqliteResourceManagerStore,
25
+ type RunEventRecord,
26
+ type WorkflowRunClaimOptions,
27
+ type WorkflowRunPreparationResult,
28
+ type WorkflowRunQueueRecord,
29
+ type WorkflowRunReservationOptions,
30
+ } from "./sqlite.js";
31
+ export {
32
+ type ResourceManagerStore,
33
+ type EffectReservation,
34
+ type QueueItem,
35
+ type QueueRequeueOptions,
36
+ type WorkflowRecordUpdate,
37
+ type WorkflowReservation,
38
+ } from "./store.js";
39
+ export {
40
+ resourceManagerFileStem,
41
+ resourceManagerSearchDirs,
42
+ discoverResourceManagers,
43
+ loadResourceManagerFile,
44
+ loadDiscoveredResourceManagers,
45
+ type DiscoveredResourceManager,
46
+ } from "./loader.js";
47
+ export {
48
+ ResourceManagerWorkflowCoordinator,
49
+ type ResourceManagerWorkflowControlRequest,
50
+ type ResourceManagerWorkflowScheduler,
51
+ type WorkflowSchedulerRequest,
52
+ type WorkflowSchedulerResult,
53
+ } from "./workflows.js";
54
+ export type {
55
+ AnyResourceManagerDefinition,
56
+ ChildWorkflowRecord,
57
+ ChildWorkflowReference,
58
+ ChildWorkflowRequest,
59
+ ChildWorkflowState,
60
+ ManagedResourceCondition,
61
+ ManagedResourceConditionInput,
62
+ ManagedResourceConditionStatus,
63
+ ResourceManagerDefinition,
64
+ ResourceManagerEffects,
65
+ ResourceManagerFollowUpResult,
66
+ ResourceManagerQueueFollowUpRequest,
67
+ ResourceManagerRemoveFollowUpRequest,
68
+ ResourceManagerSettingsChangeRequest,
69
+ ResourceManagerSettingsChangeResult,
70
+ ResourceManagerEvent,
71
+ ResourceManagerQueueClaim,
72
+ ManagedResource,
73
+ ManagedResourceRef,
74
+ ManagedResourceStatus,
75
+ ResourceManagerStatusPatch,
76
+ ResourceManagerWorkflows,
77
+ EffectApplication,
78
+ EffectDefinition,
79
+ EffectObservation,
80
+ EffectRecord,
81
+ EffectState,
82
+ JsonObject,
83
+ JsonPrimitive,
84
+ JsonValue,
85
+ MaybePromise,
86
+ ReconcileContext,
87
+ ReconcileResult,
88
+ } from "./types.js";
@@ -0,0 +1,111 @@
1
+ import fs from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { fileURLToPath, pathToFileURL } from "node:url";
5
+ import { createJiti } from "jiti";
6
+ import { isResourceManagerDefinition } from "./definition.js";
7
+ import type { AnyResourceManagerDefinition } from "./types.js";
8
+
9
+ const RESOURCE_MANAGER_FILE_SUFFIXES = [
10
+ ".resource-manager.ts",
11
+ ".resource-manager.js",
12
+ ".resource-manager.mts",
13
+ ".resource-manager.mjs",
14
+ ];
15
+
16
+ export type DiscoveredResourceManager = {
17
+ name: string;
18
+ path: string;
19
+ source: "project" | "global";
20
+ };
21
+
22
+ export function resourceManagerSearchDirs(options: {
23
+ cwd: string;
24
+ homeDir?: string;
25
+ }): { dir: string; source: DiscoveredResourceManager["source"] }[] {
26
+ const homeDir = options.homeDir ?? os.homedir();
27
+ return [
28
+ { dir: path.join(options.cwd, ".pi", "resource-managers"), source: "project" },
29
+ { dir: path.join(homeDir, ".pi", "agent", "resource-managers"), source: "global" },
30
+ ];
31
+ }
32
+
33
+ export function resourceManagerFileStem(filePath: string): string {
34
+ const base = path.basename(filePath);
35
+ const suffix = RESOURCE_MANAGER_FILE_SUFFIXES.find((candidate) => base.endsWith(candidate));
36
+ return suffix === undefined ? base : base.slice(0, -suffix.length);
37
+ }
38
+
39
+ const RESOURCE_MANAGER_ENTRY = path.join(path.dirname(fileURLToPath(import.meta.url)), "index");
40
+ const WORKFLOW_ENTRY = path.join(
41
+ path.dirname(fileURLToPath(import.meta.url)),
42
+ "../workflows/index",
43
+ );
44
+
45
+ export async function loadResourceManagerFile(
46
+ filePath: string,
47
+ ): Promise<AnyResourceManagerDefinition> {
48
+ const absolutePath = path.resolve(filePath);
49
+ const jiti = createJiti(pathToFileURL(absolutePath).href, {
50
+ interopDefault: true,
51
+ moduleCache: false,
52
+ alias: {
53
+ "@osolmaz/pi-workflows/resource-managers": RESOURCE_MANAGER_ENTRY,
54
+ "@osolmaz/pi-workflows": WORKFLOW_ENTRY,
55
+ },
56
+ });
57
+ const loaded = (await jiti.import(absolutePath, { default: true })) as unknown;
58
+ if (!isResourceManagerDefinition(loaded)) {
59
+ throw new Error(
60
+ `ResourceManager module must default-export defineResourceManager(...): ${absolutePath}`,
61
+ );
62
+ }
63
+ return loaded;
64
+ }
65
+
66
+ export async function discoverResourceManagers(options: {
67
+ cwd: string;
68
+ homeDir?: string;
69
+ }): Promise<DiscoveredResourceManager[]> {
70
+ const discovered: DiscoveredResourceManager[] = [];
71
+ const seen = new Set<string>();
72
+ for (const { dir, source } of resourceManagerSearchDirs(options)) {
73
+ for (const filePath of await listResourceManagerFiles(dir)) {
74
+ const name = resourceManagerFileStem(filePath);
75
+ if (seen.has(name)) {
76
+ continue;
77
+ }
78
+ seen.add(name);
79
+ discovered.push({ name, path: filePath, source });
80
+ }
81
+ }
82
+ return discovered;
83
+ }
84
+
85
+ export async function loadDiscoveredResourceManagers(options: {
86
+ cwd: string;
87
+ homeDir?: string;
88
+ }): Promise<AnyResourceManagerDefinition[]> {
89
+ return await Promise.all(
90
+ (await discoverResourceManagers(options)).map(
91
+ async (entry) => await loadResourceManagerFile(entry.path),
92
+ ),
93
+ );
94
+ }
95
+
96
+ async function listResourceManagerFiles(dir: string): Promise<string[]> {
97
+ let entries: import("node:fs").Dirent[];
98
+ try {
99
+ entries = await fs.readdir(dir, { withFileTypes: true });
100
+ } catch {
101
+ return [];
102
+ }
103
+ return entries
104
+ .filter(
105
+ (entry) =>
106
+ entry.isFile() &&
107
+ RESOURCE_MANAGER_FILE_SUFFIXES.some((suffix) => entry.name.endsWith(suffix)),
108
+ )
109
+ .map((entry) => path.join(dir, entry.name))
110
+ .sort();
111
+ }
@@ -1,4 +1,4 @@
1
- import type { ControllerStatusPatch, ReconcileContext, ReconcileResult } from "./types.js";
1
+ import type { ResourceManagerStatusPatch, ReconcileContext, ReconcileResult } from "./types.js";
2
2
 
3
3
  export function createResultHelpers<TStatus>(): Pick<
4
4
  ReconcileContext<TStatus>,
@@ -27,20 +27,20 @@ export function createResultHelpers<TStatus>(): Pick<
27
27
  }
28
28
 
29
29
  export function settled<TStatus>(
30
- status?: ControllerStatusPatch<TStatus>,
30
+ status?: ResourceManagerStatusPatch<TStatus>,
31
31
  ): ReconcileResult<TStatus> {
32
32
  return createResultHelpers<TStatus>().settled(status);
33
33
  }
34
34
 
35
35
  export function requeue<TStatus>(
36
- status?: ControllerStatusPatch<TStatus>,
36
+ status?: ResourceManagerStatusPatch<TStatus>,
37
37
  ): ReconcileResult<TStatus> {
38
38
  return createResultHelpers<TStatus>().requeue(status);
39
39
  }
40
40
 
41
41
  export function requeueAfter<TStatus>(
42
42
  afterMs: number,
43
- status?: ControllerStatusPatch<TStatus>,
43
+ status?: ResourceManagerStatusPatch<TStatus>,
44
44
  ): ReconcileResult<TStatus> {
45
45
  return createResultHelpers<TStatus>().requeueAfter(afterMs, status);
46
46
  }