@fragno-dev/pi-fragment 0.0.1 → 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/README.md +39 -3
- package/dist/browser/client/react.d.ts +44 -36
- package/dist/browser/client/react.d.ts.map +1 -1
- package/dist/browser/client/react.js +105 -22
- package/dist/browser/client/react.js.map +1 -1
- package/dist/browser/client/solid.d.ts +42 -36
- package/dist/browser/client/solid.d.ts.map +1 -1
- package/dist/browser/client/solid.js +27 -13
- package/dist/browser/client/solid.js.map +1 -1
- package/dist/browser/client/svelte.d.ts +42 -36
- package/dist/browser/client/svelte.d.ts.map +1 -1
- package/dist/browser/client/svelte.js +14 -6
- package/dist/browser/client/svelte.js.map +1 -1
- package/dist/browser/client/vanilla.d.ts +99 -39
- package/dist/browser/client/vanilla.d.ts.map +1 -1
- package/dist/browser/client/vanilla.js +151 -3
- package/dist/browser/client/vanilla.js.map +1 -1
- package/dist/browser/client/vue.d.ts +54 -38
- package/dist/browser/client/vue.d.ts.map +1 -1
- package/dist/browser/client/vue.js +25 -17
- package/dist/browser/client/vue.js.map +1 -1
- package/dist/browser/{factory-DKoO_lRA.js → clients-BscY_HVe.js} +1051 -799
- package/dist/browser/clients-BscY_HVe.js.map +1 -0
- package/dist/browser/index.d.ts +3 -776
- package/dist/browser/index.js +801 -2
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/routes-CpL_YGWK.d.ts +1560 -0
- package/dist/browser/routes-CpL_YGWK.d.ts.map +1 -0
- package/dist/cli/mod.d.ts.map +1 -1
- package/dist/cli/mod.js +245 -7
- package/dist/cli/mod.js.map +1 -1
- package/dist/node/{pi → client}/clients.d.ts +46 -36
- package/dist/node/client/clients.d.ts.map +1 -0
- package/dist/node/client/clients.js +54 -0
- package/dist/node/client/clients.js.map +1 -0
- package/dist/node/client/session-controller.d.ts +31 -0
- package/dist/node/client/session-controller.d.ts.map +1 -0
- package/dist/node/client/session-controller.js +33 -0
- package/dist/node/client/session-controller.js.map +1 -0
- package/dist/node/client/session-store.d.ts +71 -0
- package/dist/node/client/session-store.d.ts.map +1 -0
- package/dist/node/client/session-store.js +637 -0
- package/dist/node/client/session-store.js.map +1 -0
- package/dist/node/debug-log.d.ts +9 -0
- package/dist/node/debug-log.d.ts.map +1 -0
- package/dist/node/debug-log.js +58 -0
- package/dist/node/debug-log.js.map +1 -0
- package/dist/node/index.d.ts +5 -4
- package/dist/node/index.js +5 -3
- package/dist/node/pi/definition.d.ts +1 -1
- package/dist/node/pi/definition.d.ts.map +1 -1
- package/dist/node/pi/dsl.d.ts +5 -2
- package/dist/node/pi/dsl.d.ts.map +1 -1
- package/dist/node/pi/dsl.js +22 -3
- package/dist/node/pi/dsl.js.map +1 -1
- package/dist/node/pi/factory.d.ts +37 -34
- package/dist/node/pi/factory.d.ts.map +1 -1
- package/dist/node/pi/factory.js.map +1 -1
- package/dist/node/pi/mappers.js +0 -1
- package/dist/node/pi/mappers.js.map +1 -1
- package/dist/node/pi/route-schemas.js +42 -10
- package/dist/node/pi/route-schemas.js.map +1 -1
- package/dist/node/pi/types.d.ts +155 -7
- package/dist/node/pi/types.d.ts.map +1 -1
- package/dist/node/pi/types.js +6 -0
- package/dist/node/pi/types.js.map +1 -0
- package/dist/node/pi/workflow/active-session.d.ts +2 -0
- package/dist/node/pi/workflow/active-session.js +107 -0
- package/dist/node/pi/workflow/active-session.js.map +1 -0
- package/dist/node/pi/workflow/agent-runner.d.ts +13 -0
- package/dist/node/pi/workflow/agent-runner.d.ts.map +1 -0
- package/dist/node/pi/workflow/agent-runner.js +228 -0
- package/dist/node/pi/workflow/agent-runner.js.map +1 -0
- package/dist/node/pi/workflow/tool-journal.js +157 -0
- package/dist/node/pi/workflow/tool-journal.js.map +1 -0
- package/dist/node/pi/workflow/workflow.d.ts +29 -0
- package/dist/node/pi/workflow/workflow.d.ts.map +1 -0
- package/dist/node/pi/workflow/workflow.js +219 -0
- package/dist/node/pi/workflow/workflow.js.map +1 -0
- package/dist/node/routes.d.ts +38 -35
- package/dist/node/routes.d.ts.map +1 -1
- package/dist/node/routes.js +203 -132
- package/dist/node/routes.js.map +1 -1
- package/dist/node/schema.js +1 -1
- package/dist/node/schema.js.map +1 -1
- package/package.json +30 -29
- package/dist/browser/client-Bk-J98pf.d.ts +0 -679
- package/dist/browser/client-Bk-J98pf.d.ts.map +0 -1
- package/dist/browser/factory-DKoO_lRA.js.map +0 -1
- package/dist/browser/index.d.ts.map +0 -1
- package/dist/node/pi/clients.d.ts.map +0 -1
- package/dist/node/pi/clients.js +0 -18
- package/dist/node/pi/clients.js.map +0 -1
- package/dist/node/pi/workflow.d.ts +0 -31
- package/dist/node/pi/workflow.d.ts.map +0 -1
- package/dist/node/pi/workflow.js +0 -242
- package/dist/node/pi/workflow.js.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
package/dist/node/routes.js
CHANGED
|
@@ -1,74 +1,66 @@
|
|
|
1
1
|
import { piSchema } from "./schema.js";
|
|
2
2
|
import { piFragmentDefinition } from "./pi/definition.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { PiLogger } from "./debug-log.js";
|
|
4
|
+
import { normalizeSteeringMode, toSessionOutput } from "./pi/mappers.js";
|
|
5
|
+
import { activeSessionStreamItemSchema, messageAckSchema, sessionBaseSchema, sessionDetailSchema } from "./pi/route-schemas.js";
|
|
6
|
+
import { createInitialPiAgentLoopState, ensurePiActiveSessionState } from "./pi/workflow/active-session.js";
|
|
7
|
+
import { PI_WORKFLOW_NAME } from "./pi/workflow/workflow.js";
|
|
6
8
|
import { defineRoutes } from "@fragno-dev/core";
|
|
9
|
+
import { serviceCalls } from "@fragno-dev/db";
|
|
7
10
|
import { createId } from "@fragno-dev/db/id";
|
|
8
11
|
import { z } from "zod";
|
|
9
12
|
|
|
10
13
|
//#region src/routes.ts
|
|
11
14
|
const DEFAULT_PAGE_SIZE = 50;
|
|
12
15
|
const MAX_PAGE_SIZE = 200;
|
|
13
|
-
const MAX_HISTORY_RUNS = 5;
|
|
14
16
|
const createRouteError = (code, message, status) => {
|
|
15
17
|
const error = new Error(message);
|
|
16
18
|
error.code = code;
|
|
17
19
|
error.status = status;
|
|
18
20
|
return error;
|
|
19
21
|
};
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
if (
|
|
24
|
-
|
|
25
|
-
return
|
|
22
|
+
const parseBooleanQueryValue = (value, defaultValue) => {
|
|
23
|
+
if (value === null) return defaultValue;
|
|
24
|
+
const normalized = value.trim().toLowerCase();
|
|
25
|
+
if (normalized === "1" || normalized === "true" || normalized === "yes") return true;
|
|
26
|
+
if (normalized === "0" || normalized === "false" || normalized === "no") return false;
|
|
27
|
+
return defaultValue;
|
|
26
28
|
};
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
const projectSessionDetailState = (state) => {
|
|
30
|
+
const nextState = state ?? createInitialPiAgentLoopState();
|
|
31
|
+
return {
|
|
32
|
+
messages: nextState.messages,
|
|
33
|
+
events: nextState.events,
|
|
34
|
+
trace: nextState.trace,
|
|
35
|
+
summaries: nextState.summaries,
|
|
36
|
+
turn: nextState.turn,
|
|
37
|
+
phase: nextState.phase,
|
|
38
|
+
waitingFor: nextState.waitingFor
|
|
39
|
+
};
|
|
32
40
|
};
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
41
|
+
const isSessionStreamable = (state) => state.phase !== "complete";
|
|
42
|
+
const ensureLiveSessionActiveState = (state) => {
|
|
43
|
+
if (!isSessionStreamable(state)) return null;
|
|
44
|
+
return ensurePiActiveSessionState(state);
|
|
36
45
|
};
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (!step.result) continue;
|
|
45
|
-
const stepMessages = getArrayFromResult(step.result, "messages");
|
|
46
|
-
if (stepMessages) messages = stepMessages;
|
|
47
|
-
const stepTrace = getArrayFromResult(step.result, "trace");
|
|
48
|
-
if (stepTrace) trace.push(...stepTrace);
|
|
49
|
-
const assistant = getAssistantFromResult(step.result);
|
|
50
|
-
const turn = parseAssistantTurn(step.name);
|
|
51
|
-
if (assistant && turn !== null) {
|
|
52
|
-
lastAssistant = assistant;
|
|
53
|
-
summaries.push({
|
|
54
|
-
turn,
|
|
55
|
-
assistant,
|
|
56
|
-
summary: extractAssistantTextFromMessage(assistant) || null
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
if (messages.length === 0 && isRecord(output) && Array.isArray(output["messages"])) messages = output["messages"];
|
|
61
|
-
if (lastAssistant && !messages.some((message) => message?.role === "assistant")) messages = [...messages, lastAssistant];
|
|
46
|
+
const toActiveSessionProtocolMessage = (update, source) => {
|
|
47
|
+
if (update.type === "settled") return {
|
|
48
|
+
layer: "system",
|
|
49
|
+
type: "settled",
|
|
50
|
+
turn: update.turn,
|
|
51
|
+
status: update.status
|
|
52
|
+
};
|
|
62
53
|
return {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
54
|
+
layer: "pi",
|
|
55
|
+
type: "event",
|
|
56
|
+
turn: update.turn,
|
|
57
|
+
source,
|
|
58
|
+
event: update.event
|
|
66
59
|
};
|
|
67
60
|
};
|
|
68
|
-
const collectHistorySteps = (pages, maxRunNumber) => {
|
|
69
|
-
return pages.filter((page) => page.runNumber <= maxRunNumber).flatMap((page) => page.steps);
|
|
70
|
-
};
|
|
71
61
|
const piRoutesFactory = defineRoutes(piFragmentDefinition).create(({ config, defineRoute, serviceDeps }) => {
|
|
62
|
+
PiLogger.reset();
|
|
63
|
+
if (config.logging) PiLogger.configure(config.logging);
|
|
72
64
|
return [
|
|
73
65
|
defineRoute({
|
|
74
66
|
method: "POST",
|
|
@@ -76,23 +68,16 @@ const piRoutesFactory = defineRoutes(piFragmentDefinition).create(({ config, def
|
|
|
76
68
|
inputSchema: z.object({
|
|
77
69
|
agent: z.string(),
|
|
78
70
|
name: z.string().optional(),
|
|
71
|
+
systemMessage: z.string().optional(),
|
|
79
72
|
metadata: z.any().optional(),
|
|
80
73
|
tags: z.array(z.string()).optional(),
|
|
81
74
|
steeringMode: z.enum(["all", "one-at-a-time"]).optional()
|
|
82
75
|
}),
|
|
83
76
|
outputSchema: sessionBaseSchema,
|
|
84
|
-
errorCodes: [
|
|
85
|
-
"AGENT_NOT_FOUND",
|
|
86
|
-
"WORKFLOWS_REQUIRED",
|
|
87
|
-
"WORKFLOW_CREATE_FAILED"
|
|
88
|
-
],
|
|
77
|
+
errorCodes: ["AGENT_NOT_FOUND", "WORKFLOW_CREATE_FAILED"],
|
|
89
78
|
handler: async function({ input }, { json, error }) {
|
|
90
79
|
const values = await input.valid();
|
|
91
80
|
const workflowsService = serviceDeps.workflows;
|
|
92
|
-
if (!workflowsService) return error({
|
|
93
|
-
message: "Workflows service is required.",
|
|
94
|
-
code: "WORKFLOWS_REQUIRED"
|
|
95
|
-
}, { status: 500 });
|
|
96
81
|
const agentName = values.agent;
|
|
97
82
|
const agent = config.agents?.[agentName];
|
|
98
83
|
if (!agent) return error({
|
|
@@ -103,12 +88,13 @@ const piRoutesFactory = defineRoutes(piFragmentDefinition).create(({ config, def
|
|
|
103
88
|
const steeringMode = normalizeSteeringMode(values.steeringMode ?? config.defaultSteeringMode);
|
|
104
89
|
const sessionId = createId();
|
|
105
90
|
try {
|
|
106
|
-
const
|
|
91
|
+
const systemPrompt = [agent.systemPrompt, values.systemMessage].filter((value) => typeof value === "string" && value.trim() !== "").join("\n\n");
|
|
92
|
+
await this.handlerTx().withServiceCalls(() => [workflowsService.createInstance(PI_WORKFLOW_NAME, {
|
|
107
93
|
id: sessionId,
|
|
108
94
|
params: {
|
|
109
95
|
sessionId,
|
|
110
96
|
agentName,
|
|
111
|
-
systemPrompt
|
|
97
|
+
systemPrompt,
|
|
112
98
|
initialMessages: []
|
|
113
99
|
}
|
|
114
100
|
})]).mutate(({ forSchema }) => {
|
|
@@ -117,22 +103,18 @@ const piRoutesFactory = defineRoutes(piFragmentDefinition).create(({ config, def
|
|
|
117
103
|
name: values.name ?? null,
|
|
118
104
|
agent: agentName,
|
|
119
105
|
status: "active",
|
|
120
|
-
workflowInstanceId: sessionId,
|
|
121
106
|
steeringMode,
|
|
122
107
|
metadata: values.metadata ?? null,
|
|
123
108
|
tags: values.tags ?? null,
|
|
124
109
|
createdAt: now,
|
|
125
110
|
updatedAt: now
|
|
126
111
|
});
|
|
127
|
-
}).
|
|
128
|
-
const workflowInstanceId = created.id;
|
|
129
|
-
const workflowStatus = created.details;
|
|
112
|
+
}).execute();
|
|
130
113
|
return json({
|
|
131
114
|
id: sessionId,
|
|
132
115
|
name: values.name ?? null,
|
|
133
|
-
status:
|
|
116
|
+
status: "active",
|
|
134
117
|
agent: agentName,
|
|
135
|
-
workflowInstanceId,
|
|
136
118
|
steeringMode,
|
|
137
119
|
metadata: values.metadata ?? null,
|
|
138
120
|
tags: values.tags ?? [],
|
|
@@ -164,68 +146,55 @@ const piRoutesFactory = defineRoutes(piFragmentDefinition).create(({ config, def
|
|
|
164
146
|
defineRoute({
|
|
165
147
|
method: "GET",
|
|
166
148
|
path: "/sessions/:sessionId",
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
"
|
|
170
|
-
"
|
|
171
|
-
"WORKFLOW_INSTANCE_MISSING"
|
|
149
|
+
queryParameters: [
|
|
150
|
+
"events",
|
|
151
|
+
"trace",
|
|
152
|
+
"summaries"
|
|
172
153
|
],
|
|
173
|
-
|
|
154
|
+
outputSchema: sessionDetailSchema,
|
|
155
|
+
errorCodes: ["SESSION_NOT_FOUND", "WORKFLOW_INSTANCE_MISSING"],
|
|
156
|
+
handler: async function({ pathParams, query }, { json, error }) {
|
|
174
157
|
const sessionId = pathParams.sessionId;
|
|
158
|
+
const includeEvents = parseBooleanQueryValue(query.get("events"), true);
|
|
159
|
+
const includeTrace = parseBooleanQueryValue(query.get("trace"), true);
|
|
160
|
+
const includeSummaries = parseBooleanQueryValue(query.get("summaries"), true);
|
|
175
161
|
const workflowsService = serviceDeps.workflows;
|
|
176
|
-
if (!workflowsService) return error({
|
|
177
|
-
message: "Workflows service is required.",
|
|
178
|
-
code: "WORKFLOWS_REQUIRED"
|
|
179
|
-
}, { status: 500 });
|
|
180
162
|
const workflowName = PI_WORKFLOW_NAME;
|
|
181
163
|
try {
|
|
182
|
-
const
|
|
164
|
+
const liveSessionSnapshot = workflowsService.getLiveInstanceState(workflowName, sessionId);
|
|
165
|
+
const result = await this.handlerTx().retrieve(({ forSchema }) => {
|
|
183
166
|
return forSchema(piSchema).findFirst("session", (b) => b.whereIndex("primary", (eb) => eb("id", "=", sessionId)));
|
|
184
|
-
}).
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
const historyCalls = Array.from({ length: MAX_HISTORY_RUNS + 1 }, (_, runNumber) => workflowsService.listHistory({
|
|
190
|
-
workflowName,
|
|
191
|
-
instanceId: workflowInstanceId,
|
|
192
|
-
runNumber
|
|
193
|
-
}));
|
|
194
|
-
return [
|
|
195
|
-
workflowsService.getInstanceStatus(workflowName, workflowInstanceId),
|
|
196
|
-
workflowsService.getInstanceRunNumber(workflowName, workflowInstanceId),
|
|
197
|
-
...historyCalls
|
|
198
|
-
];
|
|
199
|
-
}).mutate(({ forSchema, serviceIntermediateResult }) => {
|
|
200
|
-
const [workflowStatus] = serviceIntermediateResult;
|
|
201
|
-
forSchema(piSchema).update("session", sessionRow.id, (b) => b.set({
|
|
202
|
-
status: workflowStatus.status,
|
|
203
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
204
|
-
}).check());
|
|
205
|
-
}).transform(({ serviceResult }) => {
|
|
206
|
-
const [workflowStatus, runNumber, ...historyPages] = serviceResult;
|
|
207
|
-
const maxRunNumber = Number.isFinite(runNumber) ? Math.max(0, Math.min(MAX_HISTORY_RUNS, runNumber)) : 0;
|
|
167
|
+
}).withServiceCalls(() => serviceCalls(workflowsService.getInstanceStatus(workflowName, sessionId), liveSessionSnapshot ? void 0 : workflowsService.restoreInstanceState(workflowName, sessionId))).transform(({ retrieveResult, serviceResult }) => {
|
|
168
|
+
const [sessionRow] = retrieveResult;
|
|
169
|
+
if (!sessionRow) throw createRouteError("SESSION_NOT_FOUND", `Session ${sessionId} not found.`, 404);
|
|
170
|
+
const [workflowStatus, restoredState] = serviceResult;
|
|
171
|
+
const detailState = projectSessionDetailState(liveSessionSnapshot?.state ?? restoredState);
|
|
208
172
|
return {
|
|
173
|
+
session: toSessionOutput(sessionRow),
|
|
209
174
|
workflowStatus,
|
|
210
|
-
|
|
175
|
+
detailState
|
|
211
176
|
};
|
|
212
177
|
}).execute();
|
|
213
178
|
return json({
|
|
214
|
-
...
|
|
179
|
+
...result.session,
|
|
215
180
|
status: result.workflowStatus.status,
|
|
216
181
|
workflow: {
|
|
217
182
|
status: result.workflowStatus.status,
|
|
218
183
|
error: result.workflowStatus.error,
|
|
219
184
|
output: result.workflowStatus.output
|
|
220
185
|
},
|
|
221
|
-
messages: result.
|
|
222
|
-
|
|
223
|
-
|
|
186
|
+
messages: result.detailState.messages,
|
|
187
|
+
events: includeEvents ? result.detailState.events : [],
|
|
188
|
+
trace: includeTrace ? result.detailState.trace : [],
|
|
189
|
+
turn: result.detailState.turn,
|
|
190
|
+
phase: result.detailState.phase,
|
|
191
|
+
waitingFor: result.detailState.waitingFor,
|
|
192
|
+
summaries: includeSummaries ? result.detailState.summaries : []
|
|
224
193
|
});
|
|
225
194
|
} catch (err) {
|
|
226
195
|
if (err && typeof err === "object" && "code" in err && "status" in err) {
|
|
227
196
|
const routeError = err;
|
|
228
|
-
const code =
|
|
197
|
+
const code = routeError.code === "SESSION_NOT_FOUND" ? "SESSION_NOT_FOUND" : "WORKFLOW_INSTANCE_MISSING";
|
|
229
198
|
const status = code === "SESSION_NOT_FOUND" ? 404 : 500;
|
|
230
199
|
return error({
|
|
231
200
|
message: routeError.message,
|
|
@@ -237,7 +206,124 @@ const piRoutesFactory = defineRoutes(piFragmentDefinition).create(({ config, def
|
|
|
237
206
|
code: "SESSION_NOT_FOUND"
|
|
238
207
|
}, { status: 404 });
|
|
239
208
|
return error({
|
|
240
|
-
message: err instanceof Error ? err.message : "Failed to load workflow
|
|
209
|
+
message: err instanceof Error ? err.message : "Failed to load workflow detail.",
|
|
210
|
+
code: "WORKFLOW_INSTANCE_MISSING"
|
|
211
|
+
}, { status: 500 });
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}),
|
|
215
|
+
defineRoute({
|
|
216
|
+
method: "GET",
|
|
217
|
+
path: "/sessions/:sessionId/active",
|
|
218
|
+
outputSchema: z.array(activeSessionStreamItemSchema),
|
|
219
|
+
errorCodes: ["SESSION_NOT_FOUND", "WORKFLOW_INSTANCE_MISSING"],
|
|
220
|
+
handler: async function({ pathParams }, { error, jsonStream }) {
|
|
221
|
+
const sessionId = pathParams.sessionId;
|
|
222
|
+
const workflowsService = serviceDeps.workflows;
|
|
223
|
+
const workflowName = PI_WORKFLOW_NAME;
|
|
224
|
+
try {
|
|
225
|
+
const liveSessionSnapshot = workflowsService.getLiveInstanceState(workflowName, sessionId);
|
|
226
|
+
const [restoredState] = liveSessionSnapshot ? [void 0] : await this.handlerTx().withServiceCalls(() => [workflowsService.restoreInstanceState(workflowName, sessionId)]).transform(({ serviceResult }) => serviceResult).execute();
|
|
227
|
+
const detailState = liveSessionSnapshot?.state ?? restoredState;
|
|
228
|
+
if (!detailState) throw createRouteError("WORKFLOW_INSTANCE_MISSING", `Session ${sessionId} could not load live workflow state.`, 500);
|
|
229
|
+
const activeSession = ensureLiveSessionActiveState(detailState);
|
|
230
|
+
const targetTurn = detailState.turn;
|
|
231
|
+
const replayUpdates = activeSession?.replayTurn(targetTurn) ?? [];
|
|
232
|
+
const snapshotMessage = {
|
|
233
|
+
layer: "system",
|
|
234
|
+
type: "snapshot",
|
|
235
|
+
turn: targetTurn,
|
|
236
|
+
phase: detailState.phase,
|
|
237
|
+
waitingFor: detailState.waitingFor,
|
|
238
|
+
replayCount: replayUpdates.filter((update) => update.type === "event").length
|
|
239
|
+
};
|
|
240
|
+
if (!activeSession) {
|
|
241
|
+
const inactiveMessage = {
|
|
242
|
+
layer: "system",
|
|
243
|
+
type: "inactive",
|
|
244
|
+
reason: detailState.phase === "complete" ? "session-complete" : "session-idle",
|
|
245
|
+
turn: detailState.turn,
|
|
246
|
+
phase: detailState.phase,
|
|
247
|
+
waitingFor: detailState.waitingFor
|
|
248
|
+
};
|
|
249
|
+
return jsonStream(async (stream) => {
|
|
250
|
+
await stream.write(snapshotMessage);
|
|
251
|
+
await stream.write(inactiveMessage);
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
const pendingMessages = replayUpdates.map((update) => toActiveSessionProtocolMessage(update, "replay"));
|
|
255
|
+
if (replayUpdates.some((update) => update.type === "settled")) return jsonStream(async (stream) => {
|
|
256
|
+
await stream.write(snapshotMessage);
|
|
257
|
+
for (const message of pendingMessages) await stream.write(message);
|
|
258
|
+
});
|
|
259
|
+
let cleanupDone = false;
|
|
260
|
+
let streamWriter = null;
|
|
261
|
+
let flushPromise = null;
|
|
262
|
+
let resolveSettled = null;
|
|
263
|
+
const settledPromise = new Promise((resolve) => {
|
|
264
|
+
resolveSettled = resolve;
|
|
265
|
+
});
|
|
266
|
+
const flushPendingMessages = async () => {
|
|
267
|
+
if (streamWriter === null || flushPromise) return flushPromise ?? Promise.resolve();
|
|
268
|
+
flushPromise = (async () => {
|
|
269
|
+
while (pendingMessages.length > 0 && streamWriter) {
|
|
270
|
+
const nextMessage = pendingMessages.shift();
|
|
271
|
+
if (!nextMessage) continue;
|
|
272
|
+
await streamWriter(nextMessage);
|
|
273
|
+
}
|
|
274
|
+
})();
|
|
275
|
+
try {
|
|
276
|
+
await flushPromise;
|
|
277
|
+
} finally {
|
|
278
|
+
flushPromise = null;
|
|
279
|
+
if (pendingMessages.length > 0 && streamWriter !== null) flushPendingMessages();
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
const unsubscribe = activeSession.subscribe((update) => {
|
|
283
|
+
if (update.turn !== targetTurn) return;
|
|
284
|
+
pendingMessages.push(toActiveSessionProtocolMessage(update, "live"));
|
|
285
|
+
if (update.type === "settled") resolveSettled?.();
|
|
286
|
+
if (streamWriter) flushPendingMessages();
|
|
287
|
+
});
|
|
288
|
+
const cleanup = () => {
|
|
289
|
+
if (cleanupDone) return;
|
|
290
|
+
cleanupDone = true;
|
|
291
|
+
unsubscribe();
|
|
292
|
+
streamWriter = null;
|
|
293
|
+
resolveSettled?.();
|
|
294
|
+
};
|
|
295
|
+
return jsonStream(async (stream) => {
|
|
296
|
+
streamWriter = (message) => stream.write(message);
|
|
297
|
+
stream.onAbort(() => {
|
|
298
|
+
cleanup();
|
|
299
|
+
});
|
|
300
|
+
try {
|
|
301
|
+
await stream.write(snapshotMessage);
|
|
302
|
+
await flushPendingMessages();
|
|
303
|
+
await settledPromise;
|
|
304
|
+
await flushPendingMessages();
|
|
305
|
+
} catch (streamError) {
|
|
306
|
+
cleanup();
|
|
307
|
+
throw streamError;
|
|
308
|
+
}
|
|
309
|
+
cleanup();
|
|
310
|
+
});
|
|
311
|
+
} catch (err) {
|
|
312
|
+
if (err && typeof err === "object" && "code" in err && "status" in err) {
|
|
313
|
+
const routeError = err;
|
|
314
|
+
const code = routeError.code === "SESSION_NOT_FOUND" ? "SESSION_NOT_FOUND" : "WORKFLOW_INSTANCE_MISSING";
|
|
315
|
+
const status = code === "SESSION_NOT_FOUND" ? 404 : 500;
|
|
316
|
+
return error({
|
|
317
|
+
message: routeError.message,
|
|
318
|
+
code
|
|
319
|
+
}, { status });
|
|
320
|
+
}
|
|
321
|
+
if (err instanceof Error && err.message === "INSTANCE_NOT_FOUND") return error({
|
|
322
|
+
message: `Session ${sessionId} not found.`,
|
|
323
|
+
code: "SESSION_NOT_FOUND"
|
|
324
|
+
}, { status: 404 });
|
|
325
|
+
return error({
|
|
326
|
+
message: err instanceof Error ? err.message : "Failed to stream the active session.",
|
|
241
327
|
code: "WORKFLOW_INSTANCE_MISSING"
|
|
242
328
|
}, { status: 500 });
|
|
243
329
|
}
|
|
@@ -254,17 +340,13 @@ const piRoutesFactory = defineRoutes(piFragmentDefinition).create(({ config, def
|
|
|
254
340
|
outputSchema: messageAckSchema,
|
|
255
341
|
errorCodes: [
|
|
256
342
|
"SESSION_NOT_FOUND",
|
|
257
|
-
"
|
|
343
|
+
"SESSION_NOT_READY",
|
|
258
344
|
"WORKFLOW_INSTANCE_MISSING"
|
|
259
345
|
],
|
|
260
346
|
handler: async function({ input, pathParams }, { json, error }) {
|
|
261
347
|
const values = await input.valid();
|
|
262
348
|
const sessionId = pathParams.sessionId;
|
|
263
349
|
const workflowsService = serviceDeps.workflows;
|
|
264
|
-
if (!workflowsService) return error({
|
|
265
|
-
message: "Workflows service is required.",
|
|
266
|
-
code: "WORKFLOWS_REQUIRED"
|
|
267
|
-
}, { status: 500 });
|
|
268
350
|
const workflowName = PI_WORKFLOW_NAME;
|
|
269
351
|
const payload = {
|
|
270
352
|
text: values.text,
|
|
@@ -276,34 +358,23 @@ const piRoutesFactory = defineRoutes(piFragmentDefinition).create(({ config, def
|
|
|
276
358
|
return forSchema(piSchema).findFirst("session", (b) => b.whereIndex("primary", (eb) => eb("id", "=", sessionId)));
|
|
277
359
|
}).execute();
|
|
278
360
|
if (!sessionRow) throw createRouteError("SESSION_NOT_FOUND", `Session ${sessionId} not found.`, 404);
|
|
279
|
-
const workflowInstanceId = sessionRow.workflowInstanceId;
|
|
280
|
-
if (!workflowInstanceId) throw createRouteError("SESSION_NOT_FOUND", `Session ${sessionId} not found.`, 404);
|
|
281
361
|
if (!payload.steeringMode) payload.steeringMode = normalizeSteeringMode(sessionRow.steeringMode ?? config.defaultSteeringMode);
|
|
282
|
-
return json({ status: (await this.handlerTx().withServiceCalls(() =>
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
}),
|
|
287
|
-
workflowsService.getInstanceStatus(workflowName, workflowInstanceId),
|
|
288
|
-
workflowsService.getInstanceRunNumber(workflowName, workflowInstanceId)
|
|
289
|
-
]).mutate(({ forSchema, serviceIntermediateResult }) => {
|
|
290
|
-
const [, workflowStatus] = serviceIntermediateResult;
|
|
362
|
+
return json({ status: (await this.handlerTx().withServiceCalls(() => serviceCalls(workflowsService.sendEvent(workflowName, sessionId, {
|
|
363
|
+
type: "user_message",
|
|
364
|
+
payload
|
|
365
|
+
}), workflowsService.getInstanceStatus(workflowName, sessionId))).mutate(({ forSchema }) => {
|
|
291
366
|
const updates = { updatedAt: /* @__PURE__ */ new Date() };
|
|
292
367
|
if (values.steeringMode) updates.steeringMode = values.steeringMode;
|
|
293
|
-
updates.status = workflowStatus.status;
|
|
294
368
|
forSchema(piSchema).update("session", sessionRow.id, (b) => b.set(updates).check());
|
|
295
369
|
}).transform(({ serviceResult }) => {
|
|
296
|
-
const [, workflowStatus
|
|
297
|
-
return {
|
|
298
|
-
workflowStatus,
|
|
299
|
-
runNumber
|
|
300
|
-
};
|
|
370
|
+
const [, workflowStatus] = serviceResult;
|
|
371
|
+
return { workflowStatus };
|
|
301
372
|
}).execute()).workflowStatus.status }, 202);
|
|
302
373
|
} catch (err) {
|
|
303
374
|
if (err && typeof err === "object" && "code" in err && "status" in err) {
|
|
304
375
|
const routeError = err;
|
|
305
|
-
const code =
|
|
306
|
-
const status = code === "SESSION_NOT_FOUND" ? 404 : 500;
|
|
376
|
+
const code = routeError.code === "SESSION_NOT_FOUND" ? "SESSION_NOT_FOUND" : routeError.code === "SESSION_NOT_READY" ? "SESSION_NOT_READY" : "WORKFLOW_INSTANCE_MISSING";
|
|
377
|
+
const status = code === "SESSION_NOT_FOUND" ? 404 : code === "SESSION_NOT_READY" ? 409 : 500;
|
|
307
378
|
return error({
|
|
308
379
|
message: routeError.message,
|
|
309
380
|
code
|
package/dist/node/routes.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.js","names":[],"sources":["../../src/routes.ts"],"sourcesContent":["import { defineRoutes } from \"@fragno-dev/core\";\nimport { createId } from \"@fragno-dev/db/id\";\nimport type { AgentEvent, AgentMessage } from \"@mariozechner/pi-agent-core\";\nimport { z } from \"zod\";\n\nimport { piSchema } from \"./schema\";\nimport { piFragmentDefinition } from \"./pi/definition\";\nimport { messageAckSchema, sessionBaseSchema, sessionDetailSchema } from \"./pi/route-schemas\";\nimport {\n extractAssistantTextFromMessage,\n normalizeSteeringMode,\n toSessionOutput,\n} from \"./pi/mappers\";\nimport { PI_WORKFLOW_NAME } from \"./pi/workflow\";\nimport type {\n PiSession,\n PiTurnSummary,\n PiWorkflowHistoryStep,\n PiWorkflowsHistoryPage,\n PiWorkflowsInstanceStatus,\n} from \"./pi/types\";\n\nconst DEFAULT_PAGE_SIZE = 50;\nconst MAX_PAGE_SIZE = 200;\nconst MAX_HISTORY_RUNS = 5;\n\ntype RouteError = Error & { code: string; status: number };\n\nconst createRouteError = (code: string, message: string, status: number): RouteError => {\n const error = new Error(message) as RouteError;\n error.code = code;\n error.status = status;\n return error;\n};\n\ntype SessionRouteErrorCode =\n | \"SESSION_NOT_FOUND\"\n | \"WORKFLOWS_REQUIRED\"\n | \"WORKFLOW_INSTANCE_MISSING\";\n\nconst isSessionRouteErrorCode = (value: unknown): value is SessionRouteErrorCode =>\n value === \"SESSION_NOT_FOUND\" ||\n value === \"WORKFLOWS_REQUIRED\" ||\n value === \"WORKFLOW_INSTANCE_MISSING\";\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null;\n\nconst getArrayFromResult = <T>(result: unknown, key: string): T[] | null => {\n if (!isRecord(result)) {\n return null;\n }\n const value = result[key];\n return Array.isArray(value) ? (value as T[]) : null;\n};\n\nconst getAssistantFromResult = (result: unknown): AgentMessage | null => {\n if (!isRecord(result)) {\n return null;\n }\n const assistant = result[\"assistant\"];\n if (!assistant || typeof assistant !== \"object\") {\n return null;\n }\n return assistant as AgentMessage;\n};\n\nconst parseAssistantTurn = (name: string): number | null => {\n const match = /^assistant-(\\d+)$/.exec(name);\n return match ? Number.parseInt(match[1], 10) : null;\n};\n\nconst deriveHistory = (steps: PiWorkflowHistoryStep[], output: unknown) => {\n let messages: AgentMessage[] = [];\n const trace: AgentEvent[] = [];\n const summaries: PiTurnSummary[] = [];\n let lastAssistant: AgentMessage | null = null;\n\n const sortedSteps = [...steps].sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());\n\n for (const step of sortedSteps) {\n if (!step.result) {\n continue;\n }\n\n const stepMessages = getArrayFromResult<AgentMessage>(step.result, \"messages\");\n if (stepMessages) {\n messages = stepMessages;\n }\n\n const stepTrace = getArrayFromResult<AgentEvent>(step.result, \"trace\");\n if (stepTrace) {\n trace.push(...stepTrace);\n }\n\n const assistant = getAssistantFromResult(step.result);\n const turn = parseAssistantTurn(step.name);\n if (assistant && turn !== null) {\n lastAssistant = assistant;\n summaries.push({\n turn,\n assistant,\n summary: extractAssistantTextFromMessage(assistant) || null,\n });\n }\n }\n\n if (messages.length === 0 && isRecord(output) && Array.isArray(output[\"messages\"])) {\n messages = output[\"messages\"] as AgentMessage[];\n }\n if (lastAssistant && !messages.some((message) => message?.role === \"assistant\")) {\n messages = [...messages, lastAssistant];\n }\n\n return { messages, trace, summaries };\n};\n\nconst collectHistorySteps = (\n pages: PiWorkflowsHistoryPage[],\n maxRunNumber: number,\n): PiWorkflowHistoryStep[] => {\n return pages.filter((page) => page.runNumber <= maxRunNumber).flatMap((page) => page.steps);\n};\n\nexport const piRoutesFactory = defineRoutes(piFragmentDefinition).create(\n ({ config, defineRoute, serviceDeps }) => {\n return [\n defineRoute({\n method: \"POST\",\n path: \"/sessions\",\n inputSchema: z.object({\n agent: z.string(),\n name: z.string().optional(),\n metadata: z.any().optional(),\n tags: z.array(z.string()).optional(),\n steeringMode: z.enum([\"all\", \"one-at-a-time\"]).optional(),\n }),\n outputSchema: sessionBaseSchema,\n errorCodes: [\"AGENT_NOT_FOUND\", \"WORKFLOWS_REQUIRED\", \"WORKFLOW_CREATE_FAILED\"],\n handler: async function ({ input }, { json, error }) {\n const values = await input.valid();\n\n const workflowsService = serviceDeps.workflows;\n if (!workflowsService) {\n return error(\n { message: \"Workflows service is required.\", code: \"WORKFLOWS_REQUIRED\" },\n { status: 500 },\n );\n }\n\n const agentName = values.agent;\n const agent = config.agents?.[agentName];\n if (!agent) {\n return error(\n { message: `Agent ${agentName} not found.`, code: \"AGENT_NOT_FOUND\" },\n { status: 404 },\n );\n }\n\n const now = new Date();\n const steeringMode = normalizeSteeringMode(\n values.steeringMode ?? config.defaultSteeringMode,\n );\n const sessionId = createId();\n\n try {\n const created = await this.handlerTx()\n .withServiceCalls(\n () =>\n [\n workflowsService.createInstance(PI_WORKFLOW_NAME, {\n id: sessionId,\n params: {\n sessionId,\n agentName,\n systemPrompt: agent.systemPrompt,\n initialMessages: [],\n },\n }),\n ] as const,\n )\n .mutate(({ forSchema }) => {\n const uow = forSchema(piSchema);\n uow.create(\"session\", {\n id: sessionId,\n name: values.name ?? null,\n agent: agentName,\n status: \"active\",\n workflowInstanceId: sessionId,\n steeringMode,\n metadata: values.metadata ?? null,\n tags: values.tags ?? null,\n createdAt: now,\n updatedAt: now,\n });\n })\n .transform(({ serviceResult }) => serviceResult[0])\n .execute();\n\n const workflowInstanceId = created.id;\n const workflowStatus = created.details;\n\n const session: PiSession = {\n id: sessionId,\n name: values.name ?? null,\n status: workflowStatus.status,\n agent: agentName,\n workflowInstanceId,\n steeringMode,\n metadata: values.metadata ?? null,\n tags: values.tags ?? [],\n createdAt: now,\n updatedAt: now,\n };\n\n return json(session);\n } catch (err) {\n // TODO: cleanup workflow/session if createInstance or session persist fails.\n const message =\n err instanceof Error ? err.message : \"Failed to create workflow instance.\";\n return error({ message, code: \"WORKFLOW_CREATE_FAILED\" }, { status: 500 });\n }\n },\n }),\n defineRoute({\n method: \"GET\",\n path: \"/sessions\",\n queryParameters: [\"limit\"],\n outputSchema: z.array(sessionBaseSchema),\n handler: async function ({ query }, { json }) {\n const limit = Number.parseInt(query.get(\"limit\") ?? `${DEFAULT_PAGE_SIZE}`, 10);\n const normalizedLimit = Number.isFinite(limit)\n ? Math.max(1, Math.min(MAX_PAGE_SIZE, limit))\n : DEFAULT_PAGE_SIZE;\n\n const [sessions] = await this.handlerTx()\n .retrieve(({ forSchema }) => {\n const uow = forSchema(piSchema);\n return uow.find(\"session\", (b) =>\n b\n .whereIndex(\"idx_session_created\")\n .orderByIndex(\"idx_session_created\", \"desc\")\n .pageSize(normalizedLimit),\n );\n })\n .execute();\n\n // TODO: hydrate workflow status without additional handlerTx calls.\n const outputs = sessions.map(toSessionOutput);\n return json(outputs);\n },\n }),\n defineRoute({\n method: \"GET\",\n path: \"/sessions/:sessionId\",\n outputSchema: sessionDetailSchema,\n errorCodes: [\"SESSION_NOT_FOUND\", \"WORKFLOWS_REQUIRED\", \"WORKFLOW_INSTANCE_MISSING\"],\n handler: async function ({ pathParams }, { json, error }) {\n const sessionId = pathParams.sessionId;\n\n const workflowsService = serviceDeps.workflows;\n if (!workflowsService) {\n return error(\n { message: \"Workflows service is required.\", code: \"WORKFLOWS_REQUIRED\" },\n { status: 500 },\n );\n }\n\n const workflowName = PI_WORKFLOW_NAME;\n\n try {\n const [sessionRow] = await this.handlerTx()\n .retrieve(({ forSchema }) => {\n const uow = forSchema(piSchema);\n return uow.findFirst(\"session\", (b) =>\n b.whereIndex(\"primary\", (eb) => eb(\"id\", \"=\", sessionId)),\n );\n })\n .execute();\n\n if (!sessionRow) {\n throw createRouteError(\"SESSION_NOT_FOUND\", `Session ${sessionId} not found.`, 404);\n }\n\n const workflowInstanceId = sessionRow.workflowInstanceId;\n if (!workflowInstanceId) {\n throw createRouteError(\"SESSION_NOT_FOUND\", `Session ${sessionId} not found.`, 404);\n }\n\n const result = await this.handlerTx()\n .withServiceCalls(() => {\n const historyCalls = Array.from({ length: MAX_HISTORY_RUNS + 1 }, (_, runNumber) =>\n workflowsService.listHistory({\n workflowName,\n instanceId: workflowInstanceId,\n runNumber,\n }),\n );\n return [\n workflowsService.getInstanceStatus(workflowName, workflowInstanceId),\n workflowsService.getInstanceRunNumber(workflowName, workflowInstanceId),\n ...historyCalls,\n ];\n })\n .mutate(({ forSchema, serviceIntermediateResult }) => {\n const [workflowStatus] = serviceIntermediateResult as [\n PiWorkflowsInstanceStatus,\n number,\n ...PiWorkflowsHistoryPage[],\n ];\n const uow = forSchema(piSchema);\n uow.update(\"session\", sessionRow.id, (b) =>\n b\n .set({\n status: workflowStatus.status,\n updatedAt: new Date(),\n })\n .check(),\n );\n })\n .transform(({ serviceResult }) => {\n const [workflowStatus, runNumber, ...historyPages] = serviceResult as [\n PiWorkflowsInstanceStatus,\n number,\n ...PiWorkflowsHistoryPage[],\n ];\n\n const maxRunNumber = Number.isFinite(runNumber)\n ? Math.max(0, Math.min(MAX_HISTORY_RUNS, runNumber))\n : 0;\n const pages = historyPages.slice(0, maxRunNumber + 1);\n const steps = collectHistorySteps(pages, maxRunNumber);\n const history = deriveHistory(steps, workflowStatus.output);\n\n return { workflowStatus, history };\n })\n .execute();\n\n const session = toSessionOutput(sessionRow);\n\n return json({\n ...session,\n status: result.workflowStatus.status,\n workflow: {\n status: result.workflowStatus.status,\n error: result.workflowStatus.error,\n output: result.workflowStatus.output,\n },\n messages: result.history.messages,\n trace: result.history.trace,\n summaries: result.history.summaries,\n });\n } catch (err) {\n if (err && typeof err === \"object\" && \"code\" in err && \"status\" in err) {\n const routeError = err as RouteError;\n const code = isSessionRouteErrorCode(routeError.code)\n ? routeError.code\n : \"WORKFLOW_INSTANCE_MISSING\";\n const status = code === \"SESSION_NOT_FOUND\" ? 404 : 500;\n return error({ message: routeError.message, code }, { status });\n }\n if (err instanceof Error && err.message === \"INSTANCE_NOT_FOUND\") {\n return error(\n { message: `Session ${sessionId} not found.`, code: \"SESSION_NOT_FOUND\" },\n { status: 404 },\n );\n }\n const message = err instanceof Error ? err.message : \"Failed to load workflow history.\";\n return error({ message, code: \"WORKFLOW_INSTANCE_MISSING\" }, { status: 500 });\n }\n },\n }),\n defineRoute({\n method: \"POST\",\n path: \"/sessions/:sessionId/messages\",\n inputSchema: z.object({\n text: z.string(),\n done: z.boolean().optional(),\n steeringMode: z.enum([\"all\", \"one-at-a-time\"]).optional(),\n }),\n outputSchema: messageAckSchema,\n errorCodes: [\"SESSION_NOT_FOUND\", \"WORKFLOWS_REQUIRED\", \"WORKFLOW_INSTANCE_MISSING\"],\n handler: async function ({ input, pathParams }, { json, error }) {\n const values = await input.valid();\n const sessionId = pathParams.sessionId;\n\n const workflowsService = serviceDeps.workflows;\n if (!workflowsService) {\n return error(\n { message: \"Workflows service is required.\", code: \"WORKFLOWS_REQUIRED\" },\n { status: 500 },\n );\n }\n\n const workflowName = PI_WORKFLOW_NAME;\n const payload: {\n text: string;\n done?: boolean;\n steeringMode?: \"all\" | \"one-at-a-time\";\n } = {\n text: values.text,\n done: values.done,\n };\n if (values.steeringMode) {\n payload.steeringMode = values.steeringMode;\n }\n\n try {\n const [sessionRow] = await this.handlerTx()\n .retrieve(({ forSchema }) => {\n const uow = forSchema(piSchema);\n return uow.findFirst(\"session\", (b) =>\n b.whereIndex(\"primary\", (eb) => eb(\"id\", \"=\", sessionId)),\n );\n })\n .execute();\n\n if (!sessionRow) {\n throw createRouteError(\"SESSION_NOT_FOUND\", `Session ${sessionId} not found.`, 404);\n }\n\n const workflowInstanceId = sessionRow.workflowInstanceId;\n if (!workflowInstanceId) {\n throw createRouteError(\"SESSION_NOT_FOUND\", `Session ${sessionId} not found.`, 404);\n }\n\n if (!payload.steeringMode) {\n // Ensure workflow events use the session's steering mode when not overridden.\n payload.steeringMode = normalizeSteeringMode(\n sessionRow.steeringMode ?? config.defaultSteeringMode,\n );\n }\n\n const result = await this.handlerTx()\n .withServiceCalls(() => [\n workflowsService.sendEvent(workflowName, workflowInstanceId, {\n type: \"user_message\",\n payload,\n }),\n workflowsService.getInstanceStatus(workflowName, workflowInstanceId),\n workflowsService.getInstanceRunNumber(workflowName, workflowInstanceId),\n ])\n .mutate(({ forSchema, serviceIntermediateResult }) => {\n const [, workflowStatus] = serviceIntermediateResult as [\n unknown,\n PiWorkflowsInstanceStatus,\n number,\n ];\n const updates: {\n updatedAt: Date;\n steeringMode?: \"all\" | \"one-at-a-time\";\n status?: string;\n } = {\n updatedAt: new Date(),\n };\n if (values.steeringMode) {\n updates.steeringMode = values.steeringMode;\n }\n updates.status = workflowStatus.status;\n const uow = forSchema(piSchema);\n uow.update(\"session\", sessionRow.id, (b) => b.set(updates).check());\n })\n .transform(({ serviceResult }) => {\n const [, workflowStatus, runNumber] = serviceResult as [\n unknown,\n PiWorkflowsInstanceStatus,\n number,\n ];\n return { workflowStatus, runNumber };\n })\n .execute();\n\n return json(\n {\n status: result.workflowStatus.status,\n },\n 202,\n );\n } catch (err) {\n if (err && typeof err === \"object\" && \"code\" in err && \"status\" in err) {\n const routeError = err as RouteError;\n const code = isSessionRouteErrorCode(routeError.code)\n ? routeError.code\n : \"WORKFLOW_INSTANCE_MISSING\";\n const status = code === \"SESSION_NOT_FOUND\" ? 404 : 500;\n return error({ message: routeError.message, code }, { status });\n }\n if (err instanceof Error && err.message === \"INSTANCE_NOT_FOUND\") {\n return error(\n { message: `Session ${sessionId} not found.`, code: \"SESSION_NOT_FOUND\" },\n { status: 404 },\n );\n }\n const message = err instanceof Error ? err.message : \"Failed to deliver message.\";\n return error({ message, code: \"WORKFLOW_INSTANCE_MISSING\" }, { status: 500 });\n }\n },\n }),\n ];\n },\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"routes.js","names":[],"sources":["../../src/routes.ts"],"sourcesContent":["import { createId } from \"@fragno-dev/db/id\";\nimport { z } from \"zod\";\n\nimport { defineRoutes } from \"@fragno-dev/core\";\nimport { serviceCalls } from \"@fragno-dev/db\";\n\nimport { PiLogger } from \"./debug-log\";\nimport { piFragmentDefinition } from \"./pi/definition\";\nimport { normalizeSteeringMode, toSessionOutput } from \"./pi/mappers\";\nimport {\n activeSessionStreamItemSchema,\n messageAckSchema,\n sessionBaseSchema,\n sessionDetailSchema,\n} from \"./pi/route-schemas\";\nimport type {\n PiActiveSessionProtocolMessage,\n PiActiveSessionUpdate,\n PiAgentLoopState,\n PiAgentLoopSerializableState,\n PiSession,\n} from \"./pi/types\";\nimport {\n createInitialPiAgentLoopState,\n ensurePiActiveSessionState,\n PI_WORKFLOW_NAME,\n} from \"./pi/workflow/workflow\";\nimport { piSchema } from \"./schema\";\n\nconst DEFAULT_PAGE_SIZE = 50;\nconst MAX_PAGE_SIZE = 200;\n\ntype RouteError = Error & { code: string; status: number };\n\nconst createRouteError = (code: string, message: string, status: number): RouteError => {\n const error = new Error(message) as RouteError;\n error.code = code;\n error.status = status;\n return error;\n};\n\nconst parseBooleanQueryValue = (value: string | null, defaultValue: boolean): boolean => {\n if (value === null) {\n return defaultValue;\n }\n const normalized = value.trim().toLowerCase();\n if (normalized === \"1\" || normalized === \"true\" || normalized === \"yes\") {\n return true;\n }\n if (normalized === \"0\" || normalized === \"false\" || normalized === \"no\") {\n return false;\n }\n return defaultValue;\n};\n\nconst projectSessionDetailState = (\n state: PiAgentLoopState | null | undefined,\n): PiAgentLoopSerializableState => {\n const nextState = state ?? createInitialPiAgentLoopState();\n\n return {\n messages: nextState.messages,\n events: nextState.events,\n trace: nextState.trace,\n summaries: nextState.summaries,\n turn: nextState.turn,\n phase: nextState.phase,\n waitingFor: nextState.waitingFor,\n };\n};\n\nconst isSessionStreamable = (state: PiAgentLoopState) => state.phase !== \"complete\";\n\nconst ensureLiveSessionActiveState = (state: PiAgentLoopState) => {\n if (!isSessionStreamable(state)) {\n return null;\n }\n return ensurePiActiveSessionState(state);\n};\n\nconst toActiveSessionProtocolMessage = (\n update: PiActiveSessionUpdate,\n source: \"replay\" | \"live\",\n): PiActiveSessionProtocolMessage => {\n if (update.type === \"settled\") {\n return {\n layer: \"system\",\n type: \"settled\",\n turn: update.turn,\n status: update.status,\n };\n }\n\n return {\n layer: \"pi\",\n type: \"event\",\n turn: update.turn,\n source,\n event: update.event,\n };\n};\n\nexport const piRoutesFactory = defineRoutes(piFragmentDefinition).create(\n ({ config, defineRoute, serviceDeps }) => {\n PiLogger.reset();\n if (config.logging) {\n PiLogger.configure(config.logging);\n }\n\n return [\n defineRoute({\n method: \"POST\",\n path: \"/sessions\",\n inputSchema: z.object({\n agent: z.string(),\n name: z.string().optional(),\n systemMessage: z.string().optional(),\n metadata: z.any().optional(),\n tags: z.array(z.string()).optional(),\n steeringMode: z.enum([\"all\", \"one-at-a-time\"]).optional(),\n }),\n outputSchema: sessionBaseSchema,\n errorCodes: [\"AGENT_NOT_FOUND\", \"WORKFLOW_CREATE_FAILED\"],\n handler: async function ({ input }, { json, error }) {\n const values = await input.valid();\n\n const workflowsService = serviceDeps.workflows;\n\n const agentName = values.agent;\n const agent = config.agents?.[agentName];\n if (!agent) {\n return error(\n { message: `Agent ${agentName} not found.`, code: \"AGENT_NOT_FOUND\" },\n { status: 404 },\n );\n }\n\n const now = new Date();\n const steeringMode = normalizeSteeringMode(\n values.steeringMode ?? config.defaultSteeringMode,\n );\n const sessionId = createId();\n\n try {\n const systemPrompt = [agent.systemPrompt, values.systemMessage]\n .filter((value): value is string => typeof value === \"string\" && value.trim() !== \"\")\n .join(\"\\n\\n\");\n\n await this.handlerTx()\n .withServiceCalls(\n () =>\n [\n workflowsService.createInstance(PI_WORKFLOW_NAME, {\n id: sessionId,\n params: {\n sessionId,\n agentName,\n systemPrompt,\n initialMessages: [],\n },\n }),\n ] as const,\n )\n .mutate(({ forSchema }) => {\n const uow = forSchema(piSchema);\n uow.create(\"session\", {\n id: sessionId,\n name: values.name ?? null,\n agent: agentName,\n status: \"active\",\n steeringMode,\n metadata: values.metadata ?? null,\n tags: values.tags ?? null,\n createdAt: now,\n updatedAt: now,\n });\n })\n .execute();\n\n const session: PiSession = {\n id: sessionId,\n name: values.name ?? null,\n status: \"active\",\n agent: agentName,\n steeringMode,\n metadata: values.metadata ?? null,\n tags: values.tags ?? [],\n createdAt: now,\n updatedAt: now,\n };\n\n return json(session);\n } catch (err) {\n // TODO: cleanup workflow/session if createInstance or session persist fails.\n const message =\n err instanceof Error ? err.message : \"Failed to create workflow instance.\";\n return error({ message, code: \"WORKFLOW_CREATE_FAILED\" }, { status: 500 });\n }\n },\n }),\n defineRoute({\n method: \"GET\",\n path: \"/sessions\",\n queryParameters: [\"limit\"],\n outputSchema: z.array(sessionBaseSchema),\n handler: async function ({ query }, { json }) {\n const limit = Number.parseInt(query.get(\"limit\") ?? `${DEFAULT_PAGE_SIZE}`, 10);\n const normalizedLimit = Number.isFinite(limit)\n ? Math.max(1, Math.min(MAX_PAGE_SIZE, limit))\n : DEFAULT_PAGE_SIZE;\n\n const [sessions] = await this.handlerTx()\n .retrieve(({ forSchema }) => {\n const uow = forSchema(piSchema);\n return uow.find(\"session\", (b) =>\n b\n .whereIndex(\"idx_session_created\")\n .orderByIndex(\"idx_session_created\", \"desc\")\n .pageSize(normalizedLimit),\n );\n })\n .execute();\n\n const outputs = sessions.map(toSessionOutput);\n return json(outputs);\n },\n }),\n defineRoute({\n method: \"GET\",\n path: \"/sessions/:sessionId\",\n queryParameters: [\"events\", \"trace\", \"summaries\"],\n outputSchema: sessionDetailSchema,\n errorCodes: [\"SESSION_NOT_FOUND\", \"WORKFLOW_INSTANCE_MISSING\"],\n handler: async function ({ pathParams, query }, { json, error }) {\n const sessionId = pathParams.sessionId;\n const includeEvents = parseBooleanQueryValue(query.get(\"events\"), true);\n const includeTrace = parseBooleanQueryValue(query.get(\"trace\"), true);\n const includeSummaries = parseBooleanQueryValue(query.get(\"summaries\"), true);\n\n const workflowsService = serviceDeps.workflows;\n\n const workflowName = PI_WORKFLOW_NAME;\n\n try {\n const liveSessionSnapshot = workflowsService.getLiveInstanceState(\n workflowName,\n sessionId,\n );\n\n const result = await this.handlerTx()\n .retrieve(({ forSchema }) => {\n const uow = forSchema(piSchema);\n return uow.findFirst(\"session\", (b) =>\n b.whereIndex(\"primary\", (eb) => eb(\"id\", \"=\", sessionId)),\n );\n })\n .withServiceCalls(() =>\n serviceCalls(\n workflowsService.getInstanceStatus(workflowName, sessionId),\n liveSessionSnapshot\n ? undefined\n : workflowsService.restoreInstanceState(workflowName, sessionId),\n ),\n )\n .transform(({ retrieveResult, serviceResult }) => {\n const [sessionRow] = retrieveResult;\n if (!sessionRow) {\n throw createRouteError(\n \"SESSION_NOT_FOUND\",\n `Session ${sessionId} not found.`,\n 404,\n );\n }\n\n const [workflowStatus, restoredState] = serviceResult;\n const detailState = projectSessionDetailState(\n liveSessionSnapshot?.state ?? restoredState,\n );\n\n return {\n session: toSessionOutput(sessionRow),\n workflowStatus,\n detailState,\n };\n })\n .execute();\n\n return json({\n ...result.session,\n status: result.workflowStatus.status,\n workflow: {\n status: result.workflowStatus.status,\n error: result.workflowStatus.error,\n output: result.workflowStatus.output,\n },\n messages: result.detailState.messages,\n events: includeEvents ? result.detailState.events : [],\n trace: includeTrace ? result.detailState.trace : [],\n turn: result.detailState.turn,\n phase: result.detailState.phase,\n waitingFor: result.detailState.waitingFor,\n summaries: includeSummaries ? result.detailState.summaries : [],\n });\n } catch (err) {\n if (err && typeof err === \"object\" && \"code\" in err && \"status\" in err) {\n const routeError = err as RouteError;\n const code =\n routeError.code === \"SESSION_NOT_FOUND\"\n ? \"SESSION_NOT_FOUND\"\n : \"WORKFLOW_INSTANCE_MISSING\";\n const status = code === \"SESSION_NOT_FOUND\" ? 404 : 500;\n return error({ message: routeError.message, code }, { status });\n }\n if (err instanceof Error && err.message === \"INSTANCE_NOT_FOUND\") {\n return error(\n { message: `Session ${sessionId} not found.`, code: \"SESSION_NOT_FOUND\" },\n { status: 404 },\n );\n }\n const message = err instanceof Error ? err.message : \"Failed to load workflow detail.\";\n return error({ message, code: \"WORKFLOW_INSTANCE_MISSING\" }, { status: 500 });\n }\n },\n }),\n defineRoute({\n method: \"GET\",\n path: \"/sessions/:sessionId/active\",\n outputSchema: z.array(activeSessionStreamItemSchema),\n errorCodes: [\"SESSION_NOT_FOUND\", \"WORKFLOW_INSTANCE_MISSING\"],\n handler: async function ({ pathParams }, { error, jsonStream }) {\n const sessionId = pathParams.sessionId;\n\n const workflowsService = serviceDeps.workflows;\n\n const workflowName = PI_WORKFLOW_NAME;\n\n try {\n const liveSessionSnapshot = workflowsService.getLiveInstanceState(\n workflowName,\n sessionId,\n );\n const [restoredState] = liveSessionSnapshot\n ? [undefined]\n : await this.handlerTx()\n .withServiceCalls(() => [\n workflowsService.restoreInstanceState(workflowName, sessionId),\n ])\n .transform(({ serviceResult }) => serviceResult)\n .execute();\n\n const detailState = liveSessionSnapshot?.state ?? restoredState;\n if (!detailState) {\n throw createRouteError(\n \"WORKFLOW_INSTANCE_MISSING\",\n `Session ${sessionId} could not load live workflow state.`,\n 500,\n );\n }\n\n const activeSession = ensureLiveSessionActiveState(detailState);\n const targetTurn = detailState.turn;\n const replayUpdates = activeSession?.replayTurn(targetTurn) ?? [];\n const snapshotMessage: PiActiveSessionProtocolMessage = {\n layer: \"system\",\n type: \"snapshot\",\n turn: targetTurn,\n phase: detailState.phase,\n waitingFor: detailState.waitingFor,\n replayCount: replayUpdates.filter((update) => update.type === \"event\").length,\n };\n\n if (!activeSession) {\n const inactiveMessage: PiActiveSessionProtocolMessage = {\n layer: \"system\",\n type: \"inactive\",\n reason: detailState.phase === \"complete\" ? \"session-complete\" : \"session-idle\",\n turn: detailState.turn,\n phase: detailState.phase,\n waitingFor: detailState.waitingFor,\n };\n\n return jsonStream(async (stream) => {\n await stream.write(snapshotMessage);\n await stream.write(inactiveMessage);\n });\n }\n\n const pendingMessages = replayUpdates.map((update) =>\n toActiveSessionProtocolMessage(update, \"replay\"),\n );\n const replayAlreadySettled = replayUpdates.some((update) => update.type === \"settled\");\n\n if (replayAlreadySettled) {\n return jsonStream(async (stream) => {\n await stream.write(snapshotMessage);\n for (const message of pendingMessages) {\n await stream.write(message);\n }\n });\n }\n\n let cleanupDone = false;\n let streamWriter: ((message: PiActiveSessionProtocolMessage) => Promise<void>) | null =\n null;\n let flushPromise: Promise<void> | null = null;\n let resolveSettled: (() => void) | null = null;\n const settledPromise = new Promise<void>((resolve) => {\n resolveSettled = resolve;\n });\n\n const flushPendingMessages = async () => {\n if (streamWriter === null || flushPromise) {\n return flushPromise ?? Promise.resolve();\n }\n\n flushPromise = (async () => {\n while (pendingMessages.length > 0 && streamWriter) {\n const nextMessage = pendingMessages.shift();\n if (!nextMessage) {\n continue;\n }\n await streamWriter(nextMessage);\n }\n })();\n\n try {\n await flushPromise;\n } finally {\n flushPromise = null;\n if (pendingMessages.length > 0 && streamWriter !== null) {\n void flushPendingMessages();\n }\n }\n };\n\n const unsubscribe = activeSession.subscribe((update: PiActiveSessionUpdate) => {\n if (update.turn !== targetTurn) {\n return;\n }\n\n pendingMessages.push(toActiveSessionProtocolMessage(update, \"live\"));\n if (update.type === \"settled\") {\n resolveSettled?.();\n }\n if (streamWriter) {\n void flushPendingMessages();\n }\n });\n\n const cleanup = () => {\n if (cleanupDone) {\n return;\n }\n cleanupDone = true;\n unsubscribe();\n streamWriter = null;\n resolveSettled?.();\n };\n\n return jsonStream(async (stream) => {\n streamWriter = (message) => stream.write(message);\n stream.onAbort(() => {\n cleanup();\n });\n\n try {\n await stream.write(snapshotMessage);\n await flushPendingMessages();\n await settledPromise;\n await flushPendingMessages();\n } catch (streamError) {\n cleanup();\n throw streamError;\n }\n cleanup();\n });\n } catch (err) {\n if (err && typeof err === \"object\" && \"code\" in err && \"status\" in err) {\n const routeError = err as RouteError;\n const code =\n routeError.code === \"SESSION_NOT_FOUND\"\n ? \"SESSION_NOT_FOUND\"\n : \"WORKFLOW_INSTANCE_MISSING\";\n const status = code === \"SESSION_NOT_FOUND\" ? 404 : 500;\n return error({ message: routeError.message, code }, { status });\n }\n if (err instanceof Error && err.message === \"INSTANCE_NOT_FOUND\") {\n return error(\n { message: `Session ${sessionId} not found.`, code: \"SESSION_NOT_FOUND\" },\n { status: 404 },\n );\n }\n const message =\n err instanceof Error ? err.message : \"Failed to stream the active session.\";\n return error({ message, code: \"WORKFLOW_INSTANCE_MISSING\" }, { status: 500 });\n }\n },\n }),\n defineRoute({\n method: \"POST\",\n path: \"/sessions/:sessionId/messages\",\n inputSchema: z.object({\n text: z.string(),\n done: z.boolean().optional(),\n steeringMode: z.enum([\"all\", \"one-at-a-time\"]).optional(),\n }),\n outputSchema: messageAckSchema,\n errorCodes: [\"SESSION_NOT_FOUND\", \"SESSION_NOT_READY\", \"WORKFLOW_INSTANCE_MISSING\"],\n handler: async function ({ input, pathParams }, { json, error }) {\n const values = await input.valid();\n const sessionId = pathParams.sessionId;\n\n const workflowsService = serviceDeps.workflows;\n\n const workflowName = PI_WORKFLOW_NAME;\n const payload: {\n text: string;\n done?: boolean;\n steeringMode?: \"all\" | \"one-at-a-time\";\n } = {\n text: values.text,\n done: values.done,\n };\n if (values.steeringMode) {\n payload.steeringMode = values.steeringMode;\n }\n\n try {\n const [sessionRow] = await this.handlerTx()\n .retrieve(({ forSchema }) => {\n const uow = forSchema(piSchema);\n return uow.findFirst(\"session\", (b) =>\n b.whereIndex(\"primary\", (eb) => eb(\"id\", \"=\", sessionId)),\n );\n })\n .execute();\n\n if (!sessionRow) {\n throw createRouteError(\"SESSION_NOT_FOUND\", `Session ${sessionId} not found.`, 404);\n }\n\n if (!payload.steeringMode) {\n // This route still needs the persisted session row before sending the event so the\n // workflow receives the session's effective steering mode when the caller omits it.\n payload.steeringMode = normalizeSteeringMode(\n sessionRow.steeringMode ?? config.defaultSteeringMode,\n );\n }\n\n const result = await this.handlerTx()\n .withServiceCalls(() =>\n serviceCalls(\n workflowsService.sendEvent(workflowName, sessionId, {\n type: \"user_message\",\n payload,\n }),\n workflowsService.getInstanceStatus(workflowName, sessionId),\n ),\n )\n .mutate(({ forSchema }) => {\n const updates: {\n updatedAt: Date;\n steeringMode?: \"all\" | \"one-at-a-time\";\n } = {\n updatedAt: new Date(),\n };\n if (values.steeringMode) {\n updates.steeringMode = values.steeringMode;\n }\n const uow = forSchema(piSchema);\n uow.update(\"session\", sessionRow.id, (b) => b.set(updates).check());\n })\n .transform(({ serviceResult }) => {\n const [, workflowStatus] = serviceResult;\n return { workflowStatus };\n })\n .execute();\n\n return json(\n {\n status: result.workflowStatus.status,\n },\n 202,\n );\n } catch (err) {\n if (err && typeof err === \"object\" && \"code\" in err && \"status\" in err) {\n const routeError = err as RouteError;\n const code =\n routeError.code === \"SESSION_NOT_FOUND\"\n ? \"SESSION_NOT_FOUND\"\n : routeError.code === \"SESSION_NOT_READY\"\n ? \"SESSION_NOT_READY\"\n : \"WORKFLOW_INSTANCE_MISSING\";\n const status =\n code === \"SESSION_NOT_FOUND\" ? 404 : code === \"SESSION_NOT_READY\" ? 409 : 500;\n return error({ message: routeError.message, code }, { status });\n }\n if (err instanceof Error && err.message === \"INSTANCE_NOT_FOUND\") {\n return error(\n { message: `Session ${sessionId} not found.`, code: \"SESSION_NOT_FOUND\" },\n { status: 404 },\n );\n }\n const message = err instanceof Error ? err.message : \"Failed to deliver message.\";\n return error({ message, code: \"WORKFLOW_INSTANCE_MISSING\" }, { status: 500 });\n }\n },\n }),\n ];\n },\n);\n"],"mappings":"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"}
|
package/dist/node/schema.js
CHANGED
|
@@ -3,7 +3,7 @@ import { column, idColumn, schema } from "@fragno-dev/db/schema";
|
|
|
3
3
|
//#region src/schema.ts
|
|
4
4
|
const piSchema = schema("pi-fragment", (s) => {
|
|
5
5
|
return s.addTable("session", (t) => {
|
|
6
|
-
return t.addColumn("id", idColumn()).addColumn("name", column("string").nullable()).addColumn("agent", column("string")).addColumn("status", column("string")).addColumn("
|
|
6
|
+
return t.addColumn("id", idColumn()).addColumn("name", column("string").nullable()).addColumn("agent", column("string")).addColumn("status", column("string")).addColumn("steeringMode", column("string")).addColumn("metadata", column("json").nullable()).addColumn("tags", column("json").nullable()).addColumn("createdAt", column("timestamp").defaultTo((b) => b.now())).addColumn("updatedAt", column("timestamp").defaultTo((b) => b.now())).createIndex("idx_session_status", ["status"]).createIndex("idx_session_created", ["createdAt"]);
|
|
7
7
|
});
|
|
8
8
|
});
|
|
9
9
|
|
package/dist/node/schema.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","names":[],"sources":["../../src/schema.ts"],"sourcesContent":["import { column, idColumn, schema } from \"@fragno-dev/db/schema\";\n\nexport const piSchema = schema(\"pi-fragment\", (s) => {\n return s.addTable(\"session\", (t) => {\n return (\n t\n .addColumn(\"id\", idColumn())\n .addColumn(\"name\", column(\"string\").nullable())\n .addColumn(\"agent\", column(\"string\"))\n // Possible statuses: active, paused, errored, terminated, complete, waiting.\n .addColumn(\"status\", column(\"string\"))\n .addColumn(\"
|
|
1
|
+
{"version":3,"file":"schema.js","names":[],"sources":["../../src/schema.ts"],"sourcesContent":["import { column, idColumn, schema } from \"@fragno-dev/db/schema\";\n\nexport const piSchema = schema(\"pi-fragment\", (s) => {\n return s.addTable(\"session\", (t) => {\n return (\n t\n // id is equal to the workflow's workflowInstanceId\n .addColumn(\"id\", idColumn())\n .addColumn(\"name\", column(\"string\").nullable())\n .addColumn(\"agent\", column(\"string\"))\n // Possible statuses: active, paused, errored, terminated, complete, waiting.\n .addColumn(\"status\", column(\"string\"))\n .addColumn(\"steeringMode\", column(\"string\"))\n .addColumn(\"metadata\", column(\"json\").nullable())\n .addColumn(\"tags\", column(\"json\").nullable())\n .addColumn(\n \"createdAt\",\n column(\"timestamp\").defaultTo((b) => b.now()),\n )\n .addColumn(\n \"updatedAt\",\n column(\"timestamp\").defaultTo((b) => b.now()),\n )\n .createIndex(\"idx_session_status\", [\"status\"])\n .createIndex(\"idx_session_created\", [\"createdAt\"])\n );\n });\n});\n"],"mappings":";;;AAEA,MAAa,WAAW,OAAO,gBAAgB,MAAM;AACnD,QAAO,EAAE,SAAS,YAAY,MAAM;AAClC,SACE,EAEG,UAAU,MAAM,UAAU,CAAC,CAC3B,UAAU,QAAQ,OAAO,SAAS,CAAC,UAAU,CAAC,CAC9C,UAAU,SAAS,OAAO,SAAS,CAAC,CAEpC,UAAU,UAAU,OAAO,SAAS,CAAC,CACrC,UAAU,gBAAgB,OAAO,SAAS,CAAC,CAC3C,UAAU,YAAY,OAAO,OAAO,CAAC,UAAU,CAAC,CAChD,UAAU,QAAQ,OAAO,OAAO,CAAC,UAAU,CAAC,CAC5C,UACC,aACA,OAAO,YAAY,CAAC,WAAW,MAAM,EAAE,KAAK,CAAC,CAC9C,CACA,UACC,aACA,OAAO,YAAY,CAAC,WAAW,MAAM,EAAE,KAAK,CAAC,CAC9C,CACA,YAAY,sBAAsB,CAAC,SAAS,CAAC,CAC7C,YAAY,uBAAuB,CAAC,YAAY,CAAC;GAEtD;EACF"}
|