acpx 0.7.0 → 0.9.0
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 +14 -6
- package/dist/{cli-T-Z-9x6a.js → cli-Bf3yjqzE.js} +35 -10
- package/dist/cli-Bf3yjqzE.js.map +1 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +724 -241
- package/dist/cli.js.map +1 -1
- package/dist/{client-COPilhO_.d.ts → client-BssohYqM.d.ts} +35 -4
- package/dist/client-BssohYqM.d.ts.map +1 -0
- package/dist/flags-C-rwARqg.js +260 -0
- package/dist/flags-C-rwARqg.js.map +1 -0
- package/dist/{flows-CF8w1rPI.js → flows-WLs26_5Y.js} +405 -337
- package/dist/flows-WLs26_5Y.js.map +1 -0
- package/dist/flows.d.ts +23 -2
- package/dist/flows.d.ts.map +1 -1
- package/dist/flows.js +1 -1
- package/dist/{prompt-turn-CVPMWdj1.js → live-checkpoint-D5d-K9s1.js} +2487 -609
- package/dist/live-checkpoint-D5d-K9s1.js.map +1 -0
- package/dist/output-DPg20dvn.js +4146 -0
- package/dist/output-DPg20dvn.js.map +1 -0
- package/dist/runtime.d.ts +56 -4
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +676 -393
- package/dist/runtime.js.map +1 -1
- package/dist/{types-CVBeQyi3.d.ts → session-options-CFudjdkU.d.ts} +62 -3
- package/dist/session-options-CFudjdkU.d.ts.map +1 -0
- package/package.json +30 -25
- package/skills/acpx/SKILL.md +211 -13
- package/dist/cli-T-Z-9x6a.js.map +0 -1
- package/dist/client-COPilhO_.d.ts.map +0 -1
- package/dist/flags-Dj-IXgo9.js +0 -163
- package/dist/flags-Dj-IXgo9.js.map +0 -1
- package/dist/flows-CF8w1rPI.js.map +0 -1
- package/dist/ipc-ABXlXzGP.js +0 -1290
- package/dist/ipc-ABXlXzGP.js.map +0 -1
- package/dist/jsonrpc-DSxh2w5R.js +0 -68
- package/dist/jsonrpc-DSxh2w5R.js.map +0 -1
- package/dist/output-DmHvT8vm.js +0 -807
- package/dist/output-DmHvT8vm.js.map +0 -1
- package/dist/perf-metrics-C2pXfxvR.js +0 -598
- package/dist/perf-metrics-C2pXfxvR.js.map +0 -1
- package/dist/prompt-turn-CVPMWdj1.js.map +0 -1
- package/dist/render-N5YwotCy.js +0 -172
- package/dist/render-N5YwotCy.js.map +0 -1
- package/dist/rolldown-runtime-CiIaOW0V.js +0 -13
- package/dist/session-CDaQe6BH.js +0 -1538
- package/dist/session-CDaQe6BH.js.map +0 -1
- package/dist/session-options-pCbHn_n7.d.ts +0 -13
- package/dist/session-options-pCbHn_n7.d.ts.map +0 -1
- package/dist/types-CVBeQyi3.d.ts.map +0 -1
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { c as createSessionWithClient, i as sendSessionDirect, l as cancelSessionPrompt, r as runOnce } from "./session-CDaQe6BH.js";
|
|
4
|
-
import { t as createOutputFormatter } from "./output-DmHvT8vm.js";
|
|
1
|
+
import { d as createSessionWithClient, f as cancelSessionPrompt, o as runOnce, s as sendSessionDirect, t as createOutputFormatter } from "./output-DPg20dvn.js";
|
|
2
|
+
import { Ft as PERMISSION_MODES, H as resolveSessionRecord, K as defaultSessionEventLog, Lt as SESSION_RECORD_SCHEMA, _ as recordPromptSubmission, _t as withTimeout, ft as promptToDisplayText, g as recordClientOperation, gt as withInterrupt, h as createSessionConversation, ht as TimeoutError, mt as InterruptedError, p as cloneSessionAcpxState, pt as textPrompt, v as recordSessionUpdate } from "./live-checkpoint-D5d-K9s1.js";
|
|
5
3
|
import path from "node:path";
|
|
6
4
|
import fs from "node:fs/promises";
|
|
7
5
|
import os from "node:os";
|
|
@@ -238,6 +236,15 @@ function renderShellCommand(command, args) {
|
|
|
238
236
|
const renderedArgs = args.map((arg) => JSON.stringify(arg)).join(" ");
|
|
239
237
|
return renderedArgs.length > 0 ? `${command} ${renderedArgs}` : command;
|
|
240
238
|
}
|
|
239
|
+
function createShellFailureError(spec, args, exitCode, signal, stderr) {
|
|
240
|
+
const status = signal ? `signal ${signal}` : `exit ${String(exitCode)}`;
|
|
241
|
+
const details = stderr.length > 0 ? `\n${stderr.trim()}` : "";
|
|
242
|
+
return /* @__PURE__ */ new Error(`Shell action failed (${renderShellCommand(spec.command, args)}): ${status}${details}`);
|
|
243
|
+
}
|
|
244
|
+
function rejectIfShellFailed(spec, args, result, timedOut) {
|
|
245
|
+
if (timedOut) return new TimeoutError(spec.timeoutMs ?? 0);
|
|
246
|
+
if (((result.exitCode ?? 0) !== 0 || result.signal != null) && spec.allowNonZeroExit !== true) return createShellFailureError(spec, args, result.exitCode, result.signal, result.stderr);
|
|
247
|
+
}
|
|
241
248
|
async function runShellAction(spec) {
|
|
242
249
|
const cwd = spec.cwd ?? process.cwd();
|
|
243
250
|
const args = spec.args ?? [];
|
|
@@ -282,12 +289,9 @@ async function runShellAction(spec) {
|
|
|
282
289
|
signal,
|
|
283
290
|
durationMs: Date.now() - startMs
|
|
284
291
|
};
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
}
|
|
289
|
-
if (((exitCode ?? 0) !== 0 || signal != null) && spec.allowNonZeroExit !== true) {
|
|
290
|
-
reject(/* @__PURE__ */ new Error(`Shell action failed (${renderShellCommand(spec.command, args)}): ${signal ? `signal ${signal}` : `exit ${String(exitCode)}`}${stderr.length > 0 ? `\n${stderr.trim()}` : ""}`));
|
|
292
|
+
const error = rejectIfShellFailed(spec, args, result, timedOut);
|
|
293
|
+
if (error) {
|
|
294
|
+
reject(error);
|
|
291
295
|
return;
|
|
292
296
|
}
|
|
293
297
|
resolve(result);
|
|
@@ -314,16 +318,20 @@ function validateFlowDefinition(flow) {
|
|
|
314
318
|
assertValidFlowDefinitionShape(flow);
|
|
315
319
|
if (!flow.nodes[flow.startAt]) throw new Error(`Flow start node is missing: ${flow.startAt}`);
|
|
316
320
|
const outgoingEdges = /* @__PURE__ */ new Set();
|
|
317
|
-
for (const edge of flow.edges)
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
321
|
+
for (const edge of flow.edges) validateFlowEdge(flow, edge, outgoingEdges);
|
|
322
|
+
}
|
|
323
|
+
function assertKnownFlowNode(flow, nodeId, description) {
|
|
324
|
+
if (!flow.nodes[nodeId]) throw new Error(`${description}: ${nodeId}`);
|
|
325
|
+
}
|
|
326
|
+
function validateFlowEdge(flow, edge, outgoingEdges) {
|
|
327
|
+
assertKnownFlowNode(flow, edge.from, "Flow edge references unknown from-node");
|
|
328
|
+
if (outgoingEdges.has(edge.from)) throw new Error(`Flow node must not declare multiple outgoing edges: ${edge.from}`);
|
|
329
|
+
outgoingEdges.add(edge.from);
|
|
330
|
+
if ("to" in edge) {
|
|
331
|
+
assertKnownFlowNode(flow, edge.to, "Flow edge references unknown to-node");
|
|
332
|
+
return;
|
|
326
333
|
}
|
|
334
|
+
for (const target of Object.values(edge.switch.cases)) assertKnownFlowNode(flow, target, "Flow switch references unknown to-node");
|
|
327
335
|
}
|
|
328
336
|
function resolveNext(edges, from, output, result) {
|
|
329
337
|
const edge = edges.find((candidate) => candidate.from === from);
|
|
@@ -586,14 +594,16 @@ function extractAttachedStepTrace(error) {
|
|
|
586
594
|
}
|
|
587
595
|
function toInlineOutput(value) {
|
|
588
596
|
if (value == null || typeof value === "number" || typeof value === "boolean") return value;
|
|
589
|
-
if (typeof value === "string") return value
|
|
597
|
+
if (typeof value === "string") return isInlineSerializableText(value) ? value : void 0;
|
|
590
598
|
try {
|
|
591
|
-
|
|
592
|
-
if (serialized.length <= 200 && !serialized.includes("\n")) return value;
|
|
599
|
+
if (isInlineSerializableText(JSON.stringify(value))) return value;
|
|
593
600
|
} catch {
|
|
594
601
|
return;
|
|
595
602
|
}
|
|
596
603
|
}
|
|
604
|
+
function isInlineSerializableText(value) {
|
|
605
|
+
return value.length <= 200 && !value.includes("\n");
|
|
606
|
+
}
|
|
597
607
|
function outputArtifactMediaType(value) {
|
|
598
608
|
return typeof value === "string" ? "text/plain" : "application/json";
|
|
599
609
|
}
|
|
@@ -887,24 +897,9 @@ function createFlowDefinitionSnapshot(flow) {
|
|
|
887
897
|
};
|
|
888
898
|
}
|
|
889
899
|
function snapshotNode(node) {
|
|
890
|
-
const common =
|
|
891
|
-
nodeType: node.nodeType,
|
|
892
|
-
...node.timeoutMs !== void 0 ? { timeoutMs: node.timeoutMs } : {},
|
|
893
|
-
...node.heartbeatMs !== void 0 ? { heartbeatMs: node.heartbeatMs } : {},
|
|
894
|
-
...node.statusDetail ? { statusDetail: node.statusDetail } : {}
|
|
895
|
-
};
|
|
900
|
+
const common = snapshotCommonNodeFields(node);
|
|
896
901
|
switch (node.nodeType) {
|
|
897
|
-
case "acp": return
|
|
898
|
-
...common,
|
|
899
|
-
...node.profile ? { profile: node.profile } : {},
|
|
900
|
-
session: {
|
|
901
|
-
...node.session?.handle ? { handle: node.session.handle } : {},
|
|
902
|
-
...node.session?.isolated ? { isolated: true } : {}
|
|
903
|
-
},
|
|
904
|
-
cwd: snapshotCwd(node.cwd),
|
|
905
|
-
hasPrompt: true,
|
|
906
|
-
hasParse: typeof node.parse === "function"
|
|
907
|
-
};
|
|
902
|
+
case "acp": return snapshotAcpNode(node, common);
|
|
908
903
|
case "compute": return {
|
|
909
904
|
...common,
|
|
910
905
|
hasRun: true
|
|
@@ -927,6 +922,27 @@ function snapshotNode(node) {
|
|
|
927
922
|
}
|
|
928
923
|
throw new Error(`Unsupported flow node type: ${String(node)}`);
|
|
929
924
|
}
|
|
925
|
+
function snapshotCommonNodeFields(node) {
|
|
926
|
+
return {
|
|
927
|
+
nodeType: node.nodeType,
|
|
928
|
+
...node.timeoutMs !== void 0 ? { timeoutMs: node.timeoutMs } : {},
|
|
929
|
+
...node.heartbeatMs !== void 0 ? { heartbeatMs: node.heartbeatMs } : {},
|
|
930
|
+
...node.statusDetail ? { statusDetail: node.statusDetail } : {}
|
|
931
|
+
};
|
|
932
|
+
}
|
|
933
|
+
function snapshotAcpNode(node, common) {
|
|
934
|
+
return {
|
|
935
|
+
...common,
|
|
936
|
+
...node.profile ? { profile: node.profile } : {},
|
|
937
|
+
session: {
|
|
938
|
+
...node.session?.handle ? { handle: node.session.handle } : {},
|
|
939
|
+
...node.session?.isolated ? { isolated: true } : {}
|
|
940
|
+
},
|
|
941
|
+
cwd: snapshotCwd(node.cwd),
|
|
942
|
+
hasPrompt: true,
|
|
943
|
+
hasParse: typeof node.parse === "function"
|
|
944
|
+
};
|
|
945
|
+
}
|
|
930
946
|
function snapshotCwd(cwd) {
|
|
931
947
|
if (typeof cwd === "function") return { mode: "dynamic" };
|
|
932
948
|
if (typeof cwd === "string") return {
|
|
@@ -989,6 +1005,7 @@ var FlowRunner = class {
|
|
|
989
1005
|
permissionMode;
|
|
990
1006
|
mcpServers;
|
|
991
1007
|
nonInteractivePermissions;
|
|
1008
|
+
permissionPolicy;
|
|
992
1009
|
authCredentials;
|
|
993
1010
|
authPolicy;
|
|
994
1011
|
timeoutMs;
|
|
@@ -1005,6 +1022,7 @@ var FlowRunner = class {
|
|
|
1005
1022
|
this.permissionMode = options.permissionMode;
|
|
1006
1023
|
this.mcpServers = options.mcpServers;
|
|
1007
1024
|
this.nonInteractivePermissions = options.nonInteractivePermissions;
|
|
1025
|
+
this.permissionPolicy = options.permissionPolicy;
|
|
1008
1026
|
this.authCredentials = options.authCredentials;
|
|
1009
1027
|
this.authPolicy = options.authPolicy;
|
|
1010
1028
|
this.timeoutMs = options.timeoutMs;
|
|
@@ -1044,156 +1062,188 @@ var FlowRunner = class {
|
|
|
1044
1062
|
state,
|
|
1045
1063
|
inputArtifact
|
|
1046
1064
|
});
|
|
1047
|
-
let current = flow.startAt;
|
|
1048
|
-
const attemptCounts = /* @__PURE__ */ new Map();
|
|
1049
1065
|
try {
|
|
1050
|
-
return await withInterrupt(async () => {
|
|
1051
|
-
try {
|
|
1052
|
-
while (current) {
|
|
1053
|
-
const node = flow.nodes[current];
|
|
1054
|
-
if (!node) throw new Error(`Unknown flow node: ${current}`);
|
|
1055
|
-
const attemptId = nextAttemptId(attemptCounts, current);
|
|
1056
|
-
const startedAt = isoNow$1();
|
|
1057
|
-
const context = makeFlowNodeContext(state, input, this.services);
|
|
1058
|
-
let output;
|
|
1059
|
-
let promptText = null;
|
|
1060
|
-
let rawText = null;
|
|
1061
|
-
let sessionInfo = null;
|
|
1062
|
-
let agentInfo = null;
|
|
1063
|
-
let trace = null;
|
|
1064
|
-
markNodeStarted(state, current, attemptId, node.nodeType, startedAt, node.statusDetail);
|
|
1065
|
-
await this.store.writeSnapshot(runDir, state, {
|
|
1066
|
-
scope: "node",
|
|
1067
|
-
type: "node_started",
|
|
1068
|
-
nodeId: current,
|
|
1069
|
-
attemptId,
|
|
1070
|
-
payload: {
|
|
1071
|
-
nodeType: node.nodeType,
|
|
1072
|
-
...node.timeoutMs !== void 0 ? { timeoutMs: node.timeoutMs ?? this.defaultNodeTimeoutMs } : { timeoutMs: this.defaultNodeTimeoutMs },
|
|
1073
|
-
...state.statusDetail ? { statusDetail: state.statusDetail } : {}
|
|
1074
|
-
}
|
|
1075
|
-
});
|
|
1076
|
-
let nodeResult;
|
|
1077
|
-
let executionError;
|
|
1078
|
-
try {
|
|
1079
|
-
({output, promptText, rawText, sessionInfo, agentInfo, trace} = await this.executeNode(runDir, state, flow, current, node, context));
|
|
1080
|
-
trace = await finalizeStepTrace(this.store, runDir, state, current, attemptId, output, trace);
|
|
1081
|
-
nodeResult = createNodeResult({
|
|
1082
|
-
attemptId,
|
|
1083
|
-
nodeId: current,
|
|
1084
|
-
nodeType: node.nodeType,
|
|
1085
|
-
outcome: "ok",
|
|
1086
|
-
startedAt,
|
|
1087
|
-
finishedAt: isoNow$1(),
|
|
1088
|
-
output
|
|
1089
|
-
});
|
|
1090
|
-
} catch (error) {
|
|
1091
|
-
executionError = error;
|
|
1092
|
-
trace = extractAttachedStepTrace(error) ?? trace;
|
|
1093
|
-
trace = await finalizeStepTrace(this.store, runDir, state, current, attemptId, void 0, trace);
|
|
1094
|
-
nodeResult = createNodeResult({
|
|
1095
|
-
attemptId,
|
|
1096
|
-
nodeId: current,
|
|
1097
|
-
nodeType: node.nodeType,
|
|
1098
|
-
outcome: outcomeForError(error),
|
|
1099
|
-
startedAt,
|
|
1100
|
-
finishedAt: isoNow$1(),
|
|
1101
|
-
error: error instanceof Error ? error.message : String(error)
|
|
1102
|
-
});
|
|
1103
|
-
}
|
|
1104
|
-
state.results[current] = nodeResult;
|
|
1105
|
-
if (nodeResult.outcome === "ok" && node.nodeType === "checkpoint") {
|
|
1106
|
-
state.outputs[current] = output;
|
|
1107
|
-
state.waitingOn = current;
|
|
1108
|
-
state.updatedAt = isoNow$1();
|
|
1109
|
-
state.status = "waiting";
|
|
1110
|
-
clearActiveNode(state, output?.summary ?? current);
|
|
1111
|
-
state.steps.push({
|
|
1112
|
-
attemptId,
|
|
1113
|
-
nodeId: current,
|
|
1114
|
-
nodeType: node.nodeType,
|
|
1115
|
-
outcome: nodeResult.outcome,
|
|
1116
|
-
startedAt,
|
|
1117
|
-
finishedAt: nodeResult.finishedAt,
|
|
1118
|
-
promptText,
|
|
1119
|
-
rawText,
|
|
1120
|
-
output,
|
|
1121
|
-
session: null,
|
|
1122
|
-
agent: null,
|
|
1123
|
-
...trace ? { trace } : {}
|
|
1124
|
-
});
|
|
1125
|
-
await this.store.writeSnapshot(runDir, state, {
|
|
1126
|
-
scope: "node",
|
|
1127
|
-
type: "node_outcome",
|
|
1128
|
-
nodeId: current,
|
|
1129
|
-
attemptId,
|
|
1130
|
-
payload: createNodeOutcomePayload(nodeResult, trace)
|
|
1131
|
-
});
|
|
1132
|
-
return {
|
|
1133
|
-
runDir,
|
|
1134
|
-
state
|
|
1135
|
-
};
|
|
1136
|
-
}
|
|
1137
|
-
if (nodeResult.outcome === "ok") state.outputs[current] = output;
|
|
1138
|
-
state.updatedAt = isoNow$1();
|
|
1139
|
-
clearActiveNode(state);
|
|
1140
|
-
state.steps.push({
|
|
1141
|
-
attemptId,
|
|
1142
|
-
nodeId: current,
|
|
1143
|
-
nodeType: node.nodeType,
|
|
1144
|
-
outcome: nodeResult.outcome,
|
|
1145
|
-
startedAt,
|
|
1146
|
-
finishedAt: nodeResult.finishedAt,
|
|
1147
|
-
promptText,
|
|
1148
|
-
rawText,
|
|
1149
|
-
output,
|
|
1150
|
-
error: nodeResult.error,
|
|
1151
|
-
session: sessionInfo,
|
|
1152
|
-
agent: agentInfo,
|
|
1153
|
-
...trace ? { trace } : {}
|
|
1154
|
-
});
|
|
1155
|
-
await this.store.writeSnapshot(runDir, state, {
|
|
1156
|
-
scope: "node",
|
|
1157
|
-
type: "node_outcome",
|
|
1158
|
-
nodeId: current,
|
|
1159
|
-
attemptId,
|
|
1160
|
-
payload: createNodeOutcomePayload(nodeResult, trace)
|
|
1161
|
-
});
|
|
1162
|
-
if (nodeResult.outcome === "ok") {
|
|
1163
|
-
current = resolveNext(flow.edges, current, output, nodeResult);
|
|
1164
|
-
continue;
|
|
1165
|
-
}
|
|
1166
|
-
const next = resolveNextForOutcome(flow.edges, current, nodeResult);
|
|
1167
|
-
if (next) {
|
|
1168
|
-
current = next;
|
|
1169
|
-
continue;
|
|
1170
|
-
}
|
|
1171
|
-
throw executionError;
|
|
1172
|
-
}
|
|
1173
|
-
state.status = "completed";
|
|
1174
|
-
state.finishedAt = isoNow$1();
|
|
1175
|
-
state.updatedAt = state.finishedAt;
|
|
1176
|
-
clearActiveNode(state);
|
|
1177
|
-
await this.store.writeSnapshot(runDir, state, {
|
|
1178
|
-
scope: "run",
|
|
1179
|
-
type: "run_completed",
|
|
1180
|
-
payload: { status: state.status }
|
|
1181
|
-
});
|
|
1182
|
-
return {
|
|
1183
|
-
runDir,
|
|
1184
|
-
state
|
|
1185
|
-
};
|
|
1186
|
-
} catch (error) {
|
|
1187
|
-
await persistRunFailure(this.store, runDir, state, error);
|
|
1188
|
-
throw error;
|
|
1189
|
-
}
|
|
1190
|
-
}, async () => {
|
|
1066
|
+
return await withInterrupt(async () => await this.executeFlowRun(flow, input, runDir, state), async () => {
|
|
1191
1067
|
await persistRunFailure(this.store, runDir, state, new InterruptedError());
|
|
1192
1068
|
});
|
|
1193
1069
|
} finally {
|
|
1194
1070
|
await this.closePendingPersistentSessionClients();
|
|
1195
1071
|
}
|
|
1196
1072
|
}
|
|
1073
|
+
async executeFlowRun(flow, input, runDir, state) {
|
|
1074
|
+
let current = flow.startAt;
|
|
1075
|
+
const attemptCounts = /* @__PURE__ */ new Map();
|
|
1076
|
+
try {
|
|
1077
|
+
while (current) {
|
|
1078
|
+
const step = await this.executeFlowStep(flow, input, runDir, state, current, attemptCounts);
|
|
1079
|
+
const waiting = await this.maybeCompleteCheckpointStep(runDir, state, step);
|
|
1080
|
+
if (waiting) return waiting;
|
|
1081
|
+
await this.recordFlowStepOutcome(runDir, state, step);
|
|
1082
|
+
current = this.resolveNextNode(flow, step);
|
|
1083
|
+
}
|
|
1084
|
+
return await this.completeFlowRun(runDir, state);
|
|
1085
|
+
} catch (error) {
|
|
1086
|
+
await persistRunFailure(this.store, runDir, state, error);
|
|
1087
|
+
throw error;
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
async executeFlowStep(flow, input, runDir, state, nodeId, attemptCounts) {
|
|
1091
|
+
const node = flow.nodes[nodeId];
|
|
1092
|
+
if (!node) throw new Error(`Unknown flow node: ${nodeId}`);
|
|
1093
|
+
const attemptId = nextAttemptId(attemptCounts, nodeId);
|
|
1094
|
+
const startedAt = isoNow$1();
|
|
1095
|
+
markNodeStarted(state, nodeId, attemptId, node.nodeType, startedAt, node.statusDetail);
|
|
1096
|
+
await this.writeNodeStartedSnapshot(runDir, state, nodeId, attemptId, node);
|
|
1097
|
+
return await this.executeStartedFlowStep({
|
|
1098
|
+
flow,
|
|
1099
|
+
input,
|
|
1100
|
+
runDir,
|
|
1101
|
+
state,
|
|
1102
|
+
nodeId,
|
|
1103
|
+
node,
|
|
1104
|
+
attemptId,
|
|
1105
|
+
startedAt
|
|
1106
|
+
});
|
|
1107
|
+
}
|
|
1108
|
+
async writeNodeStartedSnapshot(runDir, state, nodeId, attemptId, node) {
|
|
1109
|
+
await this.store.writeSnapshot(runDir, state, {
|
|
1110
|
+
scope: "node",
|
|
1111
|
+
type: "node_started",
|
|
1112
|
+
nodeId,
|
|
1113
|
+
attemptId,
|
|
1114
|
+
payload: {
|
|
1115
|
+
nodeType: node.nodeType,
|
|
1116
|
+
...node.timeoutMs !== void 0 ? { timeoutMs: node.timeoutMs ?? this.defaultNodeTimeoutMs } : { timeoutMs: this.defaultNodeTimeoutMs },
|
|
1117
|
+
...state.statusDetail ? { statusDetail: state.statusDetail } : {}
|
|
1118
|
+
}
|
|
1119
|
+
});
|
|
1120
|
+
}
|
|
1121
|
+
async executeStartedFlowStep(params) {
|
|
1122
|
+
const context = makeFlowNodeContext(params.state, params.input, this.services);
|
|
1123
|
+
try {
|
|
1124
|
+
const executed = await this.executeNode(params.runDir, params.state, params.flow, params.nodeId, params.node, context);
|
|
1125
|
+
return await this.createSuccessfulFlowStep(params, executed);
|
|
1126
|
+
} catch (error) {
|
|
1127
|
+
return await this.createFailedFlowStep(params, error);
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
async createSuccessfulFlowStep(params, executed) {
|
|
1131
|
+
const trace = await finalizeStepTrace(this.store, params.runDir, params.state, params.nodeId, params.attemptId, executed.output, executed.trace);
|
|
1132
|
+
const nodeResult = createNodeResult({
|
|
1133
|
+
attemptId: params.attemptId,
|
|
1134
|
+
nodeId: params.nodeId,
|
|
1135
|
+
nodeType: params.node.nodeType,
|
|
1136
|
+
outcome: "ok",
|
|
1137
|
+
startedAt: params.startedAt,
|
|
1138
|
+
finishedAt: isoNow$1(),
|
|
1139
|
+
output: executed.output
|
|
1140
|
+
});
|
|
1141
|
+
params.state.results[params.nodeId] = nodeResult;
|
|
1142
|
+
return {
|
|
1143
|
+
...executed,
|
|
1144
|
+
trace,
|
|
1145
|
+
nodeResult,
|
|
1146
|
+
attemptId: params.attemptId,
|
|
1147
|
+
nodeId: params.nodeId,
|
|
1148
|
+
node: params.node,
|
|
1149
|
+
startedAt: params.startedAt,
|
|
1150
|
+
state: params.state
|
|
1151
|
+
};
|
|
1152
|
+
}
|
|
1153
|
+
async createFailedFlowStep(params, error) {
|
|
1154
|
+
const trace = await finalizeStepTrace(this.store, params.runDir, params.state, params.nodeId, params.attemptId, void 0, extractAttachedStepTrace(error) ?? null);
|
|
1155
|
+
const nodeResult = createNodeResult({
|
|
1156
|
+
attemptId: params.attemptId,
|
|
1157
|
+
nodeId: params.nodeId,
|
|
1158
|
+
nodeType: params.node.nodeType,
|
|
1159
|
+
outcome: outcomeForError(error),
|
|
1160
|
+
startedAt: params.startedAt,
|
|
1161
|
+
finishedAt: isoNow$1(),
|
|
1162
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1163
|
+
});
|
|
1164
|
+
params.state.results[params.nodeId] = nodeResult;
|
|
1165
|
+
return {
|
|
1166
|
+
output: void 0,
|
|
1167
|
+
promptText: null,
|
|
1168
|
+
rawText: null,
|
|
1169
|
+
sessionInfo: null,
|
|
1170
|
+
agentInfo: null,
|
|
1171
|
+
trace,
|
|
1172
|
+
nodeResult,
|
|
1173
|
+
executionError: error,
|
|
1174
|
+
attemptId: params.attemptId,
|
|
1175
|
+
nodeId: params.nodeId,
|
|
1176
|
+
node: params.node,
|
|
1177
|
+
startedAt: params.startedAt,
|
|
1178
|
+
state: params.state
|
|
1179
|
+
};
|
|
1180
|
+
}
|
|
1181
|
+
async maybeCompleteCheckpointStep(runDir, state, step) {
|
|
1182
|
+
if (step.nodeResult.outcome !== "ok" || step.node.nodeType !== "checkpoint") return;
|
|
1183
|
+
state.outputs[step.nodeId] = step.output;
|
|
1184
|
+
state.waitingOn = step.nodeId;
|
|
1185
|
+
state.updatedAt = isoNow$1();
|
|
1186
|
+
state.status = "waiting";
|
|
1187
|
+
await this.recordFlowStepOutcome(runDir, state, step, {
|
|
1188
|
+
sessionInfo: null,
|
|
1189
|
+
agentInfo: null,
|
|
1190
|
+
statusDetail: step.output?.summary ?? step.nodeId
|
|
1191
|
+
});
|
|
1192
|
+
return {
|
|
1193
|
+
runDir,
|
|
1194
|
+
state
|
|
1195
|
+
};
|
|
1196
|
+
}
|
|
1197
|
+
resolveNextNode(flow, step) {
|
|
1198
|
+
if (step.nodeResult.outcome === "ok") {
|
|
1199
|
+
step.state.outputs[step.nodeId] = step.output;
|
|
1200
|
+
return resolveNext(flow.edges, step.nodeId, step.output, step.nodeResult);
|
|
1201
|
+
}
|
|
1202
|
+
const next = resolveNextForOutcome(flow.edges, step.nodeId, step.nodeResult);
|
|
1203
|
+
if (next) return next;
|
|
1204
|
+
throw step.executionError;
|
|
1205
|
+
}
|
|
1206
|
+
async completeFlowRun(runDir, state) {
|
|
1207
|
+
state.status = "completed";
|
|
1208
|
+
state.finishedAt = isoNow$1();
|
|
1209
|
+
state.updatedAt = state.finishedAt;
|
|
1210
|
+
clearActiveNode(state);
|
|
1211
|
+
await this.store.writeSnapshot(runDir, state, {
|
|
1212
|
+
scope: "run",
|
|
1213
|
+
type: "run_completed",
|
|
1214
|
+
payload: { status: state.status }
|
|
1215
|
+
});
|
|
1216
|
+
return {
|
|
1217
|
+
runDir,
|
|
1218
|
+
state
|
|
1219
|
+
};
|
|
1220
|
+
}
|
|
1221
|
+
async recordFlowStepOutcome(runDir, state, step, overrides = {}) {
|
|
1222
|
+
state.updatedAt = isoNow$1();
|
|
1223
|
+
clearActiveNode(state, overrides.statusDetail);
|
|
1224
|
+
state.steps.push({
|
|
1225
|
+
attemptId: step.attemptId,
|
|
1226
|
+
nodeId: step.nodeId,
|
|
1227
|
+
nodeType: step.node.nodeType,
|
|
1228
|
+
outcome: step.nodeResult.outcome,
|
|
1229
|
+
startedAt: step.startedAt,
|
|
1230
|
+
finishedAt: step.nodeResult.finishedAt,
|
|
1231
|
+
promptText: step.promptText,
|
|
1232
|
+
rawText: step.rawText,
|
|
1233
|
+
output: step.output,
|
|
1234
|
+
error: step.nodeResult.error,
|
|
1235
|
+
session: overrides.sessionInfo ?? step.sessionInfo,
|
|
1236
|
+
agent: overrides.agentInfo ?? step.agentInfo,
|
|
1237
|
+
...step.trace ? { trace: step.trace } : {}
|
|
1238
|
+
});
|
|
1239
|
+
await this.store.writeSnapshot(runDir, state, {
|
|
1240
|
+
scope: "node",
|
|
1241
|
+
type: "node_outcome",
|
|
1242
|
+
nodeId: step.nodeId,
|
|
1243
|
+
attemptId: step.attemptId,
|
|
1244
|
+
payload: createNodeOutcomePayload(step.nodeResult, step.trace)
|
|
1245
|
+
});
|
|
1246
|
+
}
|
|
1197
1247
|
async executeNode(runDir, state, flow, nodeId, node, context) {
|
|
1198
1248
|
switch (node.nodeType) {
|
|
1199
1249
|
case "compute": return await this.executeComputeNode(runDir, state, node, context);
|
|
@@ -1335,147 +1385,132 @@ var FlowRunner = class {
|
|
|
1335
1385
|
const nodeTimeoutMs = node.timeoutMs ?? this.defaultNodeTimeoutMs;
|
|
1336
1386
|
let boundSession = null;
|
|
1337
1387
|
return await this.runWithHeartbeat(runDir, state, state.currentNode ?? "", node, nodeTimeoutMs, async () => {
|
|
1338
|
-
const
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1388
|
+
const prepared = await this.prepareAcpPrompt(runDir, state, node, context, nodeTimeoutMs);
|
|
1389
|
+
if (node.session?.isolated) return await this.executeIsolatedAcpPrompt(runDir, state, flow, node, context, prepared);
|
|
1390
|
+
boundSession = await this.ensureSessionBinding(runDir, state, flow, node, prepared.agentInfo, nodeTimeoutMs);
|
|
1391
|
+
return await this.executePersistentAcpPrompt(runDir, state, node, context, prepared, boundSession);
|
|
1392
|
+
}, async () => {
|
|
1393
|
+
if (!boundSession) return;
|
|
1394
|
+
await cancelSessionPrompt({ sessionId: boundSession.acpxRecordId });
|
|
1395
|
+
});
|
|
1396
|
+
}
|
|
1397
|
+
async prepareAcpPrompt(runDir, state, node, context, nodeTimeoutMs) {
|
|
1398
|
+
const resolvedAgent = this.resolveAgent(node.profile);
|
|
1399
|
+
const agentInfo = {
|
|
1400
|
+
...resolvedAgent,
|
|
1401
|
+
cwd: await resolveNodeCwd(resolvedAgent.cwd, node.cwd, context)
|
|
1402
|
+
};
|
|
1403
|
+
const prompt = normalizePromptInput(await Promise.resolve(node.prompt(context)));
|
|
1404
|
+
const promptText = promptToDisplayText(prompt);
|
|
1405
|
+
updateStatusDetail(state, summarizePrompt(promptText, node.statusDetail));
|
|
1406
|
+
await this.writeAcpPromptHeartbeat(runDir, state);
|
|
1407
|
+
return {
|
|
1408
|
+
agentInfo,
|
|
1409
|
+
prompt,
|
|
1410
|
+
promptText,
|
|
1411
|
+
promptArtifact: await this.store.writeArtifact(runDir, state, promptText, {
|
|
1354
1412
|
mediaType: "text/plain",
|
|
1355
1413
|
extension: "txt",
|
|
1356
1414
|
nodeId: state.currentNode,
|
|
1357
1415
|
attemptId: state.currentAttemptId
|
|
1358
|
-
})
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
conversation: isolatedPrompt.conversation
|
|
1406
|
-
};
|
|
1407
|
-
let parsedOutput;
|
|
1408
|
-
try {
|
|
1409
|
-
parsedOutput = node.parse ? await node.parse(isolatedPrompt.rawText, context) : isolatedPrompt.rawText;
|
|
1410
|
-
} catch (error) {
|
|
1411
|
-
throw attachStepTrace(error, trace);
|
|
1412
|
-
}
|
|
1413
|
-
return {
|
|
1414
|
-
output: parsedOutput,
|
|
1415
|
-
promptText,
|
|
1416
|
-
rawText: isolatedPrompt.rawText,
|
|
1417
|
-
sessionInfo: isolatedBinding,
|
|
1418
|
-
agentInfo,
|
|
1419
|
-
trace
|
|
1420
|
-
};
|
|
1416
|
+
}),
|
|
1417
|
+
nodeTimeoutMs
|
|
1418
|
+
};
|
|
1419
|
+
}
|
|
1420
|
+
async writeAcpPromptHeartbeat(runDir, state) {
|
|
1421
|
+
await this.store.writeLive(runDir, state, {
|
|
1422
|
+
scope: "node",
|
|
1423
|
+
type: "node_heartbeat",
|
|
1424
|
+
nodeId: state.currentNode,
|
|
1425
|
+
attemptId: state.currentAttemptId,
|
|
1426
|
+
payload: { statusDetail: state.statusDetail }
|
|
1427
|
+
});
|
|
1428
|
+
}
|
|
1429
|
+
async executeIsolatedAcpPrompt(runDir, state, flow, node, context, prepared) {
|
|
1430
|
+
const binding = createIsolatedSessionBinding(flow.name, state.runId, state.currentAttemptId ?? randomUUID(), node.profile, prepared.agentInfo);
|
|
1431
|
+
await this.initializeIsolatedSessionBundle(runDir, state, binding);
|
|
1432
|
+
await this.appendAcpPromptPreparedTrace(runDir, state, binding, prepared.promptArtifact);
|
|
1433
|
+
const prompt = await this.runIsolatedPrompt(runDir, state, binding, prepared.agentInfo, prepared.prompt, prepared.nodeTimeoutMs);
|
|
1434
|
+
return await this.finishAcpPrompt(runDir, state, node, context, prepared, prompt, binding);
|
|
1435
|
+
}
|
|
1436
|
+
async initializeIsolatedSessionBundle(runDir, state, binding) {
|
|
1437
|
+
const timestamp = state.currentNodeStartedAt ?? isoNow$1();
|
|
1438
|
+
const initialRecord = createSyntheticSessionRecord({
|
|
1439
|
+
binding,
|
|
1440
|
+
createdAt: timestamp,
|
|
1441
|
+
updatedAt: timestamp,
|
|
1442
|
+
conversation: createSessionConversation(timestamp),
|
|
1443
|
+
acpxState: void 0,
|
|
1444
|
+
lastSeq: 0
|
|
1445
|
+
});
|
|
1446
|
+
await this.store.ensureSessionBundle(runDir, state, binding, initialRecord);
|
|
1447
|
+
}
|
|
1448
|
+
async executePersistentAcpPrompt(runDir, state, node, context, prepared, binding) {
|
|
1449
|
+
await this.appendAcpPromptPreparedTrace(runDir, state, binding, prepared.promptArtifact);
|
|
1450
|
+
const prompt = await this.runPersistentPrompt(runDir, state, binding, prepared.prompt, prepared.nodeTimeoutMs);
|
|
1451
|
+
return await this.finishAcpPrompt(runDir, state, node, context, prepared, prompt, prompt.sessionInfo);
|
|
1452
|
+
}
|
|
1453
|
+
async appendAcpPromptPreparedTrace(runDir, state, binding, promptArtifact) {
|
|
1454
|
+
await this.store.appendTrace(runDir, state, {
|
|
1455
|
+
scope: "acp",
|
|
1456
|
+
type: "acp_prompt_prepared",
|
|
1457
|
+
nodeId: state.currentNode,
|
|
1458
|
+
attemptId: state.currentAttemptId,
|
|
1459
|
+
sessionId: binding.bundleId,
|
|
1460
|
+
payload: {
|
|
1461
|
+
sessionId: binding.bundleId,
|
|
1462
|
+
promptArtifact
|
|
1421
1463
|
}
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
parsedOutput = node.parse ? await node.parse(persistentPrompt.rawText, context) : persistentPrompt.rawText;
|
|
1463
|
-
} catch (error) {
|
|
1464
|
-
throw attachStepTrace(error, trace);
|
|
1464
|
+
});
|
|
1465
|
+
}
|
|
1466
|
+
async finishAcpPrompt(runDir, state, node, context, prepared, prompt, sessionInfo) {
|
|
1467
|
+
const rawResponseArtifact = await this.writeAcpRawResponseArtifact(runDir, state, prompt, sessionInfo);
|
|
1468
|
+
await this.appendAcpResponseParsedTrace(runDir, state, prompt, sessionInfo, rawResponseArtifact);
|
|
1469
|
+
const trace = {
|
|
1470
|
+
sessionId: sessionInfo.bundleId,
|
|
1471
|
+
promptArtifact: prepared.promptArtifact,
|
|
1472
|
+
rawResponseArtifact,
|
|
1473
|
+
conversation: prompt.conversation
|
|
1474
|
+
};
|
|
1475
|
+
return {
|
|
1476
|
+
output: await this.parseAcpOutput(node, context, prompt.rawText, trace),
|
|
1477
|
+
promptText: prepared.promptText,
|
|
1478
|
+
rawText: prompt.rawText,
|
|
1479
|
+
sessionInfo,
|
|
1480
|
+
agentInfo: prepared.agentInfo,
|
|
1481
|
+
trace
|
|
1482
|
+
};
|
|
1483
|
+
}
|
|
1484
|
+
async writeAcpRawResponseArtifact(runDir, state, prompt, sessionInfo) {
|
|
1485
|
+
return await this.store.writeArtifact(runDir, state, prompt.rawText, {
|
|
1486
|
+
mediaType: "text/plain",
|
|
1487
|
+
extension: "txt",
|
|
1488
|
+
nodeId: state.currentNode,
|
|
1489
|
+
attemptId: state.currentAttemptId,
|
|
1490
|
+
sessionId: sessionInfo.bundleId
|
|
1491
|
+
});
|
|
1492
|
+
}
|
|
1493
|
+
async appendAcpResponseParsedTrace(runDir, state, prompt, sessionInfo, rawResponseArtifact) {
|
|
1494
|
+
await this.store.appendTrace(runDir, state, {
|
|
1495
|
+
scope: "acp",
|
|
1496
|
+
type: "acp_response_parsed",
|
|
1497
|
+
nodeId: state.currentNode,
|
|
1498
|
+
attemptId: state.currentAttemptId,
|
|
1499
|
+
sessionId: sessionInfo.bundleId,
|
|
1500
|
+
payload: {
|
|
1501
|
+
sessionId: sessionInfo.bundleId,
|
|
1502
|
+
conversation: prompt.conversation,
|
|
1503
|
+
rawResponseArtifact
|
|
1465
1504
|
}
|
|
1466
|
-
return {
|
|
1467
|
-
output: parsedOutput,
|
|
1468
|
-
promptText,
|
|
1469
|
-
rawText: persistentPrompt.rawText,
|
|
1470
|
-
sessionInfo: persistentPrompt.sessionInfo,
|
|
1471
|
-
agentInfo,
|
|
1472
|
-
trace
|
|
1473
|
-
};
|
|
1474
|
-
}, async () => {
|
|
1475
|
-
if (!boundSession) return;
|
|
1476
|
-
await cancelSessionPrompt({ sessionId: boundSession.acpxRecordId });
|
|
1477
1505
|
});
|
|
1478
1506
|
}
|
|
1507
|
+
async parseAcpOutput(node, context, rawText, trace) {
|
|
1508
|
+
try {
|
|
1509
|
+
return node.parse ? await node.parse(rawText, context) : rawText;
|
|
1510
|
+
} catch (error) {
|
|
1511
|
+
throw attachStepTrace(error, trace);
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1479
1514
|
async runWithHeartbeat(runDir, state, nodeId, node, timeoutMs, run, onTimeout) {
|
|
1480
1515
|
const heartbeatMs = Math.max(0, Math.round(node.heartbeatMs ?? DEFAULT_FLOW_HEARTBEAT_MS));
|
|
1481
1516
|
let timer;
|
|
@@ -1521,6 +1556,7 @@ var FlowRunner = class {
|
|
|
1521
1556
|
mcpServers: this.mcpServers,
|
|
1522
1557
|
permissionMode: this.permissionMode,
|
|
1523
1558
|
nonInteractivePermissions: this.nonInteractivePermissions,
|
|
1559
|
+
permissionPolicy: this.permissionPolicy,
|
|
1524
1560
|
authCredentials: this.authCredentials,
|
|
1525
1561
|
authPolicy: this.authPolicy,
|
|
1526
1562
|
timeoutMs,
|
|
@@ -1569,6 +1605,7 @@ var FlowRunner = class {
|
|
|
1569
1605
|
mcpServers: this.mcpServers,
|
|
1570
1606
|
permissionMode: this.permissionMode,
|
|
1571
1607
|
nonInteractivePermissions: this.nonInteractivePermissions,
|
|
1608
|
+
permissionPolicy: this.permissionPolicy,
|
|
1572
1609
|
authCredentials: this.authCredentials,
|
|
1573
1610
|
authPolicy: this.authPolicy,
|
|
1574
1611
|
outputFormatter: capture.formatter,
|
|
@@ -1632,6 +1669,7 @@ var FlowRunner = class {
|
|
|
1632
1669
|
mcpServers: this.mcpServers,
|
|
1633
1670
|
permissionMode: this.permissionMode,
|
|
1634
1671
|
nonInteractivePermissions: this.nonInteractivePermissions,
|
|
1672
|
+
permissionPolicy: this.permissionPolicy,
|
|
1635
1673
|
authCredentials: this.authCredentials,
|
|
1636
1674
|
authPolicy: this.authPolicy,
|
|
1637
1675
|
outputFormatter: capture.formatter,
|
|
@@ -1700,18 +1738,25 @@ function parseJsonObject(text, options = {}) {
|
|
|
1700
1738
|
const mode = options.mode ?? "compat";
|
|
1701
1739
|
const direct = tryParse(trimmed);
|
|
1702
1740
|
if (direct.ok) return direct.value;
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
}
|
|
1741
|
+
const fenced = parseFencedJsonIfAllowed(trimmed, mode);
|
|
1742
|
+
if (fenced.ok) return fenced.value;
|
|
1743
|
+
if (mode === "compat") {
|
|
1744
|
+
const balanced = parseBalancedJsonCandidate(trimmed);
|
|
1745
|
+
if (balanced.ok) return balanced.value;
|
|
1709
1746
|
}
|
|
1710
|
-
|
|
1747
|
+
throw new Error(`Could not parse JSON from assistant output:\n${trimmed}`);
|
|
1748
|
+
}
|
|
1749
|
+
function parseFencedJsonIfAllowed(text, mode) {
|
|
1750
|
+
if (mode !== "fenced" && mode !== "compat") return { ok: false };
|
|
1751
|
+
const fencedText = extractFencedJsonText(text);
|
|
1752
|
+
return fencedText === null ? { ok: false } : tryParse(fencedText);
|
|
1753
|
+
}
|
|
1754
|
+
function parseBalancedJsonCandidate(text) {
|
|
1755
|
+
for (const candidate of extractBalancedJsonCandidates(text)) {
|
|
1711
1756
|
const parsed = tryParse(candidate);
|
|
1712
|
-
if (parsed.ok) return parsed
|
|
1757
|
+
if (parsed.ok) return parsed;
|
|
1713
1758
|
}
|
|
1714
|
-
|
|
1759
|
+
return { ok: false };
|
|
1715
1760
|
}
|
|
1716
1761
|
function parseStrictJsonObject(text) {
|
|
1717
1762
|
return parseJsonObject(text, { mode: "strict" });
|
|
@@ -1758,27 +1803,50 @@ function scanBalanced(text, startIndex) {
|
|
|
1758
1803
|
for (let index = startIndex; index < text.length; index += 1) {
|
|
1759
1804
|
const char = text[index];
|
|
1760
1805
|
if (inString) {
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1806
|
+
const next = scanStringChar(char, escaped);
|
|
1807
|
+
escaped = next.escaped;
|
|
1808
|
+
inString = next.inString;
|
|
1764
1809
|
continue;
|
|
1765
1810
|
}
|
|
1766
1811
|
if (char === "\"") {
|
|
1767
1812
|
inString = true;
|
|
1768
1813
|
continue;
|
|
1769
1814
|
}
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
continue;
|
|
1773
|
-
}
|
|
1774
|
-
if (char !== "}" && char !== "]") continue;
|
|
1775
|
-
const last = stack.at(-1);
|
|
1776
|
-
if (last === "{" && char !== "}" || last === "[" && char !== "]") return null;
|
|
1777
|
-
stack.pop();
|
|
1778
|
-
if (stack.length === 0) return text.slice(startIndex, index + 1);
|
|
1815
|
+
const result = scanBalancedToken(text, startIndex, index, char, stack);
|
|
1816
|
+
if (result !== SCAN_CONTINUE) return result;
|
|
1779
1817
|
}
|
|
1780
1818
|
return null;
|
|
1781
1819
|
}
|
|
1820
|
+
const SCAN_CONTINUE = Symbol("scan-continue");
|
|
1821
|
+
function scanBalancedToken(text, startIndex, index, char, stack) {
|
|
1822
|
+
if (char === "{" || char === "[") {
|
|
1823
|
+
stack.push(char);
|
|
1824
|
+
return SCAN_CONTINUE;
|
|
1825
|
+
}
|
|
1826
|
+
if (char !== "}" && char !== "]") return SCAN_CONTINUE;
|
|
1827
|
+
if (!balancedClosingTokenMatches(stack.at(-1), char)) return null;
|
|
1828
|
+
stack.pop();
|
|
1829
|
+
return stack.length === 0 ? text.slice(startIndex, index + 1) : SCAN_CONTINUE;
|
|
1830
|
+
}
|
|
1831
|
+
function balancedClosingTokenMatches(open, close) {
|
|
1832
|
+
if (open === "{") return close === "}";
|
|
1833
|
+
if (open === "[") return close === "]";
|
|
1834
|
+
return false;
|
|
1835
|
+
}
|
|
1836
|
+
function scanStringChar(char, escaped) {
|
|
1837
|
+
if (escaped) return {
|
|
1838
|
+
escaped: false,
|
|
1839
|
+
inString: true
|
|
1840
|
+
};
|
|
1841
|
+
if (char === "\\") return {
|
|
1842
|
+
escaped: true,
|
|
1843
|
+
inString: true
|
|
1844
|
+
};
|
|
1845
|
+
return {
|
|
1846
|
+
escaped: false,
|
|
1847
|
+
inString: char !== "\""
|
|
1848
|
+
};
|
|
1849
|
+
}
|
|
1782
1850
|
//#endregion
|
|
1783
1851
|
//#region src/flows/decision.ts
|
|
1784
1852
|
const DEFAULT_FIELD = "route";
|
|
@@ -1848,4 +1916,4 @@ function formatDecisionPrompt(question, choices, field) {
|
|
|
1848
1916
|
//#endregion
|
|
1849
1917
|
export { parseStrictJsonObject as a, validateFlowDefinition as c, checkpoint as d, compute as f, isDefinedFlow as h, parseJsonObject as i, acp as l, shell as m, decisionEdge as n, FlowRunner as o, defineFlow as p, extractJsonObject as r, flowRunsBaseDir as s, decision as t, action as u };
|
|
1850
1918
|
|
|
1851
|
-
//# sourceMappingURL=flows-
|
|
1919
|
+
//# sourceMappingURL=flows-WLs26_5Y.js.map
|