@osolmaz/pi-workflows 0.5.3 → 0.6.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 (80) hide show
  1. package/README.md +10 -2
  2. package/dist/builtins/catalog.js +1 -1
  3. package/dist/builtins/monitor.workflow.d.ts +25 -69
  4. package/dist/builtins/monitor.workflow.js +194 -123
  5. package/dist/builtins/monitor.workflow.js.map +1 -1
  6. package/dist/extension/executor.d.ts +7 -2
  7. package/dist/extension/executor.js +20 -14
  8. package/dist/extension/executor.js.map +1 -1
  9. package/dist/extension/index.js +65 -13
  10. package/dist/extension/index.js.map +1 -1
  11. package/dist/extension/step-message.d.ts +24 -0
  12. package/dist/extension/step-message.js +106 -0
  13. package/dist/extension/step-message.js.map +1 -0
  14. package/dist/extension/widget.d.ts +2 -2
  15. package/dist/extension/widget.js +64 -5
  16. package/dist/extension/widget.js.map +1 -1
  17. package/dist/extension/workflow-tool.d.ts +9 -0
  18. package/dist/extension/workflow-tool.js +10 -0
  19. package/dist/extension/workflow-tool.js.map +1 -1
  20. package/dist/host/rpc-bridge.js +25 -11
  21. package/dist/host/rpc-bridge.js.map +1 -1
  22. package/dist/host/rpc-executor.d.ts +2 -2
  23. package/dist/host/rpc-executor.js +23 -12
  24. package/dist/host/rpc-executor.js.map +1 -1
  25. package/dist/viewer/cli.js +1 -1
  26. package/dist/viewer/cli.js.map +1 -1
  27. package/dist/viewer/render.js +14 -0
  28. package/dist/viewer/render.js.map +1 -1
  29. package/dist/viewer/tui.js +1 -1
  30. package/dist/viewer/tui.js.map +1 -1
  31. package/dist/workflows/engine.d.ts +6 -1
  32. package/dist/workflows/engine.js +88 -6
  33. package/dist/workflows/engine.js.map +1 -1
  34. package/dist/workflows/index.d.ts +4 -2
  35. package/dist/workflows/index.js +2 -0
  36. package/dist/workflows/index.js.map +1 -1
  37. package/dist/workflows/progress.d.ts +34 -0
  38. package/dist/workflows/progress.js +268 -0
  39. package/dist/workflows/progress.js.map +1 -0
  40. package/dist/workflows/schema.js +21 -1
  41. package/dist/workflows/schema.js.map +1 -1
  42. package/dist/workflows/shell.d.ts +2 -2
  43. package/dist/workflows/shell.js +103 -25
  44. package/dist/workflows/shell.js.map +1 -1
  45. package/dist/workflows/store.d.ts +15 -2
  46. package/dist/workflows/store.js +44 -2
  47. package/dist/workflows/store.js.map +1 -1
  48. package/dist/workflows/types.d.ts +52 -1
  49. package/dist/workflows/updates.d.ts +15 -0
  50. package/dist/workflows/updates.js +188 -0
  51. package/dist/workflows/updates.js.map +1 -0
  52. package/docs/DESIGN_PHILOSOPHY.md +51 -0
  53. package/docs/MONITOR.md +282 -0
  54. package/docs/WORKFLOW_STEP_MESSAGES.md +141 -0
  55. package/docs/WORKFLOW_UPDATES.md +416 -0
  56. package/docs/development.md +7 -3
  57. package/docs/plans/2026-08-16-workflow-updates-plan.md +494 -0
  58. package/docs/run-bundles.md +10 -2
  59. package/docs/workflows.md +58 -17
  60. package/package.json +1 -1
  61. package/src/builtins/catalog.ts +1 -1
  62. package/src/builtins/monitor.workflow.ts +217 -148
  63. package/src/extension/executor.ts +36 -14
  64. package/src/extension/index.ts +95 -19
  65. package/src/extension/step-message.ts +145 -0
  66. package/src/extension/widget.ts +93 -4
  67. package/src/extension/workflow-tool.ts +22 -0
  68. package/src/host/rpc-bridge.ts +37 -14
  69. package/src/host/rpc-executor.ts +35 -14
  70. package/src/viewer/cli.ts +1 -1
  71. package/src/viewer/render.ts +27 -0
  72. package/src/viewer/tui.ts +1 -1
  73. package/src/workflows/engine.ts +117 -4
  74. package/src/workflows/index.ts +32 -0
  75. package/src/workflows/progress.ts +326 -0
  76. package/src/workflows/schema.ts +23 -1
  77. package/src/workflows/shell.ts +109 -26
  78. package/src/workflows/store.ts +67 -2
  79. package/src/workflows/types.ts +78 -1
  80. package/src/workflows/updates.ts +208 -0
