@fragno-dev/pi-harness 0.0.0-stage → 0.0.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/LICENSE.md +16 -0
- package/README.md +181 -2
- package/dist/browser/agent-harness-event-protocol-CuKubox1.js +666 -0
- package/dist/browser/agent-harness-event-protocol-CuKubox1.js.map +1 -0
- package/dist/browser/agent-harness-event-protocol-d6mH_9n3.d.ts +261 -0
- package/dist/browser/agent-harness-event-protocol-d6mH_9n3.d.ts.map +1 -0
- package/dist/browser/client/clients.d.ts +2 -0
- package/dist/browser/client/clients.js +2 -0
- package/dist/browser/client/pi-workflow-emission-stream.d.ts +13 -0
- package/dist/browser/client/pi-workflow-emission-stream.d.ts.map +1 -0
- package/dist/browser/client/pi-workflow-emission-stream.js +29 -0
- package/dist/browser/client/pi-workflow-emission-stream.js.map +1 -0
- package/dist/browser/client/react.d.ts +147 -0
- package/dist/browser/client/react.d.ts.map +1 -0
- package/dist/browser/client/react.js +187 -0
- package/dist/browser/client/react.js.map +1 -0
- package/dist/browser/client/solid.d.ts +150 -0
- package/dist/browser/client/solid.d.ts.map +1 -0
- package/dist/browser/client/solid.js +130 -0
- package/dist/browser/client/solid.js.map +1 -0
- package/dist/browser/client/svelte.d.ts +150 -0
- package/dist/browser/client/svelte.d.ts.map +1 -0
- package/dist/browser/client/svelte.js +132 -0
- package/dist/browser/client/svelte.js.map +1 -0
- package/dist/browser/client/vanilla.d.ts +177 -0
- package/dist/browser/client/vanilla.d.ts.map +1 -0
- package/dist/browser/client/vanilla.js +159 -0
- package/dist/browser/client/vanilla.js.map +1 -0
- package/dist/browser/client/vue.d.ts +150 -0
- package/dist/browser/client/vue.d.ts.map +1 -0
- package/dist/browser/client/vue.js +128 -0
- package/dist/browser/client/vue.js.map +1 -0
- package/dist/browser/client/workflow-lofi-session-projection.d.ts +17 -0
- package/dist/browser/client/workflow-lofi-session-projection.d.ts.map +1 -0
- package/dist/browser/client/workflow-lofi-session-projection.js +107 -0
- package/dist/browser/client/workflow-lofi-session-projection.js.map +1 -0
- package/dist/browser/clients-DYXj19je.d.ts +247 -0
- package/dist/browser/clients-DYXj19je.d.ts.map +1 -0
- package/dist/browser/clients-pIAk6ClP.js +1853 -0
- package/dist/browser/clients-pIAk6ClP.js.map +1 -0
- package/dist/browser/pi/context-usage.d.ts +20 -0
- package/dist/browser/pi/context-usage.d.ts.map +1 -0
- package/dist/browser/pi/context-usage.js +84 -0
- package/dist/browser/pi/context-usage.js.map +1 -0
- package/dist/browser/pi/harness/agent-harness-event-protocol.d.ts +2 -0
- package/dist/browser/pi/harness/agent-harness-event-protocol.js +2 -0
- package/dist/browser/pi/route-schemas.d.ts +2 -0
- package/dist/browser/pi/route-schemas.js +130 -0
- package/dist/browser/pi/route-schemas.js.map +1 -0
- package/dist/browser/pi/workflow-session-projection.d.ts +2 -0
- package/dist/browser/pi/workflow-session-projection.js +2 -0
- package/dist/browser/route-schemas-DQB5ZR1E.d.ts +109 -0
- package/dist/browser/route-schemas-DQB5ZR1E.d.ts.map +1 -0
- package/dist/browser/types-8q4RWFXT.js +23 -0
- package/dist/browser/types-8q4RWFXT.js.map +1 -0
- package/dist/browser/types-Dk856kV1.d.ts +527 -0
- package/dist/browser/types-Dk856kV1.d.ts.map +1 -0
- package/dist/browser/workflow-session-projection-CJ4MUkpJ.js +443 -0
- package/dist/browser/workflow-session-projection-CJ4MUkpJ.js.map +1 -0
- package/dist/browser/workflow-session-projection-Dj_a79GF.d.ts +93 -0
- package/dist/browser/workflow-session-projection-Dj_a79GF.d.ts.map +1 -0
- package/dist/node/pi/compact-command-outcome-projection.js +41 -0
- package/dist/node/pi/compact-command-outcome-projection.js.map +1 -0
- package/dist/node/pi/context-usage.d.ts +20 -0
- package/dist/node/pi/context-usage.d.ts.map +1 -0
- package/dist/node/pi/context-usage.js +84 -0
- package/dist/node/pi/context-usage.js.map +1 -0
- package/dist/node/pi/definition.d.ts +535 -0
- package/dist/node/pi/definition.d.ts.map +1 -0
- package/dist/node/pi/definition.js +71 -0
- package/dist/node/pi/definition.js.map +1 -0
- package/dist/node/pi/factory.d.ts +142 -0
- package/dist/node/pi/factory.d.ts.map +1 -0
- package/dist/node/pi/factory.js +22 -0
- package/dist/node/pi/factory.js.map +1 -0
- package/dist/node/pi/harness/agent-harness-event-protocol.d.ts +261 -0
- package/dist/node/pi/harness/agent-harness-event-protocol.d.ts.map +1 -0
- package/dist/node/pi/harness/agent-harness-event-protocol.js +588 -0
- package/dist/node/pi/harness/agent-harness-event-protocol.js.map +1 -0
- package/dist/node/pi/harness/json-value.js +82 -0
- package/dist/node/pi/harness/json-value.js.map +1 -0
- package/dist/node/pi/harness/pi-operation-completed.d.ts +16 -0
- package/dist/node/pi/harness/pi-operation-completed.d.ts.map +1 -0
- package/dist/node/pi/harness/pi-operation-completed.js +71 -0
- package/dist/node/pi/harness/pi-operation-completed.js.map +1 -0
- package/dist/node/pi/harness/session-storage.d.ts +62 -0
- package/dist/node/pi/harness/session-storage.d.ts.map +1 -0
- package/dist/node/pi/harness/session-storage.js +174 -0
- package/dist/node/pi/harness/session-storage.js.map +1 -0
- package/dist/node/pi/pi-jsonl-export.d.ts +11 -0
- package/dist/node/pi/pi-jsonl-export.d.ts.map +1 -0
- package/dist/node/pi/pi-jsonl-export.js +31 -0
- package/dist/node/pi/pi-jsonl-export.js.map +1 -0
- package/dist/node/pi/route-schemas.d.ts +109 -0
- package/dist/node/pi/route-schemas.d.ts.map +1 -0
- package/dist/node/pi/route-schemas.js +130 -0
- package/dist/node/pi/route-schemas.js.map +1 -0
- package/dist/node/pi/session-command-protocol.d.ts +14 -0
- package/dist/node/pi/session-command-protocol.d.ts.map +1 -0
- package/dist/node/pi/session-command-protocol.js +25 -0
- package/dist/node/pi/session-command-protocol.js.map +1 -0
- package/dist/node/pi/session-entry-projection.js +79 -0
- package/dist/node/pi/session-entry-projection.js.map +1 -0
- package/dist/node/pi/skills.d.ts +70 -0
- package/dist/node/pi/skills.d.ts.map +1 -0
- package/dist/node/pi/skills.js +150 -0
- package/dist/node/pi/skills.js.map +1 -0
- package/dist/node/pi/tools.d.ts +12 -0
- package/dist/node/pi/tools.d.ts.map +1 -0
- package/dist/node/pi/tools.js +8 -0
- package/dist/node/pi/tools.js.map +1 -0
- package/dist/node/pi/types.d.ts +165 -0
- package/dist/node/pi/types.d.ts.map +1 -0
- package/dist/node/pi/types.js +49 -0
- package/dist/node/pi/types.js.map +1 -0
- package/dist/node/pi/wait-for-command-step.js +46 -0
- package/dist/node/pi/wait-for-command-step.js.map +1 -0
- package/dist/node/pi/workflow-session-live-projection.js +220 -0
- package/dist/node/pi/workflow-session-live-projection.js.map +1 -0
- package/dist/node/pi/workflow-session-projection.d.ts +84 -0
- package/dist/node/pi/workflow-session-projection.d.ts.map +1 -0
- package/dist/node/pi/workflow-session-projection.js +100 -0
- package/dist/node/pi/workflow-session-projection.js.map +1 -0
- package/dist/node/pi/workflows/interactive-chat-workflow.d.ts +37 -0
- package/dist/node/pi/workflows/interactive-chat-workflow.d.ts.map +1 -0
- package/dist/node/pi/workflows/interactive-chat-workflow.js +219 -0
- package/dist/node/pi/workflows/interactive-chat-workflow.js.map +1 -0
- package/dist/node/pi/workflows/workflow-agent-harness.d.ts +142 -0
- package/dist/node/pi/workflows/workflow-agent-harness.d.ts.map +1 -0
- package/dist/node/pi/workflows/workflow-agent-harness.js +450 -0
- package/dist/node/pi/workflows/workflow-agent-harness.js.map +1 -0
- package/dist/node/routes.d.ts +631 -0
- package/dist/node/routes.d.ts.map +1 -0
- package/dist/node/routes.js +355 -0
- package/dist/node/routes.js.map +1 -0
- package/dist/node/schema.d.ts +5 -0
- package/dist/node/schema.d.ts.map +1 -0
- package/dist/node/schema.js +7 -0
- package/dist/node/schema.js.map +1 -0
- package/package.json +175 -3
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { PiHarnessEventStreamDecoders, piToolCallArgumentsText } from "./harness/agent-harness-event-protocol.js";
|
|
2
|
+
//#region src/pi/workflow-session-live-projection.ts
|
|
3
|
+
const isPiWorkflowStepActive = (step) => step.status !== "completed" && !(step.status === "waiting" && step.type === "waitForEvent" && step.waitEventType === "command");
|
|
4
|
+
const createPiWorkflowSessionLiveState = (activeLiveWork = false) => ({
|
|
5
|
+
inFlightMessagesByStepKey: /* @__PURE__ */ new Map(),
|
|
6
|
+
inFlightStepKeys: [],
|
|
7
|
+
draftAgentMessage: null,
|
|
8
|
+
activeCommand: null,
|
|
9
|
+
hasOpenMessageDraft: false,
|
|
10
|
+
activeLiveWork
|
|
11
|
+
});
|
|
12
|
+
const draftActivityForAssistantEvent = (type) => {
|
|
13
|
+
if (type === "start") return "starting";
|
|
14
|
+
if (type.startsWith("thinking_")) return "thinking";
|
|
15
|
+
if (type.startsWith("toolcall_")) return "tool_calling";
|
|
16
|
+
if (type.startsWith("text_")) return "writing";
|
|
17
|
+
return null;
|
|
18
|
+
};
|
|
19
|
+
const updateDraftTool = (tools, toolCall) => {
|
|
20
|
+
const argsText = piToolCallArgumentsText(toolCall);
|
|
21
|
+
tools[toolCall.id] = {
|
|
22
|
+
...tools[toolCall.id],
|
|
23
|
+
id: toolCall.id,
|
|
24
|
+
name: toolCall.name,
|
|
25
|
+
args: toolCall.arguments,
|
|
26
|
+
...argsText === void 0 ? {} : { argsText },
|
|
27
|
+
status: tools[toolCall.id]?.status ?? "starting"
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
const ensureDraftAgentMessage = (state, emission) => {
|
|
31
|
+
const eventTime = new Date(emission.createdAt).getTime();
|
|
32
|
+
if (!Number.isFinite(eventTime)) throw new Error(`Pi workflow emission ${emission.stepKey} has an invalid timestamp.`);
|
|
33
|
+
state.draftStepKey = emission.stepKey;
|
|
34
|
+
if (!state.draftAgentMessage) state.draftAgentMessage = {
|
|
35
|
+
activity: "starting",
|
|
36
|
+
tools: {},
|
|
37
|
+
startedAt: eventTime,
|
|
38
|
+
updatedAt: eventTime
|
|
39
|
+
};
|
|
40
|
+
else state.draftAgentMessage.updatedAt = eventTime;
|
|
41
|
+
return state.draftAgentMessage;
|
|
42
|
+
};
|
|
43
|
+
const recordInFlightMessage = (state, stepKey, message) => {
|
|
44
|
+
let messages = state.inFlightMessagesByStepKey.get(stepKey);
|
|
45
|
+
if (!messages) {
|
|
46
|
+
messages = [];
|
|
47
|
+
state.inFlightMessagesByStepKey.set(stepKey, messages);
|
|
48
|
+
state.inFlightStepKeys.push(stepKey);
|
|
49
|
+
}
|
|
50
|
+
messages.push(message);
|
|
51
|
+
};
|
|
52
|
+
const createPiWorkflowSessionEmissionReducer = (activeLiveWork = false) => ({
|
|
53
|
+
live: createPiWorkflowSessionLiveState(activeLiveWork),
|
|
54
|
+
eventDecoders: new PiHarnessEventStreamDecoders()
|
|
55
|
+
});
|
|
56
|
+
const reducePiWorkflowSessionEmission = (reducer, emission) => {
|
|
57
|
+
const state = reducer.live;
|
|
58
|
+
const payload = emission.payload;
|
|
59
|
+
if (!payload?.kind) return;
|
|
60
|
+
state.activeLiveWork = true;
|
|
61
|
+
if (payload.kind === "harness-operation-start") {
|
|
62
|
+
if (!emission.executionId || !emission.epoch) throw new Error(`Pi workflow emission ${emission.stepKey} is missing its stream identity.`);
|
|
63
|
+
reducer.eventDecoders.start({
|
|
64
|
+
stepKey: emission.stepKey,
|
|
65
|
+
executionId: emission.executionId,
|
|
66
|
+
epoch: emission.epoch
|
|
67
|
+
});
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (payload.kind === "pi-session-command-start") {
|
|
71
|
+
state.activeCommand = payload.command;
|
|
72
|
+
state.activeCommandStepKey = emission.stepKey;
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (payload.kind === "harness-operation-complete") {
|
|
76
|
+
if (!emission.executionId || !emission.epoch) throw new Error(`Pi workflow emission ${emission.stepKey} is missing its stream identity.`);
|
|
77
|
+
reducer.eventDecoders.finish({
|
|
78
|
+
stepKey: emission.stepKey,
|
|
79
|
+
executionId: emission.executionId,
|
|
80
|
+
epoch: emission.epoch
|
|
81
|
+
});
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (payload.kind !== "harness-event") return;
|
|
85
|
+
if (!emission.executionId || !emission.epoch) throw new Error(`Pi workflow emission ${emission.stepKey} is missing its stream identity.`);
|
|
86
|
+
const event = reducer.eventDecoders.decode({
|
|
87
|
+
stepKey: emission.stepKey,
|
|
88
|
+
executionId: emission.executionId,
|
|
89
|
+
epoch: emission.epoch
|
|
90
|
+
}, payload.event);
|
|
91
|
+
const draft = ensureDraftAgentMessage(state, emission);
|
|
92
|
+
switch (event.type) {
|
|
93
|
+
case "message_start":
|
|
94
|
+
draft.activity = "starting";
|
|
95
|
+
if (event.message.role === "assistant") {
|
|
96
|
+
draft.assistant = void 0;
|
|
97
|
+
draft.tools = {};
|
|
98
|
+
state.currentAssistantMessage = {
|
|
99
|
+
...event.message,
|
|
100
|
+
content: [...event.message.content]
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
state.hasOpenMessageDraft = true;
|
|
104
|
+
return;
|
|
105
|
+
case "message_update": {
|
|
106
|
+
state.hasOpenMessageDraft = true;
|
|
107
|
+
if (event.message.role !== "assistant") throw new Error("Pi harness message_update did not contain an assistant message.");
|
|
108
|
+
const assistantMessage = structuredClone(event.message);
|
|
109
|
+
state.currentAssistantMessage = assistantMessage;
|
|
110
|
+
draft.assistant = assistantMessage;
|
|
111
|
+
const activity = draftActivityForAssistantEvent(event.assistantMessageEvent.type);
|
|
112
|
+
if (activity) draft.activity = activity;
|
|
113
|
+
if ("contentIndex" in event.assistantMessageEvent) {
|
|
114
|
+
const toolCall = assistantMessage.content[event.assistantMessageEvent.contentIndex];
|
|
115
|
+
if (toolCall?.type === "toolCall") updateDraftTool(draft.tools, toolCall);
|
|
116
|
+
}
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
case "message_end":
|
|
120
|
+
recordInFlightMessage(state, emission.stepKey, event.message);
|
|
121
|
+
if (event.message.role === "assistant") {
|
|
122
|
+
state.currentAssistantMessage = event.message;
|
|
123
|
+
draft.assistant = event.message;
|
|
124
|
+
} else if (event.message.role === "toolResult") draft.tools[event.message.toolCallId] = {
|
|
125
|
+
...draft.tools[event.message.toolCallId],
|
|
126
|
+
id: event.message.toolCallId,
|
|
127
|
+
name: event.message.toolName,
|
|
128
|
+
args: draft.tools[event.message.toolCallId]?.args,
|
|
129
|
+
resultMessage: event.message,
|
|
130
|
+
status: "done"
|
|
131
|
+
};
|
|
132
|
+
state.hasOpenMessageDraft = false;
|
|
133
|
+
return;
|
|
134
|
+
case "tool_execution_start":
|
|
135
|
+
draft.activity = "running_tools";
|
|
136
|
+
draft.tools[event.toolCallId] = {
|
|
137
|
+
...draft.tools[event.toolCallId],
|
|
138
|
+
id: event.toolCallId,
|
|
139
|
+
name: event.toolName,
|
|
140
|
+
args: event.args,
|
|
141
|
+
status: "running"
|
|
142
|
+
};
|
|
143
|
+
return;
|
|
144
|
+
case "tool_execution_update":
|
|
145
|
+
draft.activity = "running_tools";
|
|
146
|
+
draft.tools[event.toolCallId] = {
|
|
147
|
+
...draft.tools[event.toolCallId],
|
|
148
|
+
id: event.toolCallId,
|
|
149
|
+
name: event.toolName,
|
|
150
|
+
args: event.args,
|
|
151
|
+
partialResult: event.partialResult,
|
|
152
|
+
status: "running"
|
|
153
|
+
};
|
|
154
|
+
return;
|
|
155
|
+
case "tool_execution_end":
|
|
156
|
+
draft.tools[event.toolCallId] = {
|
|
157
|
+
...draft.tools[event.toolCallId],
|
|
158
|
+
id: event.toolCallId,
|
|
159
|
+
name: event.toolName,
|
|
160
|
+
args: draft.tools[event.toolCallId]?.args,
|
|
161
|
+
result: event.result,
|
|
162
|
+
isError: event.isError,
|
|
163
|
+
status: "done"
|
|
164
|
+
};
|
|
165
|
+
return;
|
|
166
|
+
case "abort":
|
|
167
|
+
case "after_provider_response":
|
|
168
|
+
case "agent_end":
|
|
169
|
+
case "agent_start":
|
|
170
|
+
case "before_agent_start":
|
|
171
|
+
case "before_provider_payload":
|
|
172
|
+
case "before_provider_request":
|
|
173
|
+
case "context":
|
|
174
|
+
case "model_update":
|
|
175
|
+
case "queue_update":
|
|
176
|
+
case "resources_update":
|
|
177
|
+
case "retry_attempt_start":
|
|
178
|
+
case "retry_finished":
|
|
179
|
+
case "retry_scheduled":
|
|
180
|
+
case "save_point":
|
|
181
|
+
case "session_before_compact":
|
|
182
|
+
case "session_before_tree":
|
|
183
|
+
case "session_compact":
|
|
184
|
+
case "session_tree":
|
|
185
|
+
case "settled":
|
|
186
|
+
case "thinking_level_update":
|
|
187
|
+
case "tool_call":
|
|
188
|
+
case "tool_result":
|
|
189
|
+
case "tools_update":
|
|
190
|
+
case "turn_end":
|
|
191
|
+
case "turn_start": return;
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
const projectPiWorkflowSessionLiveOverlay = ({ contextMessages: durableContextMessages, timelineMessages: durableTimelineMessages, instanceStatus, workflowSteps, live }) => {
|
|
195
|
+
const contextMessages = [...durableContextMessages];
|
|
196
|
+
const timelineMessages = [...durableTimelineMessages];
|
|
197
|
+
for (const stepKey of live.inFlightStepKeys) {
|
|
198
|
+
const messages = live.inFlightMessagesByStepKey.get(stepKey) ?? [];
|
|
199
|
+
contextMessages.push(...messages);
|
|
200
|
+
timelineMessages.push(...messages);
|
|
201
|
+
}
|
|
202
|
+
const liveTools = Object.values(live.draftAgentMessage?.tools ?? {});
|
|
203
|
+
const hasLiveTools = liveTools.some((tool) => tool.status !== "done");
|
|
204
|
+
const draftAgentMessage = live.draftAgentMessage && (live.hasOpenMessageDraft || liveTools.length > 0) ? live.draftAgentMessage : null;
|
|
205
|
+
const waitingForCommand = workflowSteps.some((step) => step.status === "waiting" && step.type === "waitForEvent" && step.waitEventType === "command");
|
|
206
|
+
const readyForInput = (instanceStatus === "active" || instanceStatus === "waiting") && !live.hasOpenMessageDraft && !hasLiveTools && (!live.activeLiveWork || waitingForCommand);
|
|
207
|
+
const activity = draftAgentMessage && (live.hasOpenMessageDraft || hasLiveTools) ? draftAgentMessage.activity : live.activeLiveWork && !readyForInput ? "working" : null;
|
|
208
|
+
return {
|
|
209
|
+
contextMessages,
|
|
210
|
+
timelineMessages,
|
|
211
|
+
draftAgentMessage,
|
|
212
|
+
activeCommand: live.activeCommand,
|
|
213
|
+
readyForInput,
|
|
214
|
+
activity
|
|
215
|
+
};
|
|
216
|
+
};
|
|
217
|
+
//#endregion
|
|
218
|
+
export { createPiWorkflowSessionEmissionReducer, createPiWorkflowSessionLiveState, isPiWorkflowStepActive, projectPiWorkflowSessionLiveOverlay, reducePiWorkflowSessionEmission };
|
|
219
|
+
|
|
220
|
+
//# sourceMappingURL=workflow-session-live-projection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-session-live-projection.js","names":[],"sources":["../../../src/pi/workflow-session-live-projection.ts"],"sourcesContent":["import type { ToolCall } from \"@earendil-works/pi-ai\";\n\nimport { PiHarnessEventStreamDecoders } from \"./harness/agent-harness-event-protocol\";\nimport {\n piToolCallArgumentsText,\n type PiHarnessFrontendAgentMessage,\n type PiHarnessFrontendAssistantMessage,\n type PiHarnessFrontendEvent,\n} from \"./harness/agent-harness-event-protocol\";\nimport type { PiSessionActiveCommand } from \"./session-command-protocol\";\nimport type { PiWorkflowStatus } from \"./types\";\nimport type {\n DraftAgentActivity,\n DraftAgentMessage,\n DraftTool,\n PiWorkflowSessionProjectionEmission,\n PiWorkflowSessionProjectionStep,\n} from \"./workflow-session-projection\";\n\nexport type PiWorkflowSessionLiveState = {\n inFlightMessagesByStepKey: Map<string, PiHarnessFrontendAgentMessage[]>;\n inFlightStepKeys: string[];\n draftAgentMessage: DraftAgentMessage | null;\n currentAssistantMessage?: PiHarnessFrontendAssistantMessage;\n draftStepKey?: string;\n activeCommand: PiSessionActiveCommand | null;\n activeCommandStepKey?: string;\n hasOpenMessageDraft: boolean;\n activeLiveWork: boolean;\n};\n\nexport type PiWorkflowSessionEmissionReducer = {\n live: PiWorkflowSessionLiveState;\n eventDecoders: PiHarnessEventStreamDecoders;\n};\n\nexport const isPiWorkflowStepActive = (step: PiWorkflowSessionProjectionStep): boolean =>\n step.status !== \"completed\" &&\n !(step.status === \"waiting\" && step.type === \"waitForEvent\" && step.waitEventType === \"command\");\n\nexport const createPiWorkflowSessionLiveState = (\n activeLiveWork = false,\n): PiWorkflowSessionLiveState => ({\n inFlightMessagesByStepKey: new Map(),\n inFlightStepKeys: [],\n draftAgentMessage: null,\n activeCommand: null,\n hasOpenMessageDraft: false,\n activeLiveWork,\n});\n\nconst draftActivityForAssistantEvent = (\n type: Extract<\n PiHarnessFrontendEvent,\n { type: \"message_update\" }\n >[\"assistantMessageEvent\"][\"type\"],\n): DraftAgentActivity | null => {\n if (type === \"start\") {\n return \"starting\";\n }\n if (type.startsWith(\"thinking_\")) {\n return \"thinking\";\n }\n if (type.startsWith(\"toolcall_\")) {\n return \"tool_calling\";\n }\n if (type.startsWith(\"text_\")) {\n return \"writing\";\n }\n return null;\n};\n\nconst updateDraftTool = (tools: Record<string, DraftTool>, toolCall: ToolCall): void => {\n const argsText = piToolCallArgumentsText(toolCall);\n tools[toolCall.id] = {\n ...tools[toolCall.id],\n id: toolCall.id,\n name: toolCall.name,\n args: toolCall.arguments,\n ...(argsText === undefined ? {} : { argsText }),\n status: tools[toolCall.id]?.status ?? \"starting\",\n };\n};\n\nconst ensureDraftAgentMessage = (\n state: PiWorkflowSessionLiveState,\n emission: Pick<PiWorkflowSessionProjectionEmission, \"createdAt\" | \"stepKey\">,\n): DraftAgentMessage => {\n const eventTime = new Date(emission.createdAt).getTime();\n if (!Number.isFinite(eventTime)) {\n throw new Error(`Pi workflow emission ${emission.stepKey} has an invalid timestamp.`);\n }\n\n state.draftStepKey = emission.stepKey;\n if (!state.draftAgentMessage) {\n state.draftAgentMessage = {\n activity: \"starting\",\n tools: {},\n startedAt: eventTime,\n updatedAt: eventTime,\n };\n } else {\n state.draftAgentMessage.updatedAt = eventTime;\n }\n return state.draftAgentMessage;\n};\n\nconst recordInFlightMessage = (\n state: PiWorkflowSessionLiveState,\n stepKey: string,\n message: PiHarnessFrontendAgentMessage,\n): void => {\n let messages = state.inFlightMessagesByStepKey.get(stepKey);\n if (!messages) {\n messages = [];\n state.inFlightMessagesByStepKey.set(stepKey, messages);\n state.inFlightStepKeys.push(stepKey);\n }\n messages.push(message);\n};\n\nexport const createPiWorkflowSessionEmissionReducer = (\n activeLiveWork = false,\n): PiWorkflowSessionEmissionReducer => ({\n live: createPiWorkflowSessionLiveState(activeLiveWork),\n eventDecoders: new PiHarnessEventStreamDecoders(),\n});\n\nexport const reducePiWorkflowSessionEmission = (\n reducer: PiWorkflowSessionEmissionReducer,\n emission: PiWorkflowSessionProjectionEmission,\n): void => {\n const state = reducer.live;\n const payload = emission.payload;\n if (!payload?.kind) {\n return;\n }\n\n state.activeLiveWork = true;\n if (payload.kind === \"harness-operation-start\") {\n if (!emission.executionId || !emission.epoch) {\n throw new Error(`Pi workflow emission ${emission.stepKey} is missing its stream identity.`);\n }\n reducer.eventDecoders.start({\n stepKey: emission.stepKey,\n executionId: emission.executionId,\n epoch: emission.epoch,\n });\n return;\n }\n if (payload.kind === \"pi-session-command-start\") {\n state.activeCommand = payload.command;\n state.activeCommandStepKey = emission.stepKey;\n return;\n }\n if (payload.kind === \"harness-operation-complete\") {\n if (!emission.executionId || !emission.epoch) {\n throw new Error(`Pi workflow emission ${emission.stepKey} is missing its stream identity.`);\n }\n reducer.eventDecoders.finish({\n stepKey: emission.stepKey,\n executionId: emission.executionId,\n epoch: emission.epoch,\n });\n return;\n }\n if (payload.kind !== \"harness-event\") {\n return;\n }\n\n if (!emission.executionId || !emission.epoch) {\n throw new Error(`Pi workflow emission ${emission.stepKey} is missing its stream identity.`);\n }\n const event = reducer.eventDecoders.decode(\n {\n stepKey: emission.stepKey,\n executionId: emission.executionId,\n epoch: emission.epoch,\n },\n payload.event,\n );\n const draft = ensureDraftAgentMessage(state, emission);\n switch (event.type) {\n case \"message_start\":\n draft.activity = \"starting\";\n if (event.message.role === \"assistant\") {\n draft.assistant = undefined;\n draft.tools = {};\n state.currentAssistantMessage = {\n ...event.message,\n content: [...event.message.content],\n };\n }\n state.hasOpenMessageDraft = true;\n return;\n case \"message_update\": {\n state.hasOpenMessageDraft = true;\n if (event.message.role !== \"assistant\") {\n throw new Error(\"Pi harness message_update did not contain an assistant message.\");\n }\n const assistantMessage = structuredClone(event.message);\n state.currentAssistantMessage = assistantMessage;\n draft.assistant = assistantMessage;\n const activity = draftActivityForAssistantEvent(event.assistantMessageEvent.type);\n if (activity) {\n draft.activity = activity;\n }\n if (\"contentIndex\" in event.assistantMessageEvent) {\n const toolCall = assistantMessage.content[event.assistantMessageEvent.contentIndex];\n if (toolCall?.type === \"toolCall\") {\n updateDraftTool(draft.tools, toolCall);\n }\n }\n return;\n }\n case \"message_end\":\n recordInFlightMessage(state, emission.stepKey, event.message);\n if (event.message.role === \"assistant\") {\n state.currentAssistantMessage = event.message;\n draft.assistant = event.message;\n } else if (event.message.role === \"toolResult\") {\n draft.tools[event.message.toolCallId] = {\n ...draft.tools[event.message.toolCallId],\n id: event.message.toolCallId,\n name: event.message.toolName,\n args: draft.tools[event.message.toolCallId]?.args,\n resultMessage: event.message,\n status: \"done\",\n };\n }\n state.hasOpenMessageDraft = false;\n return;\n case \"tool_execution_start\":\n draft.activity = \"running_tools\";\n draft.tools[event.toolCallId] = {\n ...draft.tools[event.toolCallId],\n id: event.toolCallId,\n name: event.toolName,\n args: event.args,\n status: \"running\",\n };\n return;\n case \"tool_execution_update\":\n draft.activity = \"running_tools\";\n draft.tools[event.toolCallId] = {\n ...draft.tools[event.toolCallId],\n id: event.toolCallId,\n name: event.toolName,\n args: event.args,\n partialResult: event.partialResult,\n status: \"running\",\n };\n return;\n case \"tool_execution_end\":\n draft.tools[event.toolCallId] = {\n ...draft.tools[event.toolCallId],\n id: event.toolCallId,\n name: event.toolName,\n args: draft.tools[event.toolCallId]?.args,\n result: event.result,\n isError: event.isError,\n status: \"done\",\n };\n return;\n case \"abort\":\n case \"after_provider_response\":\n case \"agent_end\":\n case \"agent_start\":\n case \"before_agent_start\":\n case \"before_provider_payload\":\n case \"before_provider_request\":\n case \"context\":\n case \"model_update\":\n case \"queue_update\":\n case \"resources_update\":\n case \"retry_attempt_start\":\n case \"retry_finished\":\n case \"retry_scheduled\":\n case \"save_point\":\n case \"session_before_compact\":\n case \"session_before_tree\":\n case \"session_compact\":\n case \"session_tree\":\n case \"settled\":\n case \"thinking_level_update\":\n case \"tool_call\":\n case \"tool_result\":\n case \"tools_update\":\n case \"turn_end\":\n case \"turn_start\":\n return;\n }\n};\n\nexport const settleCompletedPiWorkflowSessionLiveSteps = (\n state: PiWorkflowSessionLiveState,\n completedStepKeys: ReadonlySet<string>,\n): void => {\n state.inFlightStepKeys = state.inFlightStepKeys.filter((stepKey) => {\n if (!completedStepKeys.has(stepKey)) {\n return true;\n }\n state.inFlightMessagesByStepKey.delete(stepKey);\n return false;\n });\n\n if (state.draftStepKey && completedStepKeys.has(state.draftStepKey)) {\n state.draftAgentMessage = null;\n state.currentAssistantMessage = undefined;\n state.draftStepKey = undefined;\n state.hasOpenMessageDraft = false;\n }\n\n if (state.activeCommandStepKey && completedStepKeys.has(state.activeCommandStepKey)) {\n state.activeCommand = null;\n state.activeCommandStepKey = undefined;\n }\n};\n\nexport type PiWorkflowSessionLiveOverlay = {\n contextMessages: PiHarnessFrontendAgentMessage[];\n timelineMessages: PiHarnessFrontendAgentMessage[];\n draftAgentMessage: DraftAgentMessage | null;\n activeCommand: PiSessionActiveCommand | null;\n readyForInput: boolean;\n activity: DraftAgentActivity | \"working\" | null;\n};\n\nexport const projectPiWorkflowSessionLiveOverlay = ({\n contextMessages: durableContextMessages,\n timelineMessages: durableTimelineMessages,\n instanceStatus,\n workflowSteps,\n live,\n}: {\n contextMessages: readonly PiHarnessFrontendAgentMessage[];\n timelineMessages: readonly PiHarnessFrontendAgentMessage[];\n instanceStatus: PiWorkflowStatus;\n workflowSteps: readonly PiWorkflowSessionProjectionStep[];\n live: PiWorkflowSessionLiveState;\n}): PiWorkflowSessionLiveOverlay => {\n const contextMessages = [...durableContextMessages];\n const timelineMessages = [...durableTimelineMessages];\n for (const stepKey of live.inFlightStepKeys) {\n const messages = live.inFlightMessagesByStepKey.get(stepKey) ?? [];\n contextMessages.push(...messages);\n timelineMessages.push(...messages);\n }\n\n const liveTools = Object.values(live.draftAgentMessage?.tools ?? {});\n const hasLiveTools = liveTools.some((tool) => tool.status !== \"done\");\n const draftAgentMessage =\n live.draftAgentMessage && (live.hasOpenMessageDraft || liveTools.length > 0)\n ? live.draftAgentMessage\n : null;\n const waitingForCommand = workflowSteps.some(\n (step) =>\n step.status === \"waiting\" && step.type === \"waitForEvent\" && step.waitEventType === \"command\",\n );\n const workflowAcceptsCommands = instanceStatus === \"active\" || instanceStatus === \"waiting\";\n const readyForInput =\n workflowAcceptsCommands &&\n !live.hasOpenMessageDraft &&\n !hasLiveTools &&\n (!live.activeLiveWork || waitingForCommand);\n const activity =\n draftAgentMessage && (live.hasOpenMessageDraft || hasLiveTools)\n ? draftAgentMessage.activity\n : live.activeLiveWork && !readyForInput\n ? \"working\"\n : null;\n\n return {\n contextMessages,\n timelineMessages,\n draftAgentMessage,\n activeCommand: live.activeCommand,\n readyForInput,\n activity,\n };\n};\n"],"mappings":";;AAoCA,MAAa,0BAA0B,SACrC,KAAK,WAAW,eAChB,EAAE,KAAK,WAAW,aAAa,KAAK,SAAS,kBAAkB,KAAK,kBAAkB;AAExF,MAAa,oCACX,iBAAiB,WACe;CAChC,2CAA2B,IAAI,IAAI;CACnC,kBAAkB,CAAC;CACnB,mBAAmB;CACnB,eAAe;CACf,qBAAqB;CACrB;AACF;AAEA,MAAM,kCACJ,SAI8B;CAC9B,IAAI,SAAS,SACX,OAAO;CAET,IAAI,KAAK,WAAW,WAAW,GAC7B,OAAO;CAET,IAAI,KAAK,WAAW,WAAW,GAC7B,OAAO;CAET,IAAI,KAAK,WAAW,OAAO,GACzB,OAAO;CAET,OAAO;AACT;AAEA,MAAM,mBAAmB,OAAkC,aAA6B;CACtF,MAAM,WAAW,wBAAwB,QAAQ;CACjD,MAAM,SAAS,MAAM;EACnB,GAAG,MAAM,SAAS;EAClB,IAAI,SAAS;EACb,MAAM,SAAS;EACf,MAAM,SAAS;EACf,GAAI,aAAa,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS;EAC7C,QAAQ,MAAM,SAAS,GAAG,EAAE,UAAU;CACxC;AACF;AAEA,MAAM,2BACJ,OACA,aACsB;CACtB,MAAM,YAAY,IAAI,KAAK,SAAS,SAAS,CAAC,CAAC,QAAQ;CACvD,IAAI,CAAC,OAAO,SAAS,SAAS,GAC5B,MAAM,IAAI,MAAM,wBAAwB,SAAS,QAAQ,2BAA2B;CAGtF,MAAM,eAAe,SAAS;CAC9B,IAAI,CAAC,MAAM,mBACT,MAAM,oBAAoB;EACxB,UAAU;EACV,OAAO,CAAC;EACR,WAAW;EACX,WAAW;CACb;MAEA,MAAM,kBAAkB,YAAY;CAEtC,OAAO,MAAM;AACf;AAEA,MAAM,yBACJ,OACA,SACA,YACS;CACT,IAAI,WAAW,MAAM,0BAA0B,IAAI,OAAO;CAC1D,IAAI,CAAC,UAAU;EACb,WAAW,CAAC;EACZ,MAAM,0BAA0B,IAAI,SAAS,QAAQ;EACrD,MAAM,iBAAiB,KAAK,OAAO;CACrC;CACA,SAAS,KAAK,OAAO;AACvB;AAEA,MAAa,0CACX,iBAAiB,WACqB;CACtC,MAAM,iCAAiC,cAAc;CACrD,eAAe,IAAI,6BAA6B;AAClD;AAEA,MAAa,mCACX,SACA,aACS;CACT,MAAM,QAAQ,QAAQ;CACtB,MAAM,UAAU,SAAS;CACzB,IAAI,CAAC,SAAS,MACZ;CAGF,MAAM,iBAAiB;CACvB,IAAI,QAAQ,SAAS,2BAA2B;EAC9C,IAAI,CAAC,SAAS,eAAe,CAAC,SAAS,OACrC,MAAM,IAAI,MAAM,wBAAwB,SAAS,QAAQ,iCAAiC;EAE5F,QAAQ,cAAc,MAAM;GAC1B,SAAS,SAAS;GAClB,aAAa,SAAS;GACtB,OAAO,SAAS;EAClB,CAAC;EACD;CACF;CACA,IAAI,QAAQ,SAAS,4BAA4B;EAC/C,MAAM,gBAAgB,QAAQ;EAC9B,MAAM,uBAAuB,SAAS;EACtC;CACF;CACA,IAAI,QAAQ,SAAS,8BAA8B;EACjD,IAAI,CAAC,SAAS,eAAe,CAAC,SAAS,OACrC,MAAM,IAAI,MAAM,wBAAwB,SAAS,QAAQ,iCAAiC;EAE5F,QAAQ,cAAc,OAAO;GAC3B,SAAS,SAAS;GAClB,aAAa,SAAS;GACtB,OAAO,SAAS;EAClB,CAAC;EACD;CACF;CACA,IAAI,QAAQ,SAAS,iBACnB;CAGF,IAAI,CAAC,SAAS,eAAe,CAAC,SAAS,OACrC,MAAM,IAAI,MAAM,wBAAwB,SAAS,QAAQ,iCAAiC;CAE5F,MAAM,QAAQ,QAAQ,cAAc,OAClC;EACE,SAAS,SAAS;EAClB,aAAa,SAAS;EACtB,OAAO,SAAS;CAClB,GACA,QAAQ,KACV;CACA,MAAM,QAAQ,wBAAwB,OAAO,QAAQ;CACrD,QAAQ,MAAM,MAAd;EACE,KAAK;GACH,MAAM,WAAW;GACjB,IAAI,MAAM,QAAQ,SAAS,aAAa;IACtC,MAAM,YAAY,KAAA;IAClB,MAAM,QAAQ,CAAC;IACf,MAAM,0BAA0B;KAC9B,GAAG,MAAM;KACT,SAAS,CAAC,GAAG,MAAM,QAAQ,OAAO;IACpC;GACF;GACA,MAAM,sBAAsB;GAC5B;EACF,KAAK,kBAAkB;GACrB,MAAM,sBAAsB;GAC5B,IAAI,MAAM,QAAQ,SAAS,aACzB,MAAM,IAAI,MAAM,iEAAiE;GAEnF,MAAM,mBAAmB,gBAAgB,MAAM,OAAO;GACtD,MAAM,0BAA0B;GAChC,MAAM,YAAY;GAClB,MAAM,WAAW,+BAA+B,MAAM,sBAAsB,IAAI;GAChF,IAAI,UACF,MAAM,WAAW;GAEnB,IAAI,kBAAkB,MAAM,uBAAuB;IACjD,MAAM,WAAW,iBAAiB,QAAQ,MAAM,sBAAsB;IACtE,IAAI,UAAU,SAAS,YACrB,gBAAgB,MAAM,OAAO,QAAQ;GAEzC;GACA;EACF;EACA,KAAK;GACH,sBAAsB,OAAO,SAAS,SAAS,MAAM,OAAO;GAC5D,IAAI,MAAM,QAAQ,SAAS,aAAa;IACtC,MAAM,0BAA0B,MAAM;IACtC,MAAM,YAAY,MAAM;GAC1B,OAAO,IAAI,MAAM,QAAQ,SAAS,cAChC,MAAM,MAAM,MAAM,QAAQ,cAAc;IACtC,GAAG,MAAM,MAAM,MAAM,QAAQ;IAC7B,IAAI,MAAM,QAAQ;IAClB,MAAM,MAAM,QAAQ;IACpB,MAAM,MAAM,MAAM,MAAM,QAAQ,WAAW,EAAE;IAC7C,eAAe,MAAM;IACrB,QAAQ;GACV;GAEF,MAAM,sBAAsB;GAC5B;EACF,KAAK;GACH,MAAM,WAAW;GACjB,MAAM,MAAM,MAAM,cAAc;IAC9B,GAAG,MAAM,MAAM,MAAM;IACrB,IAAI,MAAM;IACV,MAAM,MAAM;IACZ,MAAM,MAAM;IACZ,QAAQ;GACV;GACA;EACF,KAAK;GACH,MAAM,WAAW;GACjB,MAAM,MAAM,MAAM,cAAc;IAC9B,GAAG,MAAM,MAAM,MAAM;IACrB,IAAI,MAAM;IACV,MAAM,MAAM;IACZ,MAAM,MAAM;IACZ,eAAe,MAAM;IACrB,QAAQ;GACV;GACA;EACF,KAAK;GACH,MAAM,MAAM,MAAM,cAAc;IAC9B,GAAG,MAAM,MAAM,MAAM;IACrB,IAAI,MAAM;IACV,MAAM,MAAM;IACZ,MAAM,MAAM,MAAM,MAAM,WAAW,EAAE;IACrC,QAAQ,MAAM;IACd,SAAS,MAAM;IACf,QAAQ;GACV;GACA;EACF,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,cACH;CACJ;AACF;AAoCA,MAAa,uCAAuC,EAClD,iBAAiB,wBACjB,kBAAkB,yBAClB,gBACA,eACA,WAOkC;CAClC,MAAM,kBAAkB,CAAC,GAAG,sBAAsB;CAClD,MAAM,mBAAmB,CAAC,GAAG,uBAAuB;CACpD,KAAK,MAAM,WAAW,KAAK,kBAAkB;EAC3C,MAAM,WAAW,KAAK,0BAA0B,IAAI,OAAO,KAAK,CAAC;EACjE,gBAAgB,KAAK,GAAG,QAAQ;EAChC,iBAAiB,KAAK,GAAG,QAAQ;CACnC;CAEA,MAAM,YAAY,OAAO,OAAO,KAAK,mBAAmB,SAAS,CAAC,CAAC;CACnE,MAAM,eAAe,UAAU,MAAM,SAAS,KAAK,WAAW,MAAM;CACpE,MAAM,oBACJ,KAAK,sBAAsB,KAAK,uBAAuB,UAAU,SAAS,KACtE,KAAK,oBACL;CACN,MAAM,oBAAoB,cAAc,MACrC,SACC,KAAK,WAAW,aAAa,KAAK,SAAS,kBAAkB,KAAK,kBAAkB,SACxF;CAEA,MAAM,iBAD0B,mBAAmB,YAAY,mBAAmB,cAGhF,CAAC,KAAK,uBACN,CAAC,iBACA,CAAC,KAAK,kBAAkB;CAC3B,MAAM,WACJ,sBAAsB,KAAK,uBAAuB,gBAC9C,kBAAkB,WAClB,KAAK,kBAAkB,CAAC,gBACtB,YACA;CAER,OAAO;EACL;EACA;EACA;EACA,eAAe,KAAK;EACpB;EACA;CACF;AACF"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { PiHarnessEncodedEventEmission, PiHarnessFrontendAgentMessage, PiHarnessFrontendAssistantMessage } from "./harness/agent-harness-event-protocol.js";
|
|
2
|
+
import { PiHarnessOperationCompleteEmission, PiHarnessOperationStartEmission, PiHarnessSessionEntryEmission } from "./workflows/workflow-agent-harness.js";
|
|
3
|
+
import { PiCompactCommandOutcome, PiWorkflowStatus } from "./types.js";
|
|
4
|
+
import { PiSessionActiveCommand, PiSessionCommandStartEmission } from "./session-command-protocol.js";
|
|
5
|
+
import { ToolResultMessage } from "@earendil-works/pi-ai";
|
|
6
|
+
//#region src/pi/workflow-session-projection.d.ts
|
|
7
|
+
type PiSessionProjectionStatus = "loading" | "ready" | "not-found";
|
|
8
|
+
type DraftAgentActivity = "starting" | "thinking" | "writing" | "tool_calling" | "running_tools";
|
|
9
|
+
interface DraftTool {
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
args: unknown;
|
|
13
|
+
argsText?: string;
|
|
14
|
+
status: "starting" | "running" | "done";
|
|
15
|
+
partialResult?: unknown;
|
|
16
|
+
result?: unknown;
|
|
17
|
+
resultMessage?: ToolResultMessage;
|
|
18
|
+
isError?: boolean;
|
|
19
|
+
}
|
|
20
|
+
interface DraftAgentMessage {
|
|
21
|
+
activity: DraftAgentActivity;
|
|
22
|
+
assistant?: PiHarnessFrontendAssistantMessage;
|
|
23
|
+
tools: Record<string, DraftTool>;
|
|
24
|
+
startedAt: number;
|
|
25
|
+
updatedAt: number;
|
|
26
|
+
}
|
|
27
|
+
type PiSessionActivity = DraftAgentActivity | "working" | null;
|
|
28
|
+
type PiWorkflowSessionProjectionData = {
|
|
29
|
+
contextMessages: PiHarnessFrontendAgentMessage[];
|
|
30
|
+
timelineMessages: PiHarnessFrontendAgentMessage[];
|
|
31
|
+
completedStepKeys: string[];
|
|
32
|
+
draftAgentMessage: DraftAgentMessage | null;
|
|
33
|
+
activeCommand: PiSessionActiveCommand | null;
|
|
34
|
+
compactOutcomesByCommandId: Readonly<Record<string, PiCompactCommandOutcome>>;
|
|
35
|
+
latestCommandCompactOutcome: PiCompactCommandOutcome | null;
|
|
36
|
+
};
|
|
37
|
+
type PiWorkflowSessionProjectionState = (PiWorkflowSessionProjectionData & {
|
|
38
|
+
status: "loading";
|
|
39
|
+
error: null;
|
|
40
|
+
readyForInput: false;
|
|
41
|
+
activity: null;
|
|
42
|
+
}) | (PiWorkflowSessionProjectionData & {
|
|
43
|
+
status: "ready";
|
|
44
|
+
error: null;
|
|
45
|
+
readyForInput: boolean;
|
|
46
|
+
activity: PiSessionActivity;
|
|
47
|
+
}) | (PiWorkflowSessionProjectionData & {
|
|
48
|
+
status: "not-found";
|
|
49
|
+
error: Error;
|
|
50
|
+
readyForInput: false;
|
|
51
|
+
activity: null;
|
|
52
|
+
});
|
|
53
|
+
type PiWorkflowSessionProjectionStep = {
|
|
54
|
+
stepKey: string;
|
|
55
|
+
type: string;
|
|
56
|
+
status: string;
|
|
57
|
+
waitEventType: string | null;
|
|
58
|
+
result: unknown;
|
|
59
|
+
};
|
|
60
|
+
type PiWorkflowSessionProjectionEmission = {
|
|
61
|
+
stepKey: string;
|
|
62
|
+
executionId: string;
|
|
63
|
+
epoch: string;
|
|
64
|
+
sequence: number;
|
|
65
|
+
payload: PiHarnessEncodedEventEmission | PiHarnessSessionEntryEmission | PiHarnessOperationStartEmission | PiHarnessOperationCompleteEmission | PiSessionCommandStartEmission | {
|
|
66
|
+
kind: undefined;
|
|
67
|
+
control: string;
|
|
68
|
+
} | null;
|
|
69
|
+
createdAt: Date;
|
|
70
|
+
};
|
|
71
|
+
type PiWorkflowSessionProjectionInstance = {
|
|
72
|
+
status: PiWorkflowStatus;
|
|
73
|
+
};
|
|
74
|
+
declare const createLoadingPiWorkflowSessionProjection: () => PiWorkflowSessionProjectionState;
|
|
75
|
+
declare const projectPiWorkflowSession: ({ workflowName, sessionId, instance, workflowSteps, workflowStepEmissions }: {
|
|
76
|
+
workflowName: string;
|
|
77
|
+
sessionId: string;
|
|
78
|
+
instance: PiWorkflowSessionProjectionInstance | null;
|
|
79
|
+
workflowSteps: readonly PiWorkflowSessionProjectionStep[];
|
|
80
|
+
workflowStepEmissions?: readonly PiWorkflowSessionProjectionEmission[];
|
|
81
|
+
}) => PiWorkflowSessionProjectionState;
|
|
82
|
+
//#endregion
|
|
83
|
+
export { DraftAgentActivity, DraftAgentMessage, DraftTool, PiSessionActivity, PiSessionProjectionStatus, PiWorkflowSessionProjectionEmission, PiWorkflowSessionProjectionInstance, PiWorkflowSessionProjectionState, PiWorkflowSessionProjectionStep, createLoadingPiWorkflowSessionProjection, projectPiWorkflowSession };
|
|
84
|
+
//# sourceMappingURL=workflow-session-projection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-session-projection.d.ts","names":[],"sources":["../../../src/pi/workflow-session-projection.ts"],"mappings":";;;;;;KA+BY;KAEA;UAOK;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA,gBAAgB;EAChB;;UAGe;EACf,UAAU;EACV,YAAY;EACZ,OAAO,eAAe;EACtB;EACA;;KAGU,oBAAoB;KAE3B;EACH,iBAAiB;EACjB,kBAAkB;EAClB;EACA,mBAAmB;EACnB,eAAe;EACf,4BAA4B,SAAS,eAAe;EACpD,6BAA6B;;KAGnB,oCACP;EACC;EACA;EACA;EACA;MAED;EACC;EACA;EACA;EACA,UAAU;MAEX;EACC;EACA,OAAO;EACP;EACA;;KAGM;EACV;EACA;EACA;EACA;EACA;;KAGU;EACV;EACA;EACA;EACA;EACA,SACI,gCACA,gCACA,kCACA,qCACA;IACE;IAAiB;;EAEvB,WAAW;;KAGD;EACV,QAAQ;;cA+EG,gDAA+C;cAQ/C,6BAA4B,cAAA,WAAA,UAAA,eAAA;EAOvC;EACA;EACA,UAAU;EACV,wBAAwB;EACxB,iCAAiC;MAC/B"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { asPersistedPiHarnessStepResult, latestCompletedPiHarnessEntries, projectPiSessionEntries } from "./session-entry-projection.js";
|
|
2
|
+
import { projectPiCompactCommandOutcomes } from "./compact-command-outcome-projection.js";
|
|
3
|
+
import { createPiWorkflowSessionEmissionReducer, isPiWorkflowStepActive, projectPiWorkflowSessionLiveOverlay, reducePiWorkflowSessionEmission } from "./workflow-session-live-projection.js";
|
|
4
|
+
//#region src/pi/workflow-session-projection.ts
|
|
5
|
+
const zeroUsage = () => ({
|
|
6
|
+
input: 0,
|
|
7
|
+
output: 0,
|
|
8
|
+
cacheRead: 0,
|
|
9
|
+
cacheWrite: 0,
|
|
10
|
+
totalTokens: 0,
|
|
11
|
+
cost: {
|
|
12
|
+
input: 0,
|
|
13
|
+
output: 0,
|
|
14
|
+
cacheRead: 0,
|
|
15
|
+
cacheWrite: 0,
|
|
16
|
+
total: 0
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
const interruptionTimestamp = (entry) => {
|
|
20
|
+
if (!entry) return 0;
|
|
21
|
+
if (entry.type === "message") return entry.message.timestamp;
|
|
22
|
+
const timestamp = new Date(entry.timestamp).getTime();
|
|
23
|
+
return Number.isFinite(timestamp) ? timestamp : 0;
|
|
24
|
+
};
|
|
25
|
+
const interruptedTimelineMessages = (steps, sessionEntries) => {
|
|
26
|
+
const entriesById = new Map(sessionEntries.map((entry) => [entry.id, entry]));
|
|
27
|
+
const messagesByLeafId = /* @__PURE__ */ new Map();
|
|
28
|
+
for (const step of steps) {
|
|
29
|
+
if (step.status !== "completed") continue;
|
|
30
|
+
const result = asPersistedPiHarnessStepResult(step.result);
|
|
31
|
+
if (result?.outcome !== "aborted") continue;
|
|
32
|
+
const leafEntry = result.leafId === null ? void 0 : entriesById.get(result.leafId);
|
|
33
|
+
if (leafEntry?.type === "message" && leafEntry.message.role === "assistant" && leafEntry.message.stopReason === "aborted") continue;
|
|
34
|
+
const messages = messagesByLeafId.get(result.leafId) ?? [];
|
|
35
|
+
messages.push({
|
|
36
|
+
role: "assistant",
|
|
37
|
+
content: [],
|
|
38
|
+
usage: zeroUsage(),
|
|
39
|
+
stopReason: "aborted",
|
|
40
|
+
timestamp: interruptionTimestamp(leafEntry)
|
|
41
|
+
});
|
|
42
|
+
messagesByLeafId.set(result.leafId, messages);
|
|
43
|
+
}
|
|
44
|
+
return messagesByLeafId;
|
|
45
|
+
};
|
|
46
|
+
const emptyProjectionData = () => ({
|
|
47
|
+
contextMessages: [],
|
|
48
|
+
timelineMessages: [],
|
|
49
|
+
completedStepKeys: [],
|
|
50
|
+
draftAgentMessage: null,
|
|
51
|
+
activeCommand: null,
|
|
52
|
+
compactOutcomesByCommandId: {},
|
|
53
|
+
latestCommandCompactOutcome: null
|
|
54
|
+
});
|
|
55
|
+
const createLoadingPiWorkflowSessionProjection = () => ({
|
|
56
|
+
...emptyProjectionData(),
|
|
57
|
+
status: "loading",
|
|
58
|
+
error: null,
|
|
59
|
+
readyForInput: false,
|
|
60
|
+
activity: null
|
|
61
|
+
});
|
|
62
|
+
const projectPiWorkflowSession = ({ workflowName, sessionId, instance, workflowSteps, workflowStepEmissions = [] }) => {
|
|
63
|
+
const identity = {
|
|
64
|
+
workflowName,
|
|
65
|
+
sessionId
|
|
66
|
+
};
|
|
67
|
+
const completedSteps = workflowSteps.filter((step) => step.status === "completed");
|
|
68
|
+
const completedStepKeys = new Set(completedSteps.map((step) => step.stepKey));
|
|
69
|
+
const sessionEntries = latestCompletedPiHarnessEntries(completedSteps);
|
|
70
|
+
const projectedEntries = projectPiSessionEntries(sessionEntries, identity, { timelineMessagesAfterEntryId: interruptedTimelineMessages(completedSteps, sessionEntries) });
|
|
71
|
+
if (instance === null) return {
|
|
72
|
+
...emptyProjectionData(),
|
|
73
|
+
...projectedEntries,
|
|
74
|
+
completedStepKeys: [...completedStepKeys],
|
|
75
|
+
status: "not-found",
|
|
76
|
+
error: /* @__PURE__ */ new Error(`Pi session ${workflowName}/${sessionId} was not found.`),
|
|
77
|
+
readyForInput: false,
|
|
78
|
+
activity: null
|
|
79
|
+
};
|
|
80
|
+
const compactCommandOutcomes = projectPiCompactCommandOutcomes(workflowSteps, identity);
|
|
81
|
+
const emissionReducer = createPiWorkflowSessionEmissionReducer(workflowSteps.some(isPiWorkflowStepActive));
|
|
82
|
+
for (const emission of workflowStepEmissions) if (!completedStepKeys.has(emission.stepKey)) reducePiWorkflowSessionEmission(emissionReducer, emission);
|
|
83
|
+
return {
|
|
84
|
+
...projectPiWorkflowSessionLiveOverlay({
|
|
85
|
+
...projectedEntries,
|
|
86
|
+
instanceStatus: instance.status,
|
|
87
|
+
workflowSteps,
|
|
88
|
+
live: emissionReducer.live
|
|
89
|
+
}),
|
|
90
|
+
status: "ready",
|
|
91
|
+
error: null,
|
|
92
|
+
completedStepKeys: [...completedStepKeys],
|
|
93
|
+
compactOutcomesByCommandId: compactCommandOutcomes.byCommandId,
|
|
94
|
+
latestCommandCompactOutcome: compactCommandOutcomes.latestCommandCompactOutcome
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
//#endregion
|
|
98
|
+
export { createLoadingPiWorkflowSessionProjection, projectPiWorkflowSession };
|
|
99
|
+
|
|
100
|
+
//# sourceMappingURL=workflow-session-projection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-session-projection.js","names":[],"sources":["../../../src/pi/workflow-session-projection.ts"],"sourcesContent":["import type { SessionTreeEntry } from \"@earendil-works/pi-agent-core\";\nimport type { ToolResultMessage } from \"@earendil-works/pi-ai\";\n\nimport { projectPiCompactCommandOutcomes } from \"./compact-command-outcome-projection\";\nimport type { PiHarnessEncodedEventEmission } from \"./harness/agent-harness-event-protocol\";\nimport type {\n PiHarnessFrontendAgentMessage,\n PiHarnessFrontendAssistantMessage,\n} from \"./harness/agent-harness-event-protocol\";\nimport type {\n PiSessionActiveCommand,\n PiSessionCommandStartEmission,\n} from \"./session-command-protocol\";\nimport {\n asPersistedPiHarnessStepResult,\n latestCompletedPiHarnessEntries,\n projectPiSessionEntries,\n} from \"./session-entry-projection\";\nimport type { PiCompactCommandOutcome, PiWorkflowStatus } from \"./types\";\nimport {\n createPiWorkflowSessionEmissionReducer,\n isPiWorkflowStepActive,\n projectPiWorkflowSessionLiveOverlay,\n reducePiWorkflowSessionEmission,\n} from \"./workflow-session-live-projection\";\nimport type {\n PiHarnessOperationCompleteEmission,\n PiHarnessOperationStartEmission,\n PiHarnessSessionEntryEmission,\n} from \"./workflows/workflow-agent-harness\";\n\nexport type PiSessionProjectionStatus = \"loading\" | \"ready\" | \"not-found\";\n\nexport type DraftAgentActivity =\n | \"starting\"\n | \"thinking\"\n | \"writing\"\n | \"tool_calling\"\n | \"running_tools\";\n\nexport interface DraftTool {\n id: string;\n name: string;\n args: unknown;\n argsText?: string;\n status: \"starting\" | \"running\" | \"done\";\n partialResult?: unknown;\n result?: unknown;\n resultMessage?: ToolResultMessage;\n isError?: boolean;\n}\n\nexport interface DraftAgentMessage {\n activity: DraftAgentActivity;\n assistant?: PiHarnessFrontendAssistantMessage;\n tools: Record<string, DraftTool>;\n startedAt: number;\n updatedAt: number;\n}\n\nexport type PiSessionActivity = DraftAgentActivity | \"working\" | null;\n\ntype PiWorkflowSessionProjectionData = {\n contextMessages: PiHarnessFrontendAgentMessage[];\n timelineMessages: PiHarnessFrontendAgentMessage[];\n completedStepKeys: string[];\n draftAgentMessage: DraftAgentMessage | null;\n activeCommand: PiSessionActiveCommand | null;\n compactOutcomesByCommandId: Readonly<Record<string, PiCompactCommandOutcome>>;\n latestCommandCompactOutcome: PiCompactCommandOutcome | null;\n};\n\nexport type PiWorkflowSessionProjectionState =\n | (PiWorkflowSessionProjectionData & {\n status: \"loading\";\n error: null;\n readyForInput: false;\n activity: null;\n })\n | (PiWorkflowSessionProjectionData & {\n status: \"ready\";\n error: null;\n readyForInput: boolean;\n activity: PiSessionActivity;\n })\n | (PiWorkflowSessionProjectionData & {\n status: \"not-found\";\n error: Error;\n readyForInput: false;\n activity: null;\n });\n\nexport type PiWorkflowSessionProjectionStep = {\n stepKey: string;\n type: string;\n status: string;\n waitEventType: string | null;\n result: unknown;\n};\n\nexport type PiWorkflowSessionProjectionEmission = {\n stepKey: string;\n executionId: string;\n epoch: string;\n sequence: number;\n payload:\n | PiHarnessEncodedEventEmission\n | PiHarnessSessionEntryEmission\n | PiHarnessOperationStartEmission\n | PiHarnessOperationCompleteEmission\n | PiSessionCommandStartEmission\n | { kind: undefined; control: string }\n | null;\n createdAt: Date;\n};\n\nexport type PiWorkflowSessionProjectionInstance = {\n status: PiWorkflowStatus;\n};\n\nconst zeroUsage = (): PiHarnessFrontendAssistantMessage[\"usage\"] => ({\n input: 0,\n output: 0,\n cacheRead: 0,\n cacheWrite: 0,\n totalTokens: 0,\n cost: {\n input: 0,\n output: 0,\n cacheRead: 0,\n cacheWrite: 0,\n total: 0,\n },\n});\n\nconst interruptionTimestamp = (entry: SessionTreeEntry | undefined): number => {\n if (!entry) {\n return 0;\n }\n if (entry.type === \"message\") {\n return entry.message.timestamp;\n }\n\n const timestamp = new Date(entry.timestamp).getTime();\n return Number.isFinite(timestamp) ? timestamp : 0;\n};\n\nconst interruptedTimelineMessages = (\n steps: readonly PiWorkflowSessionProjectionStep[],\n sessionEntries: readonly SessionTreeEntry[],\n): ReadonlyMap<string | null, readonly PiHarnessFrontendAgentMessage[]> => {\n const entriesById = new Map(sessionEntries.map((entry) => [entry.id, entry]));\n const messagesByLeafId = new Map<string | null, PiHarnessFrontendAgentMessage[]>();\n\n for (const step of steps) {\n if (step.status !== \"completed\") {\n continue;\n }\n const result = asPersistedPiHarnessStepResult(step.result);\n if (result?.outcome !== \"aborted\") {\n continue;\n }\n\n const leafEntry = result.leafId === null ? undefined : entriesById.get(result.leafId);\n if (\n leafEntry?.type === \"message\" &&\n leafEntry.message.role === \"assistant\" &&\n leafEntry.message.stopReason === \"aborted\"\n ) {\n continue;\n }\n\n const messages = messagesByLeafId.get(result.leafId) ?? [];\n messages.push({\n role: \"assistant\",\n content: [],\n usage: zeroUsage(),\n stopReason: \"aborted\",\n timestamp: interruptionTimestamp(leafEntry),\n });\n messagesByLeafId.set(result.leafId, messages);\n }\n\n return messagesByLeafId;\n};\n\nconst emptyProjectionData = (): PiWorkflowSessionProjectionData => ({\n contextMessages: [],\n timelineMessages: [],\n completedStepKeys: [],\n draftAgentMessage: null,\n activeCommand: null,\n compactOutcomesByCommandId: {},\n latestCommandCompactOutcome: null,\n});\n\nexport const createLoadingPiWorkflowSessionProjection = (): PiWorkflowSessionProjectionState => ({\n ...emptyProjectionData(),\n status: \"loading\",\n error: null,\n readyForInput: false,\n activity: null,\n});\n\nexport const projectPiWorkflowSession = ({\n workflowName,\n sessionId,\n instance,\n workflowSteps,\n workflowStepEmissions = [],\n}: {\n workflowName: string;\n sessionId: string;\n instance: PiWorkflowSessionProjectionInstance | null;\n workflowSteps: readonly PiWorkflowSessionProjectionStep[];\n workflowStepEmissions?: readonly PiWorkflowSessionProjectionEmission[];\n}): PiWorkflowSessionProjectionState => {\n const identity = { workflowName, sessionId };\n const completedSteps = workflowSteps.filter((step) => step.status === \"completed\");\n const completedStepKeys = new Set(completedSteps.map((step) => step.stepKey));\n const sessionEntries = latestCompletedPiHarnessEntries(completedSteps);\n const projectedEntries = projectPiSessionEntries(sessionEntries, identity, {\n timelineMessagesAfterEntryId: interruptedTimelineMessages(completedSteps, sessionEntries),\n });\n\n if (instance === null) {\n return {\n ...emptyProjectionData(),\n ...projectedEntries,\n completedStepKeys: [...completedStepKeys],\n status: \"not-found\",\n error: new Error(`Pi session ${workflowName}/${sessionId} was not found.`),\n readyForInput: false,\n activity: null,\n };\n }\n\n const compactCommandOutcomes = projectPiCompactCommandOutcomes(workflowSteps, identity);\n const emissionReducer = createPiWorkflowSessionEmissionReducer(\n workflowSteps.some(isPiWorkflowStepActive),\n );\n for (const emission of workflowStepEmissions) {\n if (!completedStepKeys.has(emission.stepKey)) {\n reducePiWorkflowSessionEmission(emissionReducer, emission);\n }\n }\n const liveOverlay = projectPiWorkflowSessionLiveOverlay({\n ...projectedEntries,\n instanceStatus: instance.status,\n workflowSteps,\n live: emissionReducer.live,\n });\n\n return {\n ...liveOverlay,\n status: \"ready\",\n error: null,\n completedStepKeys: [...completedStepKeys],\n compactOutcomesByCommandId: compactCommandOutcomes.byCommandId,\n latestCommandCompactOutcome: compactCommandOutcomes.latestCommandCompactOutcome,\n };\n};\n"],"mappings":";;;;AAwHA,MAAM,mBAA+D;CACnE,OAAO;CACP,QAAQ;CACR,WAAW;CACX,YAAY;CACZ,aAAa;CACb,MAAM;EACJ,OAAO;EACP,QAAQ;EACR,WAAW;EACX,YAAY;EACZ,OAAO;CACT;AACF;AAEA,MAAM,yBAAyB,UAAgD;CAC7E,IAAI,CAAC,OACH,OAAO;CAET,IAAI,MAAM,SAAS,WACjB,OAAO,MAAM,QAAQ;CAGvB,MAAM,YAAY,IAAI,KAAK,MAAM,SAAS,CAAC,CAAC,QAAQ;CACpD,OAAO,OAAO,SAAS,SAAS,IAAI,YAAY;AAClD;AAEA,MAAM,+BACJ,OACA,mBACyE;CACzE,MAAM,cAAc,IAAI,IAAI,eAAe,KAAK,UAAU,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC;CAC5E,MAAM,mCAAmB,IAAI,IAAoD;CAEjF,KAAK,MAAM,QAAQ,OAAO;EACxB,IAAI,KAAK,WAAW,aAClB;EAEF,MAAM,SAAS,+BAA+B,KAAK,MAAM;EACzD,IAAI,QAAQ,YAAY,WACtB;EAGF,MAAM,YAAY,OAAO,WAAW,OAAO,KAAA,IAAY,YAAY,IAAI,OAAO,MAAM;EACpF,IACE,WAAW,SAAS,aACpB,UAAU,QAAQ,SAAS,eAC3B,UAAU,QAAQ,eAAe,WAEjC;EAGF,MAAM,WAAW,iBAAiB,IAAI,OAAO,MAAM,KAAK,CAAC;EACzD,SAAS,KAAK;GACZ,MAAM;GACN,SAAS,CAAC;GACV,OAAO,UAAU;GACjB,YAAY;GACZ,WAAW,sBAAsB,SAAS;EAC5C,CAAC;EACD,iBAAiB,IAAI,OAAO,QAAQ,QAAQ;CAC9C;CAEA,OAAO;AACT;AAEA,MAAM,6BAA8D;CAClE,iBAAiB,CAAC;CAClB,kBAAkB,CAAC;CACnB,mBAAmB,CAAC;CACpB,mBAAmB;CACnB,eAAe;CACf,4BAA4B,CAAC;CAC7B,6BAA6B;AAC/B;AAEA,MAAa,kDAAoF;CAC/F,GAAG,oBAAoB;CACvB,QAAQ;CACR,OAAO;CACP,eAAe;CACf,UAAU;AACZ;AAEA,MAAa,4BAA4B,EACvC,cACA,WACA,UACA,eACA,wBAAwB,CAAC,QAOa;CACtC,MAAM,WAAW;EAAE;EAAc;CAAU;CAC3C,MAAM,iBAAiB,cAAc,QAAQ,SAAS,KAAK,WAAW,WAAW;CACjF,MAAM,oBAAoB,IAAI,IAAI,eAAe,KAAK,SAAS,KAAK,OAAO,CAAC;CAC5E,MAAM,iBAAiB,gCAAgC,cAAc;CACrE,MAAM,mBAAmB,wBAAwB,gBAAgB,UAAU,EACzE,8BAA8B,4BAA4B,gBAAgB,cAAc,EAC1F,CAAC;CAED,IAAI,aAAa,MACf,OAAO;EACL,GAAG,oBAAoB;EACvB,GAAG;EACH,mBAAmB,CAAC,GAAG,iBAAiB;EACxC,QAAQ;EACR,uBAAO,IAAI,MAAM,cAAc,aAAa,GAAG,UAAU,gBAAgB;EACzE,eAAe;EACf,UAAU;CACZ;CAGF,MAAM,yBAAyB,gCAAgC,eAAe,QAAQ;CACtF,MAAM,kBAAkB,uCACtB,cAAc,KAAK,sBAAsB,CAC3C;CACA,KAAK,MAAM,YAAY,uBACrB,IAAI,CAAC,kBAAkB,IAAI,SAAS,OAAO,GACzC,gCAAgC,iBAAiB,QAAQ;CAU7D,OAAO;EACL,GARkB,oCAAoC;GACtD,GAAG;GACH,gBAAgB,SAAS;GACzB;GACA,MAAM,gBAAgB;EACxB,CAGe;EACb,QAAQ;EACR,OAAO;EACP,mBAAmB,CAAC,GAAG,iBAAiB;EACxC,4BAA4B,uBAAuB;EACnD,6BAA6B,uBAAuB;CACtD;AACF"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { WorkflowAgentHarnessOptions } from "./workflow-agent-harness.js";
|
|
2
|
+
import { PiOperationDetails, PiSessionMetadata } from "../types.js";
|
|
3
|
+
import { AgentMessage, ThinkingLevel } from "@earendil-works/pi-agent-core";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { WorkflowDuration, WorkflowEvent } from "@fragno-dev/workflows/workflow";
|
|
6
|
+
//#region src/pi/workflows/interactive-chat-workflow.d.ts
|
|
7
|
+
declare const INTERACTIVE_CHAT_WORKFLOW_NAME = "interactive-chat-workflow";
|
|
8
|
+
type InteractiveChatWorkflowParams = {
|
|
9
|
+
/** Application-owned session metadata supplied by the session creation route. */
|
|
10
|
+
metadata?: PiSessionMetadata;
|
|
11
|
+
/** Opaque workflow-owned value forwarded to operation completion hooks. */
|
|
12
|
+
actor?: unknown;
|
|
13
|
+
initialMessages?: AgentMessage[];
|
|
14
|
+
systemPrompt?: string;
|
|
15
|
+
thinkingLevel?: ThinkingLevel;
|
|
16
|
+
};
|
|
17
|
+
declare const interactiveChatWorkflowParamsSchema: z.ZodType<InteractiveChatWorkflowParams>;
|
|
18
|
+
type CreateInteractiveChatWorkflowOptions = {
|
|
19
|
+
name?: string;
|
|
20
|
+
commandTimeout?: WorkflowDuration;
|
|
21
|
+
/**
|
|
22
|
+
* Runs inside each durable command attempt before Pi invokes a model. Throw to reject the
|
|
23
|
+
* operation; retries may call this again until the command step commits.
|
|
24
|
+
*/
|
|
25
|
+
beforeOperation?: (input: PiOperationDetails) => Promise<void> | void;
|
|
26
|
+
options: WorkflowAgentHarnessOptions | ((event: WorkflowEvent<InteractiveChatWorkflowParams>) => WorkflowAgentHarnessOptions | Promise<WorkflowAgentHarnessOptions>);
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Creates an interactive command loop backed entirely by workflow history.
|
|
30
|
+
*
|
|
31
|
+
* Each prompt is a separate `step.do`, while `sessionState` carries the reduced Pi session between
|
|
32
|
+
* those steps. Workflow replay rebuilds the same state by replaying completed step results in order.
|
|
33
|
+
*/
|
|
34
|
+
declare const createInteractiveChatWorkflow: (config: CreateInteractiveChatWorkflowOptions) => import("@fragno-dev/workflows/workflow").WorkflowDefinition<InteractiveChatWorkflowParams, never, z.ZodType<InteractiveChatWorkflowParams, unknown, z.core.$ZodTypeInternals<InteractiveChatWorkflowParams, unknown>>, undefined, string, import("@fragno-dev/db").HooksMap>;
|
|
35
|
+
//#endregion
|
|
36
|
+
export { CreateInteractiveChatWorkflowOptions, INTERACTIVE_CHAT_WORKFLOW_NAME, InteractiveChatWorkflowParams, createInteractiveChatWorkflow, interactiveChatWorkflowParamsSchema };
|
|
37
|
+
//# sourceMappingURL=interactive-chat-workflow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactive-chat-workflow.d.ts","names":[],"sources":["../../../../src/pi/workflows/interactive-chat-workflow.ts"],"mappings":";;;;;;cAkCa;KAED;;EAEV,WAAW;;EAEX;EACA,kBAAkB;EAClB;EACA,gBAAgB;;cAGL,qCAAqC,EAAE,QAAQ;KA8BhD;EACV;EACA,iBAAiB;;;;;EAKjB,mBAAmB,OAAO,uBAAuB;EACjD,SACI,gCAEE,OAAO,cAAc,mCAClB,8BAA8B,QAAQ;;;;;;;;cASpC,gCAAiC,QAAQ,kFAAoC,mBAAA,sCAAA,EAAA,QAAA,wCAAA,EAAA,KAAA,kBAAA,sFAAA"}
|