@osolmaz/pi-workflows 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/README.md +107 -26
  2. package/dist/builtins/monitor.workflow.d.ts +71 -0
  3. package/dist/builtins/monitor.workflow.js +234 -0
  4. package/dist/builtins/monitor.workflow.js.map +1 -0
  5. package/dist/controllers/conditions.d.ts +6 -0
  6. package/dist/controllers/conditions.js +68 -0
  7. package/dist/controllers/conditions.js.map +1 -0
  8. package/dist/controllers/definition.d.ts +6 -0
  9. package/dist/controllers/definition.js +45 -0
  10. package/dist/controllers/definition.js.map +1 -0
  11. package/dist/controllers/effects.d.ts +14 -0
  12. package/dist/controllers/effects.js +104 -0
  13. package/dist/controllers/effects.js.map +1 -0
  14. package/dist/controllers/errors.d.ts +12 -0
  15. package/dist/controllers/errors.js +25 -0
  16. package/dist/controllers/errors.js.map +1 -0
  17. package/dist/controllers/index.d.ts +13 -0
  18. package/dist/controllers/index.js +13 -0
  19. package/dist/controllers/index.js.map +1 -0
  20. package/dist/controllers/json.d.ts +5 -0
  21. package/dist/controllers/json.js +57 -0
  22. package/dist/controllers/json.js.map +1 -0
  23. package/dist/controllers/loader.d.ts +23 -0
  24. package/dist/controllers/loader.js +74 -0
  25. package/dist/controllers/loader.js.map +1 -0
  26. package/dist/controllers/manager.d.ts +58 -0
  27. package/dist/controllers/manager.js +399 -0
  28. package/dist/controllers/manager.js.map +1 -0
  29. package/dist/controllers/results.d.ts +5 -0
  30. package/dist/controllers/results.js +32 -0
  31. package/dist/controllers/results.js.map +1 -0
  32. package/dist/controllers/sqlite.d.ts +212 -0
  33. package/dist/controllers/sqlite.js +1009 -0
  34. package/dist/controllers/sqlite.js.map +1 -0
  35. package/dist/controllers/store.d.ts +112 -0
  36. package/dist/controllers/store.js +32 -0
  37. package/dist/controllers/store.js.map +1 -0
  38. package/dist/controllers/types.d.ts +159 -0
  39. package/dist/controllers/types.js +2 -0
  40. package/dist/controllers/types.js.map +1 -0
  41. package/dist/controllers/workflow-engine-scheduler.d.ts +25 -0
  42. package/dist/controllers/workflow-engine-scheduler.js +93 -0
  43. package/dist/controllers/workflow-engine-scheduler.js.map +1 -0
  44. package/dist/controllers/workflows.d.ts +27 -0
  45. package/dist/controllers/workflows.js +109 -0
  46. package/dist/controllers/workflows.js.map +1 -0
  47. package/dist/extension/controller-host.d.ts +47 -0
  48. package/dist/extension/controller-host.js +110 -0
  49. package/dist/extension/controller-host.js.map +1 -0
  50. package/dist/extension/executor.d.ts +14 -1
  51. package/dist/extension/executor.js +12 -2
  52. package/dist/extension/executor.js.map +1 -1
  53. package/dist/extension/index.d.ts +7 -0
  54. package/dist/extension/index.js +1118 -89
  55. package/dist/extension/index.js.map +1 -1
  56. package/dist/extension/recorder.d.ts +91 -0
  57. package/dist/extension/recorder.js +537 -0
  58. package/dist/extension/recorder.js.map +1 -0
  59. package/dist/extension/session-events.d.ts +134 -0
  60. package/dist/extension/session-events.js +60 -0
  61. package/dist/extension/session-events.js.map +1 -0
  62. package/dist/extension/widget.js +25 -24
  63. package/dist/extension/widget.js.map +1 -1
  64. package/dist/extension/workflow-tool.d.ts +28 -0
  65. package/dist/extension/workflow-tool.js +33 -0
  66. package/dist/extension/workflow-tool.js.map +1 -0
  67. package/dist/host/processes.d.ts +24 -0
  68. package/dist/host/processes.js +114 -0
  69. package/dist/host/processes.js.map +1 -0
  70. package/dist/host/rpc-bridge.d.ts +9 -0
  71. package/dist/host/rpc-bridge.js +39 -0
  72. package/dist/host/rpc-bridge.js.map +1 -0
  73. package/dist/host/rpc-executor.d.ts +38 -0
  74. package/dist/host/rpc-executor.js +254 -0
  75. package/dist/host/rpc-executor.js.map +1 -0
  76. package/dist/host/runner.d.ts +49 -0
  77. package/dist/host/runner.js +350 -0
  78. package/dist/host/runner.js.map +1 -0
  79. package/dist/render/canvas.d.ts +1 -1
  80. package/dist/render/canvas.js +5 -0
  81. package/dist/render/canvas.js.map +1 -1
  82. package/dist/render/graph-render.d.ts +5 -0
  83. package/dist/render/graph-render.js +211 -48
  84. package/dist/render/graph-render.js.map +1 -1
  85. package/dist/viewer/cli.d.ts +7 -3
  86. package/dist/viewer/cli.js +150 -19
  87. package/dist/viewer/cli.js.map +1 -1
  88. package/dist/viewer/render.js +19 -3
  89. package/dist/viewer/render.js.map +1 -1
  90. package/dist/viewer/session-reducer.d.ts +45 -0
  91. package/dist/viewer/session-reducer.js +266 -0
  92. package/dist/viewer/session-reducer.js.map +1 -0
  93. package/dist/workflows/artifacts.d.ts +40 -0
  94. package/dist/workflows/artifacts.js +155 -0
  95. package/dist/workflows/artifacts.js.map +1 -0
  96. package/dist/workflows/engine.d.ts +38 -0
  97. package/dist/workflows/engine.js +281 -20
  98. package/dist/workflows/engine.js.map +1 -1
  99. package/dist/workflows/errors.d.ts +23 -0
  100. package/dist/workflows/errors.js +38 -0
  101. package/dist/workflows/errors.js.map +1 -1
  102. package/dist/workflows/graph.js +0 -5
  103. package/dist/workflows/graph.js.map +1 -1
  104. package/dist/workflows/index.d.ts +3 -2
  105. package/dist/workflows/index.js +2 -1
  106. package/dist/workflows/index.js.map +1 -1
  107. package/dist/workflows/loader.d.ts +5 -3
  108. package/dist/workflows/loader.js +10 -1
  109. package/dist/workflows/loader.js.map +1 -1
  110. package/dist/workflows/schema.js +1 -1
  111. package/dist/workflows/schema.js.map +1 -1
  112. package/dist/workflows/store.d.ts +98 -10
  113. package/dist/workflows/store.js +921 -46
  114. package/dist/workflows/store.js.map +1 -1
  115. package/dist/workflows/types.d.ts +136 -3
  116. package/docs/CONTROLLERS.md +215 -0
  117. package/docs/development.md +51 -24
  118. package/docs/live-replay-protocol.md +155 -0
  119. package/docs/plans/2026-08-04-controller-runtime-plan.md +169 -0
  120. package/docs/plans/2026-08-05-always-on-workflows-plan.md +125 -0
  121. package/docs/plans/2026-08-10-agent-managed-monitor-workflows-plan.md +184 -0
  122. package/docs/plans/piw-viewer-experience-implementation-plan.md +674 -0
  123. package/docs/plans/replayable-run-bundles-implementation-plan.md +65 -0
  124. package/docs/plans/session-event-replay-implementation-plan.md +494 -0
  125. package/docs/plans/tui-viewer-implementation-plan.md +64 -0
  126. package/docs/run-bundles.md +359 -55
  127. package/docs/session-event-journal.md +470 -0
  128. package/docs/tui-viewer.md +218 -0
  129. package/docs/workflows.md +131 -11
  130. package/examples/controllers/pull-request.controller.ts +215 -0
  131. package/package.json +11 -2
  132. package/src/builtins/monitor.workflow.ts +278 -0
  133. package/src/controllers/conditions.ts +110 -0
  134. package/src/controllers/definition.ts +65 -0
  135. package/src/controllers/effects.ts +123 -0
  136. package/src/controllers/errors.ts +27 -0
  137. package/src/controllers/index.ts +90 -0
  138. package/src/controllers/json.ts +62 -0
  139. package/src/controllers/loader.ts +104 -0
  140. package/src/controllers/manager.ts +533 -0
  141. package/src/controllers/results.ts +46 -0
  142. package/src/controllers/sqlite.ts +1427 -0
  143. package/src/controllers/store.ts +160 -0
  144. package/src/controllers/types.ts +183 -0
  145. package/src/controllers/workflow-engine-scheduler.ts +145 -0
  146. package/src/controllers/workflows.ts +152 -0
  147. package/src/extension/controller-host.ts +163 -0
  148. package/src/extension/executor.ts +29 -2
  149. package/src/extension/index.ts +1315 -109
  150. package/src/extension/recorder.ts +662 -0
  151. package/src/extension/session-events.ts +119 -0
  152. package/src/extension/widget.ts +26 -24
  153. package/src/extension/workflow-tool.ts +59 -0
  154. package/src/host/processes.ts +119 -0
  155. package/src/host/rpc-bridge.ts +44 -0
  156. package/src/host/rpc-executor.ts +299 -0
  157. package/src/host/runner.ts +406 -0
  158. package/src/render/canvas.ts +19 -1
  159. package/src/render/graph-render.ts +277 -44
  160. package/src/viewer/cli.ts +167 -21
  161. package/src/viewer/render.ts +21 -3
  162. package/src/viewer/session-reducer.ts +347 -0
  163. package/src/workflows/artifacts.ts +188 -0
  164. package/src/workflows/engine.ts +365 -19
  165. package/src/workflows/errors.ts +45 -0
  166. package/src/workflows/graph.ts +0 -5
  167. package/src/workflows/index.ts +15 -0
  168. package/src/workflows/loader.ts +13 -3
  169. package/src/workflows/schema.ts +1 -1
  170. package/src/workflows/store.ts +1157 -48
  171. package/src/workflows/types.ts +151 -3
