acpx 0.8.0 → 0.10.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 +8 -4
- package/dist/{cli-BGYGVo3b.js → cli-8dP_TqBp.js} +4 -4
- package/dist/{cli-BGYGVo3b.js.map → cli-8dP_TqBp.js.map} +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +930 -252
- package/dist/cli.js.map +1 -1
- package/dist/{client-FzXPdgP7.d.ts → client-C4iJBO0j.d.ts} +30 -3
- package/dist/client-C4iJBO0j.d.ts.map +1 -0
- package/dist/{flags-D706STfk.js → flags--2oX_ubW.js} +96 -39
- package/dist/flags--2oX_ubW.js.map +1 -0
- package/dist/{flows-hcjHmU7P.js → flows-e4umXVbY.js} +401 -336
- package/dist/flows-e4umXVbY.js.map +1 -0
- package/dist/flows.d.ts +21 -1
- package/dist/flows.d.ts.map +1 -1
- package/dist/flows.js +1 -1
- package/dist/{live-checkpoint-B9ctAuqV.js → live-checkpoint-CuFft_Nd.js} +1614 -931
- package/dist/live-checkpoint-CuFft_Nd.js.map +1 -0
- package/dist/{output-BL9XRWzS.js → output-Di77Yugq.js} +1153 -719
- package/dist/output-Di77Yugq.js.map +1 -0
- package/dist/runtime.d.ts +30 -2
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +579 -425
- package/dist/runtime.js.map +1 -1
- package/dist/{session-options-BJyG6zEH.d.ts → session-options-Bh1bIqQ2.d.ts} +14 -1
- package/dist/{session-options-BJyG6zEH.d.ts.map → session-options-Bh1bIqQ2.d.ts.map} +1 -1
- package/package.json +21 -12
- package/skills/acpx/SKILL.md +22 -5
- package/dist/client-FzXPdgP7.d.ts.map +0 -1
- package/dist/flags-D706STfk.js.map +0 -1
- package/dist/flows-hcjHmU7P.js.map +0 -1
- package/dist/live-checkpoint-B9ctAuqV.js.map +0 -1
- package/dist/output-BL9XRWzS.js.map +0 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { d as createSessionWithClient, f as cancelSessionPrompt, o as runOnce, s as sendSessionDirect, t as createOutputFormatter } from "./output-
|
|
2
|
-
import {
|
|
1
|
+
import { d as createSessionWithClient, f as cancelSessionPrompt, o as runOnce, s as sendSessionDirect, t as createOutputFormatter } from "./output-Di77Yugq.js";
|
|
2
|
+
import { $ as defaultSessionEventLog, Ft as PERMISSION_MODES, Lt as SESSION_RECORD_SCHEMA, R as resolveSessionRecord, _ 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-CuFft_Nd.js";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import fs from "node:fs/promises";
|
|
5
5
|
import os from "node:os";
|
|
6
|
-
import { spawn } from "node:child_process";
|
|
7
6
|
import { createHash, randomUUID } from "node:crypto";
|
|
8
7
|
import { ZodError, z } from "zod";
|
|
8
|
+
import { spawn } from "node:child_process";
|
|
9
9
|
//#region src/flows/authoring.ts
|
|
10
10
|
const FLOW_DEFINITION_BRAND = Symbol.for("acpx.flow.definition");
|
|
11
11
|
function markDefinedFlow(definition) {
|
|
@@ -236,6 +236,15 @@ function renderShellCommand(command, args) {
|
|
|
236
236
|
const renderedArgs = args.map((arg) => JSON.stringify(arg)).join(" ");
|
|
237
237
|
return renderedArgs.length > 0 ? `${command} ${renderedArgs}` : command;
|
|
238
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
|
+
}
|
|
239
248
|
async function runShellAction(spec) {
|
|
240
249
|
const cwd = spec.cwd ?? process.cwd();
|
|
241
250
|
const args = spec.args ?? [];
|
|
@@ -280,12 +289,9 @@ async function runShellAction(spec) {
|
|
|
280
289
|
signal,
|
|
281
290
|
durationMs: Date.now() - startMs
|
|
282
291
|
};
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
}
|
|
287
|
-
if (((exitCode ?? 0) !== 0 || signal != null) && spec.allowNonZeroExit !== true) {
|
|
288
|
-
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);
|
|
289
295
|
return;
|
|
290
296
|
}
|
|
291
297
|
resolve(result);
|
|
@@ -312,16 +318,20 @@ function validateFlowDefinition(flow) {
|
|
|
312
318
|
assertValidFlowDefinitionShape(flow);
|
|
313
319
|
if (!flow.nodes[flow.startAt]) throw new Error(`Flow start node is missing: ${flow.startAt}`);
|
|
314
320
|
const outgoingEdges = /* @__PURE__ */ new Set();
|
|
315
|
-
for (const edge of flow.edges)
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
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;
|
|
324
333
|
}
|
|
334
|
+
for (const target of Object.values(edge.switch.cases)) assertKnownFlowNode(flow, target, "Flow switch references unknown to-node");
|
|
325
335
|
}
|
|
326
336
|
function resolveNext(edges, from, output, result) {
|
|
327
337
|
const edge = edges.find((candidate) => candidate.from === from);
|
|
@@ -584,14 +594,16 @@ function extractAttachedStepTrace(error) {
|
|
|
584
594
|
}
|
|
585
595
|
function toInlineOutput(value) {
|
|
586
596
|
if (value == null || typeof value === "number" || typeof value === "boolean") return value;
|
|
587
|
-
if (typeof value === "string") return value
|
|
597
|
+
if (typeof value === "string") return isInlineSerializableText(value) ? value : void 0;
|
|
588
598
|
try {
|
|
589
|
-
|
|
590
|
-
if (serialized.length <= 200 && !serialized.includes("\n")) return value;
|
|
599
|
+
if (isInlineSerializableText(JSON.stringify(value))) return value;
|
|
591
600
|
} catch {
|
|
592
601
|
return;
|
|
593
602
|
}
|
|
594
603
|
}
|
|
604
|
+
function isInlineSerializableText(value) {
|
|
605
|
+
return value.length <= 200 && !value.includes("\n");
|
|
606
|
+
}
|
|
595
607
|
function outputArtifactMediaType(value) {
|
|
596
608
|
return typeof value === "string" ? "text/plain" : "application/json";
|
|
597
609
|
}
|
|
@@ -885,24 +897,9 @@ function createFlowDefinitionSnapshot(flow) {
|
|
|
885
897
|
};
|
|
886
898
|
}
|
|
887
899
|
function snapshotNode(node) {
|
|
888
|
-
const common =
|
|
889
|
-
nodeType: node.nodeType,
|
|
890
|
-
...node.timeoutMs !== void 0 ? { timeoutMs: node.timeoutMs } : {},
|
|
891
|
-
...node.heartbeatMs !== void 0 ? { heartbeatMs: node.heartbeatMs } : {},
|
|
892
|
-
...node.statusDetail ? { statusDetail: node.statusDetail } : {}
|
|
893
|
-
};
|
|
900
|
+
const common = snapshotCommonNodeFields(node);
|
|
894
901
|
switch (node.nodeType) {
|
|
895
|
-
case "acp": return
|
|
896
|
-
...common,
|
|
897
|
-
...node.profile ? { profile: node.profile } : {},
|
|
898
|
-
session: {
|
|
899
|
-
...node.session?.handle ? { handle: node.session.handle } : {},
|
|
900
|
-
...node.session?.isolated ? { isolated: true } : {}
|
|
901
|
-
},
|
|
902
|
-
cwd: snapshotCwd(node.cwd),
|
|
903
|
-
hasPrompt: true,
|
|
904
|
-
hasParse: typeof node.parse === "function"
|
|
905
|
-
};
|
|
902
|
+
case "acp": return snapshotAcpNode(node, common);
|
|
906
903
|
case "compute": return {
|
|
907
904
|
...common,
|
|
908
905
|
hasRun: true
|
|
@@ -925,6 +922,27 @@ function snapshotNode(node) {
|
|
|
925
922
|
}
|
|
926
923
|
throw new Error(`Unsupported flow node type: ${String(node)}`);
|
|
927
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
|
+
}
|
|
928
946
|
function snapshotCwd(cwd) {
|
|
929
947
|
if (typeof cwd === "function") return { mode: "dynamic" };
|
|
930
948
|
if (typeof cwd === "string") return {
|
|
@@ -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;
|
|
@@ -1703,18 +1738,25 @@ function parseJsonObject(text, options = {}) {
|
|
|
1703
1738
|
const mode = options.mode ?? "compat";
|
|
1704
1739
|
const direct = tryParse(trimmed);
|
|
1705
1740
|
if (direct.ok) return direct.value;
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
}
|
|
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;
|
|
1712
1746
|
}
|
|
1713
|
-
|
|
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)) {
|
|
1714
1756
|
const parsed = tryParse(candidate);
|
|
1715
|
-
if (parsed.ok) return parsed
|
|
1757
|
+
if (parsed.ok) return parsed;
|
|
1716
1758
|
}
|
|
1717
|
-
|
|
1759
|
+
return { ok: false };
|
|
1718
1760
|
}
|
|
1719
1761
|
function parseStrictJsonObject(text) {
|
|
1720
1762
|
return parseJsonObject(text, { mode: "strict" });
|
|
@@ -1761,27 +1803,50 @@ function scanBalanced(text, startIndex) {
|
|
|
1761
1803
|
for (let index = startIndex; index < text.length; index += 1) {
|
|
1762
1804
|
const char = text[index];
|
|
1763
1805
|
if (inString) {
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1806
|
+
const next = scanStringChar(char, escaped);
|
|
1807
|
+
escaped = next.escaped;
|
|
1808
|
+
inString = next.inString;
|
|
1767
1809
|
continue;
|
|
1768
1810
|
}
|
|
1769
1811
|
if (char === "\"") {
|
|
1770
1812
|
inString = true;
|
|
1771
1813
|
continue;
|
|
1772
1814
|
}
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
continue;
|
|
1776
|
-
}
|
|
1777
|
-
if (char !== "}" && char !== "]") continue;
|
|
1778
|
-
const last = stack.at(-1);
|
|
1779
|
-
if (last === "{" && char !== "}" || last === "[" && char !== "]") return null;
|
|
1780
|
-
stack.pop();
|
|
1781
|
-
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;
|
|
1782
1817
|
}
|
|
1783
1818
|
return null;
|
|
1784
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
|
+
}
|
|
1785
1850
|
//#endregion
|
|
1786
1851
|
//#region src/flows/decision.ts
|
|
1787
1852
|
const DEFAULT_FIELD = "route";
|
|
@@ -1851,4 +1916,4 @@ function formatDecisionPrompt(question, choices, field) {
|
|
|
1851
1916
|
//#endregion
|
|
1852
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 };
|
|
1853
1918
|
|
|
1854
|
-
//# sourceMappingURL=flows-
|
|
1919
|
+
//# sourceMappingURL=flows-e4umXVbY.js.map
|