@osolmaz/pi-workflows 0.1.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 (113) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +182 -0
  3. package/dist/extension/executor.d.ts +58 -0
  4. package/dist/extension/executor.js +201 -0
  5. package/dist/extension/executor.js.map +1 -0
  6. package/dist/extension/index.d.ts +17 -0
  7. package/dist/extension/index.js +504 -0
  8. package/dist/extension/index.js.map +1 -0
  9. package/dist/extension/widget.d.ts +21 -0
  10. package/dist/extension/widget.js +142 -0
  11. package/dist/extension/widget.js.map +1 -0
  12. package/dist/render/ansi.d.ts +16 -0
  13. package/dist/render/ansi.js +42 -0
  14. package/dist/render/ansi.js.map +1 -0
  15. package/dist/render/canvas.d.ts +40 -0
  16. package/dist/render/canvas.js +177 -0
  17. package/dist/render/canvas.js.map +1 -0
  18. package/dist/render/format.d.ts +3 -0
  19. package/dist/render/format.js +17 -0
  20. package/dist/render/format.js.map +1 -0
  21. package/dist/render/graph-render.d.ts +22 -0
  22. package/dist/render/graph-render.js +520 -0
  23. package/dist/render/graph-render.js.map +1 -0
  24. package/dist/render/graph.d.ts +46 -0
  25. package/dist/render/graph.js +272 -0
  26. package/dist/render/graph.js.map +1 -0
  27. package/dist/viewer/cli.d.ts +10 -0
  28. package/dist/viewer/cli.js +132 -0
  29. package/dist/viewer/cli.js.map +1 -0
  30. package/dist/viewer/render.d.ts +19 -0
  31. package/dist/viewer/render.js +162 -0
  32. package/dist/viewer/render.js.map +1 -0
  33. package/dist/viewer/tui.d.ts +11 -0
  34. package/dist/viewer/tui.js +140 -0
  35. package/dist/viewer/tui.js.map +1 -0
  36. package/dist/viewer/watch.d.ts +9 -0
  37. package/dist/viewer/watch.js +46 -0
  38. package/dist/viewer/watch.js.map +1 -0
  39. package/dist/workflows/decision.d.ts +25 -0
  40. package/dist/workflows/decision.js +96 -0
  41. package/dist/workflows/decision.js.map +1 -0
  42. package/dist/workflows/definition.d.ts +9 -0
  43. package/dist/workflows/definition.js +61 -0
  44. package/dist/workflows/definition.js.map +1 -0
  45. package/dist/workflows/engine.d.ts +65 -0
  46. package/dist/workflows/engine.js +574 -0
  47. package/dist/workflows/engine.js.map +1 -0
  48. package/dist/workflows/errors.d.ts +9 -0
  49. package/dist/workflows/errors.js +24 -0
  50. package/dist/workflows/errors.js.map +1 -0
  51. package/dist/workflows/graph.d.ts +17 -0
  52. package/dist/workflows/graph.js +127 -0
  53. package/dist/workflows/graph.js.map +1 -0
  54. package/dist/workflows/index.d.ts +11 -0
  55. package/dist/workflows/index.js +11 -0
  56. package/dist/workflows/index.js.map +1 -0
  57. package/dist/workflows/json.d.ts +14 -0
  58. package/dist/workflows/json.js +134 -0
  59. package/dist/workflows/json.js.map +1 -0
  60. package/dist/workflows/loader.d.ts +28 -0
  61. package/dist/workflows/loader.js +94 -0
  62. package/dist/workflows/loader.js.map +1 -0
  63. package/dist/workflows/schema.d.ts +7 -0
  64. package/dist/workflows/schema.js +176 -0
  65. package/dist/workflows/schema.js.map +1 -0
  66. package/dist/workflows/shell.d.ts +9 -0
  67. package/dist/workflows/shell.js +177 -0
  68. package/dist/workflows/shell.js.map +1 -0
  69. package/dist/workflows/store.d.ts +35 -0
  70. package/dist/workflows/store.js +181 -0
  71. package/dist/workflows/store.js.map +1 -0
  72. package/dist/workflows/text.d.ts +10 -0
  73. package/dist/workflows/text.js +32 -0
  74. package/dist/workflows/text.js.map +1 -0
  75. package/dist/workflows/types.d.ts +280 -0
  76. package/dist/workflows/types.js +2 -0
  77. package/dist/workflows/types.js.map +1 -0
  78. package/docs/development.md +130 -0
  79. package/docs/run-bundles.md +114 -0
  80. package/docs/workflows.md +311 -0
  81. package/examples/workflows/autoimplement.workflow.ts +92 -0
  82. package/examples/workflows/autoresearch.workflow.ts +139 -0
  83. package/examples/workflows/branch.workflow.ts +63 -0
  84. package/examples/workflows/echo.workflow.ts +23 -0
  85. package/examples/workflows/elegant-solution.workflow.ts +95 -0
  86. package/examples/workflows/shell.workflow.ts +31 -0
  87. package/examples/workflows/two-turn.workflow.ts +64 -0
  88. package/package.json +80 -0
  89. package/src/extension/executor.ts +251 -0
  90. package/src/extension/index.ts +627 -0
  91. package/src/extension/widget.ts +183 -0
  92. package/src/render/ansi.ts +47 -0
  93. package/src/render/canvas.ts +196 -0
  94. package/src/render/format.ts +19 -0
  95. package/src/render/graph-render.ts +738 -0
  96. package/src/render/graph.ts +341 -0
  97. package/src/viewer/cli.ts +150 -0
  98. package/src/viewer/render.ts +236 -0
  99. package/src/viewer/tui.ts +159 -0
  100. package/src/viewer/watch.ts +55 -0
  101. package/src/workflows/decision.ts +127 -0
  102. package/src/workflows/definition.ts +104 -0
  103. package/src/workflows/engine.ts +793 -0
  104. package/src/workflows/errors.ts +27 -0
  105. package/src/workflows/graph.ts +161 -0
  106. package/src/workflows/index.ts +76 -0
  107. package/src/workflows/json.ts +155 -0
  108. package/src/workflows/loader.ts +123 -0
  109. package/src/workflows/schema.ts +218 -0
  110. package/src/workflows/shell.ts +199 -0
  111. package/src/workflows/store.ts +234 -0
  112. package/src/workflows/text.ts +34 -0
  113. package/src/workflows/types.ts +318 -0