@@ -153,6 +153,34 @@ export type WorkflowDefinition = {
153
153
 
154
154
  export type WorkflowNodeOutcome = "ok" | "timed_out" | "failed" | "cancelled";
155
155
 
156
+ /**
157
+ * Reference to a content-addressed file under the bundle's `artifacts/`
158
+ * directory. Large string leaves inside persisted values are replaced by
159
+ * `{ "$artifact": ArtifactRef }` at write time (see `docs/run-bundles.md`).
160
+ */
161
+ export type ArtifactRef = {
162
+ /** Bundle-relative path, `artifacts/sha256-<64 hex>.txt`. */
163
+ path: string;
164
+ mediaType: string;
165
+ bytes: number;
166
+ /** Hex digest of the artifact bytes. */
167
+ sha256: string;
168
+ };
169
+
170
+ /** The sentinel wrapper that replaces an externalized value. */
171
+ export type ArtifactValue = { $artifact: ArtifactRef };
172
+
173
+ /**
174
+ * Explicit linkage from a workflow attempt to the Pi conversation slice it
175
+ * produced. Ids address entries in `session/entries.ndjson` by Pi entry id.
176
+ */
177
+ export type ConversationRange = {
178
+ /** First Pi session entry id of the attempt. */
179
+ firstEntryId: string;
180
+ /** Last Pi session entry id of the attempt, inclusive. */
181
+ lastEntryId: string;
182
+ };
183
+
156
184
  export type WorkflowNodeResult = {
157
185
  attemptId: string;
158
186
  nodeId: string;
@@ -182,10 +210,16 @@ export type WorkflowStepRecord = {
182
210
  outcome: WorkflowNodeOutcome;
183
211
  startedAt: string;
184
212
  finishedAt: string;
185
- promptText: string | null;
213
+ /**
214
+ * Full prompt text for agent steps, `null` for other node types. In a
215
+ * persisted bundle a large prompt may be an `ArtifactValue`.
216
+ */
217
+ prompt: string | ArtifactValue | null;
186
218
  output: unknown;
187
219
  error?: string;
188
220
  action?: WorkflowActionReceipt;
221
+ /** For agent steps recorded inside a Pi conversation. */
222
+ conversation?: ConversationRange;
189
223
  };
190
224
 
191
225
  export type WorkflowRunStatus =
@@ -197,10 +231,27 @@ export type WorkflowRunStatus =
197
231
  | "cancelled";
198
232
 
199
233
  export type WorkflowRunState = {
234
+ schema: "pi-workflows.run-state.v1";
235
+ /**
236
+ * `seq` of the trace event this projection reflects. `trace.ndjson` is the
237
+ * source of truth; a state whose `traceSeq` is older than the trace tail is
238
+ * a stale projection.
239
+ */
240
+ traceSeq: number;
200
241
  runId: string;
201
242
  workflowName: string;
243
+ /** Set on continuation runs: the checkpointed run this one carries forward. */
244
+ parentRunId?: string;
245
+ /**
246
+ * Steps carried from the parent at continuation start. Steps beyond this
247
+ * count were recorded by this run itself; resume uses it to tell a
248
+ * carried checkpoint from this run's own.
249
+ */
250
+ carriedStepCount?: number;
202
251
  runTitle?: string;
203
252
  workflowPath?: string;
253
+ /** SHA-256 of the workflow source at run start; resume refuses mismatches. */
254
+ workflowHash?: string;
204
255
  startedAt: string;
205
256
  finishedAt?: string;
206
257
  updatedAt: string;
@@ -211,7 +262,6 @@ export type WorkflowRunState = {
211
262
  steps: WorkflowStepRecord[];
212
263
  currentNode?: string;
213
264
  currentAttemptId?: string;
214
- currentNodeType?: WorkflowNodeDefinition["nodeType"];
215
265
  currentNodeStartedAt?: string;
216
266
  statusDetail?: string;
217
267
  /** True while the run is held at a step boundary by a pause request. */
@@ -241,7 +291,7 @@ export type WorkflowDefinitionSnapshot = {
241
291
  export type WorkflowTraceEvent = {
242
292
  seq: number;
243
293
  at: string;
244
- scope: "run" | "node" | "agent" | "action";
294
+ scope: "run" | "node" | "agent" | "action" | "session";
245
295
  type: string;
246
296
  runId: string;
247
297
  nodeId?: string;
@@ -249,6 +299,77 @@ export type WorkflowTraceEvent = {
249
299
  payload: Record<string, unknown>;
250
300
  };
251
301
 
302
+ /** `session/binding.json`: written once when a run binds to a conversation. */
303
+ export type WorkflowSessionBinding = {
304
+ schema: "pi-workflows.session-binding.v1";
305
+ runId: string;
306
+ /** Pi session UUID. */
307
+ piSessionId: string;
308
+ /**
309
+ * Absolute path of the Pi session file; provenance only, never read back.
310
+ * Absent for in-memory sessions.
311
+ */
312
+ piSessionFile?: string;
313
+ /** Working directory of the conversation. */
314
+ cwd: string;
315
+ boundAt: string;
316
+ };
317
+
318
+ /**
319
+ * One line of `session/entries.ndjson`: a verbatim Pi session entry recorded
320
+ * while the run was active. The inner entry shape is owned by Pi.
321
+ */
322
+ export type WorkflowSessionEntryRecord = {
323
+ /** Starts at 1, increases by exactly 1 within the file. */
324
+ seq: number;
325
+ /** When the entry was recorded into the bundle. */
326
+ at: string;
327
+ /** Verbatim Pi session entry (has its own id/parentId/timestamp). */
328
+ entry: Record<string, unknown>;
329
+ };
330
+
331
+ export type WorkflowSessionEventType =
332
+ | "turn_started"
333
+ | "turn_finished"
334
+ | "message_started"
335
+ | "assistant_event"
336
+ | "message_finished"
337
+ | "tool_execution_started"
338
+ | "tool_execution_updated"
339
+ | "tool_execution_finished";
340
+
341
+ /** One normalized temporal Pi event in `session/events.ndjson`. */
342
+ export type WorkflowSessionEventRecord = {
343
+ /** Starts at 1 and increases by exactly 1 within the file. */
344
+ seq: number;
345
+ /** Time when the extension received the public Pi event. */
346
+ at: string;
347
+ nodeId: string;
348
+ attemptId: string;
349
+ turnId?: string;
350
+ messageId?: string;
351
+ toolCallId?: string;
352
+ type: WorkflowSessionEventType;
353
+ payload: Record<string, unknown>;
354
+ };
355
+
356
+ export type WorkflowSessionCaptureFailure = {
357
+ failedAt: string;
358
+ code: string;
359
+ message: string;
360
+ };
361
+
362
+ /** Atomic integrity projection for the temporal session journal. */
363
+ export type WorkflowSessionCapture = {
364
+ schema: "pi-workflows.session-capture.v1";
365
+ eventSchema: "pi-workflows.session-event.v1";
366
+ status: "recording" | "complete" | "failed";
367
+ eventCount: number;
368
+ entryCount: number;
369
+ lastEventSeq: number;
370
+ failure?: WorkflowSessionCaptureFailure;
371
+ };
372
+
252
373
  export type WorkflowTraceEventDraft = Omit<WorkflowTraceEvent, "seq" | "at" | "runId">;
253
374
 
254
375
  export type WorkflowRunManifest = {
@@ -265,6 +386,10 @@ export type WorkflowRunManifest = {
265
386
  workflow: string;
266
387
  state: string;
267
388
  trace: string;
389
+ /** Bundle-relative session directory, present once a session is bound. */
390
+ session?: string;
391
+ /** Bundle-relative artifacts directory, present once a value was externalized. */
392
+ artifacts?: string;
268
393
  };
269
394
  };
270
395
 
@@ -294,6 +419,11 @@ export type AgentStepRequest = {
294
419
 
295
420
  export type AgentStepSubmission = {
296
421
  output: unknown;
422
+ /**
423
+ * The Pi conversation slice this step produced, when the executor records
424
+ * one. Persisted verbatim into the step record and terminal node event.
425
+ */
426
+ conversation?: ConversationRange;
297
427
  };
298
428
 
299
429
  /**
@@ -309,6 +439,24 @@ export type WorkflowEngineOptions = {
309
439
  executor: AgentStepExecutor;
310
440
  /** Root directory for run bundles. Defaults to `~/.pi/agent/workflows/runs`. */
311
441
  outputRoot?: string;
442
+ /**
443
+ * Shared run store. Pass the same instance used by a session recorder so
444
+ * trace sequence numbers stay single-writer. Defaults to a new store on
445
+ * `outputRoot`.
446
+ */
447
+ store?: import("./store.js").WorkflowRunStore;
448
+ /**
449
+ * Awaited after `run_started` is persisted, before any node executes. This
450
+ * is where a session recorder binds, so `session_bound` lands at the start
451
+ * of the trace and can never trail the terminal event.
452
+ */
453
+ onRunStarted?: (runDir: string, state: WorkflowRunState) => MaybePromise<void>;
454
+ /**
455
+ * Awaited before the terminal snapshot is persisted. This is where a
456
+ * session recorder stops and drains, so the bundle is immutable the moment
457
+ * the terminal event exists. Errors are swallowed: finishing the run wins.
458
+ */
459
+ onRunFinishing?: (runDir: string, state: WorkflowRunState) => MaybePromise<void>;
312
460
  /** Default per-node timeout. Defaults to 15 minutes. */
313
461
  defaultNodeTimeoutMs?: number;
314
462
  /** Guard against unbounded graph loops. Defaults to 100 executed steps. */