@osolmaz/pi-workflows 0.16.2 → 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 +1 -1
- package/dist/extension/index.d.ts +1 -1
- package/dist/extension/index.js +32 -32
- 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 +1 -1
- package/dist/extension/workflow-message-coordinator.js +6 -6
- 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 +44 -44
- package/dist/{controllers → resource-managers}/sqlite.js +139 -130
- 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} +39 -38
- package/dist/{host/runner.js → server/server.js} +408 -374
- 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 +13 -13
- 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/{host/worker-entry.d.ts → server/workflow-runner-entry.d.ts} +3 -3
- package/dist/{host/worker-entry.js → server/workflow-runner-entry.js} +68 -35
- 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 +1 -1
- package/dist/state/workflow-messages.js +1 -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/engine.js +14 -15
- package/dist/workflows/engine.js.map +1 -1
- package/dist/workflows/store.d.ts +12 -11
- package/dist/workflows/store.js +24 -18
- package/dist/workflows/store.js.map +1 -1
- package/dist/workflows/types.d.ts +2 -2
- 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 +6 -6
- 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 +35 -33
- package/docs/WORKFLOW_COMPOSITION.md +1 -1
- package/docs/{WORKFLOW_HOST.md → WORKFLOW_SERVER.md} +125 -119
- 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 +72 -66
- 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 +1 -1
- package/src/extension/index.ts +44 -34
- 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 +6 -6
- 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 +198 -186
- 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} +526 -461
- package/src/{host → server}/state.ts +78 -67
- package/src/{host → server}/view.ts +15 -15
- package/src/server/workflow-runner-content.ts +119 -0
- package/src/{host/worker-entry.ts → server/workflow-runner-entry.ts} +98 -57
- 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 +1 -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/engine.ts +14 -15
- package/src/workflows/store.ts +31 -28
- package/src/workflows/types.ts +2 -2
- 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.js.map +0 -1
- package/dist/host/worker-protocol.d.ts +0 -46
- 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 -176
- 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
|
@@ -20,7 +20,7 @@ type ChannelAdapterReport = ChannelAdapterMessage extends infer Message
|
|
|
20
20
|
: never
|
|
21
21
|
: never;
|
|
22
22
|
|
|
23
|
-
class
|
|
23
|
+
class AdapterServerConnection {
|
|
24
24
|
private sequence = 0;
|
|
25
25
|
private revision = 0;
|
|
26
26
|
private readonly lines = createInterface({ input: process.stdin, crlfDelay: Infinity })[
|
|
@@ -43,13 +43,13 @@ class AdapterHostConnection {
|
|
|
43
43
|
await new Promise<void>((resolve) => process.stdout.once("drain", resolve));
|
|
44
44
|
}
|
|
45
45
|
const next = await this.lines.next();
|
|
46
|
-
if (next.done) throw new Error("Workflow
|
|
46
|
+
if (next.done) throw new Error("Workflow server closed the channel adapter connection");
|
|
47
47
|
const response = parseChannelAdapterResponse(Buffer.from(next.value, "utf8"));
|
|
48
48
|
if (response.sequence !== this.sequence) {
|
|
49
|
-
throw new Error("Workflow
|
|
49
|
+
throw new Error("Workflow server returned a mismatched channel response");
|
|
50
50
|
}
|
|
51
51
|
if (response.outcome !== "accepted") {
|
|
52
|
-
throw new Error(response.error ?? "Workflow
|
|
52
|
+
throw new Error(response.error ?? "Workflow server rejected the channel adapter message");
|
|
53
53
|
}
|
|
54
54
|
this.revision = response.revision;
|
|
55
55
|
return response;
|
|
@@ -58,7 +58,7 @@ class AdapterHostConnection {
|
|
|
58
58
|
|
|
59
59
|
export async function runChannelAdapter(): Promise<number> {
|
|
60
60
|
const launch = readLaunch();
|
|
61
|
-
const
|
|
61
|
+
const server = new AdapterServerConnection(launch);
|
|
62
62
|
const telegram = new TelegramAdapter({
|
|
63
63
|
profile: launch.profile,
|
|
64
64
|
token: launch.token,
|
|
@@ -85,7 +85,7 @@ export async function runChannelAdapter(): Promise<number> {
|
|
|
85
85
|
stopping = true;
|
|
86
86
|
});
|
|
87
87
|
|
|
88
|
-
let response = await
|
|
88
|
+
let response = await server.report({
|
|
89
89
|
kind: "channel.ready",
|
|
90
90
|
stableMessageId: controlId("ready"),
|
|
91
91
|
cursor,
|
|
@@ -94,7 +94,7 @@ export async function runChannelAdapter(): Promise<number> {
|
|
|
94
94
|
const command = response.command;
|
|
95
95
|
if (command === null) {
|
|
96
96
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
97
|
-
response = await
|
|
97
|
+
response = await server.report({
|
|
98
98
|
kind: "channel.ready",
|
|
99
99
|
stableMessageId: controlId("ready"),
|
|
100
100
|
cursor,
|
|
@@ -108,7 +108,7 @@ export async function runChannelAdapter(): Promise<number> {
|
|
|
108
108
|
if (command.kind === "channel.present") {
|
|
109
109
|
try {
|
|
110
110
|
const messages = await telegram.present(command.request);
|
|
111
|
-
response = await
|
|
111
|
+
response = await server.report({
|
|
112
112
|
kind: "channel.present",
|
|
113
113
|
stableMessageId: command.stableMessageId,
|
|
114
114
|
decisionId: command.request.decisionId,
|
|
@@ -118,7 +118,7 @@ export async function runChannelAdapter(): Promise<number> {
|
|
|
118
118
|
messages,
|
|
119
119
|
});
|
|
120
120
|
} catch (error) {
|
|
121
|
-
response = await
|
|
121
|
+
response = await server.report({
|
|
122
122
|
kind: "channel.present",
|
|
123
123
|
stableMessageId: command.stableMessageId,
|
|
124
124
|
decisionId: command.request.decisionId,
|
|
@@ -134,7 +134,7 @@ export async function runChannelAdapter(): Promise<number> {
|
|
|
134
134
|
if (command.kind === "channel.settle") {
|
|
135
135
|
try {
|
|
136
136
|
await telegram.settle(command.outcome, command.response, command.messages);
|
|
137
|
-
response = await
|
|
137
|
+
response = await server.report({
|
|
138
138
|
kind: "channel.settle",
|
|
139
139
|
stableMessageId: command.stableMessageId,
|
|
140
140
|
decisionId: command.request.decisionId,
|
|
@@ -143,7 +143,7 @@ export async function runChannelAdapter(): Promise<number> {
|
|
|
143
143
|
state: "confirmed",
|
|
144
144
|
});
|
|
145
145
|
} catch (error) {
|
|
146
|
-
response = await
|
|
146
|
+
response = await server.report({
|
|
147
147
|
kind: "channel.settle",
|
|
148
148
|
stableMessageId: command.stableMessageId,
|
|
149
149
|
decisionId: command.request.decisionId,
|
|
@@ -160,7 +160,7 @@ export async function runChannelAdapter(): Promise<number> {
|
|
|
160
160
|
const polled = await telegram.poll(command.cursor);
|
|
161
161
|
cursor = polled.cursor;
|
|
162
162
|
for (const answer of polled.answers) {
|
|
163
|
-
await
|
|
163
|
+
await server.report({
|
|
164
164
|
kind: "channel.answer",
|
|
165
165
|
stableMessageId: channelStableMessageId([
|
|
166
166
|
launch.profile,
|
|
@@ -177,14 +177,14 @@ export async function runChannelAdapter(): Promise<number> {
|
|
|
177
177
|
cursor,
|
|
178
178
|
});
|
|
179
179
|
}
|
|
180
|
-
response = await
|
|
180
|
+
response = await server.report({
|
|
181
181
|
kind: "channel.ready",
|
|
182
182
|
stableMessageId: controlId("ready"),
|
|
183
183
|
cursor,
|
|
184
184
|
});
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
-
await
|
|
187
|
+
await server.report({
|
|
188
188
|
kind: "channel.exiting",
|
|
189
189
|
stableMessageId: controlId("exiting"),
|
|
190
190
|
cursor,
|
package/src/client/client.ts
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
type ClientResponse,
|
|
21
21
|
} from "./protocol.js";
|
|
22
22
|
import type {
|
|
23
|
-
|
|
23
|
+
ResolvedResourceManagerInitialization,
|
|
24
24
|
ResolvedSettingsChange,
|
|
25
25
|
ResolvedWorkflowLaunch,
|
|
26
26
|
} from "./resolver.js";
|
|
@@ -55,7 +55,7 @@ export class WorkflowClientVersionError extends Error {
|
|
|
55
55
|
export type WorkflowClientOptions = {
|
|
56
56
|
clientId?: string;
|
|
57
57
|
databasePath?: string;
|
|
58
|
-
|
|
58
|
+
serverEntryPath?: string;
|
|
59
59
|
env?: Record<string, string>;
|
|
60
60
|
};
|
|
61
61
|
|
|
@@ -64,7 +64,7 @@ export class WorkflowClient {
|
|
|
64
64
|
readonly databasePath: string;
|
|
65
65
|
readonly endpoint: string;
|
|
66
66
|
|
|
67
|
-
private readonly
|
|
67
|
+
private readonly serverEntryPath: string | undefined;
|
|
68
68
|
private readonly env: Record<string, string> | undefined;
|
|
69
69
|
private socket: Socket | null = null;
|
|
70
70
|
private connectTask: Promise<ClientHello> | null = null;
|
|
@@ -78,7 +78,7 @@ export class WorkflowClient {
|
|
|
78
78
|
this.clientId = options.clientId ?? `client-${randomUUID()}`;
|
|
79
79
|
this.databasePath = options.databasePath ?? workflowStatePath();
|
|
80
80
|
this.endpoint = clientSocketPath(this.databasePath);
|
|
81
|
-
this.
|
|
81
|
+
this.serverEntryPath = options.serverEntryPath;
|
|
82
82
|
this.env = options.env;
|
|
83
83
|
}
|
|
84
84
|
|
|
@@ -143,7 +143,7 @@ export class WorkflowClient {
|
|
|
143
143
|
const response = await this.request({ operation: "view.run.get", runId });
|
|
144
144
|
if (response.outcome === "notFound") return null;
|
|
145
145
|
if (response.outcome !== "accepted" || !isWorkflowRunView(response.receipt, runId)) {
|
|
146
|
-
throw new Error(response.error ?? "Workflow
|
|
146
|
+
throw new Error(response.error ?? "Workflow server returned an invalid run view");
|
|
147
147
|
}
|
|
148
148
|
return response.receipt;
|
|
149
149
|
}
|
|
@@ -216,13 +216,13 @@ export class WorkflowClient {
|
|
|
216
216
|
}
|
|
217
217
|
}
|
|
218
218
|
throw new Error(
|
|
219
|
-
`Workflow
|
|
219
|
+
`Workflow server did not become ready: ${lastError instanceof Error ? lastError.message : String(lastError)}`,
|
|
220
220
|
);
|
|
221
221
|
}
|
|
222
222
|
|
|
223
223
|
async ensureRunning(): Promise<ClientResponse> {
|
|
224
224
|
await this.ensureAvailable();
|
|
225
|
-
return await this.request({ operation: "
|
|
225
|
+
return await this.request({ operation: "server.status" });
|
|
226
226
|
}
|
|
227
227
|
|
|
228
228
|
async readContent(
|
|
@@ -367,23 +367,23 @@ export class WorkflowClient {
|
|
|
367
367
|
)) as unknown as ResolvedWorkflowLaunch;
|
|
368
368
|
}
|
|
369
369
|
|
|
370
|
-
async
|
|
370
|
+
async resolveResourceManagerInitialization(options: {
|
|
371
371
|
cwd: string;
|
|
372
|
-
|
|
372
|
+
resourceManagerName: string;
|
|
373
373
|
spec: JsonValue;
|
|
374
374
|
timeoutMs?: number;
|
|
375
|
-
}): Promise<
|
|
375
|
+
}): Promise<ResolvedResourceManagerInitialization> {
|
|
376
376
|
return (await this.runResolver(
|
|
377
377
|
{
|
|
378
|
-
schema: "pi-workflows.
|
|
378
|
+
schema: "pi-workflows.resource-manager-initialization-request.v1",
|
|
379
379
|
cwd: options.cwd,
|
|
380
|
-
|
|
380
|
+
resourceManagerName: options.resourceManagerName,
|
|
381
381
|
spec: options.spec,
|
|
382
382
|
},
|
|
383
383
|
options.cwd,
|
|
384
|
-
"pi-workflows.resolved-
|
|
384
|
+
"pi-workflows.resolved-resource-manager-initialization.v1",
|
|
385
385
|
options.timeoutMs,
|
|
386
|
-
)) as unknown as
|
|
386
|
+
)) as unknown as ResolvedResourceManagerInitialization;
|
|
387
387
|
}
|
|
388
388
|
|
|
389
389
|
async resolveSettingsChange(options: {
|
|
@@ -498,7 +498,7 @@ export class WorkflowClient {
|
|
|
498
498
|
|
|
499
499
|
private async send(request: ClientRequest, signal?: AbortSignal): Promise<ClientResponse> {
|
|
500
500
|
const socket = this.socket;
|
|
501
|
-
if (socket === null || socket.destroyed) throw new Error("Workflow
|
|
501
|
+
if (socket === null || socket.destroyed) throw new Error("Workflow server is unavailable");
|
|
502
502
|
if (signal?.aborted === true) throw abortReason(signal);
|
|
503
503
|
if (this.pending.has(request.requestId)) {
|
|
504
504
|
throw new Error(`Workflow request is already pending: ${request.requestId}`);
|
|
@@ -549,10 +549,11 @@ export class WorkflowClient {
|
|
|
549
549
|
for (const frame of decoder.push(chunk)) {
|
|
550
550
|
const message = parseClientMessage(frame);
|
|
551
551
|
if (!receivedHello) {
|
|
552
|
-
if (message.type !== "hello")
|
|
552
|
+
if (message.type !== "hello")
|
|
553
|
+
throw new Error("Workflow server did not send hello first");
|
|
553
554
|
if (message.packageVersion !== CLIENT_PACKAGE_VERSION) {
|
|
554
555
|
throw new WorkflowClientVersionError(
|
|
555
|
-
`Workflow client version mismatch:
|
|
556
|
+
`Workflow client version mismatch: server ${message.packageVersion}, client ${CLIENT_PACKAGE_VERSION}. Install matching pi-workflows and piw packages.`,
|
|
556
557
|
);
|
|
557
558
|
}
|
|
558
559
|
receivedHello = true;
|
|
@@ -597,9 +598,9 @@ export class WorkflowClient {
|
|
|
597
598
|
helloReject(error);
|
|
598
599
|
});
|
|
599
600
|
socket.once("close", () => {
|
|
600
|
-
if (!receivedHello) helloReject(new Error("Workflow
|
|
601
|
+
if (!receivedHello) helloReject(new Error("Workflow server closed before hello"));
|
|
601
602
|
if (this.socket === socket) {
|
|
602
|
-
this.resetConnection(new Error("Workflow
|
|
603
|
+
this.resetConnection(new Error("Workflow server connection closed"));
|
|
603
604
|
this.scheduleReconnect();
|
|
604
605
|
}
|
|
605
606
|
});
|
|
@@ -611,7 +612,7 @@ export class WorkflowClient {
|
|
|
611
612
|
helloPromise.then(() => undefined),
|
|
612
613
|
new Promise<never>((_, reject) => {
|
|
613
614
|
connectTimer = setTimeout(
|
|
614
|
-
() => reject(new Error("Workflow
|
|
615
|
+
() => reject(new Error("Workflow server connection timed out")),
|
|
615
616
|
CONNECT_TIMEOUT_MS,
|
|
616
617
|
);
|
|
617
618
|
connectTimer.unref?.();
|
|
@@ -620,7 +621,7 @@ export class WorkflowClient {
|
|
|
620
621
|
const hello = await Promise.race([
|
|
621
622
|
helloPromise,
|
|
622
623
|
delay(CONNECT_TIMEOUT_MS).then(() => {
|
|
623
|
-
throw new Error("Workflow
|
|
624
|
+
throw new Error("Workflow server hello timed out");
|
|
624
625
|
}),
|
|
625
626
|
]);
|
|
626
627
|
await this.restoreSubscriptions();
|
|
@@ -702,7 +703,7 @@ export class WorkflowClient {
|
|
|
702
703
|
}
|
|
703
704
|
}
|
|
704
705
|
|
|
705
|
-
private resetConnection(reason = new Error("Workflow
|
|
706
|
+
private resetConnection(reason = new Error("Workflow server is unavailable")): void {
|
|
706
707
|
const socket = this.socket;
|
|
707
708
|
this.socket = null;
|
|
708
709
|
this.hello = null;
|
|
@@ -718,7 +719,7 @@ export class WorkflowClient {
|
|
|
718
719
|
type: "event",
|
|
719
720
|
subscriptionId,
|
|
720
721
|
event: "unavailable",
|
|
721
|
-
payload: { message: "Workflow
|
|
722
|
+
payload: { message: "Workflow server connection is unavailable." },
|
|
722
723
|
});
|
|
723
724
|
} catch {
|
|
724
725
|
// One renderer cannot block reconnection for other subscriptions.
|
|
@@ -742,8 +743,8 @@ export class WorkflowClient {
|
|
|
742
743
|
expectedSchema: string,
|
|
743
744
|
timeoutMs = RESOLVER_TIMEOUT_MS,
|
|
744
745
|
): Promise<JsonValue> {
|
|
745
|
-
const builtEntry = fileURLToPath(new URL("../
|
|
746
|
-
const sourceEntry = fileURLToPath(new URL("../
|
|
746
|
+
const builtEntry = fileURLToPath(new URL("../server/resolver-entry.js", import.meta.url));
|
|
747
|
+
const sourceEntry = fileURLToPath(new URL("../server/resolver-entry.ts", import.meta.url));
|
|
747
748
|
const args = fs.existsSync(builtEntry)
|
|
748
749
|
? [builtEntry]
|
|
749
750
|
: ["--import", createRequire(import.meta.url).resolve("tsx"), sourceEntry];
|
|
@@ -791,11 +792,11 @@ export class WorkflowClient {
|
|
|
791
792
|
}
|
|
792
793
|
|
|
793
794
|
private startDetached(): void {
|
|
794
|
-
const builtEntry = fileURLToPath(new URL("../
|
|
795
|
-
const sourceEntry = fileURLToPath(new URL("../
|
|
796
|
-
const entry = this.
|
|
795
|
+
const builtEntry = fileURLToPath(new URL("../server/server-entry.js", import.meta.url));
|
|
796
|
+
const sourceEntry = fileURLToPath(new URL("../server/server-entry.ts", import.meta.url));
|
|
797
|
+
const entry = this.serverEntryPath ?? builtEntry;
|
|
797
798
|
const args =
|
|
798
|
-
this.
|
|
799
|
+
this.serverEntryPath === undefined && !fs.existsSync(builtEntry)
|
|
799
800
|
? ["--import", createRequire(import.meta.url).resolve("tsx"), sourceEntry]
|
|
800
801
|
: [entry];
|
|
801
802
|
const child = spawn(process.execPath, [...args, "--database", this.databasePath], {
|
|
@@ -829,7 +830,7 @@ function parseWorkflowRunListPage(value: unknown): WorkflowRunListPage {
|
|
|
829
830
|
isRecord(item) && typeof item.runId === "string" && typeof item.workflowName === "string",
|
|
830
831
|
)
|
|
831
832
|
) {
|
|
832
|
-
throw new Error("Workflow
|
|
833
|
+
throw new Error("Workflow server returned an invalid run list page");
|
|
833
834
|
}
|
|
834
835
|
return value as unknown as WorkflowRunListPage;
|
|
835
836
|
}
|
|
@@ -851,7 +852,7 @@ function abortReason(signal: AbortSignal): Error {
|
|
|
851
852
|
|
|
852
853
|
function waitForSocketDrain(socket: Socket, signal?: AbortSignal): Promise<void> {
|
|
853
854
|
if (signal?.aborted === true) return Promise.reject(abortReason(signal));
|
|
854
|
-
if (socket.destroyed) return Promise.reject(new Error("Workflow
|
|
855
|
+
if (socket.destroyed) return Promise.reject(new Error("Workflow server connection closed"));
|
|
855
856
|
return new Promise((resolve, reject) => {
|
|
856
857
|
const cleanup = (): void => {
|
|
857
858
|
socket.off("drain", onDrain);
|
|
@@ -865,7 +866,7 @@ function waitForSocketDrain(socket: Socket, signal?: AbortSignal): Promise<void>
|
|
|
865
866
|
else reject(error);
|
|
866
867
|
};
|
|
867
868
|
const onDrain = (): void => settle();
|
|
868
|
-
const onClose = (): void => settle(new Error("Workflow
|
|
869
|
+
const onClose = (): void => settle(new Error("Workflow server connection closed"));
|
|
869
870
|
const onError = (error: Error): void => settle(error);
|
|
870
871
|
const onAbort = (): void => settle(abortReason(signal as AbortSignal));
|
|
871
872
|
socket.once("drain", onDrain);
|
package/src/client/protocol.ts
CHANGED
|
@@ -28,13 +28,13 @@ export const CLIENT_OPERATIONS = [
|
|
|
28
28
|
"channel.status",
|
|
29
29
|
"channel.reload",
|
|
30
30
|
"channel.recover",
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
31
|
+
"resourceManager.list",
|
|
32
|
+
"resourceManager.get",
|
|
33
|
+
"resourceManager.apply",
|
|
34
|
+
"resourceManager.reconcile",
|
|
35
|
+
"resourceManager.delete",
|
|
36
|
+
"server.status",
|
|
37
|
+
"server.stop",
|
|
38
38
|
"view.runs.watch",
|
|
39
39
|
"view.runs.page",
|
|
40
40
|
"view.run.get",
|
|
@@ -185,10 +185,15 @@ export function clientSocketPath(databasePath: string): string {
|
|
|
185
185
|
export class NdjsonFrameDecoder {
|
|
186
186
|
private buffered = Buffer.alloc(0);
|
|
187
187
|
|
|
188
|
+
constructor(
|
|
189
|
+
private readonly maxMessageBytes = MAX_PROTOCOL_MESSAGE_BYTES,
|
|
190
|
+
private readonly oversizedMessage = "Client protocol message exceeds 1 MiB",
|
|
191
|
+
) {}
|
|
192
|
+
|
|
188
193
|
push(chunk: Buffer): Buffer[] {
|
|
189
194
|
this.buffered = Buffer.concat([this.buffered, chunk]);
|
|
190
|
-
if (this.buffered.byteLength >
|
|
191
|
-
throw new ClientProtocolError(
|
|
195
|
+
if (this.buffered.byteLength > this.maxMessageBytes && !this.buffered.includes(0x0a)) {
|
|
196
|
+
throw new ClientProtocolError(this.oversizedMessage);
|
|
192
197
|
}
|
|
193
198
|
const frames: Buffer[] = [];
|
|
194
199
|
for (;;) {
|
|
@@ -197,8 +202,8 @@ export class NdjsonFrameDecoder {
|
|
|
197
202
|
const frame = this.buffered.subarray(0, newline);
|
|
198
203
|
this.buffered = this.buffered.subarray(newline + 1);
|
|
199
204
|
if (frame.byteLength === 0) continue;
|
|
200
|
-
if (frame.byteLength + 1 >
|
|
201
|
-
throw new ClientProtocolError(
|
|
205
|
+
if (frame.byteLength + 1 > this.maxMessageBytes) {
|
|
206
|
+
throw new ClientProtocolError(this.oversizedMessage);
|
|
202
207
|
}
|
|
203
208
|
frames.push(frame);
|
|
204
209
|
}
|
package/src/client/resolver.ts
CHANGED
|
@@ -9,10 +9,10 @@ export type ResolvedWorkflowLaunch = {
|
|
|
9
9
|
definitionSnapshot: JsonValue;
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
export type
|
|
13
|
-
schema: "pi-workflows.resolved-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
export type ResolvedResourceManagerInitialization = {
|
|
13
|
+
schema: "pi-workflows.resolved-resource-manager-initialization.v1";
|
|
14
|
+
resourceManagerName: string;
|
|
15
|
+
resourceManagerPath: string;
|
|
16
16
|
sourceHash: string;
|
|
17
17
|
initialStatus: JsonValue;
|
|
18
18
|
};
|
package/src/client/view.ts
CHANGED
|
@@ -19,7 +19,7 @@ export type WorkflowDisplayStatus =
|
|
|
19
19
|
|
|
20
20
|
export type WorkflowDisplay = {
|
|
21
21
|
status: WorkflowDisplayStatus;
|
|
22
|
-
activity: "
|
|
22
|
+
activity: "supervised_runner" | "origin_turn" | null;
|
|
23
23
|
controls: Array<"pause" | "resume" | "cancel" | "answer" | "review">;
|
|
24
24
|
reason: string | null;
|
|
25
25
|
reasonContent?: JsonValue;
|
package/src/extension/index.ts
CHANGED
|
@@ -17,7 +17,6 @@ import { errorMessage } from "../workflows/errors.js";
|
|
|
17
17
|
import { discoverWorkflows } from "../workflows/loader.js";
|
|
18
18
|
import { createRunId } from "../workflows/store.js";
|
|
19
19
|
import type { AgentStepContract, HumanDecisionResponse } from "../workflows/types.js";
|
|
20
|
-
import { parseControllerArgs, type ParsedControllerArgs } from "./controller-command.js";
|
|
21
20
|
import {
|
|
22
21
|
HerdrWorkflowViewer,
|
|
23
22
|
PIW_SHORTCUT,
|
|
@@ -27,12 +26,19 @@ import {
|
|
|
27
26
|
} from "./herdr-viewer.js";
|
|
28
27
|
import { SessionRecorder } from "./recorder.js";
|
|
29
28
|
import { RemoteSessionRecordingStore } from "./remote-recorder-store.js";
|
|
29
|
+
import {
|
|
30
|
+
parseResourceManagerArgs,
|
|
31
|
+
type ParsedResourceManagerArgs,
|
|
32
|
+
} from "./resource-manager-command.js";
|
|
30
33
|
import { SessionWorkflowView } from "./session-view.js";
|
|
31
34
|
import { recoverAssistantStep, registerWorkflowAgentStepMessageRenderer } from "./step-message.js";
|
|
32
35
|
import { responseEntryId, WorkflowMessageCoordinator } from "./workflow-message-coordinator.js";
|
|
33
36
|
import { parseWorkflowToolInput, WorkflowToolParameters } from "./workflow-tool.js";
|
|
34
37
|
|
|
35
|
-
export {
|
|
38
|
+
export {
|
|
39
|
+
parseResourceManagerArgs,
|
|
40
|
+
type ParsedResourceManagerArgs,
|
|
41
|
+
} from "./resource-manager-command.js";
|
|
36
42
|
|
|
37
43
|
export {
|
|
38
44
|
audienceChannels,
|
|
@@ -176,7 +182,7 @@ export default function piWorkflows(pi: ExtensionAPI): void {
|
|
|
176
182
|
let sessionGeneration = 0;
|
|
177
183
|
let sessionUnsubscribe: (() => Promise<void>) | null = null;
|
|
178
184
|
let sessionConnectTask: Promise<void> | null = null;
|
|
179
|
-
let
|
|
185
|
+
let serverUnavailableNotified = false;
|
|
180
186
|
let pollTimer: ReturnType<typeof setInterval> | null = null;
|
|
181
187
|
let presentationTail = Promise.resolve();
|
|
182
188
|
let toolTail = Promise.resolve();
|
|
@@ -460,8 +466,8 @@ export default function piWorkflows(pi: ExtensionAPI): void {
|
|
|
460
466
|
},
|
|
461
467
|
});
|
|
462
468
|
|
|
463
|
-
pi.registerCommand("
|
|
464
|
-
description: "Manage hosted
|
|
469
|
+
pi.registerCommand("resource-manager", {
|
|
470
|
+
description: "Manage hosted managed resources: list, get, apply, reconcile, or delete",
|
|
465
471
|
getArgumentCompletions: (prefix: string) => {
|
|
466
472
|
const items = ["list", "get", "apply", "reconcile", "delete"]
|
|
467
473
|
.filter((value) => value.startsWith(prefix))
|
|
@@ -470,7 +476,11 @@ export default function piWorkflows(pi: ExtensionAPI): void {
|
|
|
470
476
|
},
|
|
471
477
|
handler: async (args, ctx) => {
|
|
472
478
|
try {
|
|
473
|
-
const result = await
|
|
479
|
+
const result = await executeResourceManagerCommand(
|
|
480
|
+
client,
|
|
481
|
+
ctx,
|
|
482
|
+
parseResourceManagerArgs(args),
|
|
483
|
+
);
|
|
474
484
|
ctx.ui.notify(result.message, result.level ?? "info");
|
|
475
485
|
} catch (error) {
|
|
476
486
|
ctx.ui.notify(errorMessage(error), "error");
|
|
@@ -579,7 +589,7 @@ export default function piWorkflows(pi: ExtensionAPI): void {
|
|
|
579
589
|
|
|
580
590
|
pi.on("session_start", (_event, ctx) => {
|
|
581
591
|
sessionContext = ctx;
|
|
582
|
-
|
|
592
|
+
serverUnavailableNotified = false;
|
|
583
593
|
const sessionId = ctx.sessionManager.getSessionId();
|
|
584
594
|
const generation = ++sessionGeneration;
|
|
585
595
|
let snapshotGeneration = 0;
|
|
@@ -645,7 +655,7 @@ export default function piWorkflows(pi: ExtensionAPI): void {
|
|
|
645
655
|
return;
|
|
646
656
|
}
|
|
647
657
|
sessionUnsubscribe = unsubscribe;
|
|
648
|
-
|
|
658
|
+
serverUnavailableNotified = false;
|
|
649
659
|
const capability = await herdrViewer.probe();
|
|
650
660
|
if (generation !== sessionGeneration || sessionContext !== ctx) return;
|
|
651
661
|
sessionView.setActionHint(capability.available ? PIW_SHORTCUT_HINT : undefined, ctx);
|
|
@@ -654,10 +664,10 @@ export default function piWorkflows(pi: ExtensionAPI): void {
|
|
|
654
664
|
if (
|
|
655
665
|
generation === sessionGeneration &&
|
|
656
666
|
sessionContext === ctx &&
|
|
657
|
-
!
|
|
667
|
+
!serverUnavailableNotified
|
|
658
668
|
) {
|
|
659
|
-
|
|
660
|
-
ctx.ui.notify(`Workflow
|
|
669
|
+
serverUnavailableNotified = true;
|
|
670
|
+
ctx.ui.notify(`Workflow server is unavailable: ${errorMessage(error)}`, "warning");
|
|
661
671
|
}
|
|
662
672
|
}
|
|
663
673
|
})();
|
|
@@ -778,7 +788,7 @@ export default function piWorkflows(pi: ExtensionAPI): void {
|
|
|
778
788
|
if (sessionUnsubscribe !== null) await sessionUnsubscribe().catch(() => undefined);
|
|
779
789
|
sessionUnsubscribe = null;
|
|
780
790
|
sessionConnectTask = null;
|
|
781
|
-
|
|
791
|
+
serverUnavailableNotified = false;
|
|
782
792
|
await client.close();
|
|
783
793
|
client = new WorkflowClient({ clientId: `pi-extension-${randomUUID()}` });
|
|
784
794
|
});
|
|
@@ -1083,57 +1093,57 @@ async function executeCommand(
|
|
|
1083
1093
|
}
|
|
1084
1094
|
}
|
|
1085
1095
|
|
|
1086
|
-
async function
|
|
1096
|
+
async function executeResourceManagerCommand(
|
|
1087
1097
|
client: WorkflowClient,
|
|
1088
1098
|
ctx: ExtensionContext,
|
|
1089
|
-
command:
|
|
1099
|
+
command: ParsedResourceManagerArgs,
|
|
1090
1100
|
): Promise<CommandResult> {
|
|
1091
1101
|
const projectPath = path.resolve(ctx.cwd);
|
|
1092
1102
|
if (command.kind === "list") {
|
|
1093
1103
|
const response = await requestAccepted(client, {
|
|
1094
|
-
operation: "
|
|
1104
|
+
operation: "resourceManager.list",
|
|
1095
1105
|
payload: { projectPath },
|
|
1096
1106
|
});
|
|
1097
1107
|
return {
|
|
1098
|
-
message:
|
|
1108
|
+
message: summarizeManagedResources(response.receipt),
|
|
1099
1109
|
details: { action: "list", resources: response.receipt ?? [] },
|
|
1100
1110
|
};
|
|
1101
1111
|
}
|
|
1102
1112
|
|
|
1103
1113
|
const idempotencyKey = randomUUID();
|
|
1104
1114
|
if (command.kind === "apply") {
|
|
1105
|
-
const resolved = await client.
|
|
1115
|
+
const resolved = await client.resolveResourceManagerInitialization({
|
|
1106
1116
|
cwd: projectPath,
|
|
1107
|
-
|
|
1117
|
+
resourceManagerName: command.resourceManager,
|
|
1108
1118
|
spec: command.spec,
|
|
1109
1119
|
});
|
|
1110
1120
|
const response = await requestAccepted(client, {
|
|
1111
|
-
operation: "
|
|
1112
|
-
requestId: `
|
|
1121
|
+
operation: "resourceManager.apply",
|
|
1122
|
+
requestId: `resource-manager-apply-${idempotencyKey}`,
|
|
1113
1123
|
idempotencyKey,
|
|
1114
1124
|
payload: {
|
|
1115
1125
|
projectPath,
|
|
1116
|
-
|
|
1126
|
+
resourceManager: resolved.resourceManagerName,
|
|
1117
1127
|
key: command.key,
|
|
1118
1128
|
spec: command.spec,
|
|
1119
1129
|
initialStatus: resolved.initialStatus,
|
|
1120
|
-
|
|
1130
|
+
resourceManagerPath: resolved.resourceManagerPath,
|
|
1121
1131
|
sourceHash: resolved.sourceHash,
|
|
1122
1132
|
},
|
|
1123
1133
|
});
|
|
1124
1134
|
return {
|
|
1125
|
-
message: `Applied
|
|
1135
|
+
message: `Applied managed resource ${command.resourceManager}/${command.key}.`,
|
|
1126
1136
|
details: { action: "apply", resource: response.receipt ?? null },
|
|
1127
1137
|
};
|
|
1128
1138
|
}
|
|
1129
1139
|
|
|
1130
1140
|
const response = await requestAccepted(client, {
|
|
1131
|
-
operation: `
|
|
1132
|
-
requestId: `
|
|
1141
|
+
operation: `resourceManager.${command.kind}`,
|
|
1142
|
+
requestId: `resource-manager-${command.kind}-${idempotencyKey}`,
|
|
1133
1143
|
idempotencyKey,
|
|
1134
1144
|
payload: {
|
|
1135
1145
|
projectPath,
|
|
1136
|
-
|
|
1146
|
+
resourceManager: command.resourceManager,
|
|
1137
1147
|
key: command.key,
|
|
1138
1148
|
},
|
|
1139
1149
|
});
|
|
@@ -1144,7 +1154,7 @@ async function executeControllerCommand(
|
|
|
1144
1154
|
};
|
|
1145
1155
|
}
|
|
1146
1156
|
return {
|
|
1147
|
-
message: `
|
|
1157
|
+
message: `Managed resource ${command.resourceManager}/${command.key} ${command.kind} request accepted.`,
|
|
1148
1158
|
details: { action: command.kind, resource: response.receipt ?? null },
|
|
1149
1159
|
};
|
|
1150
1160
|
}
|
|
@@ -1333,7 +1343,7 @@ async function requestAccepted(
|
|
|
1333
1343
|
? await client.request(options)
|
|
1334
1344
|
: await client.requestDurable({ ...options, idempotencyKey: options.idempotencyKey });
|
|
1335
1345
|
if (response.outcome !== "accepted" && response.outcome !== "adopted") {
|
|
1336
|
-
throw new Error(response.error ?? `Workflow
|
|
1346
|
+
throw new Error(response.error ?? `Workflow server rejected ${options.operation}`);
|
|
1337
1347
|
}
|
|
1338
1348
|
return response;
|
|
1339
1349
|
}
|
|
@@ -1418,18 +1428,18 @@ function summarizeRun(value: JsonValue | undefined): string {
|
|
|
1418
1428
|
.join(" ");
|
|
1419
1429
|
}
|
|
1420
1430
|
|
|
1421
|
-
function
|
|
1422
|
-
if (!Array.isArray(value) || value.length === 0) return "No
|
|
1431
|
+
function summarizeManagedResources(value: JsonValue | undefined): string {
|
|
1432
|
+
if (!Array.isArray(value) || value.length === 0) return "No managed resources.";
|
|
1423
1433
|
const resources = value.map((item) => {
|
|
1424
1434
|
if (!isRecord(item) || !isRecord(item.metadata)) return "unknown";
|
|
1425
|
-
const
|
|
1426
|
-
typeof item.metadata.
|
|
1435
|
+
const resourceManager =
|
|
1436
|
+
typeof item.metadata.resourceManager === "string" ? item.metadata.resourceManager : "unknown";
|
|
1427
1437
|
const key = typeof item.metadata.key === "string" ? item.metadata.key : "unknown";
|
|
1428
1438
|
const generation =
|
|
1429
1439
|
typeof item.metadata.generation === "number" ? item.metadata.generation : "unknown";
|
|
1430
|
-
return `${
|
|
1440
|
+
return `${resourceManager}/${key} generation=${generation}`;
|
|
1431
1441
|
});
|
|
1432
|
-
return `
|
|
1442
|
+
return `Managed resources: ${resources.join(", ")}.`;
|
|
1433
1443
|
}
|
|
1434
1444
|
|
|
1435
1445
|
function jsonValue(value: unknown): JsonValue {
|
|
@@ -104,7 +104,7 @@ export type SessionRecordingStore = {
|
|
|
104
104
|
): Promise<{ eventCount: number; entryCount: number; lastEventSeq: number }>;
|
|
105
105
|
};
|
|
106
106
|
|
|
107
|
-
/** Records settled Pi entries and normalized temporal events through the workflow
|
|
107
|
+
/** Records settled Pi entries and normalized temporal events through the workflow server. */
|
|
108
108
|
export class SessionRecorder {
|
|
109
109
|
private readonly store: SessionRecordingStore;
|
|
110
110
|
private readonly runId: string;
|
|
@@ -13,7 +13,7 @@ type SessionCommandContext = {
|
|
|
13
13
|
coordinatorEpoch: string;
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
/** Sends bounded session recording batches to the single workflow
|
|
16
|
+
/** Sends bounded session recording batches to the single workflow server writer. */
|
|
17
17
|
export class RemoteSessionRecordingStore implements SessionRecordingStore {
|
|
18
18
|
constructor(
|
|
19
19
|
private readonly client: WorkflowClient,
|
|
@@ -103,7 +103,7 @@ export class RemoteSessionRecordingStore implements SessionRecordingStore {
|
|
|
103
103
|
payload: { ...this.context(), action, ...extra },
|
|
104
104
|
});
|
|
105
105
|
if (response.outcome !== "accepted" && response.outcome !== "adopted") {
|
|
106
|
-
throw new Error(response.error ?? "Workflow
|
|
106
|
+
throw new Error(response.error ?? "Workflow server rejected the session recording batch");
|
|
107
107
|
}
|
|
108
108
|
if (!isRecord(response.receipt)) throw new Error("Session recording receipt is invalid");
|
|
109
109
|
return response.receipt;
|