@osolmaz/pi-workflows 0.16.1 → 0.16.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 +41 -41
- package/dist/builtins/monitor.workflow.d.ts +1 -1
- package/dist/builtins/monitor.workflow.js +8 -8
- package/dist/builtins/pi-agent-group.js +3 -3
- package/dist/builtins/pi-agent-group.js.map +1 -1
- package/dist/channels/adapter-entry.js +14 -14
- package/dist/channels/adapter-entry.js.map +1 -1
- package/dist/client/client.d.ts +6 -6
- package/dist/client/client.js +27 -27
- package/dist/client/client.js.map +1 -1
- package/dist/client/protocol.d.ts +4 -1
- package/dist/client/protocol.js +17 -11
- package/dist/client/protocol.js.map +1 -1
- package/dist/client/resolver.d.ts +4 -4
- package/dist/client/view.d.ts +7 -1
- package/dist/client/view.js +1 -0
- package/dist/client/view.js.map +1 -1
- package/dist/extension/index.d.ts +1 -1
- package/dist/extension/index.js +66 -47
- package/dist/extension/index.js.map +1 -1
- package/dist/extension/recorder.d.ts +1 -1
- package/dist/extension/recorder.js +1 -1
- package/dist/extension/recorder.js.map +1 -1
- package/dist/extension/remote-recorder-store.d.ts +1 -1
- package/dist/extension/remote-recorder-store.js +2 -2
- package/dist/extension/remote-recorder-store.js.map +1 -1
- package/dist/extension/{controller-command.d.ts → resource-manager-command.d.ts} +6 -6
- package/dist/extension/{controller-command.js → resource-manager-command.js} +7 -7
- package/dist/extension/resource-manager-command.js.map +1 -0
- package/dist/extension/session-delivery.d.ts +1 -1
- package/dist/extension/session-delivery.js +2 -2
- package/dist/extension/session-delivery.js.map +1 -1
- package/dist/extension/session-view.d.ts +1 -1
- package/dist/extension/session-view.js +1 -1
- package/dist/extension/session-view.js.map +1 -1
- package/dist/extension/workflow-message-coordinator.d.ts +4 -3
- package/dist/extension/workflow-message-coordinator.js +81 -29
- package/dist/extension/workflow-message-coordinator.js.map +1 -1
- package/dist/resource-managers/conditions.d.ts +6 -0
- package/dist/{controllers → resource-managers}/conditions.js +3 -3
- package/dist/resource-managers/conditions.js.map +1 -0
- package/dist/resource-managers/definition.d.ts +6 -0
- package/dist/resource-managers/definition.js +45 -0
- package/dist/resource-managers/definition.js.map +1 -0
- package/dist/resource-managers/effects.d.ts +15 -0
- package/dist/{controllers → resource-managers}/effects.js +2 -2
- package/dist/resource-managers/effects.js.map +1 -0
- package/dist/resource-managers/errors.d.ts +12 -0
- package/dist/resource-managers/errors.js +25 -0
- package/dist/resource-managers/errors.js.map +1 -0
- package/dist/resource-managers/index.d.ts +12 -0
- package/dist/resource-managers/index.js +12 -0
- package/dist/resource-managers/index.js.map +1 -0
- package/dist/resource-managers/json.js.map +1 -0
- package/dist/resource-managers/loader.d.ts +23 -0
- package/dist/resource-managers/loader.js +75 -0
- package/dist/resource-managers/loader.js.map +1 -0
- package/dist/resource-managers/results.d.ts +5 -0
- package/dist/resource-managers/results.js.map +1 -0
- package/dist/resource-managers/runtime.d.ts +59 -0
- package/dist/{controllers/manager.js → resource-managers/runtime.js} +57 -57
- package/dist/resource-managers/runtime.js.map +1 -0
- package/dist/{controllers → resource-managers}/sqlite.d.ts +51 -43
- package/dist/{controllers → resource-managers}/sqlite.js +187 -125
- package/dist/resource-managers/sqlite.js.map +1 -0
- package/dist/{controllers → resource-managers}/store.d.ts +33 -33
- package/dist/{controllers → resource-managers}/store.js.map +1 -1
- package/dist/{controllers → resource-managers}/types.d.ts +41 -41
- package/dist/{controllers → resource-managers}/types.js.map +1 -1
- package/dist/resource-managers/workflows.d.ts +34 -0
- package/dist/{controllers → resource-managers}/workflows.js +15 -15
- package/dist/resource-managers/workflows.js.map +1 -0
- package/dist/server/channel-effects.js.map +1 -0
- package/dist/{host → server}/channel-supervisor.d.ts +6 -6
- package/dist/{host → server}/channel-supervisor.js +3 -3
- package/dist/server/channel-supervisor.js.map +1 -0
- package/dist/{host/child-worker-supervisor.d.ts → server/child-runner-supervisor.d.ts} +15 -13
- package/dist/{host/child-worker-supervisor.js → server/child-runner-supervisor.js} +6 -5
- package/dist/server/child-runner-supervisor.js.map +1 -0
- package/dist/{host → server}/processes.d.ts +3 -3
- package/dist/{host → server}/processes.js +3 -3
- package/dist/server/processes.js.map +1 -0
- package/dist/{host → server}/resolver-entry.d.ts +6 -6
- package/dist/{host → server}/resolver-entry.js +14 -14
- package/dist/server/resolver-entry.js.map +1 -0
- package/dist/server/resource-runner-entry.d.ts +2 -0
- package/dist/{host/controller-worker-entry.js → server/resource-runner-entry.js} +33 -33
- package/dist/server/resource-runner-entry.js.map +1 -0
- package/dist/server/resource-runner-protocol.d.ts +36 -0
- package/dist/server/resource-runner-protocol.js +49 -0
- package/dist/server/resource-runner-protocol.js.map +1 -0
- package/dist/server/resource-runner-supervisor.d.ts +21 -0
- package/dist/{host/worker-supervisor.js → server/resource-runner-supervisor.js} +17 -17
- package/dist/server/resource-runner-supervisor.js.map +1 -0
- package/dist/{host → server}/rpc-bridge.d.ts +3 -3
- package/dist/{host → server}/rpc-bridge.js +3 -3
- package/dist/server/rpc-bridge.js.map +1 -0
- package/dist/{host → server}/rpc-executor.d.ts +1 -1
- package/dist/{host → server}/rpc-executor.js +3 -3
- package/dist/server/rpc-executor.js.map +1 -0
- package/dist/{host/host-entry.js → server/server-entry.js} +6 -6
- package/dist/server/server-entry.js.map +1 -0
- package/dist/{host/runner.d.ts → server/server.d.ts} +47 -39
- package/dist/{host/runner.js → server/server.js} +624 -535
- package/dist/server/server.js.map +1 -0
- package/dist/{host → server}/state.d.ts +25 -25
- package/dist/{host → server}/state.js +49 -49
- package/dist/server/state.js.map +1 -0
- package/dist/{host → server}/view.d.ts +7 -7
- package/dist/{host → server}/view.js +19 -15
- package/dist/server/view.js.map +1 -0
- package/dist/server/workflow-runner-content.d.ts +6 -0
- package/dist/server/workflow-runner-content.js +96 -0
- package/dist/server/workflow-runner-content.js.map +1 -0
- package/dist/server/workflow-runner-entry.d.ts +13 -0
- package/dist/{host/worker-entry.js → server/workflow-runner-entry.js} +89 -57
- package/dist/server/workflow-runner-entry.js.map +1 -0
- package/dist/server/workflow-runner-protocol.d.ts +69 -0
- package/dist/server/workflow-runner-protocol.js +176 -0
- package/dist/server/workflow-runner-protocol.js.map +1 -0
- package/dist/{host/worker-store.d.ts → server/workflow-runner-store.d.ts} +11 -11
- package/dist/{host/worker-store.js → server/workflow-runner-store.js} +8 -8
- package/dist/server/workflow-runner-store.js.map +1 -0
- package/dist/server/workflow-runner-supervisor.d.ts +22 -0
- package/dist/server/workflow-runner-supervisor.js +56 -0
- package/dist/server/workflow-runner-supervisor.js.map +1 -0
- package/dist/state/prune.d.ts +1 -1
- package/dist/state/prune.js +17 -10
- package/dist/state/prune.js.map +1 -1
- package/dist/state/schema.js +2 -2
- package/dist/state/workflow-messages.d.ts +3 -1
- package/dist/state/workflow-messages.js +32 -1
- package/dist/state/workflow-messages.js.map +1 -1
- package/dist/viewer/backup.js +1 -1
- package/dist/viewer/backup.js.map +1 -1
- package/dist/viewer/cli.d.ts +2 -2
- package/dist/viewer/cli.js +46 -32
- package/dist/viewer/cli.js.map +1 -1
- package/dist/viewer/tui.d.ts +1 -1
- package/dist/viewer/tui.js +1 -1
- package/dist/viewer/tui.js.map +1 -1
- package/dist/workflows/command-batch.js +2 -2
- package/dist/workflows/composition.js +0 -4
- package/dist/workflows/composition.js.map +1 -1
- package/dist/workflows/definition.js +0 -8
- package/dist/workflows/definition.js.map +1 -1
- package/dist/workflows/engine.js +18 -20
- package/dist/workflows/engine.js.map +1 -1
- package/dist/workflows/schema.js +0 -4
- package/dist/workflows/schema.js.map +1 -1
- package/dist/workflows/store.d.ts +27 -11
- package/dist/workflows/store.js +66 -18
- package/dist/workflows/store.js.map +1 -1
- package/dist/workflows/types.d.ts +3 -5
- package/docs/2026-08-20-durable-workflow-launch-plan.md +12 -12
- package/docs/2026-08-25-workflow-follow-ups.md +7 -7
- package/docs/2026-08-25-workflow-settings.md +3 -3
- package/docs/2026-08-30-out-of-process-workflow-host-plan.md +3 -3
- package/docs/2026-09-01-restore-session-delivery-controls-plan.md +5 -5
- package/docs/2026-09-01-unified-workflow-client-plan.md +6 -6
- package/docs/2026-09-02-installed-live-e2e-plan.md +3 -3
- package/docs/2026-09-02-unify-workflow-messages-plan.md +8 -8
- package/docs/2026-09-04-workflow-run-state-plan.md +363 -0
- package/docs/DEFERRED_TURNS.md +7 -7
- package/docs/DESIGN_PHILOSOPHY.md +1 -1
- package/docs/HUMAN_DECISIONS.md +11 -11
- package/docs/HUMAN_DECISION_PRESENTATIONS.md +4 -4
- package/docs/MONITOR.md +1 -1
- package/docs/RESOURCE_MANAGERS.md +221 -0
- package/docs/SQLITE_STATE.md +40 -34
- package/docs/WORKFLOW_COMPOSITION.md +1 -1
- package/docs/{WORKFLOW_HOST.md → WORKFLOW_SERVER.md} +131 -116
- package/docs/WORKFLOW_STEP_MESSAGES.md +18 -18
- package/docs/WORKFLOW_UPDATES.md +16 -16
- package/docs/development.md +15 -14
- package/docs/live-replay-protocol.md +20 -20
- package/docs/plans/2026-08-04-controller-runtime-plan.md +25 -25
- package/docs/plans/2026-08-05-always-on-workflows-plan.md +8 -8
- package/docs/plans/2026-08-10-agent-managed-monitor-workflows-plan.md +2 -2
- package/docs/plans/2026-08-13-session-addressed-workflow-notifications-plan.md +1 -1
- package/docs/plans/2026-08-16-workflow-updates-plan.md +5 -5
- package/docs/plans/2026-08-19-human-decision-gates-plan.md +1 -1
- package/docs/plans/2026-08-20-bounded-command-batches-plan.md +1 -1
- package/docs/plans/2026-08-21-deferred-turn-intents-plan.md +3 -3
- package/docs/plans/2026-08-21-sanity-check-plan.md +2 -2
- package/docs/plans/2026-08-23-assistant-agent-completion-plan.md +5 -5
- package/docs/plans/2026-08-23-sqlite-state-plan.md +25 -25
- package/docs/plans/2026-08-25-live-workflow-settings-plan.md +4 -4
- package/docs/plans/2026-08-27-workflow-terminal-restart-plan.md +3 -3
- package/docs/plans/2026-09-04-workflow-runner-resume-state-plan.md +318 -0
- package/docs/plans/piw-viewer-experience-implementation-plan.md +1 -1
- package/docs/tui-viewer.md +9 -9
- package/docs/workflows.md +78 -63
- package/examples/{controllers/pull-request.controller.ts → resource-managers/pull-request.resource-manager.ts} +12 -12
- package/herdr-plugin.toml +1 -1
- package/package.json +5 -5
- package/protocol/client.v1.schema.json +7 -7
- package/protocol/fixtures/client-v1.json +1 -1
- package/src/builtins/monitor.workflow.ts +9 -9
- package/src/builtins/pi-agent-group.ts +3 -3
- package/src/channels/adapter-entry.ts +14 -14
- package/src/client/client.ts +33 -32
- package/src/client/protocol.ts +16 -11
- package/src/client/resolver.ts +4 -4
- package/src/client/view.ts +9 -1
- package/src/extension/index.ts +81 -53
- package/src/extension/recorder.ts +1 -1
- package/src/extension/remote-recorder-store.ts +2 -2
- package/src/extension/resource-manager-command.ts +45 -0
- package/src/extension/session-delivery.ts +2 -2
- package/src/extension/session-view.ts +1 -1
- package/src/extension/workflow-message-coordinator.ts +94 -30
- package/src/{controllers → resource-managers}/conditions.ts +23 -23
- package/src/resource-managers/definition.ts +71 -0
- package/src/{controllers → resource-managers}/effects.ts +9 -9
- package/src/resource-managers/errors.ts +27 -0
- package/src/resource-managers/index.ts +88 -0
- package/src/resource-managers/loader.ts +111 -0
- package/src/{controllers → resource-managers}/results.ts +4 -4
- package/src/{controllers/manager.ts → resource-managers/runtime.ts} +95 -92
- package/src/{controllers → resource-managers}/sqlite.ts +275 -181
- package/src/{controllers → resource-managers}/store.ts +46 -38
- package/src/{controllers → resource-managers}/types.ts +50 -41
- package/src/{controllers → resource-managers}/workflows.ts +43 -41
- package/src/{host → server}/channel-supervisor.ts +8 -8
- package/src/{host/child-worker-supervisor.ts → server/child-runner-supervisor.ts} +22 -18
- package/src/{host → server}/processes.ts +3 -3
- package/src/{host → server}/resolver-entry.ts +28 -25
- package/src/{host/controller-worker-entry.ts → server/resource-runner-entry.ts} +67 -65
- package/src/server/resource-runner-protocol.ts +103 -0
- package/src/server/resource-runner-supervisor.ts +76 -0
- package/src/{host → server}/rpc-bridge.ts +3 -3
- package/src/{host → server}/rpc-executor.ts +4 -4
- package/src/{host/host-entry.ts → server/server-entry.ts} +5 -5
- package/src/{host/runner.ts → server/server.ts} +786 -672
- package/src/{host → server}/state.ts +78 -67
- package/src/{host → server}/view.ts +21 -17
- package/src/server/workflow-runner-content.ts +119 -0
- package/src/{host/worker-entry.ts → server/workflow-runner-entry.ts} +131 -82
- package/src/server/workflow-runner-protocol.ts +241 -0
- package/src/{host/worker-store.ts → server/workflow-runner-store.ts} +18 -20
- package/src/server/workflow-runner-supervisor.ts +79 -0
- package/src/state/prune.ts +27 -9
- package/src/state/schema.ts +2 -2
- package/src/state/workflow-messages.ts +52 -1
- package/src/viewer/backup.ts +1 -1
- package/src/viewer/cli.ts +50 -36
- package/src/viewer/tui.ts +1 -1
- package/src/workflows/command-batch.ts +2 -2
- package/src/workflows/composition.ts +0 -5
- package/src/workflows/definition.ts +0 -8
- package/src/workflows/engine.ts +18 -21
- package/src/workflows/schema.ts +0 -6
- package/src/workflows/store.ts +95 -28
- package/src/workflows/types.ts +3 -5
- package/dist/controllers/conditions.d.ts +0 -6
- package/dist/controllers/conditions.js.map +0 -1
- package/dist/controllers/definition.d.ts +0 -6
- package/dist/controllers/definition.js +0 -45
- package/dist/controllers/definition.js.map +0 -1
- package/dist/controllers/effects.d.ts +0 -15
- package/dist/controllers/effects.js.map +0 -1
- package/dist/controllers/errors.d.ts +0 -12
- package/dist/controllers/errors.js +0 -25
- package/dist/controllers/errors.js.map +0 -1
- package/dist/controllers/index.d.ts +0 -12
- package/dist/controllers/index.js +0 -12
- package/dist/controllers/index.js.map +0 -1
- package/dist/controllers/json.js.map +0 -1
- package/dist/controllers/loader.d.ts +0 -23
- package/dist/controllers/loader.js +0 -74
- package/dist/controllers/loader.js.map +0 -1
- package/dist/controllers/manager.d.ts +0 -59
- package/dist/controllers/manager.js.map +0 -1
- package/dist/controllers/results.d.ts +0 -5
- package/dist/controllers/results.js.map +0 -1
- package/dist/controllers/sqlite.js.map +0 -1
- package/dist/controllers/workflows.d.ts +0 -34
- package/dist/controllers/workflows.js.map +0 -1
- package/dist/extension/controller-command.js.map +0 -1
- package/dist/host/channel-effects.js.map +0 -1
- package/dist/host/channel-supervisor.js.map +0 -1
- package/dist/host/child-worker-supervisor.js.map +0 -1
- package/dist/host/controller-worker-entry.d.ts +0 -2
- package/dist/host/controller-worker-entry.js.map +0 -1
- package/dist/host/controller-worker-protocol.d.ts +0 -36
- package/dist/host/controller-worker-protocol.js +0 -49
- package/dist/host/controller-worker-protocol.js.map +0 -1
- package/dist/host/controller-worker-supervisor.d.ts +0 -21
- package/dist/host/controller-worker-supervisor.js +0 -54
- package/dist/host/controller-worker-supervisor.js.map +0 -1
- package/dist/host/host-entry.js.map +0 -1
- package/dist/host/processes.js.map +0 -1
- package/dist/host/resolver-entry.js.map +0 -1
- package/dist/host/rpc-bridge.js.map +0 -1
- package/dist/host/rpc-executor.js.map +0 -1
- package/dist/host/runner.js.map +0 -1
- package/dist/host/state.js.map +0 -1
- package/dist/host/view.js.map +0 -1
- package/dist/host/worker-entry.d.ts +0 -10
- package/dist/host/worker-entry.js.map +0 -1
- package/dist/host/worker-protocol.d.ts +0 -31
- package/dist/host/worker-protocol.js +0 -122
- package/dist/host/worker-protocol.js.map +0 -1
- package/dist/host/worker-store.js.map +0 -1
- package/dist/host/worker-supervisor.d.ts +0 -22
- package/dist/host/worker-supervisor.js.map +0 -1
- package/docs/CONTROLLERS.md +0 -217
- package/src/controllers/definition.ts +0 -65
- package/src/controllers/errors.ts +0 -27
- package/src/controllers/index.ts +0 -88
- package/src/controllers/loader.ts +0 -104
- package/src/extension/controller-command.ts +0 -45
- package/src/host/controller-worker-protocol.ts +0 -104
- package/src/host/controller-worker-supervisor.ts +0 -79
- package/src/host/worker-protocol.ts +0 -165
- package/src/host/worker-supervisor.ts +0 -74
- /package/dist/{controllers → resource-managers}/json.d.ts +0 -0
- /package/dist/{controllers → resource-managers}/json.js +0 -0
- /package/dist/{controllers → resource-managers}/results.js +0 -0
- /package/dist/{controllers → resource-managers}/store.js +0 -0
- /package/dist/{controllers → resource-managers}/types.js +0 -0
- /package/dist/{host → server}/channel-effects.d.ts +0 -0
- /package/dist/{host → server}/channel-effects.js +0 -0
- /package/dist/{host/host-entry.d.ts → server/server-entry.d.ts} +0 -0
- /package/src/{controllers → resource-managers}/json.ts +0 -0
- /package/src/{host → server}/channel-effects.ts +0 -0
|
@@ -4,8 +4,6 @@ import type { WorkflowSettingsScopeRecord } from "../workflows/settings.js";
|
|
|
4
4
|
import {
|
|
5
5
|
createDefinitionSnapshot,
|
|
6
6
|
type InitializeWorkflowRunOptions,
|
|
7
|
-
type LoadedWorkflowRun,
|
|
8
|
-
type ReadWorkflowRunOptions,
|
|
9
7
|
type WorkflowExecutionStore,
|
|
10
8
|
} from "../workflows/store.js";
|
|
11
9
|
import type {
|
|
@@ -22,28 +20,31 @@ import type {
|
|
|
22
20
|
WorkflowUpdateInput,
|
|
23
21
|
WorkflowUpdateRecord,
|
|
24
22
|
} from "../workflows/types.js";
|
|
25
|
-
import type {
|
|
26
|
-
|
|
23
|
+
import type {
|
|
24
|
+
WorkflowRunnerMessageKind,
|
|
25
|
+
WorkflowRunnerStoreOperation,
|
|
26
|
+
} from "./workflow-runner-protocol.js";
|
|
27
|
+
import { runnerKindForOperation } from "./workflow-runner-protocol.js";
|
|
27
28
|
|
|
28
|
-
export interface
|
|
29
|
+
export interface WorkflowRunnerStoreTransport {
|
|
29
30
|
request(options: {
|
|
30
31
|
messageId: string;
|
|
31
|
-
operation:
|
|
32
|
-
kind:
|
|
32
|
+
operation: WorkflowRunnerStoreOperation;
|
|
33
|
+
kind: WorkflowRunnerMessageKind;
|
|
33
34
|
expectedRevision: number;
|
|
34
35
|
attemptId?: string;
|
|
35
36
|
payload: JsonValue;
|
|
36
37
|
}): Promise<{ result?: JsonValue; revision?: number }>;
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
/** A
|
|
40
|
-
export class
|
|
41
|
-
readonly databasePath = "
|
|
40
|
+
/** A runner-side store that can only propose state changes to its server. */
|
|
41
|
+
export class ServerBackedWorkflowStore implements WorkflowExecutionStore {
|
|
42
|
+
readonly databasePath = "server://pi-workflows-state";
|
|
42
43
|
private revision: number;
|
|
43
44
|
|
|
44
45
|
constructor(
|
|
45
46
|
private readonly runId: string,
|
|
46
|
-
private readonly transport:
|
|
47
|
+
private readonly transport: WorkflowRunnerStoreTransport,
|
|
47
48
|
initialRevision = 0,
|
|
48
49
|
) {
|
|
49
50
|
this.revision = initialRevision;
|
|
@@ -62,15 +63,12 @@ export class HostBackedWorkflowStore implements WorkflowExecutionStore {
|
|
|
62
63
|
});
|
|
63
64
|
}
|
|
64
65
|
|
|
65
|
-
async prepareRunResume(runId: string): Promise<
|
|
66
|
-
return await this.call<
|
|
66
|
+
async prepareRunResume(runId: string): Promise<WorkflowRunState> {
|
|
67
|
+
return await this.call<WorkflowRunState>("store.prepareRunResume", { runId });
|
|
67
68
|
}
|
|
68
69
|
|
|
69
|
-
async
|
|
70
|
-
runId
|
|
71
|
-
options: ReadWorkflowRunOptions = {},
|
|
72
|
-
): Promise<LoadedWorkflowRun | null> {
|
|
73
|
-
return await this.call<LoadedWorkflowRun | null>("store.readRun", { runId, options });
|
|
70
|
+
async readRunState(runId: string): Promise<WorkflowRunState | null> {
|
|
71
|
+
return await this.call<WorkflowRunState | null>("store.readRunState", { runId });
|
|
74
72
|
}
|
|
75
73
|
|
|
76
74
|
async writeSnapshot(
|
|
@@ -211,14 +209,14 @@ export class HostBackedWorkflowStore implements WorkflowExecutionStore {
|
|
|
211
209
|
}
|
|
212
210
|
|
|
213
211
|
private async call<T>(
|
|
214
|
-
operation:
|
|
212
|
+
operation: WorkflowRunnerStoreOperation,
|
|
215
213
|
payload: Record<string, unknown>,
|
|
216
214
|
attemptId?: string,
|
|
217
215
|
): Promise<T> {
|
|
218
216
|
const response = await this.transport.request({
|
|
219
217
|
messageId: randomUUID(),
|
|
220
218
|
operation,
|
|
221
|
-
kind:
|
|
219
|
+
kind: runnerKindForOperation(operation, payload),
|
|
222
220
|
expectedRevision: this.revision,
|
|
223
221
|
...(attemptId === undefined ? {} : { attemptId }),
|
|
224
222
|
payload: payload as JsonValue,
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { canonicalJson } from "../state/json.js";
|
|
5
|
+
import { ChildRunnerSupervisor, type SupervisedRunnerResult } from "./child-runner-supervisor.js";
|
|
6
|
+
import { ServerProcessRegistry, type ProcessIdentity } from "./processes.js";
|
|
7
|
+
import type { WorkflowRunnerLaunchEnvelope, RunnerOutcome } from "./state.js";
|
|
8
|
+
import {
|
|
9
|
+
MAX_WORKFLOW_RUNNER_PROTOCOL_MESSAGE_BYTES,
|
|
10
|
+
encodeRunnerLine,
|
|
11
|
+
parseRunnerMessage,
|
|
12
|
+
type WorkflowRunnerMessage,
|
|
13
|
+
type WorkflowRunnerResponse,
|
|
14
|
+
} from "./workflow-runner-protocol.js";
|
|
15
|
+
|
|
16
|
+
export type WorkflowRunnerResult = SupervisedRunnerResult;
|
|
17
|
+
|
|
18
|
+
export class WorkflowRunnerSupervisor {
|
|
19
|
+
private readonly supervisor: ChildRunnerSupervisor<WorkflowRunnerMessage, WorkflowRunnerResponse>;
|
|
20
|
+
|
|
21
|
+
constructor(
|
|
22
|
+
readonly envelope: WorkflowRunnerLaunchEnvelope,
|
|
23
|
+
private readonly options: {
|
|
24
|
+
registry: ServerProcessRegistry;
|
|
25
|
+
onMessage: (message: WorkflowRunnerMessage) => Promise<WorkflowRunnerResponse>;
|
|
26
|
+
env?: Record<string, string>;
|
|
27
|
+
startupTimeoutMs?: number;
|
|
28
|
+
runnerEntryPath?: string;
|
|
29
|
+
onSpawn?: (identity: ProcessIdentity) => void;
|
|
30
|
+
onDiagnostic?: (message: string) => void;
|
|
31
|
+
},
|
|
32
|
+
) {
|
|
33
|
+
this.supervisor = new ChildRunnerSupervisor({
|
|
34
|
+
label: "Workflow runner",
|
|
35
|
+
registry: options.registry,
|
|
36
|
+
onMessage: options.onMessage,
|
|
37
|
+
parseMessage: parseRunnerMessage,
|
|
38
|
+
encodeResponse: encodeRunnerLine,
|
|
39
|
+
isReady: (message) => message.kind === "runner.ready",
|
|
40
|
+
isTerminal: (message) => message.kind === "runner.exiting",
|
|
41
|
+
maxMessageBytes: MAX_WORKFLOW_RUNNER_PROTOCOL_MESSAGE_BYTES,
|
|
42
|
+
oversizedMessage: "Runner protocol message exceeds 1 MiB",
|
|
43
|
+
...(options.startupTimeoutMs === undefined
|
|
44
|
+
? {}
|
|
45
|
+
: { startupTimeoutMs: options.startupTimeoutMs }),
|
|
46
|
+
...(options.onSpawn === undefined ? {} : { onSpawn: options.onSpawn }),
|
|
47
|
+
...(options.onDiagnostic === undefined ? {} : { onDiagnostic: options.onDiagnostic }),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async start(): Promise<void> {
|
|
52
|
+
const builtEntry = fileURLToPath(new URL("./workflow-runner-entry.js", import.meta.url));
|
|
53
|
+
const sourceEntry = fileURLToPath(new URL("./workflow-runner-entry.ts", import.meta.url));
|
|
54
|
+
const runnerEntry = this.options.runnerEntryPath ?? builtEntry;
|
|
55
|
+
const args =
|
|
56
|
+
this.options.runnerEntryPath === undefined && !fs.existsSync(builtEntry)
|
|
57
|
+
? ["--import", createRequire(import.meta.url).resolve("tsx"), sourceEntry]
|
|
58
|
+
: [runnerEntry];
|
|
59
|
+
await this.supervisor.start({
|
|
60
|
+
args,
|
|
61
|
+
cwd: this.envelope.projectPath,
|
|
62
|
+
env: {
|
|
63
|
+
...process.env,
|
|
64
|
+
...this.options.env,
|
|
65
|
+
PI_WORKFLOWS_WORKFLOW_RUNNER_LAUNCH: Buffer.from(canonicalJson(this.envelope)).toString(
|
|
66
|
+
"base64url",
|
|
67
|
+
),
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async wait(): Promise<WorkflowRunnerResult> {
|
|
73
|
+
return await this.supervisor.wait();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async stop(outcome: RunnerOutcome = "cancelled"): Promise<void> {
|
|
77
|
+
await this.supervisor.stop(outcome);
|
|
78
|
+
}
|
|
79
|
+
}
|
package/src/state/prune.ts
CHANGED
|
@@ -48,6 +48,7 @@ export async function pruneState(
|
|
|
48
48
|
state: StateDatabase,
|
|
49
49
|
databasePath: string,
|
|
50
50
|
options: StatePruneOptions,
|
|
51
|
+
activeBlobHashes: () => readonly Buffer[] = () => [],
|
|
51
52
|
): Promise<StatePruneReport> {
|
|
52
53
|
validateStatePruneOptions(options);
|
|
53
54
|
const cutoff = parseCutoff(options.before);
|
|
@@ -114,8 +115,9 @@ export async function pruneState(
|
|
|
114
115
|
)`,
|
|
115
116
|
)
|
|
116
117
|
.run();
|
|
117
|
-
const
|
|
118
|
-
|
|
118
|
+
const retainedBlobHashes = activeBlobHashes();
|
|
119
|
+
const blobStats = unreferencedBlobStats(state.connection, retainedBlobHashes);
|
|
120
|
+
deleteUnreferencedBlobs(state.connection, retainedBlobHashes);
|
|
119
121
|
deletedRows = totalChanges(state.connection) - beforeChanges;
|
|
120
122
|
deletedBlobs = blobStats.count;
|
|
121
123
|
deletedBlobBytes = blobStats.bytes;
|
|
@@ -356,21 +358,31 @@ function selectionSignature(database: Database.Database, runIds: string[]): stri
|
|
|
356
358
|
return JSON.stringify([resourceRows, queueRows]);
|
|
357
359
|
}
|
|
358
360
|
|
|
359
|
-
function unreferencedBlobStats(
|
|
360
|
-
|
|
361
|
+
function unreferencedBlobStats(
|
|
362
|
+
database: Database.Database,
|
|
363
|
+
retainedBlobHashes: readonly Buffer[],
|
|
364
|
+
): { count: number; bytes: number } {
|
|
365
|
+
const predicate = blobReferencePredicate(database, retainedBlobHashes.length);
|
|
361
366
|
const row = database
|
|
362
367
|
.prepare(
|
|
363
368
|
`SELECT count(*) AS count, COALESCE(sum(byte_length), 0) AS bytes FROM blobs WHERE ${predicate}`,
|
|
364
369
|
)
|
|
365
|
-
.get();
|
|
370
|
+
.get(...retainedBlobHashes);
|
|
366
371
|
return isBlobStatsRow(row) ? row : { count: 0, bytes: 0 };
|
|
367
372
|
}
|
|
368
373
|
|
|
369
|
-
function deleteUnreferencedBlobs(
|
|
370
|
-
database
|
|
374
|
+
function deleteUnreferencedBlobs(
|
|
375
|
+
database: Database.Database,
|
|
376
|
+
retainedBlobHashes: readonly Buffer[],
|
|
377
|
+
): void {
|
|
378
|
+
database
|
|
379
|
+
.prepare(
|
|
380
|
+
`DELETE FROM blobs WHERE ${blobReferencePredicate(database, retainedBlobHashes.length)}`,
|
|
381
|
+
)
|
|
382
|
+
.run(...retainedBlobHashes);
|
|
371
383
|
}
|
|
372
384
|
|
|
373
|
-
function blobReferencePredicate(database: Database.Database): string {
|
|
385
|
+
function blobReferencePredicate(database: Database.Database, retainedBlobCount: number): string {
|
|
374
386
|
const tables = database
|
|
375
387
|
.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'")
|
|
376
388
|
.all()
|
|
@@ -387,7 +399,13 @@ function blobReferencePredicate(database: Database.Database): string {
|
|
|
387
399
|
);
|
|
388
400
|
}
|
|
389
401
|
}
|
|
390
|
-
|
|
402
|
+
const unreferenced =
|
|
403
|
+
references.length === 0 ? "1 = 1" : `blob_hash NOT IN (${references.join(" UNION ")})`;
|
|
404
|
+
if (retainedBlobCount === 0) return unreferenced;
|
|
405
|
+
const retainedPlaceholders = placeholders(
|
|
406
|
+
Array.from({ length: retainedBlobCount }, () => undefined),
|
|
407
|
+
);
|
|
408
|
+
return `${unreferenced} AND blob_hash NOT IN (${retainedPlaceholders})`;
|
|
391
409
|
}
|
|
392
410
|
|
|
393
411
|
function descendants(root: string, children: Map<string, string[]>): string[] {
|
package/src/state/schema.ts
CHANGED
|
@@ -302,8 +302,8 @@ CREATE TABLE host_commands (
|
|
|
302
302
|
'workflowMessage.reportBranch', 'workflowTurn.report', 'sessionView.clearTerminal',
|
|
303
303
|
'run.restart', 'run.changeSettings', 'followUp.queue', 'followUp.remove', 'session.record',
|
|
304
304
|
'channel.reload', 'channel.recover',
|
|
305
|
-
'
|
|
306
|
-
'
|
|
305
|
+
'resourceManager.list', 'resourceManager.get', 'resourceManager.apply', 'resourceManager.reconcile', 'resourceManager.delete',
|
|
306
|
+
'server.status', 'server.stop', 'state.backup', 'state.prune'
|
|
307
307
|
)),
|
|
308
308
|
idempotency_key TEXT NOT NULL,
|
|
309
309
|
request_fingerprint BLOB NOT NULL CHECK (length(request_fingerprint) = 32),
|
|
@@ -92,7 +92,7 @@ type WorkflowTurnRow = {
|
|
|
92
92
|
endedAt: number | null;
|
|
93
93
|
};
|
|
94
94
|
|
|
95
|
-
/** Durable workflow content that the
|
|
95
|
+
/** Durable workflow content that the server requires Pi to add to one origin session. */
|
|
96
96
|
export class WorkflowMessageStore {
|
|
97
97
|
constructor(readonly state: StateDatabase) {}
|
|
98
98
|
|
|
@@ -279,6 +279,12 @@ export class WorkflowMessageStore {
|
|
|
279
279
|
throw new Error("Workflow turn does not match its message");
|
|
280
280
|
}
|
|
281
281
|
if (message.status !== "sent") throw new Error("Workflow turn requires a sent message");
|
|
282
|
+
const open = this.openTurnForMessage(options.workflowMessageId);
|
|
283
|
+
if (open !== undefined) {
|
|
284
|
+
throw new Error(
|
|
285
|
+
`Workflow message ${options.workflowMessageId} already has open turn ${open.workflowTurnId}`,
|
|
286
|
+
);
|
|
287
|
+
}
|
|
282
288
|
this.state.connection
|
|
283
289
|
.prepare(
|
|
284
290
|
`INSERT INTO workflow_turns(
|
|
@@ -337,6 +343,51 @@ export class WorkflowMessageStore {
|
|
|
337
343
|
});
|
|
338
344
|
}
|
|
339
345
|
|
|
346
|
+
settleOpenTurnsForRun(
|
|
347
|
+
runId: string,
|
|
348
|
+
stopReason: WorkflowTurnStopReason = "lost",
|
|
349
|
+
now: number = Date.now(),
|
|
350
|
+
): WorkflowTurn[] {
|
|
351
|
+
return this.state.transaction(() => {
|
|
352
|
+
const open = this.state.connection
|
|
353
|
+
.prepare(
|
|
354
|
+
`SELECT workflow_turn_id AS workflowTurnId, workflow_message_id AS workflowMessageId,
|
|
355
|
+
run_id AS runId, target_session_id AS targetSessionId, state,
|
|
356
|
+
stop_reason AS stopReason, response_session_entry_id AS responseSessionEntryId,
|
|
357
|
+
started_at AS startedAt, ended_at AS endedAt
|
|
358
|
+
FROM workflow_turns WHERE run_id = ? AND state = 'started' ORDER BY started_at`,
|
|
359
|
+
)
|
|
360
|
+
.all(runId)
|
|
361
|
+
.filter(isWorkflowTurnRow)
|
|
362
|
+
.map(mapTurn);
|
|
363
|
+
this.state.connection
|
|
364
|
+
.prepare(
|
|
365
|
+
`UPDATE workflow_turns SET state = 'ended', stop_reason = ?, ended_at = ?
|
|
366
|
+
WHERE run_id = ? AND state = 'started'`,
|
|
367
|
+
)
|
|
368
|
+
.run(stopReason, now, runId);
|
|
369
|
+
return open.map((turn) => this.requireTurn(turn.workflowTurnId));
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
cancelPendingForRun(
|
|
374
|
+
runId: string,
|
|
375
|
+
now: number = Date.now(),
|
|
376
|
+
kinds: readonly WorkflowMessageKind[] = ["step", "decision", "followUp"],
|
|
377
|
+
): number {
|
|
378
|
+
if (kinds.length === 0) return 0;
|
|
379
|
+
return this.state.transaction(
|
|
380
|
+
() =>
|
|
381
|
+
this.state.connection
|
|
382
|
+
.prepare(
|
|
383
|
+
`UPDATE workflow_messages SET status = 'cancelled', updated_at = ?
|
|
384
|
+
WHERE run_id = ? AND status = 'pending'
|
|
385
|
+
AND kind IN (${kinds.map(() => "?").join(", ")})`,
|
|
386
|
+
)
|
|
387
|
+
.run(now, runId, ...kinds).changes,
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
|
|
340
391
|
getTurn(workflowTurnId: string): WorkflowTurn | undefined {
|
|
341
392
|
const row = this.state.connection
|
|
342
393
|
.prepare(
|
package/src/viewer/backup.ts
CHANGED
|
@@ -10,7 +10,7 @@ export function verifyInactiveBackup(
|
|
|
10
10
|
const resolved = path.resolve(databasePath);
|
|
11
11
|
const active = path.resolve(activeDatabasePath);
|
|
12
12
|
if (sameFile(resolved, active)) {
|
|
13
|
-
throw new Error("Active workflow state must be verified through the workflow
|
|
13
|
+
throw new Error("Active workflow state must be verified through the workflow server");
|
|
14
14
|
}
|
|
15
15
|
const state = new StateDatabase({ filePath: resolved, mode: "read-only" });
|
|
16
16
|
try {
|
package/src/viewer/cli.ts
CHANGED
|
@@ -12,35 +12,35 @@ import { renderClientView, runViewer } from "./tui.js";
|
|
|
12
12
|
|
|
13
13
|
const CLI_CLIENT_ID = "pi-workflows-cli";
|
|
14
14
|
|
|
15
|
-
const USAGE = `pi-workflows — workflow runs and
|
|
15
|
+
const USAGE = `pi-workflows — workflow runs and managed resources
|
|
16
16
|
|
|
17
17
|
Usage:
|
|
18
18
|
pi-workflows view [runId] [--once]
|
|
19
19
|
pi-workflows runs
|
|
20
|
-
pi-workflows
|
|
21
|
-
pi-workflows
|
|
20
|
+
pi-workflows resource-managers
|
|
21
|
+
pi-workflows resource-manager <resource-manager> <key>
|
|
22
22
|
pi-workflows state status
|
|
23
23
|
pi-workflows state verify [inactive-backup]
|
|
24
24
|
pi-workflows state backup <destination>
|
|
25
25
|
pi-workflows state prune --before <timestamp> --dry-run
|
|
26
26
|
pi-workflows state prune --before <timestamp> --backup <absolute-path> --apply
|
|
27
|
-
pi-workflows
|
|
28
|
-
pi-workflows
|
|
29
|
-
pi-workflows
|
|
30
|
-
pi-workflows
|
|
27
|
+
pi-workflows server start
|
|
28
|
+
pi-workflows server status
|
|
29
|
+
pi-workflows server stop
|
|
30
|
+
pi-workflows server run [-- <extra pi args>]
|
|
31
31
|
pi-workflows herdr sync [--json]
|
|
32
32
|
pi-workflows herdr setup [--json]
|
|
33
33
|
|
|
34
|
-
Active state is available only through the package-owned workflow
|
|
34
|
+
Active state is available only through the package-owned workflow server.
|
|
35
35
|
`;
|
|
36
36
|
|
|
37
37
|
export type CliArgs = {
|
|
38
38
|
command: string;
|
|
39
39
|
runId?: string;
|
|
40
|
-
|
|
40
|
+
resourceManagerName?: string;
|
|
41
41
|
resourceKey?: string;
|
|
42
42
|
herdrAction?: string;
|
|
43
|
-
|
|
43
|
+
serverAction?: "start" | "status" | "stop" | "run";
|
|
44
44
|
stateAction?: "status" | "verify" | "backup" | "prune";
|
|
45
45
|
backupDestination?: string;
|
|
46
46
|
verifyBackup?: string;
|
|
@@ -55,9 +55,16 @@ export function parseCliArgs(argv: string[]): CliArgs {
|
|
|
55
55
|
const args = [...argv];
|
|
56
56
|
const command = args[0] && !args[0].startsWith("-") ? (args.shift() as string) : "view";
|
|
57
57
|
if (
|
|
58
|
-
![
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
![
|
|
59
|
+
"view",
|
|
60
|
+
"runs",
|
|
61
|
+
"resource-managers",
|
|
62
|
+
"resource-manager",
|
|
63
|
+
"state",
|
|
64
|
+
"server",
|
|
65
|
+
"herdr",
|
|
66
|
+
"help",
|
|
67
|
+
].includes(command)
|
|
61
68
|
) {
|
|
62
69
|
throw new Error(`Unknown command: ${command}`);
|
|
63
70
|
}
|
|
@@ -87,23 +94,24 @@ export function parseCliArgs(argv: string[]): CliArgs {
|
|
|
87
94
|
}
|
|
88
95
|
|
|
89
96
|
if (command !== "herdr" && json) throw new Error("--json is available only for herdr sync");
|
|
90
|
-
if (command === "
|
|
91
|
-
if (project !== undefined) throw new Error("The global
|
|
97
|
+
if (command === "server") {
|
|
98
|
+
if (project !== undefined) throw new Error("The global server does not accept --project");
|
|
92
99
|
const action = positionals[0];
|
|
93
100
|
if (action !== "start" && action !== "status" && action !== "stop" && action !== "run") {
|
|
94
|
-
throw new Error("
|
|
101
|
+
throw new Error("server requires start, status, stop, or run");
|
|
95
102
|
}
|
|
96
|
-
if (positionals.length !== 1) throw new Error("
|
|
103
|
+
if (positionals.length !== 1) throw new Error("server accepts one lifecycle action");
|
|
97
104
|
if (piArgs.length > 0 && action !== "run") {
|
|
98
|
-
throw new Error("Extra Pi arguments are available only for
|
|
105
|
+
throw new Error("Extra Pi arguments are available only for server run");
|
|
99
106
|
}
|
|
100
|
-
return { command,
|
|
107
|
+
return { command, serverAction: action, once, json, piArgs };
|
|
101
108
|
}
|
|
102
|
-
if (command === "
|
|
103
|
-
if (positionals.length !== 2)
|
|
109
|
+
if (command === "resource-manager") {
|
|
110
|
+
if (positionals.length !== 2)
|
|
111
|
+
throw new Error("resource-manager requires <resource-manager> and <key>");
|
|
104
112
|
return {
|
|
105
113
|
command,
|
|
106
|
-
|
|
114
|
+
resourceManagerName: positionals[0] as string,
|
|
107
115
|
resourceKey: positionals[1] as string,
|
|
108
116
|
once,
|
|
109
117
|
json,
|
|
@@ -188,8 +196,8 @@ export async function main(argv = process.argv.slice(2)): Promise<number> {
|
|
|
188
196
|
}
|
|
189
197
|
|
|
190
198
|
try {
|
|
191
|
-
if (args.command === "
|
|
192
|
-
return await
|
|
199
|
+
if (args.command === "server") {
|
|
200
|
+
return await runServer(args.serverAction as "start" | "status" | "stop" | "run", args.piArgs);
|
|
193
201
|
}
|
|
194
202
|
if (args.command === "herdr") {
|
|
195
203
|
const result = syncHerdrPlugin(packageRoot());
|
|
@@ -223,13 +231,17 @@ export async function main(argv = process.argv.slice(2)): Promise<number> {
|
|
|
223
231
|
printJsonLines(runs);
|
|
224
232
|
return 0;
|
|
225
233
|
}
|
|
226
|
-
if (args.command === "
|
|
234
|
+
if (args.command === "resource-managers" || args.command === "resource-manager") {
|
|
227
235
|
const response = await client.request({
|
|
228
|
-
operation:
|
|
236
|
+
operation:
|
|
237
|
+
args.command === "resource-managers" ? "resourceManager.list" : "resourceManager.get",
|
|
229
238
|
payload: {
|
|
230
239
|
projectPath: process.cwd(),
|
|
231
|
-
...(args.command === "
|
|
232
|
-
? {
|
|
240
|
+
...(args.command === "resource-manager"
|
|
241
|
+
? {
|
|
242
|
+
resourceManager: args.resourceManagerName as string,
|
|
243
|
+
key: args.resourceKey as string,
|
|
244
|
+
}
|
|
233
245
|
: {}),
|
|
234
246
|
},
|
|
235
247
|
});
|
|
@@ -298,19 +310,19 @@ async function runStateCommand(client: WorkflowClient, args: CliArgs): Promise<v
|
|
|
298
310
|
process.stdout.write(`${JSON.stringify(response.receipt ?? {})}\n`);
|
|
299
311
|
}
|
|
300
312
|
|
|
301
|
-
async function
|
|
313
|
+
async function runServer(
|
|
302
314
|
action: "start" | "status" | "stop" | "run",
|
|
303
315
|
piArgs: string[] | undefined,
|
|
304
316
|
): Promise<number> {
|
|
305
317
|
if (action === "run") {
|
|
306
|
-
const {
|
|
307
|
-
const
|
|
318
|
+
const { WorkflowServer } = await import("../server/server.js");
|
|
319
|
+
const server = new WorkflowServer({
|
|
308
320
|
piArgs: piArgs ?? [],
|
|
309
|
-
onLog: (message) => process.stdout.write(`[
|
|
321
|
+
onLog: (message) => process.stdout.write(`[server] ${message}\n`),
|
|
310
322
|
});
|
|
311
|
-
await
|
|
323
|
+
await server.start();
|
|
312
324
|
await new Promise<void>((resolve) => {
|
|
313
|
-
const shutdown = () => void
|
|
325
|
+
const shutdown = () => void server.stop().then(resolve);
|
|
314
326
|
process.once("SIGTERM", shutdown);
|
|
315
327
|
process.once("SIGINT", shutdown);
|
|
316
328
|
});
|
|
@@ -321,7 +333,9 @@ async function runHost(
|
|
|
321
333
|
const response =
|
|
322
334
|
action === "start"
|
|
323
335
|
? await client.ensureRunning()
|
|
324
|
-
: await client.request({
|
|
336
|
+
: await client.request({
|
|
337
|
+
operation: action === "status" ? "server.status" : "server.stop",
|
|
338
|
+
});
|
|
325
339
|
process.stdout.write(`${JSON.stringify(response.receipt ?? {})}\n`);
|
|
326
340
|
return response.outcome === "accepted" || response.outcome === "adopted" ? 0 : 1;
|
|
327
341
|
} finally {
|
|
@@ -364,7 +378,7 @@ function printJsonLines(value: JsonValue): void {
|
|
|
364
378
|
|
|
365
379
|
function requireAccepted(response: { outcome: string; error?: string }): void {
|
|
366
380
|
if (response.outcome !== "accepted" && response.outcome !== "adopted") {
|
|
367
|
-
throw new Error(response.error ?? `Workflow
|
|
381
|
+
throw new Error(response.error ?? `Workflow server returned ${response.outcome}`);
|
|
368
382
|
}
|
|
369
383
|
}
|
|
370
384
|
|
package/src/viewer/tui.ts
CHANGED
|
@@ -13,7 +13,7 @@ export type ViewerOptions = {
|
|
|
13
13
|
runId?: string | undefined;
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
/** Interactive client view. All durable reads stay in the workflow
|
|
16
|
+
/** Interactive client view. All durable reads stay in the workflow server. */
|
|
17
17
|
export async function runViewer(options: ViewerOptions): Promise<void> {
|
|
18
18
|
let value: JsonValue = options.runId === undefined ? [] : null;
|
|
19
19
|
let selected = 0;
|
|
@@ -117,8 +117,8 @@ export async function runCommandBatch(
|
|
|
117
117
|
}
|
|
118
118
|
};
|
|
119
119
|
|
|
120
|
-
const
|
|
121
|
-
await Promise.all(Array.from({ length:
|
|
120
|
+
const runnerCount = Math.min(request.maxConcurrency, total);
|
|
121
|
+
await Promise.all(Array.from({ length: runnerCount }, worker));
|
|
122
122
|
|
|
123
123
|
for (let index = 0; index < total; index += 1) {
|
|
124
124
|
if (results[index] !== undefined) continue;
|
|
@@ -589,15 +589,10 @@ function wrappedEffect(
|
|
|
589
589
|
project: (context: WorkflowNodeContext) => WorkflowNodeContext,
|
|
590
590
|
): WorkflowManagedEffect | undefined {
|
|
591
591
|
if (node.effect === undefined) return undefined;
|
|
592
|
-
const idempotencyKey = node.effect.idempotencyKey;
|
|
593
592
|
const request = node.effect.request;
|
|
594
593
|
return {
|
|
595
594
|
type: node.effect.type,
|
|
596
595
|
recovery: node.effect.recovery,
|
|
597
|
-
idempotencyKey:
|
|
598
|
-
typeof idempotencyKey === "function"
|
|
599
|
-
? (context: WorkflowNodeContext) => idempotencyKey(project(context))
|
|
600
|
-
: idempotencyKey,
|
|
601
596
|
request:
|
|
602
597
|
typeof request === "function"
|
|
603
598
|
? (context: WorkflowNodeContext) => request(project(context))
|
|
@@ -191,14 +191,6 @@ function workflowEffect(
|
|
|
191
191
|
return {
|
|
192
192
|
type: normalized,
|
|
193
193
|
recovery,
|
|
194
|
-
idempotencyKey: ({ state }: WorkflowNodeContext) => {
|
|
195
|
-
const nodeId = state.currentNode;
|
|
196
|
-
if (nodeId === undefined) {
|
|
197
|
-
throw new Error("Managed effect resolution requires an active workflow node");
|
|
198
|
-
}
|
|
199
|
-
const nodeInvocation = state.steps.filter((step) => step.nodeId === nodeId).length + 1;
|
|
200
|
-
return `${state.runId}:${normalized}:${nodeId}:${nodeInvocation}`;
|
|
201
|
-
},
|
|
202
194
|
request: ({ input, outputs }: WorkflowNodeContext) => ({ input, outputs }),
|
|
203
195
|
};
|
|
204
196
|
}
|