@@ -1,6 +1,7 @@
1
1
  import { type ChildProcess, spawn } from "node:child_process";
2
2
  import fs from "node:fs";
3
3
  import { fileURLToPath } from "node:url";
4
+ import { errorMessage } from "../workflows/errors.js";
4
5
  import type {
5
6
  AgentStepExecutor,
6
7
  AgentStepRequest,
@@ -23,6 +24,16 @@ type StepSubmission = {
23
24
  output: unknown;
24
25
  };
25
26
 
27
+ type StepUpdate = {
28
+ action: "update";
29
+ step: string;
30
+ attempt: string;
31
+ update: { type: string; key: string; data: Record<string, unknown> };
32
+ idempotencyKey?: string;
33
+ };
34
+
35
+ type StepAction = StepSubmission | StepUpdate;
36
+
26
37
  export type RpcStepExecutorOptions = {
27
38
  cwd: string;
28
39
  registry: HostProcessRegistry;
@@ -46,7 +57,7 @@ export class RpcStepExecutor implements AgentStepExecutor {
46
57
  private child: ChildProcess | null = null;
47
58
  private childExited: { code: number | null; signal: string | null } | null = null;
48
59
  private stderrBuffer = "";
49
- private submissions: StepSubmission[] = [];
60
+ private actions: StepAction[] = [];
50
61
  private submissionWaiters: Array<() => void> = [];
51
62
  private stdoutBuffer = "";
52
63
 
@@ -179,13 +190,13 @@ export class RpcStepExecutor implements AgentStepExecutor {
179
190
  continue;
180
191
  }
181
192
  try {
182
- const parsed = JSON.parse(line.slice(RPC_SUBMISSION_PREFIX.length)) as StepSubmission;
193
+ const parsed = JSON.parse(line.slice(RPC_SUBMISSION_PREFIX.length)) as StepAction;
183
194
  if (
184
- parsed.action === "submit" &&
195
+ (parsed.action === "submit" || parsed.action === "update") &&
185
196
  typeof parsed.step === "string" &&
186
197
  typeof parsed.attempt === "string"
187
198
  ) {
188
- this.submissions.push(parsed);
199
+ this.actions.push(parsed);
189
200
  }
190
201
  } catch {
191
202
  // A malformed marker line is ignored; the step times out instead.
@@ -209,10 +220,6 @@ export class RpcStepExecutor implements AgentStepExecutor {
209
220
  if (child === null || this.childExited !== null) {
210
221
  throw new Error("Headless pi session is not running");
211
222
  }
212
- const matching = this.takeMatchingSubmission(request);
213
- if (matching !== undefined) {
214
- return matching;
215
- }
216
223
  child.stdin?.write(`${JSON.stringify({ type: "prompt", message: prompt })}\n`);
217
224
  for (;;) {
218
225
  throwIfAborted(signal);
@@ -220,9 +227,23 @@ export class RpcStepExecutor implements AgentStepExecutor {
220
227
  if (exited !== null) {
221
228
  throw new Error(`Headless pi session exited mid-step (code ${exited.code})`);
222
229
  }
223
- const found = this.takeMatchingSubmission(request);
224
- if (found !== undefined) {
225
- return found;
230
+ const found = this.takeMatchingAction(request);
231
+ if (found?.action === "submit") return found;
232
+ if (found?.action === "update") {
233
+ if (request.publishUpdate === undefined) {
234
+ throw new Error("This workflow host does not support step updates");
235
+ }
236
+ try {
237
+ await request.publishUpdate(found.update, found.idempotencyKey);
238
+ } catch (error) {
239
+ child.stdin?.write(
240
+ `${JSON.stringify({
241
+ type: "prompt",
242
+ message: `Workflow update rejected: ${errorMessage(error)}. Correct the update and continue the same step.`,
243
+ })}\n`,
244
+ );
245
+ }
246
+ continue;
226
247
  }
227
248
  await new Promise<void>((resolve, reject) => {
228
249
  const waiter = () => {
@@ -239,13 +260,13 @@ export class RpcStepExecutor implements AgentStepExecutor {
239
260
  }
240
261
  }
241
262
 
242
- private takeMatchingSubmission(request: AgentStepRequest): StepSubmission | undefined {
243
- const index = this.submissions.findIndex(
263
+ private takeMatchingAction(request: AgentStepRequest): StepAction | undefined {
264
+ const index = this.actions.findIndex(
244
265
  (candidate) =>
245
266
  candidate.step === request.contract.nodeId &&
246
267
  candidate.attempt === request.contract.attemptId,
247
268
  );
248
- return index === -1 ? undefined : (this.submissions.splice(index, 1)[0] as StepSubmission);
269
+ return index === -1 ? undefined : (this.actions.splice(index, 1)[0] as StepAction);
249
270
  }
250
271
 
251
272
  private sendAbortQuietly(): void {
package/src/viewer/cli.ts CHANGED
@@ -138,7 +138,7 @@ async function printOnce(dir: string, runId: string | undefined): Promise<void>
138
138
  if (!match) {
139
139
  throw new Error(`Run not found: ${runId}`);
140
140
  }
141
- const bundle = await readRunBundle(match.runDir);
141
+ const bundle = await readRunBundle(match.runDir, { includeTrace: true });
142
142
  if (!bundle) {
143
143
  throw new Error(`Run bundle unreadable: ${match.runDir}`);
144
144
  }
@@ -2,6 +2,11 @@ import { ansi, fitWidth, sanitizeText } from "../render/ansi.js";
2
2
  import { formatDuration, runElapsedMs } from "../render/format.js";
3
3
  import { renderGraphLines } from "../render/graph-render.js";
4
4
  import { decodeValueWith } from "../workflows/artifacts.js";
5
+ import {
6
+ formatProgressLine,
7
+ progressRecordsFromTrace,
8
+ progressTracksFromRecords,
9
+ } from "../workflows/progress.js";
5
10
  import type { LoadedRunBundle } from "../workflows/store.js";
6
11
  import type { WorkflowRunStatus, WorkflowStepRecord } from "../workflows/types.js";
7
12
 
@@ -204,6 +209,28 @@ export function renderRunDetailLines(
204
209
  }
205
210
  }
206
211
 
212
+ const progressRecords =
213
+ bundle.traceEvents === undefined
214
+ ? (state.updates ?? []).filter((update) => update.type === "progress")
215
+ : progressRecordsFromTrace(bundle.traceEvents);
216
+ const progress = progressTracksFromRecords(progressRecords, now);
217
+ if (progress.length > 0) {
218
+ lines.push("");
219
+ lines.push(ansi.bold("progress"));
220
+ for (const track of progress) {
221
+ lines.push(fitWidth(formatProgressLine(track.estimate, now), size.width));
222
+ const latest = track.samples.at(-1);
223
+ lines.push(
224
+ fitWidth(
225
+ ansi.dim(
226
+ ` ${track.estimate.sampleCount} samples · ${track.estimate.confidence ?? "no"} confidence · updated ${latest?.at ?? "unknown"}`,
227
+ ),
228
+ size.width,
229
+ ),
230
+ );
231
+ }
232
+ }
233
+
207
234
  if (steps.length > 0) {
208
235
  lines.push("");
209
236
  lines.push(ansi.bold("steps"));
package/src/viewer/tui.ts CHANGED
@@ -62,7 +62,7 @@ export async function runViewer(options: ViewerOptions): Promise<void> {
62
62
  };
63
63
 
64
64
  const renderDetail = async (runDir: string, size: ViewportSize): Promise<string[]> => {
65
- const bundle = await readRunBundle(runDir);
65
+ const bundle = await readRunBundle(runDir, { includeTrace: true });
66
66
  if (!bundle) {
67
67
  return ["Run bundle disappeared. Press q to go back."];
68
68
  }
@@ -23,6 +23,7 @@ import type {
23
23
  ConversationRange,
24
24
  ShellActionNodeDefinition,
25
25
  ShellActionResult,
26
+ WorkflowActionContext,
26
27
  WorkflowActionReceipt,
27
28
  WorkflowDefinition,
28
29
  WorkflowEngineOptions,
@@ -36,7 +37,10 @@ import type {
36
37
  WorkflowSource,
37
38
  WorkflowStepRecord,
38
39
  WorkflowTraceEventDraft,
40
+ WorkflowUpdateInput,
41
+ WorkflowUpdateReceipt,
39
42
  } from "./types.js";
43
+ import { UpdateRateLimiter, updateReceipt, validateWorkflowUpdate } from "./updates.js";
40
44
 
41
45
  const DEFAULT_NODE_TIMEOUT_MS = 15 * 60_000;
42
46
  const DEFAULT_MAX_STEPS = 100;
@@ -83,6 +87,17 @@ export class WorkflowEngine {
83
87
  private readonly onRunStarted?: WorkflowEngineOptions["onRunStarted"];
84
88
  private readonly onRunFinishing?: WorkflowEngineOptions["onRunFinishing"];
85
89
  private activeAbort: AbortController | null = null;
90
+ private activeAttempt:
91
+ | {
92
+ runDir: string;
93
+ state: WorkflowRunState;
94
+ nodeId: string;
95
+ attemptId: string;
96
+ signal: AbortSignal;
97
+ }
98
+ | undefined;
99
+ private readonly updateLimiters = new Map<string, UpdateRateLimiter>();
100
+ private readonly updatePublications = new Map<string, Promise<WorkflowUpdateReceipt>>();
86
101
  private cancelled = false;
87
102
  private parked = false;
88
103
  private paused = false;
@@ -103,6 +118,59 @@ export class WorkflowEngine {
103
118
  return this.store.outputRoot;
104
119
  }
105
120
 
121
+ /** Publish a durable update for the currently active attempt without completing it. */
122
+ async publishUpdate(
123
+ step: string,
124
+ attempt: string,
125
+ input: WorkflowUpdateInput,
126
+ idempotencyKey?: string,
127
+ ): Promise<WorkflowUpdateReceipt> {
128
+ const active = this.activeAttempt;
129
+ if (
130
+ active === undefined ||
131
+ active.nodeId !== step ||
132
+ active.attemptId !== attempt ||
133
+ active.signal.aborted
134
+ ) {
135
+ throw new Error(
136
+ `Workflow step ${JSON.stringify(step)} attempt ${JSON.stringify(attempt)} is not active`,
137
+ );
138
+ }
139
+ const receiptKey =
140
+ idempotencyKey === undefined
141
+ ? undefined
142
+ : `${active.state.runId}:${active.attemptId}:${idempotencyKey}`;
143
+ if (receiptKey !== undefined) {
144
+ const prior = this.updatePublications.get(receiptKey);
145
+ if (prior !== undefined) return await prior;
146
+ }
147
+ const publication = (async () => {
148
+ const update = validateWorkflowUpdate(input);
149
+ let limiter = this.updateLimiters.get(active.state.runId);
150
+ if (limiter === undefined) {
151
+ limiter = new UpdateRateLimiter();
152
+ this.updateLimiters.set(active.state.runId, limiter);
153
+ }
154
+ limiter.take();
155
+ const { event, record } = await this.store.publishUpdate(
156
+ active.runDir,
157
+ active.state,
158
+ active.nodeId,
159
+ active.attemptId,
160
+ update,
161
+ { signal: active.signal },
162
+ );
163
+ try {
164
+ this.onEvent?.(event, active.state);
165
+ } catch {
166
+ // UI and logging observers never determine workflow correctness.
167
+ }
168
+ return updateReceipt(record);
169
+ })();
170
+ if (receiptKey !== undefined) this.updatePublications.set(receiptKey, publication);
171
+ return await publication;
172
+ }
173
+
106
174
  /** Abort the currently running node and mark the run cancelled. */
107
175
  cancel(): void {
108
176
  this.cancelled = true;
@@ -492,6 +560,7 @@ export class WorkflowEngine {
492
560
  outputs: {},
493
561
  results: {},
494
562
  steps: [],
563
+ updates: [],
495
564
  };
496
565
  }
497
566
 
@@ -775,6 +844,7 @@ export class WorkflowEngine {
775
844
  timer = setTimeout(() => {
776
845
  abort.abort(new TimeoutError(timeoutMs));
777
846
  }, timeoutMs);
847
+ this.activeAttempt = { runDir, state, nodeId, attemptId, signal: abort.signal };
778
848
  const dispatched = this.dispatchNode(
779
849
  workflow,
780
850
  state,
@@ -815,9 +885,19 @@ export class WorkflowEngine {
815
885
  if (timer !== undefined) {
816
886
  clearTimeout(timer);
817
887
  }
888
+ if (!abort.signal.aborted) {
889
+ abort.abort(new Error(`Workflow node ${nodeId} is no longer active`));
890
+ }
818
891
  if (this.activeAbort === abort) {
819
892
  this.activeAbort = null;
820
893
  }
894
+ if (this.activeAttempt?.attemptId === attemptId) {
895
+ this.activeAttempt = undefined;
896
+ }
897
+ const receiptPrefix = `${state.runId}:${attemptId}:`;
898
+ for (const key of this.updatePublications.keys()) {
899
+ if (key.startsWith(receiptPrefix)) this.updatePublications.delete(key);
900
+ }
821
901
  }
822
902
  }
823
903
 
@@ -895,7 +975,7 @@ export class WorkflowEngine {
895
975
  return { output: receipt, promptText: null };
896
976
  }
897
977
  case "action":
898
- return await this.runActionNode(node, context, signal, meta);
978
+ return await this.runActionNode(node, context, nodeId, attemptId, signal, meta);
899
979
  case "checkpoint":
900
980
  return await runCheckpointNode(node, context);
901
981
  }
@@ -955,7 +1035,17 @@ export class WorkflowEngine {
955
1035
  ...(node.expectedOutput !== undefined ? { expectedOutput: node.expectedOutput } : {}),
956
1036
  },
957
1037
  prompt,
1038
+ ...(state.runTitle !== undefined || node.statusDetail !== undefined
1039
+ ? {
1040
+ presentation: {
1041
+ ...(state.runTitle !== undefined ? { runTitle: state.runTitle } : {}),
1042
+ ...(node.statusDetail !== undefined ? { statusDetail: node.statusDetail } : {}),
1043
+ },
1044
+ }
1045
+ : {}),
958
1046
  accept: async (output) => await this.acceptSubmission(node, context, output),
1047
+ publishUpdate: async (update, idempotencyKey) =>
1048
+ await this.publishUpdate(nodeId, attemptId, update, idempotencyKey),
959
1049
  },
960
1050
  signal,
961
1051
  );
@@ -987,14 +1077,20 @@ export class WorkflowEngine {
987
1077
  private async runActionNode(
988
1078
  node: ActionNodeDefinition,
989
1079
  context: WorkflowNodeContext,
1080
+ nodeId: string,
1081
+ attemptId: string,
990
1082
  signal: AbortSignal,
991
1083
  meta: NodeExecutionMeta,
992
1084
  ): Promise<NodeExecution> {
1085
+ const actionContext: WorkflowActionContext = {
1086
+ ...context,
1087
+ publishUpdate: async (update) => await this.publishUpdate(nodeId, attemptId, update),
1088
+ };
993
1089
  if ("exec" in node) {
994
- return await runShellActionNode(node, context, signal, meta);
1090
+ return await runShellActionNode(node, context, actionContext, signal, meta);
995
1091
  }
996
1092
  meta.action = { actionType: "function" };
997
- const output = await node.run(context);
1093
+ const output = await node.run(actionContext);
998
1094
  return { output, promptText: null, action: { actionType: "function" } };
999
1095
  }
1000
1096
 
@@ -1078,13 +1174,28 @@ function shellReceipt(result: ShellActionResult): WorkflowActionReceipt {
1078
1174
  async function runShellActionNode(
1079
1175
  node: ShellActionNodeDefinition,
1080
1176
  context: WorkflowNodeContext,
1177
+ actionContext: WorkflowActionContext,
1081
1178
  signal: AbortSignal,
1082
1179
  meta: NodeExecutionMeta,
1083
1180
  ): Promise<NodeExecution> {
1084
1181
  const spec = await node.exec(context);
1182
+ const streams = new Set(node.updates?.streams ?? ["stdout"]);
1085
1183
  let result: ShellActionResult;
1086
1184
  try {
1087
- result = await runShellAction(spec, signal);
1185
+ result = await runShellAction(
1186
+ spec,
1187
+ signal,
1188
+ node.updates === undefined
1189
+ ? undefined
1190
+ : async (line) => {
1191
+ if (!streams.has(line.stream)) return;
1192
+ const parsed = await node.updates?.parseLine(line, actionContext);
1193
+ if (parsed === undefined) return;
1194
+ for (const update of Array.isArray(parsed) ? parsed : [parsed]) {
1195
+ await actionContext.publishUpdate(update);
1196
+ }
1197
+ },
1198
+ );
1088
1199
  } catch (error) {
1089
1200
  const failed = shellResultFromError(error);
1090
1201
  if (failed) {
@@ -1191,6 +1302,8 @@ export function appendStepContract(
1191
1302
  "---",
1192
1303
  `Workflow step contract (workflow: ${workflowName}, step: ${nodeId}, attempt: ${attemptId})`,
1193
1304
  "",
1305
+ "While this step is active, you may publish non-completing updates with:",
1306
+ `{"action": "update", "step": ${JSON.stringify(nodeId)}, "attempt": ${JSON.stringify(attemptId)}, "update": {"type": "...", "key": "...", "data": {...}}}`,
1194
1307
  "Complete this step by calling the `workflow` tool exactly once with:",
1195
1308
  `{"action": "submit", "step": ${JSON.stringify(nodeId)}, "attempt": ${JSON.stringify(attemptId)}, "output": <your result>}`,
1196
1309
  `Expected output: ${expectedOutput ?? "a JSON object with your result"}`,
@@ -29,6 +29,28 @@ export {
29
29
  type WorkflowSearchPaths,
30
30
  } from "./loader.js";
31
31
  export { renderShellCommand, runShellAction } from "./shell.js";
32
+ export {
33
+ estimateProgress,
34
+ formatProgressLine,
35
+ formatProgressReport,
36
+ formatRemaining,
37
+ prioritizeProgressEstimates,
38
+ progressRecordsFromTrace,
39
+ progressTracksFromRecords,
40
+ type ProgressConfidence,
41
+ type ProgressEstimate,
42
+ type ProgressSample,
43
+ type ProgressTrackState,
44
+ } from "./progress.js";
45
+ export {
46
+ MAX_CURRENT_UPDATES,
47
+ MAX_UPDATE_DATA_BYTES,
48
+ UPDATE_RATE_BURST,
49
+ UPDATE_RATE_PER_SECOND,
50
+ updateProjection,
51
+ validateProgressData,
52
+ validateWorkflowUpdate,
53
+ } from "./updates.js";
32
54
  export { sanitizeText, stripAnsi } from "./text.js";
33
55
  export {
34
56
  ARTIFACT_THRESHOLD_BYTES,
@@ -51,11 +73,13 @@ export {
51
73
  readRunBundle,
52
74
  workflowRunsBaseDir,
53
75
  type LoadedRunBundle,
76
+ type ReadRunBundleOptions,
54
77
  } from "./store.js";
55
78
  export type {
56
79
  AgentNodeDefinition,
57
80
  AgentStepContract,
58
81
  AgentStepExecutor,
82
+ AgentStepPresentation,
59
83
  AgentStepRequest,
60
84
  AgentStepSubmission,
61
85
  ActionNodeDefinition,
@@ -70,6 +94,7 @@ export type {
70
94
  ShellActionExecution,
71
95
  ShellActionNodeDefinition,
72
96
  ShellActionResult,
97
+ WorkflowActionContext,
73
98
  WorkflowActionReceipt,
74
99
  WorkflowDefinition,
75
100
  WorkflowDefinitionSnapshot,
@@ -85,6 +110,8 @@ export type {
85
110
  WorkflowNotificationRequest,
86
111
  WorkflowNotificationSink,
87
112
  WorkflowPresentationContext,
113
+ WorkflowProgressData,
114
+ WorkflowProgressStatus,
88
115
  WorkflowRunManifest,
89
116
  WorkflowRunResult,
90
117
  WorkflowRunState,
@@ -95,4 +122,9 @@ export type {
95
122
  WorkflowStepRecord,
96
123
  WorkflowTraceEvent,
97
124
  WorkflowTraceEventDraft,
125
+ WorkflowUpdateInput,
126
+ WorkflowUpdateReceipt,
127
+ WorkflowUpdateRecord,
128
+ ShellActionUpdates,
129
+ ShellUpdateLine,
98
130
  } from "./types.js";