@osolmaz/pi-workflows 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +8 -5
  2. package/dist/builtins/catalog.js +12 -2
  3. package/dist/builtins/catalog.js.map +1 -1
  4. package/dist/builtins/monitor.workflow.d.ts +2 -2
  5. package/dist/builtins/monitor.workflow.js +11 -27
  6. package/dist/builtins/monitor.workflow.js.map +1 -1
  7. package/dist/controllers/index.d.ts +1 -1
  8. package/dist/controllers/index.js.map +1 -1
  9. package/dist/controllers/sqlite.d.ts +43 -5
  10. package/dist/controllers/sqlite.js +128 -32
  11. package/dist/controllers/sqlite.js.map +1 -1
  12. package/dist/extension/index.js +109 -94
  13. package/dist/extension/index.js.map +1 -1
  14. package/dist/extension/widget.d.ts +5 -2
  15. package/dist/extension/widget.js +52 -17
  16. package/dist/extension/widget.js.map +1 -1
  17. package/dist/host/runner.js +20 -1
  18. package/dist/host/runner.js.map +1 -1
  19. package/dist/render/graph-render.js +3 -0
  20. package/dist/render/graph-render.js.map +1 -1
  21. package/dist/workflows/definition.d.ts +2 -1
  22. package/dist/workflows/definition.js +9 -1
  23. package/dist/workflows/definition.js.map +1 -1
  24. package/dist/workflows/engine.d.ts +1 -0
  25. package/dist/workflows/engine.js +22 -0
  26. package/dist/workflows/engine.js.map +1 -1
  27. package/dist/workflows/index.d.ts +2 -2
  28. package/dist/workflows/index.js +1 -1
  29. package/dist/workflows/index.js.map +1 -1
  30. package/dist/workflows/migrate-sources.d.ts +1 -0
  31. package/dist/workflows/migrate-sources.js +4 -0
  32. package/dist/workflows/migrate-sources.js.map +1 -1
  33. package/dist/workflows/schema.d.ts +2 -1
  34. package/dist/workflows/schema.js +12 -0
  35. package/dist/workflows/schema.js.map +1 -1
  36. package/dist/workflows/store.js +3 -0
  37. package/dist/workflows/store.js.map +1 -1
  38. package/dist/workflows/types.d.ts +26 -1
  39. package/docs/plans/2026-08-13-responsive-workflow-widget-plan.md +64 -0
  40. package/docs/plans/2026-08-13-session-addressed-workflow-notifications-plan.md +95 -0
  41. package/docs/workflows.md +23 -4
  42. package/package.json +3 -1
  43. package/src/builtins/catalog.ts +12 -2
  44. package/src/builtins/monitor.workflow.ts +11 -28
  45. package/src/controllers/index.ts +1 -0
  46. package/src/controllers/sqlite.ts +225 -33
  47. package/src/extension/index.ts +123 -125
  48. package/src/extension/widget.ts +83 -20
  49. package/src/host/runner.ts +20 -1
  50. package/src/render/graph-render.ts +3 -0
  51. package/src/workflows/definition.ts +11 -0
  52. package/src/workflows/engine.ts +26 -0
  53. package/src/workflows/index.ts +5 -0
  54. package/src/workflows/migrate-sources.ts +7 -0
  55. package/src/workflows/schema.ts +14 -0
  56. package/src/workflows/store.ts +3 -0
  57. package/src/workflows/types.ts +30 -0
@@ -5,6 +5,7 @@ export {
5
5
  compute,
6
6
  defineWorkflow,
7
7
  isWorkflowDefinition,
8
+ notify,
8
9
  shell,
9
10
  } from "./definition.js";
10
11
  export { decision, decisionEdge, type DecisionDefinition } from "./decision.js";
@@ -65,6 +66,7 @@ export type {
65
66
  ComputeNodeDefinition,
66
67
  FunctionActionNodeDefinition,
67
68
  MaybePromise,
69
+ NotifyNodeDefinition,
68
70
  ShellActionExecution,
69
71
  ShellActionNodeDefinition,
70
72
  ShellActionResult,
@@ -79,6 +81,9 @@ export type {
79
81
  WorkflowNodeOutcome,
80
82
  WorkflowNodeResult,
81
83
  WorkflowNodeSnapshot,
84
+ WorkflowNotificationReceipt,
85
+ WorkflowNotificationRequest,
86
+ WorkflowNotificationSink,
82
87
  WorkflowPresentationContext,
83
88
  WorkflowRunManifest,
84
89
  WorkflowRunResult,
@@ -25,6 +25,7 @@ export type LegacySourceMigrationQueue = {
25
25
  }): boolean;
26
26
  parkWorkflowRun(options: { runId: string; claimToken: string }): boolean;
27
27
  getWorkflowRun(runId: string): { status: "claimed" | "parked" | "done" } | undefined;
28
+ setWorkflowRunOriginSession?(runId: string, originSessionId: string): boolean;
28
29
  };
29
30
 
30
31
  const MIGRATION_LEASE_MS = 30_000;