@@ -0,0 +1,140 @@
1
+ import { listRunBundles, readRunBundle } from "../workflows/store.js";
2
+ import { maxDetailScroll, renderRunDetailLines, renderRunListLines, } from "./render.js";
3
+ import { watchRunsDir } from "./watch.js";
4
+ const ALT_SCREEN_ON = "\u001b[?1049h\u001b[?25l";
5
+ const ALT_SCREEN_OFF = "\u001b[?25h\u001b[?1049l";
6
+ const CLEAR = "\u001b[2J\u001b[H";
7
+ function viewportSize() {
8
+ return {
9
+ width: process.stdout.columns ?? 80,
10
+ height: process.stdout.rows ?? 24,
11
+ };
12
+ }
13
+ /**
14
+ * Interactive live viewer. Watches the runs directory and re-renders as run
15
+ * bundles change on disk. Returns when the user quits.
16
+ */
17
+ export async function runViewer(options) {
18
+ let mode = { view: "list" };
19
+ let bundles = [];
20
+ let selectedIndex = 0;
21
+ let detailScroll = 0;
22
+ /** Replay position; null follows the latest step live. */
23
+ let selectedStep = null;
24
+ let detailStepCount = 0;
25
+ if (options.runId) {
26
+ bundles = await listRunBundles(options.runsDir);
27
+ const match = bundles.find((bundle) => bundle.state.runId === options.runId);
28
+ if (!match) {
29
+ throw new Error(`Run not found: ${options.runId}`);
30
+ }
31
+ mode = { view: "detail", runDir: match.runDir };
32
+ }
33
+ const draw = async () => {
34
+ bundles = await listRunBundles(options.runsDir);
35
+ selectedIndex = Math.min(selectedIndex, Math.max(0, bundles.length - 1));
36
+ const size = viewportSize();
37
+ const lines = mode.view === "list"
38
+ ? renderRunListLines(bundles, selectedIndex, size)
39
+ : await renderDetail(mode.runDir, size);
40
+ process.stdout.write(CLEAR + lines.join("\n"));
41
+ };
42
+ const renderDetail = async (runDir, size) => {
43
+ const bundle = await readRunBundle(runDir);
44
+ if (!bundle) {
45
+ return ["Run bundle disappeared. Press q to go back."];
46
+ }
47
+ detailStepCount = bundle.state.steps.length;
48
+ if (selectedStep !== null && selectedStep >= detailStepCount - 1) {
49
+ // Scrubbed to (or past) the end: snap back to following live updates.
50
+ selectedStep = null;
51
+ }
52
+ detailScroll = Math.min(detailScroll, maxDetailScroll(bundle, size, selectedStep));
53
+ return renderRunDetailLines(bundle, size, new Date(), detailScroll, selectedStep);
54
+ };
55
+ process.stdout.write(ALT_SCREEN_ON);
56
+ const stopWatching = watchRunsDir(options.runsDir, () => {
57
+ void draw();
58
+ });
59
+ const ticker = setInterval(() => {
60
+ void draw();
61
+ }, options.tickMs ?? 1_000);
62
+ const rawModeSupported = process.stdin.isTTY === true;
63
+ if (rawModeSupported) {
64
+ process.stdin.setRawMode(true);
65
+ }
66
+ process.stdin.resume();
67
+ try {
68
+ await new Promise((resolve) => {
69
+ const onKey = (data) => {
70
+ const key = data.toString("utf8");
71
+ if (key === "q" || key === "\u0003" || key === "\u001b") {
72
+ if (mode.view === "detail" && key === "q") {
73
+ mode = { view: "list" };
74
+ void draw();
75
+ return;
76
+ }
77
+ resolve();
78
+ return;
79
+ }
80
+ handleNavigationKey(key);
81
+ };
82
+ const handleNavigationKey = (key) => {
83
+ if (mode.view !== "list") {
84
+ if (key === "r") {
85
+ void draw();
86
+ }
87
+ else if (key === "\u001b[A" || key === "k") {
88
+ detailScroll = Math.max(0, detailScroll - 1);
89
+ void draw();
90
+ }
91
+ else if (key === "\u001b[B" || key === "j") {
92
+ // Clamped against the content height in renderDetail.
93
+ detailScroll += 1;
94
+ void draw();
95
+ }
96
+ else if (key === "\u001b[D" || key === "h") {
97
+ const current = selectedStep ?? detailStepCount - 1;
98
+ selectedStep = Math.max(0, current - 1);
99
+ void draw();
100
+ }
101
+ else if (key === "\u001b[C" || key === "l") {
102
+ // renderDetail snaps back to live once this reaches the end.
103
+ selectedStep = selectedStep === null ? null : selectedStep + 1;
104
+ void draw();
105
+ }
106
+ return;
107
+ }
108
+ if (key === "\u001b[A" || key === "k") {
109
+ selectedIndex = Math.max(0, selectedIndex - 1);
110
+ void draw();
111
+ }
112
+ else if (key === "\u001b[B" || key === "j") {
113
+ selectedIndex = Math.min(Math.max(0, bundles.length - 1), selectedIndex + 1);
114
+ void draw();
115
+ }
116
+ else if (key === "\r" || key === "\n") {
117
+ const selected = bundles[selectedIndex];
118
+ if (selected) {
119
+ mode = { view: "detail", runDir: selected.runDir };
120
+ detailScroll = 0;
121
+ selectedStep = null;
122
+ void draw();
123
+ }
124
+ }
125
+ };
126
+ process.stdin.on("data", onKey);
127
+ void draw();
128
+ });
129
+ }
130
+ finally {
131
+ clearInterval(ticker);
132
+ stopWatching();
133
+ if (rawModeSupported) {
134
+ process.stdin.setRawMode(false);
135
+ }
136
+ process.stdin.pause();
137
+ process.stdout.write(ALT_SCREEN_OFF);
138
+ }
139
+ }
140
+ //# sourceMappingURL=tui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tui.js","sourceRoot":"","sources":["../../src/viewer/tui.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export type Unsubscribe = () => void;
2
+ /**
3
+ * Watch a directory tree for changes with a polling fallback. `onChange` is
4
+ * debounced so bursts of writes trigger one refresh.
5
+ */
6
+ export declare function watchRunsDir(dir: string, onChange: () => void, options?: {
7
+ pollMs?: number;
8
+ debounceMs?: number;
9
+ }): Unsubscribe;
@@ -0,0 +1,46 @@
1
+ import fs from "node:fs";
2
+ /**
3
+ * Watch a directory tree for changes with a polling fallback. `onChange` is
4
+ * debounced so bursts of writes trigger one refresh.
5
+ */
6
+ export function watchRunsDir(dir, onChange, options = {}) {
7
+ const pollMs = options.pollMs ?? 1_000;
8
+ const debounceMs = options.debounceMs ?? 80;
9
+ let debounceTimer = null;
10
+ let closed = false;
11
+ const fire = () => {
12
+ if (closed) {
13
+ return;
14
+ }
15
+ if (debounceTimer) {
16
+ clearTimeout(debounceTimer);
17
+ }
18
+ debounceTimer = setTimeout(() => {
19
+ debounceTimer = null;
20
+ onChange();
21
+ }, debounceMs);
22
+ };
23
+ let watcher = null;
24
+ try {
25
+ watcher = fs.watch(dir, { recursive: true }, fire);
26
+ watcher.on("error", () => {
27
+ watcher?.close();
28
+ watcher = null;
29
+ });
30
+ }
31
+ catch {
32
+ watcher = null;
33
+ }
34
+ // Polling fallback covers platforms without recursive fs.watch and missed events.
35
+ const poller = setInterval(fire, pollMs);
36
+ poller.unref?.();
37
+ return () => {
38
+ closed = true;
39
+ if (debounceTimer) {
40
+ clearTimeout(debounceTimer);
41
+ }
42
+ clearInterval(poller);
43
+ watcher?.close();
44
+ };
45
+ }
46
+ //# sourceMappingURL=watch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/viewer/watch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAIzB;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,GAAW,EACX,QAAoB,EACpB,OAAO,GAA6C,EAAE;IAEtD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,KAAK,CAAC;IACvC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC;IAC5C,IAAI,aAAa,GAA0B,IAAI,CAAC;IAChD,IAAI,MAAM,GAAG,KAAK,CAAC;IAEnB,MAAM,IAAI,GAAG,GAAG,EAAE;QAChB,IAAI,MAAM,EAAE,CAAC;YACX,OAAO;QACT,CAAC;QACD,IAAI,aAAa,EAAE,CAAC;YAClB,YAAY,CAAC,aAAa,CAAC,CAAC;QAC9B,CAAC;QACD,aAAa,GAAG,UAAU,CAAC,GAAG,EAAE;YAC9B,aAAa,GAAG,IAAI,CAAC;YACrB,QAAQ,EAAE,CAAC;QACb,CAAC,EAAE,UAAU,CAAC,CAAC;IACjB,CAAC,CAAC;IAEF,IAAI,OAAO,GAAwB,IAAI,CAAC;IACxC,IAAI,CAAC;QACH,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;QACnD,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACvB,OAAO,EAAE,KAAK,EAAE,CAAC;YACjB,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,IAAI,CAAC;IACjB,CAAC;IAED,kFAAkF;IAClF,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACzC,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC;IAEjB,OAAO,GAAG,EAAE;QACV,MAAM,GAAG,IAAI,CAAC;QACd,IAAI,aAAa,EAAE,CAAC;YAClB,YAAY,CAAC,aAAa,CAAC,CAAC;QAC9B,CAAC;QACD,aAAa,CAAC,MAAM,CAAC,CAAC;QACtB,OAAO,EAAE,KAAK,EAAE,CAAC;IACnB,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type { AgentNodeDefinition, WorkflowEdge, WorkflowNodeContext } from "./types.js";
2
+ type DecisionAgentOptions = Omit<AgentNodeDefinition, "nodeType" | "prompt" | "expectedOutput" | "validate">;
3
+ export type DecisionDefinition<TChoice extends string> = DecisionAgentOptions & {
4
+ question: string | ((context: WorkflowNodeContext) => string | Promise<string>);
5
+ choices: readonly TChoice[];
6
+ field?: string;
7
+ };
8
+ /**
9
+ * Build an `agent` node that asks the model to pick one of `choices` and
10
+ * submit a JSON object whose chosen field is validated. Pair with
11
+ * `decisionEdge` (or any `switch` edge keyed on `$.<field>`) to route on the
12
+ * result.
13
+ */
14
+ export declare function decision<TChoice extends string>(definition: DecisionDefinition<TChoice>): AgentNodeDefinition;
15
+ /**
16
+ * Build the matching `switch` edge for a `decision` node. Typing `cases` as
17
+ * `Record<TChoice, string>` makes a missing case a compile error.
18
+ */
19
+ export declare function decisionEdge<TChoice extends string>(args: {
20
+ from: string;
21
+ choices: readonly TChoice[];
22
+ field?: string;
23
+ cases: Record<TChoice, string>;
24
+ }): WorkflowEdge;
25
+ export {};
@@ -0,0 +1,96 @@
1
+ import { agent } from "./definition.js";
2
+ import { extractJsonValue } from "./json.js";
3
+ const DEFAULT_FIELD = "route";
4
+ const SIMPLE_FIELD_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
5
+ /**
6
+ * Build an `agent` node that asks the model to pick one of `choices` and
7
+ * submit a JSON object whose chosen field is validated. Pair with
8
+ * `decisionEdge` (or any `switch` edge keyed on `$.<field>`) to route on the
9
+ * result.
10
+ */
11
+ export function decision(definition) {
12
+ const { question, choices, field: fieldOverride, ...agentOptions } = definition;
13
+ const field = normalizeField(fieldOverride);
14
+ assertValidChoices(choices);
15
+ const allowed = new Set(choices);
16
+ const allowedLabels = choices.map((choice) => JSON.stringify(choice)).join(" | ");
17
+ return agent({
18
+ ...agentOptions,
19
+ async prompt(context) {
20
+ const text = typeof question === "function" ? await question(context) : question;
21
+ return [
22
+ text,
23
+ "",
24
+ `Answer by picking exactly one of: ${allowedLabels}.`,
25
+ `Include a short "reason" alongside your choice.`,
26
+ ].join("\n");
27
+ },
28
+ expectedOutput: `{ ${JSON.stringify(field)}: ${allowedLabels}, "reason": "short justification" }`,
29
+ validate(output) {
30
+ const raw = normalizeDecisionOutput(output);
31
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
32
+ throw new Error(`Decision output must be a JSON object, got ${describeValue(raw)}`);
33
+ }
34
+ const value = raw[field];
35
+ if (typeof value !== "string" || !allowed.has(value)) {
36
+ throw new Error(`Decision returned invalid ${field}=${JSON.stringify(value)}; expected one of ${allowedLabels}`);
37
+ }
38
+ return raw;
39
+ },
40
+ });
41
+ }
42
+ /**
43
+ * Build the matching `switch` edge for a `decision` node. Typing `cases` as
44
+ * `Record<TChoice, string>` makes a missing case a compile error.
45
+ */
46
+ export function decisionEdge(args) {
47
+ const field = normalizeField(args.field);
48
+ assertValidChoices(args.choices);
49
+ for (const choice of args.choices) {
50
+ if (!Object.hasOwn(args.cases, choice)) {
51
+ throw new Error(`Decision edge is missing case for choice ${JSON.stringify(choice)}`);
52
+ }
53
+ }
54
+ return {
55
+ from: args.from,
56
+ switch: {
57
+ on: `$.${field}`,
58
+ cases: args.cases,
59
+ },
60
+ };
61
+ }
62
+ function normalizeDecisionOutput(output) {
63
+ if (typeof output === "string") {
64
+ return extractJsonValue(output);
65
+ }
66
+ return output;
67
+ }
68
+ function describeValue(value) {
69
+ if (value === null) {
70
+ return "null";
71
+ }
72
+ return Array.isArray(value) ? "array" : typeof value;
73
+ }
74
+ function assertValidChoices(choices) {
75
+ if (choices.length === 0) {
76
+ throw new Error("Decision choices must include at least one value");
77
+ }
78
+ const seen = new Set();
79
+ for (const choice of choices) {
80
+ if (typeof choice !== "string" || choice.length === 0) {
81
+ throw new Error("Decision choices must be non-empty strings");
82
+ }
83
+ if (seen.has(choice)) {
84
+ throw new Error(`Decision choices must be unique; duplicate ${JSON.stringify(choice)}`);
85
+ }
86
+ seen.add(choice);
87
+ }
88
+ }
89
+ function normalizeField(fieldOverride) {
90
+ const field = fieldOverride ?? DEFAULT_FIELD;
91
+ if (!SIMPLE_FIELD_PATTERN.test(field)) {
92
+ throw new Error(`Decision field must be a simple JSON key matching ${SIMPLE_FIELD_PATTERN.source}`);
93
+ }
94
+ return field;
95
+ }
96
+ //# sourceMappingURL=decision.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision.js","sourceRoot":"","sources":["../../src/workflows/decision.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { AgentNodeDefinition, CheckpointNodeDefinition, ComputeNodeDefinition, FunctionActionNodeDefinition, ShellActionNodeDefinition, WorkflowDefinition } from "./types.js";
2
+ export declare function defineWorkflow<TWorkflow extends WorkflowDefinition>(definition: TWorkflow): TWorkflow;
3
+ export declare function isWorkflowDefinition(value: unknown): value is WorkflowDefinition;
4
+ export declare function agent(definition: Omit<AgentNodeDefinition, "nodeType">): AgentNodeDefinition;
5
+ export declare function compute(definition: Omit<ComputeNodeDefinition, "nodeType">): ComputeNodeDefinition;
6
+ export declare function action(definition: Omit<FunctionActionNodeDefinition, "nodeType">): FunctionActionNodeDefinition;
7
+ export declare function action(definition: Omit<ShellActionNodeDefinition, "nodeType">): ShellActionNodeDefinition;
8
+ export declare function shell(definition: Omit<ShellActionNodeDefinition, "nodeType">): ShellActionNodeDefinition;
9
+ export declare function checkpoint(definition?: Omit<CheckpointNodeDefinition, "nodeType">): CheckpointNodeDefinition;
@@ -0,0 +1,61 @@
1
+ import { assertValidAgentNode, assertValidActionNode, assertValidCheckpointNode, assertValidComputeNode, assertValidShellActionNode, assertValidWorkflowDefinitionShape, } from "./schema.js";
2
+ const WORKFLOW_DEFINITION_BRAND = Symbol.for("pi-workflows.definition");
3
+ export function defineWorkflow(definition) {
4
+ assertValidWorkflowDefinitionShape(definition);
5
+ if (isWorkflowDefinition(definition)) {
6
+ return definition;
7
+ }
8
+ Object.defineProperty(definition, WORKFLOW_DEFINITION_BRAND, {
9
+ value: true,
10
+ enumerable: false,
11
+ configurable: false,
12
+ writable: false,
13
+ });
14
+ return definition;
15
+ }
16
+ export function isWorkflowDefinition(value) {
17
+ return (value != null &&
18
+ typeof value === "object" &&
19
+ value[WORKFLOW_DEFINITION_BRAND] === true);
20
+ }
21
+ export function agent(definition) {
22
+ const node = {
23
+ nodeType: "agent",
24
+ ...definition,
25
+ };
26
+ assertValidAgentNode(node);
27
+ return node;
28
+ }
29
+ export function compute(definition) {
30
+ const node = {
31
+ nodeType: "compute",
32
+ ...definition,
33
+ };
34
+ assertValidComputeNode(node);
35
+ return node;
36
+ }
37
+ export function action(definition) {
38
+ const node = {
39
+ nodeType: "action",
40
+ ...definition,
41
+ };
42
+ assertValidActionNode(node);
43
+ return node;
44
+ }
45
+ export function shell(definition) {
46
+ const node = {
47
+ nodeType: "action",
48
+ ...definition,
49
+ };
50
+ assertValidShellActionNode(node);
51
+ return node;
52
+ }
53
+ export function checkpoint(definition = {}) {
54
+ const node = {
55
+ nodeType: "checkpoint",
56
+ ...definition,
57
+ };
58
+ assertValidCheckpointNode(node);
59
+ return node;
60
+ }
61
+ //# sourceMappingURL=definition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"definition.js","sourceRoot":"","sources":["../../src/workflows/definition.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,yBAAyB,EACzB,sBAAsB,EACtB,0BAA0B,EAC1B,kCAAkC,GACnC,MAAM,aAAa,CAAC;AAWrB,MAAM,yBAAyB,GAAG,MAAM,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;AAExE,MAAM,UAAU,cAAc,CAC5B,UAAqB;IAErB,kCAAkC,CAAC,UAAU,CAAC,CAAC;IAC/C,IAAI,oBAAoB,CAAC,UAAU,CAAC,EAAE,CAAC;QACrC,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,MAAM,CAAC,cAAc,CAAC,UAAU,EAAE,yBAAyB,EAAE;QAC3D,KAAK,EAAE,IAAI;QACX,UAAU,EAAE,KAAK;QACjB,YAAY,EAAE,KAAK;QACnB,QAAQ,EAAE,KAAK;KAChB,CAAC,CAAC;IACH,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAc;IACjD,OAAO,CACL,KAAK,IAAI,IAAI;QACb,OAAO,KAAK,KAAK,QAAQ;QACxB,KAAsC,CAAC,yBAAyB,CAAC,KAAK,IAAI,CAC5E,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,UAAiD;IACrE,MAAM,IAAI,GAAwB;QAChC,QAAQ,EAAE,OAAO;QACjB,GAAG,UAAU;KACd,CAAC;IACF,oBAAoB,CAAC,IAAI,CAAC,CAAC;IAC3B,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,OAAO,CACrB,UAAmD;IAEnD,MAAM,IAAI,GAA0B;QAClC,QAAQ,EAAE,SAAS;QACnB,GAAG,UAAU;KACd,CAAC;IACF,sBAAsB,CAAC,IAAI,CAAC,CAAC;IAC7B,OAAO,IAAI,CAAC;AACd,CAAC;AAQD,MAAM,UAAU,MAAM,CACpB,UAE+C;IAE/C,MAAM,IAAI,GAAyB;QACjC,QAAQ,EAAE,QAAQ;QAClB,GAAG,UAAU;KACd,CAAC;IACF,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAC5B,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,KAAK,CACnB,UAAuD;IAEvD,MAAM,IAAI,GAA8B;QACtC,QAAQ,EAAE,QAAQ;QAClB,GAAG,UAAU;KACd,CAAC;IACF,0BAA0B,CAAC,IAAI,CAAC,CAAC;IACjC,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,UAAU,GAA+C,EAAE;IAE3D,MAAM,IAAI,GAA6B;QACrC,QAAQ,EAAE,YAAY;QACtB,GAAG,UAAU;KACd,CAAC;IACF,yBAAyB,CAAC,IAAI,CAAC,CAAC;IAChC,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,65 @@
1
+ import type { WorkflowDefinition, WorkflowEngineOptions, WorkflowRunResult } from "./types.js";
2
+ /**
3
+ * Executes a workflow graph step by step. Agent steps are delegated to the
4
+ * configured executor; compute/action/checkpoint nodes run inline. Every
5
+ * state transition is persisted to the run bundle before the engine moves on,
6
+ * so a live viewer can follow along by watching the bundle directory.
7
+ */
8
+ export declare class WorkflowEngine {
9
+ private readonly executor;
10
+ private readonly store;
11
+ private readonly defaultNodeTimeoutMs;
12
+ private readonly maxSteps;
13
+ private readonly onEvent?;
14
+ private activeAbort;
15
+ private cancelled;
16
+ private paused;
17
+ private wakePause;
18
+ constructor(options: WorkflowEngineOptions);
19
+ get outputRoot(): string;
20
+ /** Abort the currently running node and mark the run cancelled. */
21
+ cancel(): void;
22
+ /**
23
+ * Request a pause. The current step finishes normally; the engine then
24
+ * holds before dispatching the next node until `resume` (or `cancel`).
25
+ */
26
+ pause(): void;
27
+ /** Release a pause requested with `pause`. */
28
+ resume(): void;
29
+ /** True when a pause has been requested or the run is already held. */
30
+ get pauseRequested(): boolean;
31
+ run(workflow: WorkflowDefinition, input: unknown, options?: {
32
+ workflowPath?: string;
33
+ }): Promise<WorkflowRunResult>;
34
+ /**
35
+ * Resolve the run title inside a cancellation and timeout boundary. This
36
+ * runs before any node abort controller exists, so without it a hung async
37
+ * `title` callback would leave the session permanently occupied.
38
+ */
39
+ private resolveTitleBounded;
40
+ private createRunState;
41
+ private executeGraph;
42
+ /**
43
+ * Hold the run at the step boundary while a pause is in effect. Pausing
44
+ * never interrupts a node mid-flight; it only delays the next dispatch.
45
+ */
46
+ private holdWhilePaused;
47
+ private routeAfterFailure;
48
+ private recordAttempt;
49
+ private executeNode;
50
+ private outcomeForError;
51
+ private createNodeResult;
52
+ private runNodeWithTimeout;
53
+ private dispatchNode;
54
+ private createNodeContext;
55
+ private runAgentNode;
56
+ private acceptSubmission;
57
+ private runActionNode;
58
+ private persist;
59
+ private finishRun;
60
+ }
61
+ /**
62
+ * The step contract appended to every agent-node prompt. This is the
63
+ * documented standard for how the model completes a workflow step.
64
+ */
65
+ export declare function appendStepContract(prompt: string, workflowName: string, nodeId: string, attemptId: string, expectedOutput: string | undefined): string;