@osolmaz/pi-workflows 0.13.1 → 0.13.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.
- package/README.md +9 -7
- package/dist/builtins/autodoc.workflow.d.ts +5 -5
- package/dist/builtins/autoimplement.workflow.d.ts +69 -61
- package/dist/builtins/autoimplement.workflow.js +47 -8
- package/dist/builtins/autoimplement.workflow.js.map +1 -1
- package/dist/builtins/autoplan.workflow.d.ts +11 -5
- package/dist/builtins/autoplan.workflow.js +68 -32
- package/dist/builtins/autoplan.workflow.js.map +1 -1
- package/dist/builtins/catalog.js +4 -4
- package/dist/builtins/change-verification.workflow.d.ts +1 -1
- package/dist/builtins/plain-summary.workflow.d.ts +1 -1
- package/dist/builtins/plain-summary.workflow.js +35 -24
- package/dist/builtins/plain-summary.workflow.js.map +1 -1
- package/dist/builtins/plan-approval.workflow.d.ts +1 -1
- package/dist/builtins/plan-change.workflow.d.ts +25 -23
- package/dist/builtins/sanity-check.workflow.d.ts +3 -3
- package/dist/builtins/sanity-check.workflow.js +19 -22
- package/dist/builtins/sanity-check.workflow.js.map +1 -1
- package/dist/builtins/workspace-preparation.workflow.d.ts +1 -1
- package/dist/controllers/index.d.ts +2 -2
- package/dist/controllers/index.js.map +1 -1
- package/dist/controllers/sqlite.js +88 -61
- package/dist/controllers/sqlite.js.map +1 -1
- package/dist/controllers/types.d.ts +34 -0
- package/dist/controllers/workflow-engine-scheduler.d.ts +5 -1
- package/dist/controllers/workflow-engine-scheduler.js +83 -1
- package/dist/controllers/workflow-engine-scheduler.js.map +1 -1
- package/dist/controllers/workflows.d.ts +8 -1
- package/dist/controllers/workflows.js +36 -0
- package/dist/controllers/workflows.js.map +1 -1
- package/dist/extension/controller-host.d.ts +2 -1
- package/dist/extension/controller-host.js +1 -1
- package/dist/extension/controller-host.js.map +1 -1
- package/dist/extension/decision-channels.js +45 -7
- package/dist/extension/decision-channels.js.map +1 -1
- package/dist/extension/follow-up-coordinator.d.ts +27 -0
- package/dist/extension/follow-up-coordinator.js +131 -0
- package/dist/extension/follow-up-coordinator.js.map +1 -0
- package/dist/extension/index.d.ts +9 -0
- package/dist/extension/index.js +462 -76
- package/dist/extension/index.js.map +1 -1
- package/dist/extension/recorder.d.ts +1 -1
- package/dist/extension/recorder.js +8 -8
- package/dist/extension/recorder.js.map +1 -1
- package/dist/extension/session-events.d.ts +2 -3
- package/dist/extension/session-events.js +11 -10
- package/dist/extension/session-events.js.map +1 -1
- package/dist/extension/widget.js +9 -0
- package/dist/extension/widget.js.map +1 -1
- package/dist/state/database.d.ts +2 -1
- package/dist/state/database.js +11 -13
- package/dist/state/database.js.map +1 -1
- package/dist/state/json.js +6 -1
- package/dist/state/json.js.map +1 -1
- package/dist/state/mutation.d.ts +1 -1
- package/dist/state/mutation.js.map +1 -1
- package/dist/state/prune.d.ts +18 -0
- package/dist/state/prune.js +373 -0
- package/dist/state/prune.js.map +1 -0
- package/dist/state/schema.d.ts +1 -1
- package/dist/state/schema.js +130 -13
- package/dist/state/schema.js.map +1 -1
- package/dist/viewer/cli.d.ts +3 -1
- package/dist/viewer/cli.js +55 -4
- package/dist/viewer/cli.js.map +1 -1
- package/dist/viewer/render.js +19 -1
- package/dist/viewer/render.js.map +1 -1
- package/dist/viewer/session-reducer.d.ts +0 -1
- package/dist/viewer/session-reducer.js +2 -24
- package/dist/viewer/session-reducer.js.map +1 -1
- package/dist/workflows/composition.d.ts +2 -0
- package/dist/workflows/composition.js +15 -0
- package/dist/workflows/composition.js.map +1 -1
- package/dist/workflows/definition.d.ts +6 -3
- package/dist/workflows/definition.js +3 -0
- package/dist/workflows/definition.js.map +1 -1
- package/dist/workflows/engine.d.ts +6 -1
- package/dist/workflows/engine.js +303 -36
- package/dist/workflows/engine.js.map +1 -1
- package/dist/workflows/human-decision.d.ts +1 -0
- package/dist/workflows/human-decision.js +25 -9
- package/dist/workflows/human-decision.js.map +1 -1
- package/dist/workflows/index.d.ts +3 -1
- package/dist/workflows/index.js +2 -0
- package/dist/workflows/index.js.map +1 -1
- package/dist/workflows/json-patch.d.ts +47 -0
- package/dist/workflows/json-patch.js +298 -0
- package/dist/workflows/json-patch.js.map +1 -0
- package/dist/workflows/schema.js +29 -1
- package/dist/workflows/schema.js.map +1 -1
- package/dist/workflows/settings.d.ts +128 -0
- package/dist/workflows/settings.js +199 -0
- package/dist/workflows/settings.js.map +1 -0
- package/dist/workflows/store.d.ts +81 -3
- package/dist/workflows/store.js +1563 -50
- package/dist/workflows/store.js.map +1 -1
- package/dist/workflows/tool-input.d.ts +22 -0
- package/dist/workflows/tool-input.js +43 -0
- package/dist/workflows/tool-input.js.map +1 -1
- package/dist/workflows/types.d.ts +41 -6
- package/docs/2026-08-25-workflow-follow-ups.md +132 -0
- package/docs/2026-08-25-workflow-settings.md +169 -0
- package/docs/DEFERRED_TURNS.md +6 -0
- package/docs/DESIGN_PHILOSOPHY.md +2 -0
- package/docs/SQLITE_STATE.md +36 -17
- package/docs/WORKFLOW_COMPOSITION.md +15 -0
- package/docs/WORKFLOW_STEP_MESSAGES.md +4 -2
- package/docs/plans/2026-08-25-autoplan-user-intent-capture-plan.md +107 -0
- package/docs/plans/2026-08-25-live-workflow-settings-plan.md +532 -0
- package/docs/plans/2026-08-25-workflow-run-storage-plan.md +67 -0
- package/docs/session-event-journal.md +2 -3
- package/docs/tui-viewer.md +7 -6
- package/docs/workflows.md +58 -10
- package/examples/workflows/live-settings.workflow.ts +93 -0
- package/herdr-plugin.toml +1 -1
- package/package.json +1 -1
- package/src/builtins/autoimplement.workflow.ts +56 -8
- package/src/builtins/autoplan.workflow.ts +80 -32
- package/src/builtins/catalog.ts +4 -4
- package/src/builtins/plain-summary.workflow.ts +38 -40
- package/src/builtins/sanity-check.workflow.ts +19 -22
- package/src/controllers/index.ts +6 -0
- package/src/controllers/sqlite.ts +132 -72
- package/src/controllers/types.ts +40 -0
- package/src/controllers/workflow-engine-scheduler.ts +103 -1
- package/src/controllers/workflows.ts +68 -0
- package/src/extension/controller-host.ts +6 -1
- package/src/extension/decision-channels.ts +47 -7
- package/src/extension/follow-up-coordinator.ts +151 -0
- package/src/extension/index.ts +540 -89
- package/src/extension/recorder.ts +10 -8
- package/src/extension/session-events.ts +15 -13
- package/src/extension/widget.ts +8 -0
- package/src/state/database.ts +12 -12
- package/src/state/json.ts +6 -1
- package/src/state/mutation.ts +4 -1
- package/src/state/prune.ts +502 -0
- package/src/state/schema.ts +130 -13
- package/src/viewer/cli.ts +52 -5
- package/src/viewer/render.ts +43 -1
- package/src/viewer/session-reducer.ts +2 -29
- package/src/workflows/composition.ts +19 -0
- package/src/workflows/definition.ts +19 -5
- package/src/workflows/engine.ts +365 -36
- package/src/workflows/human-decision.ts +41 -11
- package/src/workflows/index.ts +43 -0
- package/src/workflows/json-patch.ts +375 -0
- package/src/workflows/schema.ts +31 -1
- package/src/workflows/settings.ts +430 -0
- package/src/workflows/store.ts +2268 -121
- package/src/workflows/tool-input.ts +58 -0
- package/src/workflows/types.ts +43 -5
package/src/state/schema.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { createHash } from "node:crypto";
|
|
|
3
3
|
export const STATE_APPLICATION_ID = 0x50495746;
|
|
4
4
|
export const STATE_SCHEMA_NAME = "pi-workflows-state";
|
|
5
5
|
export const STATE_SCHEMA_VERSION = 1;
|
|
6
|
-
export const STATE_APP_VERSION = "0.
|
|
6
|
+
export const STATE_APP_VERSION = "0.13.3";
|
|
7
7
|
|
|
8
8
|
export const STATE_SCHEMA_SQL = String.raw`
|
|
9
9
|
CREATE TABLE schema_meta (
|
|
@@ -34,7 +34,8 @@ CREATE TABLE blobs (
|
|
|
34
34
|
CREATE TABLE resources (
|
|
35
35
|
resource_id TEXT PRIMARY KEY,
|
|
36
36
|
resource_type TEXT NOT NULL CHECK (resource_type IN (
|
|
37
|
-
'run', 'session', 'decision', 'controller', 'effect', 'channel', 'notification', 'turn_intent'
|
|
37
|
+
'run', 'session', 'decision', 'controller', 'effect', 'channel', 'notification', 'turn_intent',
|
|
38
|
+
'settings', 'follow_up_queue', 'follow_up'
|
|
38
39
|
)),
|
|
39
40
|
aggregate_key TEXT NOT NULL,
|
|
40
41
|
revision INTEGER NOT NULL DEFAULT 0 CHECK (revision >= 0),
|
|
@@ -94,11 +95,7 @@ CREATE TABLE runs (
|
|
|
94
95
|
parent_run_id TEXT REFERENCES runs(run_id),
|
|
95
96
|
definition_digest BLOB NOT NULL REFERENCES workflow_definitions(definition_digest),
|
|
96
97
|
workflow_ref TEXT NOT NULL,
|
|
97
|
-
workflow_source_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
|
|
98
98
|
launch_options_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
|
|
99
|
-
source_type TEXT NOT NULL CHECK (source_type IN ('builtin', 'file')),
|
|
100
|
-
source_ref TEXT NOT NULL,
|
|
101
|
-
source_revision TEXT NOT NULL,
|
|
102
99
|
title TEXT,
|
|
103
100
|
status TEXT NOT NULL CHECK (status IN (
|
|
104
101
|
'queued', 'running', 'waiting', 'completed', 'failed', 'timed_out', 'cancelled'
|
|
@@ -106,7 +103,7 @@ CREATE TABLE runs (
|
|
|
106
103
|
paused INTEGER NOT NULL DEFAULT 0 CHECK (paused IN (0, 1)),
|
|
107
104
|
status_detail TEXT,
|
|
108
105
|
input_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
|
|
109
|
-
|
|
106
|
+
final_output_hash BLOB REFERENCES blobs(blob_hash),
|
|
110
107
|
error_hash BLOB REFERENCES blobs(blob_hash),
|
|
111
108
|
created_at INTEGER NOT NULL,
|
|
112
109
|
updated_at INTEGER NOT NULL,
|
|
@@ -118,6 +115,15 @@ CREATE INDEX runs_project_idx ON runs(project_id, created_at DESC);
|
|
|
118
115
|
CREATE INDEX runs_status_idx ON runs(status, updated_at DESC);
|
|
119
116
|
CREATE INDEX runs_parent_idx ON runs(parent_run_id);
|
|
120
117
|
|
|
118
|
+
CREATE TABLE run_sources (
|
|
119
|
+
run_id TEXT NOT NULL REFERENCES runs(run_id) ON DELETE CASCADE,
|
|
120
|
+
mount_path TEXT NOT NULL,
|
|
121
|
+
source_type TEXT NOT NULL CHECK (source_type IN ('builtin', 'file')),
|
|
122
|
+
source_ref TEXT NOT NULL,
|
|
123
|
+
source_revision TEXT NOT NULL,
|
|
124
|
+
PRIMARY KEY (run_id, mount_path)
|
|
125
|
+
) STRICT;
|
|
126
|
+
|
|
121
127
|
CREATE TABLE run_bindings (
|
|
122
128
|
run_id TEXT PRIMARY KEY REFERENCES runs(run_id) ON DELETE CASCADE,
|
|
123
129
|
origin_session_id TEXT NOT NULL,
|
|
@@ -127,6 +133,92 @@ CREATE TABLE run_bindings (
|
|
|
127
133
|
|
|
128
134
|
CREATE INDEX run_bindings_session_idx ON run_bindings(origin_session_id, created_at DESC);
|
|
129
135
|
|
|
136
|
+
CREATE TABLE workflow_settings (
|
|
137
|
+
scope_id TEXT PRIMARY KEY,
|
|
138
|
+
resource_id TEXT NOT NULL UNIQUE REFERENCES resources(resource_id) ON DELETE CASCADE,
|
|
139
|
+
origin_run_id TEXT NOT NULL REFERENCES runs(run_id) ON DELETE CASCADE,
|
|
140
|
+
active_run_id TEXT NOT NULL REFERENCES runs(run_id) ON DELETE CASCADE,
|
|
141
|
+
mount_path TEXT NOT NULL,
|
|
142
|
+
invocation INTEGER NOT NULL CHECK (invocation > 0),
|
|
143
|
+
initial_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
|
|
144
|
+
current_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
|
|
145
|
+
created_at INTEGER NOT NULL,
|
|
146
|
+
updated_at INTEGER NOT NULL,
|
|
147
|
+
UNIQUE (origin_run_id, mount_path, invocation)
|
|
148
|
+
) STRICT;
|
|
149
|
+
|
|
150
|
+
CREATE INDEX workflow_settings_active_run_idx ON workflow_settings(active_run_id, mount_path, invocation);
|
|
151
|
+
|
|
152
|
+
CREATE TABLE workflow_setting_changes (
|
|
153
|
+
change_id TEXT PRIMARY KEY,
|
|
154
|
+
scope_id TEXT NOT NULL REFERENCES workflow_settings(scope_id) ON DELETE CASCADE,
|
|
155
|
+
request_id TEXT NOT NULL,
|
|
156
|
+
change_number INTEGER NOT NULL CHECK (change_number > 0),
|
|
157
|
+
actor_type TEXT NOT NULL CHECK (actor_type IN (
|
|
158
|
+
'session', 'host', 'controller', 'channel', 'human', 'policy', 'control', 'system'
|
|
159
|
+
)),
|
|
160
|
+
actor_id TEXT,
|
|
161
|
+
source_type TEXT NOT NULL,
|
|
162
|
+
patch_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
|
|
163
|
+
before_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
|
|
164
|
+
after_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
|
|
165
|
+
accepted_at INTEGER NOT NULL,
|
|
166
|
+
UNIQUE (scope_id, request_id),
|
|
167
|
+
UNIQUE (scope_id, change_number)
|
|
168
|
+
) STRICT;
|
|
169
|
+
|
|
170
|
+
CREATE TABLE workflow_follow_up_queues (
|
|
171
|
+
run_id TEXT PRIMARY KEY REFERENCES runs(run_id) ON DELETE CASCADE,
|
|
172
|
+
resource_id TEXT NOT NULL UNIQUE REFERENCES resources(resource_id) ON DELETE CASCADE,
|
|
173
|
+
origin_session_id TEXT,
|
|
174
|
+
presentation_state TEXT NOT NULL DEFAULT 'none' CHECK (presentation_state IN (
|
|
175
|
+
'none', 'not-needed', 'pending', 'settled', 'unavailable'
|
|
176
|
+
)),
|
|
177
|
+
presentation_entry_id TEXT,
|
|
178
|
+
presentation_assistant_entry_id TEXT,
|
|
179
|
+
presentation_reason_hash BLOB REFERENCES blobs(blob_hash),
|
|
180
|
+
presentation_updated_at INTEGER,
|
|
181
|
+
created_at INTEGER NOT NULL,
|
|
182
|
+
updated_at INTEGER NOT NULL,
|
|
183
|
+
CHECK (
|
|
184
|
+
(presentation_state IN ('none', 'not-needed', 'pending') AND presentation_assistant_entry_id IS NULL AND presentation_reason_hash IS NULL)
|
|
185
|
+
OR
|
|
186
|
+
(presentation_state = 'unavailable' AND presentation_assistant_entry_id IS NULL AND presentation_reason_hash IS NOT NULL)
|
|
187
|
+
OR
|
|
188
|
+
(presentation_state = 'settled' AND presentation_entry_id IS NOT NULL AND presentation_assistant_entry_id IS NOT NULL AND presentation_reason_hash IS NULL)
|
|
189
|
+
)
|
|
190
|
+
) STRICT;
|
|
191
|
+
|
|
192
|
+
CREATE TABLE workflow_follow_ups (
|
|
193
|
+
follow_up_id TEXT PRIMARY KEY,
|
|
194
|
+
resource_id TEXT NOT NULL UNIQUE REFERENCES resources(resource_id) ON DELETE CASCADE,
|
|
195
|
+
queue_resource_id TEXT NOT NULL REFERENCES resources(resource_id),
|
|
196
|
+
run_id TEXT NOT NULL REFERENCES workflow_follow_up_queues(run_id) ON DELETE CASCADE,
|
|
197
|
+
request_id TEXT NOT NULL,
|
|
198
|
+
order_number INTEGER NOT NULL CHECK (order_number > 0),
|
|
199
|
+
target_session_id TEXT NOT NULL,
|
|
200
|
+
actor_type TEXT NOT NULL CHECK (actor_type IN (
|
|
201
|
+
'session', 'host', 'controller', 'channel', 'human', 'policy', 'control', 'system'
|
|
202
|
+
)),
|
|
203
|
+
actor_id TEXT,
|
|
204
|
+
source_type TEXT NOT NULL,
|
|
205
|
+
prompt_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
|
|
206
|
+
status TEXT NOT NULL CHECK (status IN (
|
|
207
|
+
'queued', 'pending_presentation', 'ready', 'sent', 'removed', 'cancelled'
|
|
208
|
+
)),
|
|
209
|
+
session_entry_id TEXT,
|
|
210
|
+
reason_hash BLOB REFERENCES blobs(blob_hash),
|
|
211
|
+
created_at INTEGER NOT NULL,
|
|
212
|
+
updated_at INTEGER NOT NULL,
|
|
213
|
+
sent_at INTEGER,
|
|
214
|
+
UNIQUE (run_id, request_id),
|
|
215
|
+
UNIQUE (run_id, order_number),
|
|
216
|
+
CHECK ((status = 'sent') = (session_entry_id IS NOT NULL AND sent_at IS NOT NULL)),
|
|
217
|
+
CHECK ((status IN ('removed', 'cancelled')) = (reason_hash IS NOT NULL))
|
|
218
|
+
) STRICT;
|
|
219
|
+
|
|
220
|
+
CREATE INDEX workflow_follow_ups_delivery_idx ON workflow_follow_ups(target_session_id, status, order_number);
|
|
221
|
+
|
|
130
222
|
CREATE TABLE run_queue (
|
|
131
223
|
run_id TEXT PRIMARY KEY REFERENCES runs(run_id) ON DELETE CASCADE,
|
|
132
224
|
status TEXT NOT NULL CHECK (status IN (
|
|
@@ -155,14 +247,16 @@ CREATE TABLE node_attempts (
|
|
|
155
247
|
attempt_number INTEGER NOT NULL CHECK (attempt_number > 0),
|
|
156
248
|
node_type TEXT NOT NULL,
|
|
157
249
|
status TEXT NOT NULL CHECK (status IN (
|
|
158
|
-
'pending', 'running', 'waiting', '
|
|
250
|
+
'pending', 'running', 'waiting', 'interrupted',
|
|
251
|
+
'completed', 'failed', 'timed_out', 'cancelled'
|
|
159
252
|
)),
|
|
160
|
-
|
|
161
|
-
contract_hash BLOB REFERENCES blobs(blob_hash),
|
|
162
|
-
presentation_hash BLOB REFERENCES blobs(blob_hash),
|
|
253
|
+
prompt_hash BLOB REFERENCES blobs(blob_hash),
|
|
163
254
|
output_hash BLOB REFERENCES blobs(blob_hash),
|
|
164
|
-
|
|
255
|
+
receipt_hash BLOB REFERENCES blobs(blob_hash),
|
|
165
256
|
error_hash BLOB REFERENCES blobs(blob_hash),
|
|
257
|
+
settings_scope_id TEXT REFERENCES workflow_settings(scope_id),
|
|
258
|
+
settings_change_number INTEGER CHECK (settings_change_number IS NULL OR settings_change_number >= 0),
|
|
259
|
+
settings_hash BLOB REFERENCES blobs(blob_hash),
|
|
166
260
|
started_at INTEGER,
|
|
167
261
|
deadline_at INTEGER,
|
|
168
262
|
finished_at INTEGER,
|
|
@@ -175,10 +269,22 @@ CREATE UNIQUE INDEX node_attempts_active_idx ON node_attempts(run_id)
|
|
|
175
269
|
WHERE status IN ('pending', 'running', 'waiting');
|
|
176
270
|
CREATE INDEX node_attempts_run_idx ON node_attempts(run_id, created_at);
|
|
177
271
|
|
|
272
|
+
CREATE TABLE run_steps (
|
|
273
|
+
run_id TEXT NOT NULL REFERENCES runs(run_id) ON DELETE CASCADE,
|
|
274
|
+
step_index INTEGER NOT NULL CHECK (step_index >= 0),
|
|
275
|
+
attempt_id TEXT NOT NULL REFERENCES node_attempts(attempt_id),
|
|
276
|
+
output_override_hash BLOB REFERENCES blobs(blob_hash),
|
|
277
|
+
PRIMARY KEY (run_id, step_index),
|
|
278
|
+
UNIQUE (run_id, attempt_id)
|
|
279
|
+
) STRICT;
|
|
280
|
+
|
|
281
|
+
CREATE INDEX run_steps_attempt_idx ON run_steps(attempt_id);
|
|
282
|
+
|
|
178
283
|
CREATE TABLE workflow_updates (
|
|
179
284
|
update_id TEXT PRIMARY KEY,
|
|
180
285
|
attempt_id TEXT NOT NULL REFERENCES node_attempts(attempt_id) ON DELETE CASCADE,
|
|
181
286
|
update_seq INTEGER NOT NULL CHECK (update_seq > 0),
|
|
287
|
+
run_revision INTEGER NOT NULL CHECK (run_revision > 0),
|
|
182
288
|
update_type TEXT NOT NULL,
|
|
183
289
|
update_key TEXT NOT NULL,
|
|
184
290
|
data_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
|
|
@@ -216,6 +322,18 @@ CREATE TABLE session_entries (
|
|
|
216
322
|
UNIQUE (segment_id, entry_id)
|
|
217
323
|
) STRICT;
|
|
218
324
|
|
|
325
|
+
CREATE TABLE attempt_entries (
|
|
326
|
+
attempt_id TEXT NOT NULL REFERENCES node_attempts(attempt_id) ON DELETE CASCADE,
|
|
327
|
+
role TEXT NOT NULL CHECK (role IN ('prompt', 'response', 'first', 'last')),
|
|
328
|
+
segment_id TEXT NOT NULL,
|
|
329
|
+
entry_id TEXT NOT NULL,
|
|
330
|
+
PRIMARY KEY (attempt_id, role),
|
|
331
|
+
FOREIGN KEY (segment_id, entry_id)
|
|
332
|
+
REFERENCES session_entries(segment_id, entry_id) ON DELETE CASCADE
|
|
333
|
+
) STRICT;
|
|
334
|
+
|
|
335
|
+
CREATE INDEX attempt_entries_entry_idx ON attempt_entries(segment_id, entry_id);
|
|
336
|
+
|
|
219
337
|
CREATE TABLE session_events (
|
|
220
338
|
segment_id TEXT NOT NULL REFERENCES session_segments(segment_id) ON DELETE CASCADE,
|
|
221
339
|
event_seq INTEGER NOT NULL CHECK (event_seq > 0),
|
|
@@ -287,7 +405,6 @@ CREATE TABLE continuations (
|
|
|
287
405
|
decision_id TEXT PRIMARY KEY REFERENCES human_decisions(decision_id) ON DELETE CASCADE,
|
|
288
406
|
parent_run_id TEXT NOT NULL UNIQUE REFERENCES runs(run_id),
|
|
289
407
|
continuation_run_id TEXT NOT NULL UNIQUE REFERENCES runs(run_id),
|
|
290
|
-
response_hash BLOB NOT NULL REFERENCES blobs(blob_hash),
|
|
291
408
|
created_at INTEGER NOT NULL
|
|
292
409
|
) STRICT;
|
|
293
410
|
|
package/src/viewer/cli.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { SqliteControllerStore } from "../controllers/sqlite.js";
|
|
|
6
6
|
import { syncHerdrPlugin } from "../herdr/setup.js";
|
|
7
7
|
import { sanitizeText } from "../render/ansi.js";
|
|
8
8
|
import { StateDatabase } from "../state/database.js";
|
|
9
|
+
import { pruneState } from "../state/prune.js";
|
|
9
10
|
import { WorkflowRunStore, workflowStateDatabasePath } from "../workflows/store.js";
|
|
10
11
|
import {
|
|
11
12
|
formatDuration,
|
|
@@ -25,6 +26,8 @@ Usage:
|
|
|
25
26
|
pi-workflows controller <controller> <key>
|
|
26
27
|
pi-workflows state status|verify
|
|
27
28
|
pi-workflows state backup <destination>
|
|
29
|
+
pi-workflows state prune --before <timestamp> --dry-run
|
|
30
|
+
pi-workflows state prune --before <timestamp> --backup <absolute-path> --apply
|
|
28
31
|
pi-workflows host [--project <dir>] [-- <extra pi args>]
|
|
29
32
|
pi-workflows herdr sync [--json]
|
|
30
33
|
pi-workflows herdr setup [--json]
|
|
@@ -38,8 +41,10 @@ export type CliArgs = {
|
|
|
38
41
|
controllerName?: string;
|
|
39
42
|
resourceKey?: string;
|
|
40
43
|
herdrAction?: string;
|
|
41
|
-
stateAction?: "status" | "verify" | "backup";
|
|
44
|
+
stateAction?: "status" | "verify" | "backup" | "prune";
|
|
42
45
|
backupDestination?: string;
|
|
46
|
+
pruneBefore?: string;
|
|
47
|
+
pruneApply?: boolean;
|
|
43
48
|
once: boolean;
|
|
44
49
|
json: boolean;
|
|
45
50
|
project?: string | undefined;
|
|
@@ -52,12 +57,20 @@ export function parseCliArgs(argv: string[]): CliArgs {
|
|
|
52
57
|
let once = false;
|
|
53
58
|
let json = false;
|
|
54
59
|
let project: string | undefined;
|
|
60
|
+
let pruneBefore: string | undefined;
|
|
61
|
+
let backupDestination: string | undefined;
|
|
62
|
+
let pruneApply = false;
|
|
63
|
+
let pruneDryRun = false;
|
|
55
64
|
const positionals: string[] = [];
|
|
56
65
|
const piArgs: string[] = [];
|
|
57
66
|
|
|
58
67
|
while (args.length > 0) {
|
|
59
68
|
const arg = args.shift() as string;
|
|
60
69
|
if (arg === "--project") project = requiredValue(args, "--project");
|
|
70
|
+
else if (arg === "--before") pruneBefore = requiredValue(args, "--before");
|
|
71
|
+
else if (arg === "--backup") backupDestination = requiredValue(args, "--backup");
|
|
72
|
+
else if (arg === "--apply") pruneApply = true;
|
|
73
|
+
else if (arg === "--dry-run") pruneDryRun = true;
|
|
61
74
|
else if (arg === "--once") once = true;
|
|
62
75
|
else if (arg === "--json") json = true;
|
|
63
76
|
else if (arg === "--help" || arg === "-h") return { command: "help", once, json };
|
|
@@ -80,8 +93,30 @@ export function parseCliArgs(argv: string[]): CliArgs {
|
|
|
80
93
|
}
|
|
81
94
|
if (command === "state") {
|
|
82
95
|
const action = positionals[0];
|
|
83
|
-
if (action !== "status" && action !== "verify" && action !== "backup") {
|
|
84
|
-
throw new Error("state requires status, verify, or
|
|
96
|
+
if (action !== "status" && action !== "verify" && action !== "backup" && action !== "prune") {
|
|
97
|
+
throw new Error("state requires status, verify, backup, or prune");
|
|
98
|
+
}
|
|
99
|
+
if (action === "prune") {
|
|
100
|
+
if (positionals.length !== 1) throw new Error("state prune accepts no positional arguments");
|
|
101
|
+
if (pruneBefore === undefined) throw new Error("state prune requires --before <timestamp>");
|
|
102
|
+
if (pruneApply === pruneDryRun) {
|
|
103
|
+
throw new Error("state prune requires exactly one of --dry-run or --apply");
|
|
104
|
+
}
|
|
105
|
+
if (pruneApply && backupDestination === undefined) {
|
|
106
|
+
throw new Error("state prune --apply requires --backup <absolute-path>");
|
|
107
|
+
}
|
|
108
|
+
if (pruneDryRun && backupDestination !== undefined) {
|
|
109
|
+
throw new Error("state prune --dry-run does not accept --backup");
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
command,
|
|
113
|
+
stateAction: action,
|
|
114
|
+
pruneBefore,
|
|
115
|
+
pruneApply,
|
|
116
|
+
...(backupDestination === undefined ? {} : { backupDestination }),
|
|
117
|
+
once,
|
|
118
|
+
json,
|
|
119
|
+
};
|
|
85
120
|
}
|
|
86
121
|
if (action === "backup") {
|
|
87
122
|
if (positionals.length !== 2) throw new Error("state backup requires <destination>");
|
|
@@ -251,6 +286,15 @@ export async function main(argv = process.argv.slice(2)): Promise<number> {
|
|
|
251
286
|
}
|
|
252
287
|
|
|
253
288
|
async function runStateCommand(databasePath: string, args: CliArgs): Promise<void> {
|
|
289
|
+
if (args.stateAction === "prune") {
|
|
290
|
+
const report = await pruneState(databasePath, {
|
|
291
|
+
before: args.pruneBefore as string,
|
|
292
|
+
apply: args.pruneApply === true,
|
|
293
|
+
...(args.backupDestination === undefined ? {} : { backupPath: args.backupDestination }),
|
|
294
|
+
});
|
|
295
|
+
process.stdout.write(`${JSON.stringify(report)}\n`);
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
254
298
|
if (args.stateAction === "backup") {
|
|
255
299
|
const state = new StateDatabase({ filePath: databasePath });
|
|
256
300
|
try {
|
|
@@ -274,10 +318,13 @@ async function runStateCommand(databasePath: string, args: CliArgs): Promise<voi
|
|
|
274
318
|
(SELECT count(*) FROM runs) AS runs,
|
|
275
319
|
(SELECT count(*) FROM controller_resources) AS controllers,
|
|
276
320
|
(SELECT count(*) FROM human_decisions) AS decisions,
|
|
321
|
+
(SELECT count(*) FROM workflow_settings) AS settingsScopes,
|
|
322
|
+
(SELECT count(*) FROM workflow_follow_ups WHERE status IN ('queued', 'pending_presentation', 'ready')) AS pendingFollowUps,
|
|
277
323
|
(SELECT count(*) FROM effects WHERE status IN ('pending', 'applying', 'ambiguous')) AS unsettledEffects,
|
|
278
|
-
(SELECT count(*) FROM leases
|
|
324
|
+
(SELECT count(*) FROM leases
|
|
325
|
+
WHERE owner_id IS NOT NULL AND expires_at > ?) AS activeLeases`,
|
|
279
326
|
)
|
|
280
|
-
.get();
|
|
327
|
+
.get(Date.now());
|
|
281
328
|
process.stdout.write(
|
|
282
329
|
`Database: ${databasePath}\nSize: ${fs.statSync(databasePath).size} bytes\n${JSON.stringify(counts)}\n`,
|
|
283
330
|
);
|
package/src/viewer/render.ts
CHANGED
|
@@ -102,8 +102,10 @@ function stepLine(
|
|
|
102
102
|
step.error !== undefined
|
|
103
103
|
? ansi.red(previewValue(step.error, 60))
|
|
104
104
|
: ansi.dim(previewValue(step.output, 60));
|
|
105
|
+
const settings =
|
|
106
|
+
step.settingsChangeNumber === undefined ? "" : `, settings ${step.settingsChangeNumber}`;
|
|
105
107
|
return fitWidth(
|
|
106
|
-
` ${marker}${glyph} ${step.nodeId} ${ansi.dim(`(${step.nodeType}, ${formatDuration(durationMs)})`)} ${preview}`,
|
|
108
|
+
` ${marker}${glyph} ${step.nodeId} ${ansi.dim(`(${step.nodeType}, ${formatDuration(durationMs)}${settings})`)} ${preview}`,
|
|
107
109
|
width,
|
|
108
110
|
);
|
|
109
111
|
}
|
|
@@ -181,6 +183,16 @@ function inspectorLines(step: WorkflowStepRecord, width: number): string[] {
|
|
|
181
183
|
for (const raw of (rendered ?? "null").split("\n")) {
|
|
182
184
|
lines.push(fitWidth(` ${sanitizeText(raw)}`, width));
|
|
183
185
|
}
|
|
186
|
+
if (step.settingsScopeId !== undefined) {
|
|
187
|
+
lines.push(
|
|
188
|
+
fitWidth(
|
|
189
|
+
ansi.dim(
|
|
190
|
+
` settings ${step.settingsChangeNumber ?? 0} · ${sanitizeText(step.settingsScopeId)} · ${step.settingsHash?.slice(0, 12) ?? "unknown hash"}`,
|
|
191
|
+
),
|
|
192
|
+
width,
|
|
193
|
+
),
|
|
194
|
+
);
|
|
195
|
+
}
|
|
184
196
|
if (step.action) {
|
|
185
197
|
const receipt = [
|
|
186
198
|
step.action.actionType,
|
|
@@ -273,6 +285,36 @@ export function renderRunDetailLines(
|
|
|
273
285
|
}
|
|
274
286
|
}
|
|
275
287
|
|
|
288
|
+
if ((bundle.settingsScopes?.length ?? 0) > 0) {
|
|
289
|
+
lines.push("");
|
|
290
|
+
lines.push(ansi.bold("workflow settings"));
|
|
291
|
+
for (const scope of bundle.settingsScopes ?? []) {
|
|
292
|
+
lines.push(
|
|
293
|
+
fitWidth(
|
|
294
|
+
` ${sanitizeText(scope.mountPath || "root")} #${scope.invocation} · change ${scope.changeNumber} · ${scope.settingsHash.slice(0, 12)}`,
|
|
295
|
+
size.width,
|
|
296
|
+
),
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if ((bundle.followUpQueue?.followUps.length ?? 0) > 0) {
|
|
302
|
+
lines.push("");
|
|
303
|
+
lines.push(
|
|
304
|
+
ansi.bold(
|
|
305
|
+
`follow-ups · presentation ${bundle.followUpQueue?.presentationState ?? "unknown"}`,
|
|
306
|
+
),
|
|
307
|
+
);
|
|
308
|
+
for (const followUp of bundle.followUpQueue?.followUps ?? []) {
|
|
309
|
+
lines.push(
|
|
310
|
+
fitWidth(
|
|
311
|
+
` ${followUp.order}. ${followUp.state} · ${followUp.followUpId} · ${sanitizeText(followUp.source)}`,
|
|
312
|
+
size.width,
|
|
313
|
+
),
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
276
318
|
if (steps.length > 0) {
|
|
277
319
|
lines.push("");
|
|
278
320
|
lines.push(ansi.bold("steps"));
|
|
@@ -20,7 +20,6 @@ export type TemporalTool = {
|
|
|
20
20
|
messageId: string;
|
|
21
21
|
toolName: string;
|
|
22
22
|
status: "running" | "finished" | "failed";
|
|
23
|
-
updates: number;
|
|
24
23
|
args?: unknown;
|
|
25
24
|
result?: unknown;
|
|
26
25
|
};
|
|
@@ -155,22 +154,6 @@ function foldSessionEvents(
|
|
|
155
154
|
? "thinking"
|
|
156
155
|
: "toolCall",
|
|
157
156
|
);
|
|
158
|
-
} else if (
|
|
159
|
-
contentIndex !== undefined &&
|
|
160
|
-
(assistantType === "text_delta" ||
|
|
161
|
-
assistantType === "thinking_delta" ||
|
|
162
|
-
assistantType === "toolcall_delta")
|
|
163
|
-
) {
|
|
164
|
-
const block = ensureBlock(
|
|
165
|
-
message,
|
|
166
|
-
contentIndex,
|
|
167
|
-
assistantType === "text_delta"
|
|
168
|
-
? "text"
|
|
169
|
-
: assistantType === "thinking_delta"
|
|
170
|
-
? "thinking"
|
|
171
|
-
: "toolCall",
|
|
172
|
-
);
|
|
173
|
-
block.text += payloadString(event.payload, "delta") ?? "";
|
|
174
157
|
} else if (
|
|
175
158
|
contentIndex !== undefined &&
|
|
176
159
|
(assistantType === "text_end" || assistantType === "thinking_end")
|
|
@@ -181,10 +164,10 @@ function foldSessionEvents(
|
|
|
181
164
|
assistantType === "text_end" ? "text" : "thinking",
|
|
182
165
|
);
|
|
183
166
|
const content = payloadString(event.payload, "content") ?? "";
|
|
184
|
-
if (block.text !== content) {
|
|
167
|
+
if (block.text.length > 0 && block.text !== content) {
|
|
185
168
|
diagnostics.push(`${assistantType} mismatch for ${event.messageId}:${contentIndex}`);
|
|
186
|
-
block.text = content;
|
|
187
169
|
}
|
|
170
|
+
block.text = content;
|
|
188
171
|
} else if (contentIndex !== undefined && assistantType === "toolcall_end") {
|
|
189
172
|
const block = ensureBlock(message, contentIndex, "toolCall");
|
|
190
173
|
block.value = event.payload.toolCall;
|
|
@@ -229,22 +212,12 @@ function foldSessionEvents(
|
|
|
229
212
|
messageId: event.messageId,
|
|
230
213
|
toolName: payloadString(event.payload, "toolName") ?? "tool",
|
|
231
214
|
status: "running",
|
|
232
|
-
updates: 0,
|
|
233
215
|
...(event.payload.args === undefined ? {} : { args: event.payload.args }),
|
|
234
216
|
};
|
|
235
217
|
tools.set(event.toolCallId, tool);
|
|
236
218
|
toolOrder.push(event.toolCallId);
|
|
237
219
|
break;
|
|
238
220
|
}
|
|
239
|
-
case "tool_execution_updated": {
|
|
240
|
-
const tool = event.toolCallId ? tools.get(event.toolCallId) : undefined;
|
|
241
|
-
if (tool) {
|
|
242
|
-
tool.updates += 1;
|
|
243
|
-
} else {
|
|
244
|
-
diagnostics.push(`tool_execution_updated ${event.seq} precedes start`);
|
|
245
|
-
}
|
|
246
|
-
break;
|
|
247
|
-
}
|
|
248
221
|
case "tool_execution_finished": {
|
|
249
222
|
const tool = event.toolCallId ? tools.get(event.toolCallId) : undefined;
|
|
250
223
|
if (!tool) {
|
|
@@ -31,6 +31,7 @@ export type WorkflowScopeMetadata = {
|
|
|
31
31
|
path: string;
|
|
32
32
|
workflowName: string;
|
|
33
33
|
maxSteps?: number;
|
|
34
|
+
settings?: WorkflowDefinition["settings"];
|
|
34
35
|
authoredNodes: Record<string, string>;
|
|
35
36
|
childMounts: Record<string, string>;
|
|
36
37
|
};
|
|
@@ -41,6 +42,7 @@ export type WorkflowEntryMetadata = {
|
|
|
41
42
|
parentPath: string;
|
|
42
43
|
workflowName: string;
|
|
43
44
|
input: WorkflowIncludeDefinition["input"];
|
|
45
|
+
settings?: WorkflowIncludeDefinition["settings"];
|
|
44
46
|
normalizeInput?: WorkflowDefinition["input"];
|
|
45
47
|
};
|
|
46
48
|
|
|
@@ -125,6 +127,7 @@ export function compileWorkflowDefinition<TWorkflow extends WorkflowDefinition<a
|
|
|
125
127
|
path: scopePath,
|
|
126
128
|
workflowName: current.name,
|
|
127
129
|
...(current.maxSteps !== undefined ? { maxSteps: current.maxSteps } : {}),
|
|
130
|
+
...(current.settings !== undefined ? { settings: current.settings } : {}),
|
|
128
131
|
authoredNodes,
|
|
129
132
|
childMounts,
|
|
130
133
|
};
|
|
@@ -155,6 +158,11 @@ export function compileWorkflowDefinition<TWorkflow extends WorkflowDefinition<a
|
|
|
155
158
|
`Workflow include ${qualify(scopePath, name)} is unresolved: ${include.workflow}`,
|
|
156
159
|
);
|
|
157
160
|
}
|
|
161
|
+
if (include.settings !== undefined && child.settings === undefined) {
|
|
162
|
+
throw new Error(
|
|
163
|
+
`Workflow include ${qualify(scopePath, name)} maps settings but child ${child.name} declares none`,
|
|
164
|
+
);
|
|
165
|
+
}
|
|
158
166
|
const mountPath = qualify(scopePath, name);
|
|
159
167
|
const childExits = child.exits ?? {};
|
|
160
168
|
if (Object.keys(childExits).length === 0) {
|
|
@@ -167,6 +175,7 @@ export function compileWorkflowDefinition<TWorkflow extends WorkflowDefinition<a
|
|
|
167
175
|
parentPath: scopePath,
|
|
168
176
|
workflowName: child.name,
|
|
169
177
|
input: include.input,
|
|
178
|
+
...(include.settings !== undefined ? { settings: include.settings } : {}),
|
|
170
179
|
normalizeInput: child.input,
|
|
171
180
|
};
|
|
172
181
|
nodes[entryNode] = {
|
|
@@ -176,10 +185,14 @@ export function compileWorkflowDefinition<TWorkflow extends WorkflowDefinition<a
|
|
|
176
185
|
const parentContext = projectWorkflowContext(context, scopePath, scopes, entries, exits);
|
|
177
186
|
const mapped = include.input ? await include.input(parentContext) : parentContext.input;
|
|
178
187
|
const normalized = child.input ? await child.input(mapped) : mapped;
|
|
188
|
+
const initialSettings = include.settings
|
|
189
|
+
? await include.settings(parentContext)
|
|
190
|
+
: undefined;
|
|
179
191
|
return {
|
|
180
192
|
schema: "pi-workflows.include-entry.v1",
|
|
181
193
|
invocation: countCompletedEntries(context.state, entryNode) + 1,
|
|
182
194
|
input: normalized === undefined ? null : normalized,
|
|
195
|
+
...(initialSettings !== undefined ? { settings: initialSettings } : {}),
|
|
183
196
|
};
|
|
184
197
|
},
|
|
185
198
|
};
|
|
@@ -478,6 +491,7 @@ function wrapNode(
|
|
|
478
491
|
...common,
|
|
479
492
|
nodeType: "compute",
|
|
480
493
|
run: (context) => (node as ComputeNodeDefinition).run(project(context)),
|
|
494
|
+
...(node.settingsRoute === true ? { settingsRoute: true as const } : {}),
|
|
481
495
|
};
|
|
482
496
|
case "notify":
|
|
483
497
|
return {
|
|
@@ -637,6 +651,11 @@ export function projectWorkflowContext(
|
|
|
637
651
|
outputs,
|
|
638
652
|
results,
|
|
639
653
|
state,
|
|
654
|
+
...(context.settings !== undefined ? { settings: context.settings } : {}),
|
|
655
|
+
...(context.settingsScopeId !== undefined ? { settingsScopeId: context.settingsScopeId } : {}),
|
|
656
|
+
...(context.settingsChangeNumber !== undefined
|
|
657
|
+
? { settingsChangeNumber: context.settingsChangeNumber }
|
|
658
|
+
: {}),
|
|
640
659
|
signal: context.signal,
|
|
641
660
|
};
|
|
642
661
|
}
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
assertValidShellActionNode,
|
|
8
8
|
assertValidWorkflowDefinitionShape,
|
|
9
9
|
} from "./schema.js";
|
|
10
|
+
import type { WorkflowSettingsDefinition } from "./settings.js";
|
|
10
11
|
import type {
|
|
11
12
|
AgentNodeDefinition,
|
|
12
13
|
AssistantAgentNodeDefinition,
|
|
@@ -26,6 +27,7 @@ import type {
|
|
|
26
27
|
WorkflowInputOf,
|
|
27
28
|
WorkflowNodeContext,
|
|
28
29
|
WorkflowNodeDefinition,
|
|
30
|
+
WorkflowSettingsOf,
|
|
29
31
|
WorkflowTypedEdge,
|
|
30
32
|
WorkflowValueParser,
|
|
31
33
|
} from "./types.js";
|
|
@@ -37,11 +39,13 @@ type WorkflowDefinitionInput<
|
|
|
37
39
|
TNodes extends Record<string, WorkflowNodeDefinition>,
|
|
38
40
|
TIncludes extends WorkflowIncludeMap,
|
|
39
41
|
TExits extends WorkflowExitMap,
|
|
42
|
+
TSettings,
|
|
40
43
|
> = Omit<
|
|
41
|
-
WorkflowDefinition<TInput, TExits, TIncludes>,
|
|
42
|
-
"input" | "nodes" | "includes" | "exits" | "edges"
|
|
44
|
+
WorkflowDefinition<TInput, TExits, TIncludes, TSettings>,
|
|
45
|
+
"input" | "settings" | "nodes" | "includes" | "exits" | "edges"
|
|
43
46
|
> & {
|
|
44
47
|
input?: WorkflowValueParser<TInput>;
|
|
48
|
+
settings?: WorkflowSettingsDefinition<TSettings, TInput>;
|
|
45
49
|
nodes: TNodes;
|
|
46
50
|
includes?: TIncludes;
|
|
47
51
|
exits?: TExits;
|
|
@@ -56,15 +60,16 @@ export function defineWorkflow<
|
|
|
56
60
|
>,
|
|
57
61
|
const TIncludes extends WorkflowIncludeMap = Record<never, never>,
|
|
58
62
|
const TExits extends WorkflowExitMap = Record<never, never>,
|
|
63
|
+
TSettings = unknown,
|
|
59
64
|
>(
|
|
60
|
-
definition: WorkflowDefinitionInput<TInput, TNodes, TIncludes, TExits>,
|
|
61
|
-
): WorkflowDefinition<TInput, TExits, TIncludes> & {
|
|
65
|
+
definition: WorkflowDefinitionInput<TInput, TNodes, TIncludes, TExits, TSettings>,
|
|
66
|
+
): WorkflowDefinition<TInput, TExits, TIncludes, TSettings> & {
|
|
62
67
|
nodes: TNodes;
|
|
63
68
|
includes?: TIncludes;
|
|
64
69
|
exits?: TExits;
|
|
65
70
|
} {
|
|
66
71
|
assertValidWorkflowDefinitionShape(definition as WorkflowDefinition);
|
|
67
|
-
const typed = definition as WorkflowDefinition<TInput, TExits, TIncludes> & {
|
|
72
|
+
const typed = definition as WorkflowDefinition<TInput, TExits, TIncludes, TSettings> & {
|
|
68
73
|
nodes: TNodes;
|
|
69
74
|
includes?: TIncludes;
|
|
70
75
|
exits?: TExits;
|
|
@@ -87,6 +92,9 @@ export function includeWorkflow<TWorkflow extends WorkflowDefinition<any, any, a
|
|
|
87
92
|
input?: (
|
|
88
93
|
context: WorkflowNodeContext,
|
|
89
94
|
) => Promise<WorkflowInputOf<TWorkflow>> | WorkflowInputOf<TWorkflow>;
|
|
95
|
+
settings?: (
|
|
96
|
+
context: WorkflowNodeContext,
|
|
97
|
+
) => Promise<WorkflowSettingsOf<TWorkflow>> | WorkflowSettingsOf<TWorkflow>;
|
|
90
98
|
},
|
|
91
99
|
): WorkflowIncludeDefinition<TWorkflow>;
|
|
92
100
|
export function includeWorkflow<TWorkflow extends WorkflowDefinition<any, any, any>>(
|
|
@@ -98,6 +106,9 @@ export function includeWorkflow<TWorkflow extends WorkflowDefinition<any, any, a
|
|
|
98
106
|
input?: (
|
|
99
107
|
context: WorkflowNodeContext,
|
|
100
108
|
) => Promise<WorkflowInputOf<TWorkflow>> | WorkflowInputOf<TWorkflow>;
|
|
109
|
+
settings?: (
|
|
110
|
+
context: WorkflowNodeContext,
|
|
111
|
+
) => Promise<WorkflowSettingsOf<TWorkflow>> | WorkflowSettingsOf<TWorkflow>;
|
|
101
112
|
} = {},
|
|
102
113
|
): WorkflowIncludeDefinition<TWorkflow> {
|
|
103
114
|
const definition = isWorkflowDefinition(workflowOrDefinition)
|
|
@@ -109,6 +120,9 @@ export function includeWorkflow<TWorkflow extends WorkflowDefinition<any, any, a
|
|
|
109
120
|
if (definition.input !== undefined && typeof definition.input !== "function") {
|
|
110
121
|
throw new Error("Included workflow input must be a function");
|
|
111
122
|
}
|
|
123
|
+
if (definition.settings !== undefined && typeof definition.settings !== "function") {
|
|
124
|
+
throw new Error("Included workflow settings must be a function");
|
|
125
|
+
}
|
|
112
126
|
if (definition.contract !== undefined && !isWorkflowDefinition(definition.contract)) {
|
|
113
127
|
throw new Error("Included workflow contract must be defined with defineWorkflow");
|
|
114
128
|
}
|