@@ -45,6 +46,12 @@ export async function migrateLegacyWorkflowSources(options: {
45
46
  for (const bundle of await listRunBundles(store.outputRoot)) {
46
47
  const state = bundle.state;
47
48
  if (state.status !== "running" && state.status !== "waiting") continue;
49
+ if (
50
+ options.queue?.setWorkflowRunOriginSession !== undefined &&
51
+ bundle.sessionBinding !== null
52
+ ) {
53
+ options.queue.setWorkflowRunOriginSession(state.runId, bundle.sessionBinding.piSessionId);
54
+ }
48
55
  if (state.workflowSource !== undefined) {
49
56
  if (options.queue === undefined) continue;
50
57
  const claimToken = randomUUID();
@@ -4,6 +4,7 @@ import type {
4
4
  CheckpointNodeDefinition,
5
5
  ComputeNodeDefinition,
6
6
  FunctionActionNodeDefinition,
7
+ NotifyNodeDefinition,
7
8
  ShellActionNodeDefinition,
8
9
  WorkflowDefinition,
9
10
  WorkflowEdge,
@@ -62,6 +63,16 @@ export function assertValidComputeNode(node: ComputeNodeDefinition, nodeId = "co
62
63
  assertCommonNodeFields(node, nodeId);
63
64
  }
64
65
 
66
+ export function assertValidNotifyNode(node: NotifyNodeDefinition, nodeId = "notify"): void {
67
+ if (typeof node.message !== "function") {
68
+ fail(`node ${nodeId} requires a message function`);
69
+ }
70
+ if (node.kind !== undefined && node.kind !== "progress" && node.kind !== "final") {
71
+ fail(`node ${nodeId} kind must be progress or final`);
72
+ }
73
+ assertCommonNodeFields(node, nodeId);
74
+ }
75
+
65
76
  export function assertValidActionNode(node: ActionNodeDefinition, nodeId = "action"): void {
66
77
  // Dispatch discriminates with `"exec" in node`, so validation must use the
67
78
  // same property semantics: a present-but-invalid `exec` is an error even
@@ -112,6 +123,9 @@ function assertValidNode(node: WorkflowNodeDefinition, nodeId: string): void {
112
123
  case "compute":
113
124
  assertValidComputeNode(node, nodeId);
114
125
  return;
126
+ case "notify":
127
+ assertValidNotifyNode(node, nodeId);
128
+ return;
115
129
  case "action":
116
130
  assertValidActionNode(node, nodeId);
117
131
  return;
@@ -1323,6 +1323,9 @@ function snapshotNode(node: WorkflowNodeDefinition): WorkflowNodeSnapshot {
1323
1323
  if (node.nodeType === "agent" && node.expectedOutput !== undefined) {
1324
1324
  common.expectedOutput = node.expectedOutput;
1325
1325
  }
1326
+ if (node.nodeType === "notify") {
1327
+ common.summary = node.kind ?? "progress";
1328
+ }
1326
1329
  if (node.nodeType === "checkpoint" && node.summary !== undefined) {
1327
1330
  common.summary = node.summary;
1328
1331
  }
@@ -68,6 +68,13 @@ export type ComputeNodeDefinition = WorkflowNodeCommon & {
68
68
  run: (context: WorkflowNodeContext) => MaybePromise<unknown>;
69
69
  };
70
70
 
71
+ /** A durable user-facing message addressed by the runtime to the run's origin session. */
72
+ export type NotifyNodeDefinition = WorkflowNodeCommon & {
73
+ nodeType: "notify";
74
+ message: (context: WorkflowNodeContext) => MaybePromise<string>;
75
+ kind?: "progress" | "final";
76
+ };
77
+
71
78
  /** A deterministic runtime-owned step implemented as a local function. */
72
79
  export type FunctionActionNodeDefinition = WorkflowNodeCommon & {
73
80
  nodeType: "action";
@@ -121,6 +128,7 @@ export type CheckpointNodeDefinition = WorkflowNodeCommon & {
121
128
  export type WorkflowNodeDefinition =
122
129
  | AgentNodeDefinition
123
130
  | ComputeNodeDefinition
131
+ | NotifyNodeDefinition
124
132
  | ActionNodeDefinition
125
133
  | CheckpointNodeDefinition;
126
134
 
@@ -444,8 +452,30 @@ export interface AgentStepExecutor {
444
452
  runAgentStep(request: AgentStepRequest, signal: AbortSignal): Promise<AgentStepSubmission>;
445
453
  }
446
454
 
455
+ export type WorkflowNotificationRequest = {
456
+ runId: string;
457
+ workflowName: string;
458
+ nodeId: string;
459
+ attemptId: string;
460
+ /** Stable one-based occurrence of this notify node within the run. */
461
+ notificationIndex: number;
462
+ kind: "progress" | "final";
463
+ content: string;
464
+ };
465
+
466
+ export type WorkflowNotificationReceipt = {
467
+ notificationId: string;
468
+ targetSessionId: string;
469
+ };
470
+
471
+ export interface WorkflowNotificationSink {
472
+ notify(request: WorkflowNotificationRequest): MaybePromise<WorkflowNotificationReceipt>;
473
+ }
474
+
447
475
  export type WorkflowEngineOptions = {
448
476
  executor: AgentStepExecutor;
477
+ /** Durable destination for notify nodes. Required when a workflow uses one. */
478
+ notificationSink?: WorkflowNotificationSink;
449
479
  /** Root directory for run bundles. Defaults to `~/.pi/agent/workflows/runs`. */
450
480
  outputRoot?: string;
451
481
  /**