@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,219 @@
|
|
|
1
|
+
import { PI_SESSION_COMMAND_STEP_PREFIX } from "../types.js";
|
|
2
|
+
import { agentMessageSchema, piSessionCommandPayloadSchema } from "../route-schemas.js";
|
|
3
|
+
import { schedulePiOperationCompletedHook } from "../harness/pi-operation-completed.js";
|
|
4
|
+
import { applyWorkflowAgentHarnessStepResult, createPiHarnessSessionState, hasSummarizableCompactionHistory, restoreWorkflowBackedSession, withWorkflowAgentHarness } from "./workflow-agent-harness.js";
|
|
5
|
+
import { AgentHarness, AgentHarnessError, CompactionError, DEFAULT_COMPACTION_SETTINGS, prepareCompaction } from "@earendil-works/pi-agent-core";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { NonRetryableError, defineWorkflow } from "@fragno-dev/workflows/workflow";
|
|
8
|
+
//#region src/pi/workflows/interactive-chat-workflow.ts
|
|
9
|
+
const WAIT_FOR_COMMAND_TIMEOUT = "7 days";
|
|
10
|
+
const INTERACTIVE_CHAT_WORKFLOW_NAME = "interactive-chat-workflow";
|
|
11
|
+
const interactiveChatWorkflowParamsSchema = z.object({
|
|
12
|
+
metadata: z.record(z.string(), z.unknown()).optional(),
|
|
13
|
+
actor: z.unknown().optional(),
|
|
14
|
+
initialMessages: z.array(agentMessageSchema).optional(),
|
|
15
|
+
systemPrompt: z.string().optional(),
|
|
16
|
+
thinkingLevel: z.enum([
|
|
17
|
+
"off",
|
|
18
|
+
"minimal",
|
|
19
|
+
"low",
|
|
20
|
+
"medium",
|
|
21
|
+
"high",
|
|
22
|
+
"xhigh",
|
|
23
|
+
"max"
|
|
24
|
+
]).optional()
|
|
25
|
+
});
|
|
26
|
+
const logInteractiveChatAssistantError = (assistant, context) => {
|
|
27
|
+
if (assistant.stopReason !== "error") return;
|
|
28
|
+
console.error("Pi interactive chat model operation failed.", {
|
|
29
|
+
...context,
|
|
30
|
+
provider: assistant.provider,
|
|
31
|
+
model: assistant.model,
|
|
32
|
+
...assistant.errorMessage !== void 0 ? { errorMessage: assistant.errorMessage } : {}
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Creates an interactive command loop backed entirely by workflow history.
|
|
37
|
+
*
|
|
38
|
+
* Each prompt is a separate `step.do`, while `sessionState` carries the reduced Pi session between
|
|
39
|
+
* those steps. Workflow replay rebuilds the same state by replaying completed step results in order.
|
|
40
|
+
*/
|
|
41
|
+
const createInteractiveChatWorkflow = (config) => {
|
|
42
|
+
const workflowName = config.name ?? "interactive-chat-workflow";
|
|
43
|
+
const commandTimeout = config.commandTimeout ?? WAIT_FOR_COMMAND_TIMEOUT;
|
|
44
|
+
return defineWorkflow({
|
|
45
|
+
name: workflowName,
|
|
46
|
+
schema: interactiveChatWorkflowParamsSchema
|
|
47
|
+
}, async (event, step) => {
|
|
48
|
+
const params = interactiveChatWorkflowParamsSchema.parse(event.payload ?? {});
|
|
49
|
+
const initialEvent = {
|
|
50
|
+
...event,
|
|
51
|
+
payload: params
|
|
52
|
+
};
|
|
53
|
+
const harnessOptions = typeof config.options === "function" ? await config.options(initialEvent) : config.options;
|
|
54
|
+
let sessionState = createPiHarnessSessionState({
|
|
55
|
+
metadata: {
|
|
56
|
+
id: event.instanceId,
|
|
57
|
+
createdAt: event.timestamp.toISOString()
|
|
58
|
+
},
|
|
59
|
+
initialMessages: params.initialMessages
|
|
60
|
+
});
|
|
61
|
+
while (true) {
|
|
62
|
+
const commandEvent = await step.waitForEvent("wait-command", {
|
|
63
|
+
type: "command",
|
|
64
|
+
timeout: commandTimeout
|
|
65
|
+
});
|
|
66
|
+
const queuedCommand = piSessionCommandPayloadSchema.parse(commandEvent.payload);
|
|
67
|
+
const command = queuedCommand.kind === "steer" || queuedCommand.kind === "followUp" ? {
|
|
68
|
+
...queuedCommand,
|
|
69
|
+
kind: "prompt"
|
|
70
|
+
} : queuedCommand;
|
|
71
|
+
if (command.kind === "abort") continue;
|
|
72
|
+
const invocation = {
|
|
73
|
+
stepName: `${PI_SESSION_COMMAND_STEP_PREFIX}${command.commandId}`,
|
|
74
|
+
operationId: `${workflowName}:${event.instanceId}:command:${command.commandId}`
|
|
75
|
+
};
|
|
76
|
+
const committedResult = await step.do(invocation.stepName, async (tx) => {
|
|
77
|
+
const restored = restoreWorkflowBackedSession({
|
|
78
|
+
operationId: invocation.operationId,
|
|
79
|
+
state: sessionState,
|
|
80
|
+
previousEmissions: await tx.previousEmissions(),
|
|
81
|
+
models: harnessOptions.models
|
|
82
|
+
});
|
|
83
|
+
const harness = new AgentHarness({
|
|
84
|
+
...harnessOptions,
|
|
85
|
+
...restored.options
|
|
86
|
+
});
|
|
87
|
+
return await withWorkflowAgentHarness({
|
|
88
|
+
restored,
|
|
89
|
+
harness,
|
|
90
|
+
tx,
|
|
91
|
+
observeLiveEvents: (onLiveEvent) => {
|
|
92
|
+
onLiveEvent("command", async (event) => {
|
|
93
|
+
const controlCommand = piSessionCommandPayloadSchema.parse(event.payload);
|
|
94
|
+
switch (controlCommand.kind) {
|
|
95
|
+
case "abort":
|
|
96
|
+
await harness.abort();
|
|
97
|
+
event.consume();
|
|
98
|
+
break;
|
|
99
|
+
case "steer":
|
|
100
|
+
case "followUp": {
|
|
101
|
+
const { text, images } = controlCommand.input;
|
|
102
|
+
const promptOptions = images ? { images } : void 0;
|
|
103
|
+
if (controlCommand.kind === "steer") await harness.steer(text, promptOptions);
|
|
104
|
+
else await harness.followUp(text, promptOptions);
|
|
105
|
+
event.consume();
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
case "prompt":
|
|
109
|
+
case "skill":
|
|
110
|
+
case "promptFromTemplate":
|
|
111
|
+
case "compact": break;
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
},
|
|
115
|
+
checkpointTerminalAssistantError: true,
|
|
116
|
+
runDurableStep: async () => {
|
|
117
|
+
await config.beforeOperation?.({
|
|
118
|
+
actor: params.actor ?? null,
|
|
119
|
+
workflowName,
|
|
120
|
+
sessionId: event.instanceId,
|
|
121
|
+
metadata: params.metadata ?? null,
|
|
122
|
+
stepName: invocation.stepName,
|
|
123
|
+
operationId: invocation.operationId,
|
|
124
|
+
operation: command.kind
|
|
125
|
+
});
|
|
126
|
+
tx.emit({
|
|
127
|
+
kind: "pi-session-command-start",
|
|
128
|
+
command: {
|
|
129
|
+
commandId: command.commandId,
|
|
130
|
+
kind: command.kind
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
const logAssistantError = (commandKind, assistant) => {
|
|
134
|
+
logInteractiveChatAssistantError(assistant, {
|
|
135
|
+
workflowName,
|
|
136
|
+
sessionId: event.instanceId,
|
|
137
|
+
commandId: command.commandId,
|
|
138
|
+
commandKind
|
|
139
|
+
});
|
|
140
|
+
};
|
|
141
|
+
switch (command.kind) {
|
|
142
|
+
case "prompt": {
|
|
143
|
+
const assistant = await harness.prompt(command.input.text, command.input.images ? { images: command.input.images } : void 0);
|
|
144
|
+
logAssistantError("prompt", assistant);
|
|
145
|
+
return assistant;
|
|
146
|
+
}
|
|
147
|
+
case "skill": {
|
|
148
|
+
const assistant = await harness.skill(command.input.name, command.input.additionalInstructions);
|
|
149
|
+
logAssistantError("skill", assistant);
|
|
150
|
+
return assistant;
|
|
151
|
+
}
|
|
152
|
+
case "promptFromTemplate": {
|
|
153
|
+
const assistant = await harness.promptFromTemplate(command.input.name, command.input.args);
|
|
154
|
+
logAssistantError("promptFromTemplate", assistant);
|
|
155
|
+
return assistant;
|
|
156
|
+
}
|
|
157
|
+
case "compact": {
|
|
158
|
+
const preparationResult = prepareCompaction(await restored.session.getBranch(), DEFAULT_COMPACTION_SETTINGS);
|
|
159
|
+
if (!preparationResult.ok) {
|
|
160
|
+
if (preparationResult.error.code === "invalid_session") throw new NonRetryableError(`PI_COMPACTION_INVALID_SESSION: ${preparationResult.error.message}`);
|
|
161
|
+
throw preparationResult.error;
|
|
162
|
+
}
|
|
163
|
+
if (!preparationResult.value || !hasSummarizableCompactionHistory(preparationResult.value)) return {
|
|
164
|
+
kind: "compact",
|
|
165
|
+
commandId: command.commandId,
|
|
166
|
+
status: "rejected",
|
|
167
|
+
code: "nothing_to_compact",
|
|
168
|
+
message: "Nothing to compact."
|
|
169
|
+
};
|
|
170
|
+
try {
|
|
171
|
+
await harness.compact(command.input.customInstructions);
|
|
172
|
+
return {
|
|
173
|
+
kind: "compact",
|
|
174
|
+
commandId: command.commandId,
|
|
175
|
+
status: "succeeded"
|
|
176
|
+
};
|
|
177
|
+
} catch (error) {
|
|
178
|
+
if (!(error instanceof AgentHarnessError) || error.code !== "compaction") throw error;
|
|
179
|
+
if (!(error.cause instanceof CompactionError)) throw error;
|
|
180
|
+
switch (error.cause.code) {
|
|
181
|
+
case "aborted":
|
|
182
|
+
case "summarization_failed": return {
|
|
183
|
+
kind: "compact",
|
|
184
|
+
commandId: command.commandId,
|
|
185
|
+
status: "rejected",
|
|
186
|
+
code: "compaction_failed",
|
|
187
|
+
message: error.cause.message
|
|
188
|
+
};
|
|
189
|
+
case "invalid_session": throw new NonRetryableError(`PI_COMPACTION_INVALID_SESSION: ${error.cause.message}`);
|
|
190
|
+
case "unknown": throw error;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
throw new Error("Unsupported durable Pi session command.");
|
|
196
|
+
},
|
|
197
|
+
onTerminalOutcome: ({ operationEntries }) => {
|
|
198
|
+
schedulePiOperationCompletedHook({
|
|
199
|
+
tx,
|
|
200
|
+
actor: params.actor ?? null,
|
|
201
|
+
workflowName,
|
|
202
|
+
sessionId: sessionState.metadata.id,
|
|
203
|
+
metadata: params.metadata ?? null,
|
|
204
|
+
stepName: invocation.stepName,
|
|
205
|
+
operationId: invocation.operationId,
|
|
206
|
+
operation: command.kind,
|
|
207
|
+
operationEntries
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
sessionState = applyWorkflowAgentHarnessStepResult(sessionState, committedResult);
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
};
|
|
216
|
+
//#endregion
|
|
217
|
+
export { INTERACTIVE_CHAT_WORKFLOW_NAME, createInteractiveChatWorkflow, interactiveChatWorkflowParamsSchema };
|
|
218
|
+
|
|
219
|
+
//# sourceMappingURL=interactive-chat-workflow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactive-chat-workflow.js","names":[],"sources":["../../../../src/pi/workflows/interactive-chat-workflow.ts"],"sourcesContent":["import type { WorkflowDuration, WorkflowEvent } from \"@fragno-dev/workflows/workflow\";\nimport { defineWorkflow, NonRetryableError } from \"@fragno-dev/workflows/workflow\";\nimport { z } from \"zod\";\n\nimport {\n AgentHarness,\n AgentHarnessError,\n CompactionError,\n DEFAULT_COMPACTION_SETTINGS,\n prepareCompaction,\n type AgentMessage,\n type ThinkingLevel,\n} from \"@earendil-works/pi-agent-core\";\nimport type { AssistantMessage } from \"@earendil-works/pi-ai\";\n\nimport { schedulePiOperationCompletedHook } from \"../harness/pi-operation-completed\";\nimport { agentMessageSchema, piSessionCommandPayloadSchema } from \"../route-schemas\";\nimport type { PiSessionCommandStartEmission } from \"../session-command-protocol\";\nimport {\n PI_SESSION_COMMAND_STEP_PREFIX,\n type PiCompactCommandOutcome,\n type PiOperationDetails,\n type PiSessionMetadata,\n} from \"../types\";\nimport {\n applyWorkflowAgentHarnessStepResult,\n createPiHarnessSessionState,\n hasSummarizableCompactionHistory,\n restoreWorkflowBackedSession,\n withWorkflowAgentHarness,\n type WorkflowAgentHarnessOptions,\n} from \"./workflow-agent-harness\";\n\nconst WAIT_FOR_COMMAND_TIMEOUT = \"7 days\" as const;\nexport const INTERACTIVE_CHAT_WORKFLOW_NAME = \"interactive-chat-workflow\";\n\nexport type InteractiveChatWorkflowParams = {\n /** Application-owned session metadata supplied by the session creation route. */\n metadata?: PiSessionMetadata;\n /** Opaque workflow-owned value forwarded to operation completion hooks. */\n actor?: unknown;\n initialMessages?: AgentMessage[];\n systemPrompt?: string;\n thinkingLevel?: ThinkingLevel;\n};\n\nexport const interactiveChatWorkflowParamsSchema: z.ZodType<InteractiveChatWorkflowParams> =\n z.object({\n metadata: z.record(z.string(), z.unknown()).optional(),\n actor: z.unknown().optional(),\n initialMessages: z.array(agentMessageSchema).optional(),\n systemPrompt: z.string().optional(),\n thinkingLevel: z.enum([\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"]).optional(),\n });\n\nconst logInteractiveChatAssistantError = (\n assistant: AssistantMessage,\n context: {\n workflowName: string;\n sessionId: string;\n commandId: string;\n commandKind: \"prompt\" | \"skill\" | \"promptFromTemplate\";\n },\n): void => {\n if (assistant.stopReason !== \"error\") {\n return;\n }\n\n console.error(\"Pi interactive chat model operation failed.\", {\n ...context,\n provider: assistant.provider,\n model: assistant.model,\n ...(assistant.errorMessage !== undefined ? { errorMessage: assistant.errorMessage } : {}),\n });\n};\n\nexport type CreateInteractiveChatWorkflowOptions = {\n name?: string;\n commandTimeout?: WorkflowDuration;\n /**\n * Runs inside each durable command attempt before Pi invokes a model. Throw to reject the\n * operation; retries may call this again until the command step commits.\n */\n beforeOperation?: (input: PiOperationDetails) => Promise<void> | void;\n options:\n | WorkflowAgentHarnessOptions\n | ((\n event: WorkflowEvent<InteractiveChatWorkflowParams>,\n ) => WorkflowAgentHarnessOptions | Promise<WorkflowAgentHarnessOptions>);\n};\n\n/**\n * Creates an interactive command loop backed entirely by workflow history.\n *\n * Each prompt is a separate `step.do`, while `sessionState` carries the reduced Pi session between\n * those steps. Workflow replay rebuilds the same state by replaying completed step results in order.\n */\nexport const createInteractiveChatWorkflow = (config: CreateInteractiveChatWorkflowOptions) => {\n const workflowName = config.name ?? INTERACTIVE_CHAT_WORKFLOW_NAME;\n const commandTimeout = config.commandTimeout ?? WAIT_FOR_COMMAND_TIMEOUT;\n\n return defineWorkflow(\n {\n name: workflowName,\n schema: interactiveChatWorkflowParamsSchema,\n },\n async (event, step) => {\n const params = interactiveChatWorkflowParamsSchema.parse(event.payload ?? {});\n const initialEvent: WorkflowEvent<InteractiveChatWorkflowParams> = {\n ...event,\n payload: params,\n };\n // AgentHarness options are runtime dependencies, so resolve them outside durable model steps\n // and reconstruct them whenever the workflow replays.\n const harnessOptions =\n typeof config.options === \"function\" ? await config.options(initialEvent) : config.options;\n let sessionState = createPiHarnessSessionState({\n metadata: {\n id: event.instanceId,\n createdAt: event.timestamp.toISOString(),\n },\n initialMessages: params.initialMessages,\n });\n while (true) {\n const commandEvent = await step.waitForEvent(\"wait-command\", {\n type: \"command\",\n timeout: commandTimeout,\n });\n const queuedCommand = piSessionCommandPayloadSchema.parse(commandEvent.payload);\n\n // Controls consumed by a live harness normally never reach this durable wait. If steer or\n // followUp does reach it, the targeted operation is no longer active, so preserve its text.\n\n const command =\n queuedCommand.kind === \"steer\" || queuedCommand.kind === \"followUp\"\n ? { ...queuedCommand, kind: \"prompt\" as const }\n : queuedCommand;\n\n if (command.kind === \"abort\") {\n continue;\n }\n\n const invocation = {\n stepName: `${PI_SESSION_COMMAND_STEP_PREFIX}${command.commandId}`,\n operationId: `${workflowName}:${event.instanceId}:command:${command.commandId}`,\n };\n const committedResult = await step.do(invocation.stepName, async (tx) => {\n const restored = restoreWorkflowBackedSession({\n operationId: invocation.operationId,\n state: sessionState,\n previousEmissions: await tx.previousEmissions(),\n models: harnessOptions.models,\n });\n const harness = new AgentHarness({ ...harnessOptions, ...restored.options });\n\n return await withWorkflowAgentHarness({\n restored,\n harness,\n tx,\n observeLiveEvents: (onLiveEvent) => {\n // Durable commands stay unconsumed so the outer loop executes them as the next step.\n onLiveEvent(\"command\", async (event) => {\n const controlCommand = piSessionCommandPayloadSchema.parse(event.payload);\n\n switch (controlCommand.kind) {\n case \"abort\":\n await harness.abort();\n event.consume();\n break;\n case \"steer\":\n case \"followUp\": {\n const { text, images } = controlCommand.input;\n const promptOptions = images ? { images } : undefined;\n if (controlCommand.kind === \"steer\") {\n await harness.steer(text, promptOptions);\n } else {\n await harness.followUp(text, promptOptions);\n }\n event.consume();\n break;\n }\n case \"prompt\":\n case \"skill\":\n case \"promptFromTemplate\":\n case \"compact\":\n break;\n }\n });\n },\n checkpointTerminalAssistantError: true,\n runDurableStep: async () => {\n await config.beforeOperation?.({\n actor: params.actor ?? null,\n workflowName,\n sessionId: event.instanceId,\n metadata: params.metadata ?? null,\n stepName: invocation.stepName,\n operationId: invocation.operationId,\n operation: command.kind,\n });\n\n tx.emit({\n kind: \"pi-session-command-start\",\n command: { commandId: command.commandId, kind: command.kind },\n } satisfies PiSessionCommandStartEmission);\n\n const logAssistantError = (\n commandKind: \"prompt\" | \"skill\" | \"promptFromTemplate\",\n assistant: AssistantMessage,\n ) => {\n logInteractiveChatAssistantError(assistant, {\n workflowName,\n sessionId: event.instanceId,\n commandId: command.commandId,\n commandKind,\n });\n };\n\n switch (command.kind) {\n case \"prompt\": {\n const assistant = await harness.prompt(\n command.input.text,\n command.input.images ? { images: command.input.images } : undefined,\n );\n logAssistantError(\"prompt\", assistant);\n return assistant;\n }\n case \"skill\": {\n const assistant = await harness.skill(\n command.input.name,\n command.input.additionalInstructions,\n );\n logAssistantError(\"skill\", assistant);\n return assistant;\n }\n case \"promptFromTemplate\": {\n const assistant = await harness.promptFromTemplate(\n command.input.name,\n command.input.args,\n );\n logAssistantError(\"promptFromTemplate\", assistant);\n return assistant;\n }\n case \"compact\": {\n const preparationResult = prepareCompaction(\n await restored.session.getBranch(),\n DEFAULT_COMPACTION_SETTINGS,\n );\n if (!preparationResult.ok) {\n if (preparationResult.error.code === \"invalid_session\") {\n throw new NonRetryableError(\n `PI_COMPACTION_INVALID_SESSION: ${preparationResult.error.message}`,\n );\n }\n throw preparationResult.error;\n }\n if (\n !preparationResult.value ||\n !hasSummarizableCompactionHistory(preparationResult.value)\n ) {\n return {\n kind: \"compact\",\n commandId: command.commandId,\n status: \"rejected\",\n code: \"nothing_to_compact\",\n message: \"Nothing to compact.\",\n } satisfies PiCompactCommandOutcome;\n }\n\n try {\n await harness.compact(command.input.customInstructions);\n return {\n kind: \"compact\",\n commandId: command.commandId,\n status: \"succeeded\",\n } satisfies PiCompactCommandOutcome;\n } catch (error) {\n if (!(error instanceof AgentHarnessError) || error.code !== \"compaction\") {\n throw error;\n }\n if (!(error.cause instanceof CompactionError)) {\n throw error;\n }\n\n switch (error.cause.code) {\n case \"aborted\":\n case \"summarization_failed\":\n return {\n kind: \"compact\",\n commandId: command.commandId,\n status: \"rejected\",\n code: \"compaction_failed\",\n message: error.cause.message,\n } satisfies PiCompactCommandOutcome;\n case \"invalid_session\":\n throw new NonRetryableError(\n `PI_COMPACTION_INVALID_SESSION: ${error.cause.message}`,\n );\n case \"unknown\":\n throw error;\n }\n }\n }\n }\n\n throw new Error(\"Unsupported durable Pi session command.\");\n },\n // Accounting is registered before the adapter accepts or rejects the terminal\n // assistant, so failed model calls are still recorded by the terminal-error\n // transaction path.\n onTerminalOutcome: ({ operationEntries }) => {\n schedulePiOperationCompletedHook({\n tx,\n actor: params.actor ?? null,\n workflowName,\n sessionId: sessionState.metadata.id,\n metadata: params.metadata ?? null,\n stepName: invocation.stepName,\n operationId: invocation.operationId,\n operation: command.kind,\n operationEntries,\n });\n },\n });\n });\n // Only reduce after the durable step completes; interrupted attempts reconstruct their\n // uncommitted entries from step emissions instead.\n sessionState = applyWorkflowAgentHarnessStepResult(sessionState, committedResult);\n }\n },\n );\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { PiHarnessEncodedEventEmission } from "../harness/agent-harness-event-protocol.js";
|
|
2
|
+
import { WorkflowBackedSessionStorage } from "../harness/session-storage.js";
|
|
3
|
+
import { AgentHarness, AgentHarnessOptions, AgentHarnessTool, AgentMessage, CompactionPreparation, PromptTemplate, Session, SessionMetadata, SessionTreeEntry, Skill } from "@earendil-works/pi-agent-core";
|
|
4
|
+
import { WorkflowStepEmission, WorkflowStepEventHandler, WorkflowStepTx } from "@fragno-dev/workflows/workflow";
|
|
5
|
+
import { ToolCall } from "@earendil-works/pi-ai";
|
|
6
|
+
//#region src/pi/workflows/workflow-agent-harness.d.ts
|
|
7
|
+
type PiHarnessOperation = {
|
|
8
|
+
kind: "prompt";
|
|
9
|
+
args: Parameters<AgentHarness["prompt"]>;
|
|
10
|
+
stopOnTools?: readonly string[];
|
|
11
|
+
} | {
|
|
12
|
+
kind: "skill";
|
|
13
|
+
args: Parameters<AgentHarness["skill"]>;
|
|
14
|
+
} | {
|
|
15
|
+
kind: "promptFromTemplate";
|
|
16
|
+
args: Parameters<AgentHarness["promptFromTemplate"]>;
|
|
17
|
+
} | {
|
|
18
|
+
kind: "compact";
|
|
19
|
+
args: Parameters<AgentHarness["compact"]>;
|
|
20
|
+
} | {
|
|
21
|
+
kind: "navigateTree";
|
|
22
|
+
args: Parameters<AgentHarness["navigateTree"]>;
|
|
23
|
+
};
|
|
24
|
+
type PiHarnessStepResult = {
|
|
25
|
+
type: "harness-run";
|
|
26
|
+
appendedEntries: SessionTreeEntry[];
|
|
27
|
+
leafId: string | null;
|
|
28
|
+
};
|
|
29
|
+
type PiHarnessSessionEntryEmission = {
|
|
30
|
+
kind: "harness-session-entry";
|
|
31
|
+
entry: SessionTreeEntry;
|
|
32
|
+
};
|
|
33
|
+
type PiHarnessOperationStartEmission = {
|
|
34
|
+
kind: "harness-operation-start";
|
|
35
|
+
operationId: string;
|
|
36
|
+
replay: {
|
|
37
|
+
protocol: "pi-harness-operation";
|
|
38
|
+
version: 1;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
type PiHarnessOperationCompleteEmission<TResult = PiHarnessStepResult> = {
|
|
42
|
+
kind: "harness-operation-complete";
|
|
43
|
+
operationId: string;
|
|
44
|
+
result: TResult;
|
|
45
|
+
};
|
|
46
|
+
type PiHarnessEmission<TResult = PiHarnessStepResult> = PiHarnessSessionEntryEmission | PiHarnessEncodedEventEmission | PiHarnessOperationStartEmission | PiHarnessOperationCompleteEmission<TResult>;
|
|
47
|
+
type WorkflowAgentHarnessOptions<TContext extends object | undefined = undefined, TSkill extends Skill = Skill, TPromptTemplate extends PromptTemplate = PromptTemplate, TTool extends AgentHarnessTool<TContext> = AgentHarnessTool<TContext>> = Omit<AgentHarnessOptions<TContext, TSkill, TPromptTemplate, TTool>, "session">;
|
|
48
|
+
type PiHarnessSessionStepState = {
|
|
49
|
+
metadata: SessionMetadata;
|
|
50
|
+
entries: readonly SessionTreeEntry[];
|
|
51
|
+
checkpointedEntryCount: number;
|
|
52
|
+
};
|
|
53
|
+
type CreatePiHarnessSessionStateOptions = {
|
|
54
|
+
metadata: SessionMetadata;
|
|
55
|
+
/** Messages must carry timestamps created outside workflow replay. */
|
|
56
|
+
initialMessages?: readonly AgentMessage[];
|
|
57
|
+
};
|
|
58
|
+
declare const createPiHarnessSessionState: (options: CreatePiHarnessSessionStateOptions) => PiHarnessSessionStepState;
|
|
59
|
+
/**
|
|
60
|
+
* Restore one runner-selected attempt from emissions in persisted order. Session entries are an
|
|
61
|
+
* immutable append log; repeated IDs or mixed attempt identities are corruption.
|
|
62
|
+
*/
|
|
63
|
+
type AppendEntryListener = (entry: SessionTreeEntry) => void | Promise<void>;
|
|
64
|
+
/** Starts an AgentHarness operation when the selected workflow attempt has no prior journal. */
|
|
65
|
+
type ExecuteWorkflowAgentHarnessRecovery = {
|
|
66
|
+
readonly kind: "execute";
|
|
67
|
+
};
|
|
68
|
+
/** Checkpoints durable transcript progress from an interrupted workflow attempt without rerunning it. */
|
|
69
|
+
type InterruptedWorkflowAgentHarnessRecovery = {
|
|
70
|
+
readonly kind: "interrupted";
|
|
71
|
+
readonly transcript: InterruptedTranscript;
|
|
72
|
+
readonly replayedEntries: readonly SessionTreeEntry[];
|
|
73
|
+
};
|
|
74
|
+
/** Replays a finished AgentHarness operation whose entries and result were emitted before the process died, but whose workflow step had not committed. */
|
|
75
|
+
type CompletedWorkflowAgentHarnessRecovery = {
|
|
76
|
+
readonly kind: "completed";
|
|
77
|
+
readonly result: WorkflowAgentHarnessStepResult;
|
|
78
|
+
};
|
|
79
|
+
/** Tells withWorkflowAgentHarness whether to run, recover, or replay the operation. */
|
|
80
|
+
type WorkflowAgentHarnessRecovery = ExecuteWorkflowAgentHarnessRecovery | InterruptedWorkflowAgentHarnessRecovery | CompletedWorkflowAgentHarnessRecovery;
|
|
81
|
+
type WorkflowAgentHarnessStorageMetadata = {
|
|
82
|
+
readonly operationId: string;
|
|
83
|
+
readonly operationEntryStart: number;
|
|
84
|
+
readonly checkpointEntryStart: number;
|
|
85
|
+
readonly recovery: WorkflowAgentHarnessRecovery;
|
|
86
|
+
};
|
|
87
|
+
type RestoredWorkflowAgentHarnessOptions = Pick<AgentHarnessOptions, "session"> & Partial<Pick<AgentHarnessOptions, "model" | "thinkingLevel" | "activeToolNames">>;
|
|
88
|
+
type RestoredWorkflowBackedSession = WorkflowAgentHarnessStorageMetadata & {
|
|
89
|
+
session: Session;
|
|
90
|
+
storage: WorkflowBackedSessionStorage;
|
|
91
|
+
options: RestoredWorkflowAgentHarnessOptions;
|
|
92
|
+
subscribeToAppendedEntries: (listener: AppendEntryListener) => () => void;
|
|
93
|
+
};
|
|
94
|
+
type RestoreWorkflowBackedSessionOptions = {
|
|
95
|
+
operationId: string;
|
|
96
|
+
state: PiHarnessSessionStepState;
|
|
97
|
+
previousEmissions: readonly WorkflowStepEmission[];
|
|
98
|
+
models: AgentHarnessOptions["models"];
|
|
99
|
+
};
|
|
100
|
+
type InterruptedTranscript = {
|
|
101
|
+
recoverableLeafId: string | null;
|
|
102
|
+
missingToolCalls: ToolCall[];
|
|
103
|
+
};
|
|
104
|
+
declare const restoreWorkflowBackedSession: (options: RestoreWorkflowBackedSessionOptions) => RestoredWorkflowBackedSession;
|
|
105
|
+
/**
|
|
106
|
+
* Execute a fresh invocation, replay a completed result, or checkpoint interrupted progress as
|
|
107
|
+
* aborted. Recovery never calls runDurableStep and never re-executes provider or tool work.
|
|
108
|
+
*/
|
|
109
|
+
type WorkflowAgentHarnessStepResultBase = Pick<PiHarnessStepResult, "type" | "appendedEntries" | "leafId">;
|
|
110
|
+
type WorkflowAgentHarnessStepResult<TResult = unknown> = WorkflowAgentHarnessStepResultBase & ({
|
|
111
|
+
readonly outcome: "completed";
|
|
112
|
+
readonly value: TResult;
|
|
113
|
+
} | {
|
|
114
|
+
readonly outcome: "aborted";
|
|
115
|
+
});
|
|
116
|
+
type WorkflowAgentHarnessTerminalOutcome<TResult = unknown> = {
|
|
117
|
+
operationId: string;
|
|
118
|
+
operationEntries: readonly SessionTreeEntry[];
|
|
119
|
+
result: WorkflowAgentHarnessStepResult<TResult>;
|
|
120
|
+
};
|
|
121
|
+
type WorkflowAgentHarnessOnLiveEvent = <TPayload = unknown>(type: string, handler: WorkflowStepEventHandler<TPayload>) => void;
|
|
122
|
+
type WorkflowAgentHarnessTerminalOptions<TResult> = {
|
|
123
|
+
/** Persist terminal provider errors as completed operations instead of failing the workflow step. */
|
|
124
|
+
checkpointTerminalAssistantError?: boolean;
|
|
125
|
+
/** May run more than once before the enclosing workflow step commits. */
|
|
126
|
+
onTerminalOutcome?: (outcome: WorkflowAgentHarnessTerminalOutcome<TResult>) => Promise<void> | void;
|
|
127
|
+
};
|
|
128
|
+
type WithWorkflowAgentHarnessOptions<TResult = unknown> = WorkflowAgentHarnessTerminalOptions<TResult> & {
|
|
129
|
+
restored: RestoredWorkflowBackedSession;
|
|
130
|
+
harness: AgentHarness;
|
|
131
|
+
tx: WorkflowAgentHarnessExecutionTx;
|
|
132
|
+
observeLiveEvents?: (onLiveEvent: WorkflowAgentHarnessOnLiveEvent) => void;
|
|
133
|
+
runDurableStep: () => Promise<TResult>;
|
|
134
|
+
};
|
|
135
|
+
type WorkflowAgentHarnessExecutionTx = Pick<WorkflowStepTx, "emit" | "onEvent">;
|
|
136
|
+
declare const hasSummarizableCompactionHistory: (preparation: CompactionPreparation) => boolean;
|
|
137
|
+
declare const withWorkflowAgentHarness: <TResult>({ restored, harness, tx, observeLiveEvents, runDurableStep, checkpointTerminalAssistantError, onTerminalOutcome }: WithWorkflowAgentHarnessOptions<TResult>) => Promise<WorkflowAgentHarnessStepResult<TResult>>;
|
|
138
|
+
/** Append one completed checkpoint suffix and verify its derived active leaf. */
|
|
139
|
+
declare const applyWorkflowAgentHarnessStepResult: (state: PiHarnessSessionStepState, result: Pick<WorkflowAgentHarnessStepResult, "appendedEntries" | "leafId">) => PiHarnessSessionStepState;
|
|
140
|
+
//#endregion
|
|
141
|
+
export { CreatePiHarnessSessionStateOptions, PiHarnessEmission, PiHarnessOperation, PiHarnessOperationCompleteEmission, PiHarnessOperationStartEmission, PiHarnessSessionEntryEmission, PiHarnessSessionStepState, PiHarnessStepResult, RestoredWorkflowAgentHarnessOptions, RestoredWorkflowBackedSession, WithWorkflowAgentHarnessOptions, WorkflowAgentHarnessOnLiveEvent, WorkflowAgentHarnessOptions, WorkflowAgentHarnessStepResult, WorkflowAgentHarnessTerminalOutcome, applyWorkflowAgentHarnessStepResult, createPiHarnessSessionState, hasSummarizableCompactionHistory, restoreWorkflowBackedSession, withWorkflowAgentHarness };
|
|
142
|
+
//# sourceMappingURL=workflow-agent-harness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-agent-harness.d.ts","names":[],"sources":["../../../../src/pi/workflows/workflow-agent-harness.ts"],"mappings":";;;;;;KAiCY;EACN;EAAgB,MAAM,WAAW;EAAyB;;EAC1D;EAAe,MAAM,WAAW;;EAChC;EAA4B,MAAM,WAAW;;EAC7C;EAAiB,MAAM,WAAW;;EAClC;EAAsB,MAAM,WAAW;;KAEjC;EACV;EACA,iBAAiB;EACjB;;KAGU;EACV;EACA,OAAO;;KAGG;EACV;EACA;EACA;IACE;IACA;;;KAIQ,mCAAmC,UAAU;EACvD;EACA;EACA,QAAQ;;KAGE,kBAAkB,UAAU,uBACpC,gCACA,gCACA,kCACA,mCAAmC;KAE3B,4BACV,iDACA,eAAe,QAAQ,OACvB,wBAAwB,iBAAiB,gBACzC,cAAc,iBAAiB,YAAY,iBAAiB,aAC1D,KAAK,oBAAoB,UAAU,QAAQ,iBAAiB;KAEpD;EACV,UAAU;EACV,kBAAkB;EAClB;;KAGU;EACV,UAAU;;EAEV,2BAA2B;;cAyBhB,8BACX,SAAS,uCACR;;;;;KAWE,uBAAuB,OAAO,4BAA4B;;KAO1D;WAAiD;;;KAGjD;WACM;WACA,YAAY;WACZ,0BAA0B;;;KAIhC;WACM;WACA,QAAQ;;;KAId,+BACD,sCACA,0CACA;KAEC;WACM;WACA;WACA;WACA,UAAU;;KAGT,sCAAsC,KAAK,kCACrD,QAAQ,KAAK;KAEH,gCAAgC;EAC1C,SAAS;EACT,SAAS;EACT,SAAS;EACT,6BAA6B,UAAU;;KAGpC;EACH;EACA,OAAO;EACP,4BAA4B;EAC5B,QAAQ;;KAmGL;EACH;EACA,kBAAkB;;cAiMP,+BACX,SAAS,wCACR;;;;;KAgFE,qCAAqC,KACxC;KAIU,+BAA+B,qBAAqB;WAClD;WAA+B,OAAO;;WAAuB;;KAE/D,oCAAoC;EAC9C;EACA,2BAA2B;EAC3B,QAAQ,+BAA+B;;KAG7B,mCAAmC,oBAC7C,cACA,SAAS,yBAAyB;KAG/B,oCAAoC;;EAEvC;;EAEA,qBACE,SAAS,oCAAoC,aAC1C;;KAGK,gCAAgC,qBAC1C,oCAAoC;EAClC,UAAU;EACV,SAAS;EACT,IAAI;EACJ,qBAAqB,aAAa;EAClC,sBAAsB,QAAQ;;KAG7B,kCAAkC,KAAK;cA+C/B,mCAAoC,aAAa;cAqBjD,2BAAkC,WAAS,UAAA,SAAA,IAAA,mBAAA,gBAAA,kCAAA,qBAQrD,gCAAgC,aAAW,QAAQ,+BAA+B;;cAqNxE,sCACX,OAAO,2BACP,QAAQ,KAAK,kEACZ"}
|