@osolmaz/pi-workflows 0.16.5 → 0.16.7
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 +5 -5
- package/dist/builtins/autoimplement.workflow.d.ts +5 -1
- package/dist/builtins/autoimplement.workflow.js +29 -10
- package/dist/builtins/autoimplement.workflow.js.map +1 -1
- package/dist/client/client.js +3 -1
- package/dist/client/client.js.map +1 -1
- package/dist/client/protocol.d.ts +1 -1
- package/dist/client/protocol.js +18 -1
- package/dist/client/protocol.js.map +1 -1
- package/dist/client/view.d.ts +7 -5
- package/dist/extension/index.d.ts +2 -1
- package/dist/extension/index.js +116 -166
- package/dist/extension/index.js.map +1 -1
- package/dist/extension/recorder.d.ts +1 -1
- package/dist/extension/recorder.js +2 -2
- package/dist/extension/recorder.js.map +1 -1
- package/dist/extension/step-message.d.ts +1 -1
- package/dist/extension/step-message.js +4 -4
- package/dist/extension/step-message.js.map +1 -1
- package/dist/extension/widget.js +1 -1
- package/dist/extension/widget.js.map +1 -1
- package/dist/extension/workflow-message-coordinator.d.ts +12 -3
- package/dist/extension/workflow-message-coordinator.js +108 -94
- package/dist/extension/workflow-message-coordinator.js.map +1 -1
- package/dist/render/graph-render.js +1 -1
- package/dist/resource-managers/index.d.ts +1 -2
- package/dist/resource-managers/index.js +1 -2
- package/dist/resource-managers/index.js.map +1 -1
- package/dist/resource-managers/sqlite.d.ts +2 -295
- package/dist/resource-managers/sqlite.js +71 -1528
- package/dist/resource-managers/sqlite.js.map +1 -1
- package/dist/resource-managers/types.d.ts +2 -7
- package/dist/server/resource-runner-entry.js +2 -6
- package/dist/server/resource-runner-entry.js.map +1 -1
- package/dist/server/rpc-bridge.js +1 -1
- package/dist/server/rpc-bridge.js.map +1 -1
- package/dist/server/rpc-executor.js +2 -4
- package/dist/server/rpc-executor.js.map +1 -1
- package/dist/server/server-entry.js +3 -0
- package/dist/server/server-entry.js.map +1 -1
- package/dist/server/server.d.ts +9 -8
- package/dist/server/server.js +364 -541
- package/dist/server/server.js.map +1 -1
- package/dist/server/state.d.ts +16 -29
- package/dist/server/state.js +105 -319
- package/dist/server/state.js.map +1 -1
- package/dist/server/view.d.ts +6 -5
- package/dist/server/view.js +68 -51
- package/dist/server/view.js.map +1 -1
- package/dist/server/workflow-runner-entry.d.ts +1 -1
- package/dist/server/workflow-runner-entry.js +1 -49
- package/dist/server/workflow-runner-entry.js.map +1 -1
- package/dist/server/workflow-runner-protocol.d.ts +2 -7
- package/dist/server/workflow-runner-protocol.js +5 -10
- package/dist/server/workflow-runner-protocol.js.map +1 -1
- package/dist/server/workflow-runner-store.d.ts +5 -6
- package/dist/server/workflow-runner-store.js +7 -14
- package/dist/server/workflow-runner-store.js.map +1 -1
- package/dist/state/attempt-time.d.ts +21 -0
- package/dist/state/attempt-time.js +95 -0
- package/dist/state/attempt-time.js.map +1 -0
- package/dist/state/json.d.ts +2 -1
- package/dist/state/json.js.map +1 -1
- package/dist/state/project-store.d.ts +39 -0
- package/dist/state/project-store.js +154 -0
- package/dist/state/project-store.js.map +1 -0
- package/dist/state/prune.js +0 -7
- package/dist/state/prune.js.map +1 -1
- package/dist/state/schema.js +23 -23
- package/dist/state/workflow-messages.d.ts +1 -1
- package/dist/state/workflow-messages.js +3 -1
- package/dist/state/workflow-messages.js.map +1 -1
- package/dist/viewer/backup.js +5 -0
- package/dist/viewer/backup.js.map +1 -1
- package/dist/workflows/diagnostics.d.ts +8 -0
- package/dist/workflows/diagnostics.js +61 -0
- package/dist/workflows/diagnostics.js.map +1 -0
- package/dist/workflows/engine.d.ts +2 -16
- package/dist/workflows/engine.js +128 -252
- package/dist/workflows/engine.js.map +1 -1
- package/dist/workflows/errors.d.ts +1 -1
- package/dist/workflows/errors.js +2 -2
- package/dist/workflows/errors.js.map +1 -1
- package/dist/workflows/human-decision.d.ts +3 -7
- package/dist/workflows/human-decision.js +2 -56
- package/dist/workflows/human-decision.js.map +1 -1
- package/dist/workflows/index.d.ts +2 -1
- package/dist/workflows/index.js +1 -0
- package/dist/workflows/index.js.map +1 -1
- package/dist/workflows/queue.d.ts +267 -0
- package/dist/workflows/queue.js +1248 -0
- package/dist/workflows/queue.js.map +1 -0
- package/dist/workflows/requests.d.ts +47 -0
- package/dist/workflows/requests.js +158 -0
- package/dist/workflows/requests.js.map +1 -0
- package/dist/workflows/schema.js +2 -4
- package/dist/workflows/schema.js.map +1 -1
- package/dist/workflows/store.d.ts +11 -16
- package/dist/workflows/store.js +177 -174
- package/dist/workflows/store.js.map +1 -1
- package/dist/workflows/tool-input.d.ts +6 -9
- package/dist/workflows/tool-input.js +15 -12
- package/dist/workflows/tool-input.js.map +1 -1
- package/dist/workflows/transitions.d.ts +38 -0
- package/dist/workflows/transitions.js +276 -0
- package/dist/workflows/transitions.js.map +1 -0
- package/dist/workflows/types.d.ts +9 -42
- package/dist/workflows/workflow-message-content.d.ts +7 -1
- package/dist/workflows/workflow-message-content.js +22 -4
- package/dist/workflows/workflow-message-content.js.map +1 -1
- package/docs/2026-08-25-workflow-follow-ups.md +5 -5
- package/docs/2026-09-02-unify-workflow-messages-plan.md +2 -0
- package/docs/2026-09-04-workflow-run-state-plan.md +2 -0
- package/docs/2026-09-06-durable-execution-plan.md +176 -0
- package/docs/2026-09-07-workflow-handoff-plan.md +84 -0
- package/docs/DEFERRED_TURNS.md +84 -105
- package/docs/HUMAN_DECISIONS.md +17 -19
- package/docs/HUMAN_DECISION_PRESENTATIONS.md +1 -1
- package/docs/SQLITE_STATE.md +68 -29
- package/docs/WORKFLOW_SERVER.md +21 -10
- package/docs/WORKFLOW_STEP_MESSAGES.md +83 -54
- package/docs/plans/2026-08-04-controller-runtime-plan.md +2 -0
- package/docs/plans/2026-08-21-deferred-turn-intents-plan.md +2 -0
- package/docs/plans/2026-08-27-workflow-terminal-restart-plan.md +2 -0
- package/docs/workflows.md +111 -45
- package/examples/workflows/autoresearch.workflow.ts +0 -2
- package/examples/workflows/branch.workflow.ts +0 -4
- package/examples/workflows/echo.workflow.ts +0 -2
- package/examples/workflows/live-settings.workflow.ts +0 -2
- package/examples/workflows/two-turn.workflow.ts +0 -2
- package/herdr-plugin.toml +1 -1
- package/package.json +1 -1
- package/protocol/fixtures/client-v1.json +1 -1
- package/skills/pi-workflows/SKILL.md +8 -7
- package/src/builtins/autoimplement.workflow.ts +31 -10
- package/src/client/client.ts +3 -1
- package/src/client/protocol.ts +21 -1
- package/src/client/view.ts +9 -5
- package/src/extension/index.ts +118 -190
- package/src/extension/recorder.ts +2 -2
- package/src/extension/step-message.ts +4 -4
- package/src/extension/widget.ts +1 -1
- package/src/extension/workflow-message-coordinator.ts +133 -95
- package/src/render/graph-render.ts +1 -1
- package/src/resource-managers/index.ts +1 -9
- package/src/resource-managers/sqlite.ts +330 -2655
- package/src/resource-managers/types.ts +2 -3
- package/src/server/resource-runner-entry.ts +2 -7
- package/src/server/rpc-bridge.ts +1 -1
- package/src/server/rpc-executor.ts +4 -9
- package/src/server/server-entry.ts +3 -0
- package/src/server/server.ts +416 -641
- package/src/server/state.ts +122 -466
- package/src/server/view.ts +73 -58
- package/src/server/workflow-runner-entry.ts +2 -55
- package/src/server/workflow-runner-protocol.ts +5 -15
- package/src/server/workflow-runner-store.ts +12 -27
- package/src/state/attempt-time.ts +122 -0
- package/src/state/json.ts +2 -1
- package/src/state/project-store.ts +218 -0
- package/src/state/prune.ts +0 -13
- package/src/state/schema.ts +23 -23
- package/src/state/workflow-messages.ts +4 -2
- package/src/viewer/backup.ts +7 -0
- package/src/workflows/diagnostics.ts +78 -0
- package/src/workflows/engine.ts +136 -299
- package/src/workflows/errors.ts +4 -2
- package/src/workflows/human-decision.ts +3 -81
- package/src/workflows/index.ts +8 -2
- package/src/workflows/queue.ts +2091 -0
- package/src/workflows/requests.ts +283 -0
- package/src/workflows/schema.ts +2 -6
- package/src/workflows/store.ts +226 -236
- package/src/workflows/tool-input.ts +20 -12
- package/src/workflows/transitions.ts +330 -0
- package/src/workflows/types.ts +9 -46
- package/src/workflows/workflow-message-content.ts +28 -4
- package/dist/resource-managers/runtime.d.ts +0 -59
- package/dist/resource-managers/runtime.js +0 -423
- package/dist/resource-managers/runtime.js.map +0 -1
- package/src/resource-managers/runtime.ts +0 -576
|
@@ -16,24 +16,28 @@ import {
|
|
|
16
16
|
|
|
17
17
|
const WORKFLOW_MESSAGE_ID_FIELD = "workflowMessageId";
|
|
18
18
|
|
|
19
|
-
type
|
|
19
|
+
type SettledTurn = { stopReason: WorkflowTurnStopReason; responseSessionEntryId: string | null };
|
|
20
|
+
type BeforeTurnEnd = (message: WorkflowMessage, end: SettledTurn) => Promise<void>;
|
|
21
|
+
type DeliveryCallbacks = {
|
|
22
|
+
beforeTurnEnd?: BeforeTurnEnd;
|
|
23
|
+
terminalDelivered?: (message: WorkflowMessage) => Promise<void>;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
type OwnedTurn = {
|
|
20
27
|
workflowTurnId: string;
|
|
21
|
-
|
|
22
|
-
runId: string | null;
|
|
23
|
-
message: WorkflowMessage | null;
|
|
28
|
+
message: WorkflowMessage;
|
|
24
29
|
startedReported: boolean;
|
|
25
|
-
|
|
26
|
-
};
|
|
30
|
+
} & ({ phase: "delivering" | "running" } | { phase: "settled"; end: SettledTurn });
|
|
27
31
|
|
|
28
32
|
/** Adds every server-owned workflow message to one Pi session through one public API path. */
|
|
29
33
|
export class WorkflowMessageCoordinator {
|
|
30
34
|
private readonly queued = new Set<string>();
|
|
31
35
|
private readonly closedTurnMessages = new Set<string>();
|
|
36
|
+
private readonly finalizedTerminals = new Set<string>();
|
|
32
37
|
private synchronizing = false;
|
|
33
38
|
private lastBranchEpoch: string | null = null;
|
|
34
39
|
private view: WorkflowSessionView | null = null;
|
|
35
|
-
private
|
|
36
|
-
private turn: PendingTurn | null = null;
|
|
40
|
+
private turn: OwnedTurn | null = null;
|
|
37
41
|
|
|
38
42
|
updateView(view: WorkflowSessionView): void {
|
|
39
43
|
this.view = view;
|
|
@@ -41,19 +45,14 @@ export class WorkflowMessageCoordinator {
|
|
|
41
45
|
for (const messageId of this.closedTurnMessages) {
|
|
42
46
|
if (!visibleIds.has(messageId)) this.closedTurnMessages.delete(messageId);
|
|
43
47
|
}
|
|
48
|
+
for (const messageId of this.finalizedTerminals) {
|
|
49
|
+
if (!visibleIds.has(messageId)) this.finalizedTerminals.delete(messageId);
|
|
50
|
+
}
|
|
44
51
|
for (const message of view.workflowMessages) {
|
|
45
52
|
if (message.status === "sent" || message.status === "cancelled") {
|
|
46
53
|
this.queued.delete(message.workflowMessageId);
|
|
47
54
|
}
|
|
48
55
|
}
|
|
49
|
-
if (
|
|
50
|
-
this.turn !== null &&
|
|
51
|
-
this.turn.workflowMessageId === null &&
|
|
52
|
-
view.openWorkflowMessageId !== null
|
|
53
|
-
) {
|
|
54
|
-
const message = messageById(view, view.openWorkflowMessageId);
|
|
55
|
-
if (message !== undefined && messageStartsTurn(message)) this.bindTurn(message);
|
|
56
|
-
}
|
|
57
56
|
}
|
|
58
57
|
|
|
59
58
|
branchChanged(): void {
|
|
@@ -61,23 +60,15 @@ export class WorkflowMessageCoordinator {
|
|
|
61
60
|
}
|
|
62
61
|
|
|
63
62
|
startTurn(): void {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
this.turn = {
|
|
67
|
-
workflowTurnId: `workflow-turn-${randomUUID()}`,
|
|
68
|
-
workflowMessageId: null,
|
|
69
|
-
runId: null,
|
|
70
|
-
message: null,
|
|
71
|
-
startedReported: false,
|
|
72
|
-
end: null,
|
|
73
|
-
};
|
|
74
|
-
const candidate = awaited ?? this.turnCandidate();
|
|
75
|
-
if (candidate !== undefined) this.bindTurn(candidate);
|
|
63
|
+
// Ordinary chat owns no workflow turn. Automatic Pi retries retain the
|
|
64
|
+
// existing turn, including a settled result whose acknowledgment is pending.
|
|
65
|
+
if (this.turn?.phase === "delivering") this.turn = { ...this.turn, phase: "running" };
|
|
76
66
|
}
|
|
77
67
|
|
|
78
68
|
endTurn(stopReason: WorkflowTurnStopReason, responseSessionEntryId: string | null): void {
|
|
79
|
-
if (this.turn ===
|
|
80
|
-
|
|
69
|
+
if (this.turn?.phase === "running") {
|
|
70
|
+
this.turn = { ...this.turn, phase: "settled", end: { stopReason, responseSessionEntryId } };
|
|
71
|
+
}
|
|
81
72
|
}
|
|
82
73
|
|
|
83
74
|
activeTurnMessage(): WorkflowMessage | undefined {
|
|
@@ -89,21 +80,32 @@ export class WorkflowMessageCoordinator {
|
|
|
89
80
|
pi: ExtensionAPI,
|
|
90
81
|
client: WorkflowClient,
|
|
91
82
|
ctx: Pick<ExtensionContext, "hasPendingMessages" | "isIdle" | "sessionManager">,
|
|
83
|
+
callbacks: DeliveryCallbacks = {},
|
|
92
84
|
): Promise<void> {
|
|
93
85
|
if (this.synchronizing || this.view === null) return;
|
|
94
86
|
this.synchronizing = true;
|
|
95
87
|
try {
|
|
96
88
|
const view = this.view;
|
|
97
89
|
if (!view.coordinatorActive || view.coordinatorEpoch === null) return;
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
90
|
+
const branchEntries = branchWorkflowEntries(ctx.sessionManager.getBranch());
|
|
91
|
+
if (this.turn === null && !ctx.isIdle()) {
|
|
92
|
+
const candidate = this.turnCandidate();
|
|
93
|
+
const open = view.openWorkflowTurn;
|
|
94
|
+
if (
|
|
95
|
+
candidate !== undefined &&
|
|
96
|
+
open?.state === "started" &&
|
|
97
|
+
open.workflowMessageId === candidate.workflowMessageId &&
|
|
98
|
+
open.runId === candidate.runId &&
|
|
99
|
+
open.targetSessionId === view.sessionId &&
|
|
100
|
+
latestTurnInputIsWorkflow(ctx.sessionManager.getBranch(), candidate.workflowMessageId)
|
|
101
|
+
) {
|
|
102
|
+
this.turn = {
|
|
103
|
+
workflowTurnId: open.workflowTurnId,
|
|
104
|
+
message: candidate,
|
|
105
|
+
startedReported: true,
|
|
106
|
+
phase: "running",
|
|
107
|
+
};
|
|
108
|
+
}
|
|
107
109
|
}
|
|
108
110
|
if (
|
|
109
111
|
view.branchReportRequired ||
|
|
@@ -112,7 +114,19 @@ export class WorkflowMessageCoordinator {
|
|
|
112
114
|
) {
|
|
113
115
|
await this.reportBranch(client, ctx, view);
|
|
114
116
|
}
|
|
115
|
-
await this.flushTurn(client, view);
|
|
117
|
+
await this.flushTurn(client, view, callbacks.beforeTurnEnd);
|
|
118
|
+
if (this.turn !== null || !ctx.isIdle() || ctx.hasPendingMessages()) return;
|
|
119
|
+
for (const message of view.workflowMessages) {
|
|
120
|
+
if (
|
|
121
|
+
message.kind === "terminal" &&
|
|
122
|
+
message.status === "sent" &&
|
|
123
|
+
branchEntries.has(message.workflowMessageId) &&
|
|
124
|
+
!this.finalizedTerminals.has(message.workflowMessageId)
|
|
125
|
+
) {
|
|
126
|
+
await callbacks.terminalDelivered?.(message);
|
|
127
|
+
this.finalizedTerminals.add(message.workflowMessageId);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
116
130
|
const messageId = view.nextWorkflowMessageId;
|
|
117
131
|
if (messageId === null || this.queued.has(messageId)) return;
|
|
118
132
|
const message = messageById(view, messageId);
|
|
@@ -140,8 +154,13 @@ export class WorkflowMessageCoordinator {
|
|
|
140
154
|
this.queued.delete(messageId);
|
|
141
155
|
return;
|
|
142
156
|
}
|
|
143
|
-
if (
|
|
144
|
-
this.
|
|
157
|
+
if (messageStartsTurn(message)) {
|
|
158
|
+
this.turn = {
|
|
159
|
+
workflowTurnId: `workflow-turn-${randomUUID()}`,
|
|
160
|
+
message,
|
|
161
|
+
startedReported: false,
|
|
162
|
+
phase: "delivering",
|
|
163
|
+
};
|
|
145
164
|
}
|
|
146
165
|
try {
|
|
147
166
|
pi.sendMessage(
|
|
@@ -155,13 +174,16 @@ export class WorkflowMessageCoordinator {
|
|
|
155
174
|
);
|
|
156
175
|
} catch (error) {
|
|
157
176
|
this.queued.delete(messageId);
|
|
158
|
-
if (
|
|
159
|
-
this.
|
|
177
|
+
if (
|
|
178
|
+
this.turn?.phase === "delivering" &&
|
|
179
|
+
this.turn.message.workflowMessageId === messageId
|
|
180
|
+
) {
|
|
181
|
+
this.turn = null;
|
|
160
182
|
}
|
|
161
183
|
throw error;
|
|
162
184
|
}
|
|
163
185
|
await this.reportBranch(client, ctx, view);
|
|
164
|
-
await this.flushTurn(client, view);
|
|
186
|
+
await this.flushTurn(client, view, callbacks.beforeTurnEnd);
|
|
165
187
|
} finally {
|
|
166
188
|
this.synchronizing = false;
|
|
167
189
|
}
|
|
@@ -170,8 +192,8 @@ export class WorkflowMessageCoordinator {
|
|
|
170
192
|
clear(): void {
|
|
171
193
|
this.queued.clear();
|
|
172
194
|
this.closedTurnMessages.clear();
|
|
195
|
+
this.finalizedTerminals.clear();
|
|
173
196
|
this.view = null;
|
|
174
|
-
this.awaitingTurnMessage = null;
|
|
175
197
|
this.turn = null;
|
|
176
198
|
this.lastBranchEpoch = null;
|
|
177
199
|
this.synchronizing = false;
|
|
@@ -197,19 +219,15 @@ export class WorkflowMessageCoordinator {
|
|
|
197
219
|
return undefined;
|
|
198
220
|
}
|
|
199
221
|
|
|
200
|
-
private
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
private async flushTurn(client: WorkflowClient, view: WorkflowSessionView): Promise<void> {
|
|
208
|
-
const pending = this.turn;
|
|
222
|
+
private async flushTurn(
|
|
223
|
+
client: WorkflowClient,
|
|
224
|
+
view: WorkflowSessionView,
|
|
225
|
+
beforeTurnEnd?: BeforeTurnEnd,
|
|
226
|
+
): Promise<void> {
|
|
227
|
+
let pending = this.turn;
|
|
209
228
|
if (
|
|
210
229
|
pending === null ||
|
|
211
|
-
pending.
|
|
212
|
-
pending.runId === null ||
|
|
230
|
+
pending.phase === "delivering" ||
|
|
213
231
|
view.coordinatorEpoch === null ||
|
|
214
232
|
this.lastBranchEpoch !== view.coordinatorEpoch
|
|
215
233
|
) {
|
|
@@ -217,54 +235,53 @@ export class WorkflowMessageCoordinator {
|
|
|
217
235
|
}
|
|
218
236
|
let message = pending.message;
|
|
219
237
|
if (!pending.startedReported) {
|
|
220
|
-
|
|
221
|
-
if (
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
workflowTurnId: pending.workflowTurnId,
|
|
227
|
-
runId: pending.runId,
|
|
228
|
-
targetSessionId: view.sessionId,
|
|
229
|
-
coordinatorEpoch: view.coordinatorEpoch,
|
|
230
|
-
});
|
|
231
|
-
if (receipt.ownership !== "active") {
|
|
232
|
-
this.turn = null;
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
pending.message = message;
|
|
236
|
-
pending.startedReported = true;
|
|
237
|
-
} catch (error) {
|
|
238
|
-
this.turn = null;
|
|
239
|
-
throw error;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
if (pending.end === null) return;
|
|
243
|
-
try {
|
|
244
|
-
await reportTurn(client, {
|
|
245
|
-
state: "ended",
|
|
246
|
-
workflowMessageId: pending.workflowMessageId,
|
|
238
|
+
const confirmed = messageById(view, message.workflowMessageId);
|
|
239
|
+
if (confirmed?.status !== "sent") return;
|
|
240
|
+
message = confirmed;
|
|
241
|
+
const receipt = await reportTurn(client, {
|
|
242
|
+
state: "started",
|
|
243
|
+
workflowMessageId: message.workflowMessageId,
|
|
247
244
|
workflowTurnId: pending.workflowTurnId,
|
|
248
|
-
runId:
|
|
245
|
+
runId: message.runId,
|
|
249
246
|
targetSessionId: view.sessionId,
|
|
250
247
|
coordinatorEpoch: view.coordinatorEpoch,
|
|
251
|
-
stopReason: pending.end.stopReason,
|
|
252
|
-
responseSessionEntryId: pending.end.responseSessionEntryId,
|
|
253
248
|
});
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
249
|
+
// Pi can settle while the start report is in flight. Keep that exact
|
|
250
|
+
// response and do not restore a turn cleared by session shutdown.
|
|
251
|
+
if (this.turn?.workflowTurnId !== pending.workflowTurnId) return;
|
|
252
|
+
pending = this.turn;
|
|
253
|
+
if (
|
|
254
|
+
receipt.ownership !== "active" &&
|
|
255
|
+
!(receipt.ownership === "settled" && pending.phase === "settled")
|
|
256
|
+
) {
|
|
257
|
+
this.turn = null;
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
pending.message = message;
|
|
261
|
+
pending.startedReported = true;
|
|
257
262
|
}
|
|
258
|
-
if (
|
|
259
|
-
|
|
263
|
+
if (pending.phase !== "settled") return;
|
|
264
|
+
await beforeTurnEnd?.(message, pending.end);
|
|
265
|
+
await reportTurn(client, {
|
|
266
|
+
state: "ended",
|
|
267
|
+
workflowMessageId: message.workflowMessageId,
|
|
268
|
+
workflowTurnId: pending.workflowTurnId,
|
|
269
|
+
runId: message.runId,
|
|
270
|
+
targetSessionId: view.sessionId,
|
|
271
|
+
coordinatorEpoch: view.coordinatorEpoch,
|
|
272
|
+
stopReason: pending.end.stopReason,
|
|
273
|
+
responseSessionEntryId: pending.end.responseSessionEntryId,
|
|
274
|
+
});
|
|
275
|
+
if (message.kind === "followUp") {
|
|
276
|
+
this.closedTurnMessages.add(message.workflowMessageId);
|
|
260
277
|
}
|
|
261
278
|
for (const current of new Set([view, this.view])) {
|
|
262
279
|
if (current?.openWorkflowTurn?.workflowTurnId === pending.workflowTurnId) {
|
|
263
280
|
current.openWorkflowTurn = null;
|
|
264
281
|
}
|
|
265
282
|
if (
|
|
266
|
-
current?.openWorkflowMessageId ===
|
|
267
|
-
|
|
283
|
+
current?.openWorkflowMessageId === message.workflowMessageId &&
|
|
284
|
+
message.kind === "followUp"
|
|
268
285
|
) {
|
|
269
286
|
current.openWorkflowMessageId = null;
|
|
270
287
|
}
|
|
@@ -332,6 +349,27 @@ export function branchWorkflowEntries(entries: readonly unknown[]): Map<string,
|
|
|
332
349
|
return found;
|
|
333
350
|
}
|
|
334
351
|
|
|
352
|
+
function latestTurnInputIsWorkflow(
|
|
353
|
+
entries: readonly unknown[],
|
|
354
|
+
workflowMessageId: string,
|
|
355
|
+
): boolean {
|
|
356
|
+
for (const value of [...entries].reverse()) {
|
|
357
|
+
if (!isRecord(value)) continue;
|
|
358
|
+
if (
|
|
359
|
+
value.role === "user" ||
|
|
360
|
+
(value.type === "message" && isRecord(value.message) && value.message.role === "user")
|
|
361
|
+
) {
|
|
362
|
+
return false;
|
|
363
|
+
}
|
|
364
|
+
if (value.type === "custom_message" || value.role === "custom") {
|
|
365
|
+
return (
|
|
366
|
+
isRecord(value.details) && value.details[WORKFLOW_MESSAGE_ID_FIELD] === workflowMessageId
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return false;
|
|
371
|
+
}
|
|
372
|
+
|
|
335
373
|
export function responseEntryId(entries: readonly unknown[]): string | null {
|
|
336
374
|
for (const value of [...entries].reverse()) {
|
|
337
375
|
if (!isRecord(value) || typeof value.id !== "string") continue;
|
|
@@ -351,7 +389,7 @@ function messageById(
|
|
|
351
389
|
}
|
|
352
390
|
|
|
353
391
|
function messageStartsTurn(message: WorkflowMessage): boolean {
|
|
354
|
-
return message.
|
|
392
|
+
return message.content.triggerTurn;
|
|
355
393
|
}
|
|
356
394
|
|
|
357
395
|
async function reportTurn(
|
|
@@ -18,16 +18,8 @@ export {
|
|
|
18
18
|
} from "./errors.js";
|
|
19
19
|
export { ResourceManagerEffectService } from "./effects.js";
|
|
20
20
|
export { canonicalJson, jsonFingerprint } from "./json.js";
|
|
21
|
-
export { ResourceManagerRuntime, type ResourceManagerRuntimeOptions } from "./runtime.js";
|
|
22
21
|
export { createResultHelpers, requeue, requeueAfter, settled } from "./results.js";
|
|
23
|
-
export {
|
|
24
|
-
SqliteResourceManagerStore,
|
|
25
|
-
type RunEventRecord,
|
|
26
|
-
type WorkflowRunClaimOptions,
|
|
27
|
-
type WorkflowRunPreparationResult,
|
|
28
|
-
type WorkflowRunQueueRecord,
|
|
29
|
-
type WorkflowRunReservationOptions,
|
|
30
|
-
} from "./sqlite.js";
|
|
22
|
+
export { SqliteResourceManagerStore } from "./sqlite.js";
|
|
31
23
|
export {
|
|
32
24
|
type ResourceManagerStore,
|
|
33
25
|
type EffectReservation,
|