acpx 0.15.1 → 0.17.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.
Files changed (47) hide show
  1. package/README.md +2 -0
  2. package/dist/agent-registry-DU6mhZBL.js +785 -0
  3. package/dist/agent-registry-DU6mhZBL.js.map +1 -0
  4. package/dist/agent-registry.d.ts +70 -0
  5. package/dist/agent-registry.d.ts.map +1 -0
  6. package/dist/agent-registry.js +2 -0
  7. package/dist/{cli-BHAT_D3V.js → cli-CiyfEC7L.js} +7 -14
  8. package/dist/cli-CiyfEC7L.js.map +1 -0
  9. package/dist/cli.d.ts +1 -1
  10. package/dist/cli.d.ts.map +1 -1
  11. package/dist/cli.js +160 -349
  12. package/dist/cli.js.map +1 -1
  13. package/dist/{client-Cvz6msGc.d.ts → client-C6NUFqr-.d.ts} +21 -13
  14. package/dist/client-C6NUFqr-.d.ts.map +1 -0
  15. package/dist/{flows-BOI1XkMp.js → flows-CTOdIk-m.js} +208 -279
  16. package/dist/flows-CTOdIk-m.js.map +1 -0
  17. package/dist/flows.d.ts +6 -17
  18. package/dist/flows.d.ts.map +1 -1
  19. package/dist/flows.js +1 -1
  20. package/dist/{flags-BHcZWTov.js → invocation-options-DbCcOAzM.js} +83 -58
  21. package/dist/invocation-options-DbCcOAzM.js.map +1 -0
  22. package/dist/ipc-D3akHMEq.js +3350 -0
  23. package/dist/ipc-D3akHMEq.js.map +1 -0
  24. package/dist/output-BPPjvJTI.js +980 -0
  25. package/dist/output-BPPjvJTI.js.map +1 -0
  26. package/dist/{live-checkpoint-sB7dFOYR.js → queue-owner-runtime--IbbndGz.js} +5359 -4574
  27. package/dist/queue-owner-runtime--IbbndGz.js.map +1 -0
  28. package/dist/runtime.d.ts +197 -27
  29. package/dist/runtime.d.ts.map +1 -1
  30. package/dist/runtime.js +864 -409
  31. package/dist/runtime.js.map +1 -1
  32. package/dist/{session-options-DyIGRNfu.d.ts → session-options-Dp6mzNSy.d.ts} +8 -6
  33. package/dist/session-options-Dp6mzNSy.d.ts.map +1 -0
  34. package/dist/session-watch--UX5dh00.js +76 -0
  35. package/dist/session-watch--UX5dh00.js.map +1 -0
  36. package/dist/watch-BbBxO-kb.js +32 -0
  37. package/dist/watch-BbBxO-kb.js.map +1 -0
  38. package/package.json +27 -25
  39. package/skills/acpx/SKILL.md +24 -19
  40. package/dist/cli-BHAT_D3V.js.map +0 -1
  41. package/dist/client-Cvz6msGc.d.ts.map +0 -1
  42. package/dist/flags-BHcZWTov.js.map +0 -1
  43. package/dist/flows-BOI1XkMp.js.map +0 -1
  44. package/dist/live-checkpoint-sB7dFOYR.js.map +0 -1
  45. package/dist/output-8-D6Gd4Z.js +0 -4714
  46. package/dist/output-8-D6Gd4Z.js.map +0 -1
  47. package/dist/session-options-DyIGRNfu.d.ts.map +0 -1
@@ -1,12 +1,15 @@
1
- import { d as createSessionWithClient, f as cancelSessionPrompt, o as runOnce, s as sendSessionDirect, t as createOutputFormatter } from "./output-8-D6Gd4Z.js";
2
- import { Dt as TimeoutError, Et as InterruptedError, F as runTimedExecFile, Ot as withInterrupt, Tt as textPrompt, Y as resolveSessionRecord, Yt as PERMISSION_MODES, Zt as SESSION_RECORD_SCHEMA, _ as recordPromptSubmission, dt as defaultSessionEventLog, g as recordClientOperation, h as createSessionConversation, kt as withTimeout, p as cloneSessionAcpxState, v as recordSessionUpdate, wt as promptToDisplayText } from "./live-checkpoint-sB7dFOYR.js";
1
+ import { t as createOutputFormatter } from "./output-BPPjvJTI.js";
2
+ import { C as textPrompt, Dt as SESSION_RECORD_SCHEMA, F as resolveSessionRecord, S as promptToDisplayText, Tt as PERMISSION_MODES, ct as defaultSessionEventLog, mt as writePrivateJsonFile, pt as writePrivateFile } from "./ipc-D3akHMEq.js";
3
+ import { B as recordClientOperation, H as recordSessionUpdate, L as cloneSessionAcpxState, V as recordPromptSubmission, _ as cancelSessionPrompt, at as withInterrupt, i as runOnce, m as createSessionWithClient, nt as InterruptedError, o as sendSessionDirect, ot as withTimeout, rt as TimeoutError, z as createSessionConversation } from "./queue-owner-runtime--IbbndGz.js";
4
+ import { M as runTimedExecFile } from "./agent-registry-DU6mhZBL.js";
3
5
  import path from "node:path";
6
+ import { spawn } from "node:child_process";
4
7
  import fs from "node:fs/promises";
5
8
  import os from "node:os";
6
- import { createHash, randomUUID } from "node:crypto";
7
- import { ZodError, z } from "zod";
8
- import { spawn } from "node:child_process";
9
+ import { appendRegularFile } from "@openclaw/fs-safe/advanced";
9
10
  import { setTimeout as setTimeout$1 } from "node:timers/promises";
11
+ import { ZodError, z } from "zod";
12
+ import { createHash, randomUUID } from "node:crypto";
10
13
  //#region src/flows/authoring.ts
11
14
  const FLOW_DEFINITION_BRAND = Symbol.for("acpx.flow.definition");
12
15
  function markDefinedFlow(definition) {
@@ -592,9 +595,12 @@ function validateFlowEdge(flow, edge, outgoingEdges) {
592
595
  }
593
596
  for (const target of Object.values(edge.switch.cases)) assertKnownFlowNode(flow, target, "Flow switch references unknown to-node");
594
597
  }
598
+ function canFollowEdge(edge, result) {
599
+ return !result || result.outcome === "ok" || "switch" in edge && edge.switch.on.startsWith("$result.");
600
+ }
595
601
  function resolveNext(edges, from, output, result) {
596
602
  const edge = edges.find((candidate) => candidate.from === from);
597
- if (!edge) return null;
603
+ if (!edge || !canFollowEdge(edge, result)) return null;
598
604
  if ("to" in edge) return edge.to;
599
605
  const value = getBySwitchPath(output, result, edge.switch.on);
600
606
  if (typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean") throw new Error(`Flow switch value must be scalar for ${edge.switch.on}`);
@@ -602,16 +608,6 @@ function resolveNext(edges, from, output, result) {
602
608
  if (!next) throw new Error(`No flow switch case for ${edge.switch.on}=${JSON.stringify(value)}`);
603
609
  return next;
604
610
  }
605
- function resolveNextForOutcome(edges, from, result) {
606
- const edge = edges.find((candidate) => candidate.from === from);
607
- if (!edge || "to" in edge) return null;
608
- if (!edge.switch.on.startsWith("$result.")) return null;
609
- const value = getBySwitchPath(void 0, result, edge.switch.on);
610
- if (typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean") throw new Error(`Flow switch value must be scalar for ${edge.switch.on}`);
611
- const next = edge.switch.cases[String(value)];
612
- if (!next) throw new Error(`No flow switch case for ${edge.switch.on}=${JSON.stringify(value)}`);
613
- return next;
614
- }
615
611
  function getBySwitchPath(output, result, jsonPath) {
616
612
  if (jsonPath.startsWith("$result.")) return getByPath(result, `$.${jsonPath.slice(8)}`);
617
613
  if (jsonPath.startsWith("$output.")) return getByPath(output, `$.${jsonPath.slice(8)}`);
@@ -919,41 +915,30 @@ var FlowRunStore = class {
919
915
  }
920
916
  async createRunDir(runId) {
921
917
  const runDir = path.join(this.outputRoot, runId);
922
- await fs.mkdir(path.join(runDir, PROJECTIONS_DIR), { recursive: true });
923
- await fs.mkdir(path.join(runDir, SESSIONS_DIR), { recursive: true });
924
- await fs.mkdir(path.join(runDir, ARTIFACTS_DIR), { recursive: true });
918
+ await fs.mkdir(path.join(runDir, PROJECTIONS_DIR), {
919
+ recursive: true,
920
+ mode: 448
921
+ });
922
+ await fs.mkdir(path.join(runDir, SESSIONS_DIR), {
923
+ recursive: true,
924
+ mode: 448
925
+ });
926
+ await fs.mkdir(path.join(runDir, ARTIFACTS_DIR), {
927
+ recursive: true,
928
+ mode: 448
929
+ });
925
930
  this.traceSeqByRun.set(runDir, 0);
926
931
  return runDir;
927
932
  }
928
933
  async initializeRunBundle(runDir, options) {
929
934
  const snapshot = createFlowDefinitionSnapshot(options.flow);
930
- const manifest = {
931
- schema: FLOW_BUNDLE_SCHEMA,
932
- runId: options.state.runId,
933
- flowName: options.state.flowName,
934
- runTitle: options.state.runTitle,
935
- flowPath: options.state.flowPath,
936
- startedAt: options.state.startedAt,
937
- finishedAt: options.state.finishedAt,
938
- status: options.state.status,
939
- traceSchema: FLOW_TRACE_SCHEMA,
940
- paths: {
941
- flow: FLOW_SNAPSHOT_PATH,
942
- trace: TRACE_PATH,
943
- runProjection: RUN_PROJECTION_PATH,
944
- liveProjection: LIVE_PROJECTION_PATH,
945
- stepsProjection: STEPS_PROJECTION_PATH,
946
- sessionsDir: SESSIONS_DIR,
947
- artifactsDir: ARTIFACTS_DIR
948
- },
949
- sessions: []
950
- };
935
+ const manifest = createRunManifest(options.state);
951
936
  this.manifestByRun.set(runDir, manifest);
952
- await writeJsonAtomic(this.resolveRunPath(runDir, FLOW_SNAPSHOT_PATH), snapshot);
953
- await writeJsonAtomic(this.resolveRunPath(runDir, MANIFEST_PATH), manifest);
954
- await writeJsonAtomic(this.resolveRunPath(runDir, RUN_PROJECTION_PATH), options.state);
955
- await writeJsonAtomic(this.resolveRunPath(runDir, LIVE_PROJECTION_PATH), createLiveState(options.state));
956
- await writeJsonAtomic(this.resolveRunPath(runDir, STEPS_PROJECTION_PATH), options.state.steps);
937
+ await writePrivateJsonFile(this.resolveRunPath(runDir, FLOW_SNAPSHOT_PATH), snapshot);
938
+ await writePrivateJsonFile(this.resolveRunPath(runDir, MANIFEST_PATH), manifest);
939
+ await writePrivateJsonFile(this.resolveRunPath(runDir, RUN_PROJECTION_PATH), options.state);
940
+ await writePrivateJsonFile(this.resolveRunPath(runDir, LIVE_PROJECTION_PATH), createLiveState(options.state));
941
+ await writePrivateJsonFile(this.resolveRunPath(runDir, STEPS_PROJECTION_PATH), options.state.steps);
957
942
  await ensureFile(this.resolveRunPath(runDir, TRACE_PATH));
958
943
  await this.appendTrace(runDir, options.state, {
959
944
  scope: "run",
@@ -968,15 +953,15 @@ var FlowRunStore = class {
968
953
  }
969
954
  async writeSnapshot(runDir, state, event) {
970
955
  state.updatedAt = isoNow();
971
- await writeJsonAtomic(this.resolveRunPath(runDir, RUN_PROJECTION_PATH), state);
972
- await writeJsonAtomic(this.resolveRunPath(runDir, LIVE_PROJECTION_PATH), createLiveState(state));
973
- await writeJsonAtomic(this.resolveRunPath(runDir, STEPS_PROJECTION_PATH), state.steps);
956
+ await writePrivateJsonFile(this.resolveRunPath(runDir, RUN_PROJECTION_PATH), state);
957
+ await writePrivateJsonFile(this.resolveRunPath(runDir, LIVE_PROJECTION_PATH), createLiveState(state));
958
+ await writePrivateJsonFile(this.resolveRunPath(runDir, STEPS_PROJECTION_PATH), state.steps);
974
959
  await this.writeManifest(runDir, state);
975
960
  await this.appendTrace(runDir, state, event);
976
961
  }
977
962
  async writeLive(runDir, state, event) {
978
963
  state.updatedAt = isoNow();
979
- await writeJsonAtomic(this.resolveRunPath(runDir, LIVE_PROJECTION_PATH), createLiveState(state));
964
+ await writePrivateJsonFile(this.resolveRunPath(runDir, LIVE_PROJECTION_PATH), createLiveState(state));
980
965
  await this.writeManifest(runDir, state);
981
966
  await this.appendTrace(runDir, state, event);
982
967
  }
@@ -995,11 +980,10 @@ var FlowRunStore = class {
995
980
  const sha256 = createHash("sha256").update(buffer).digest("hex");
996
981
  const relativePath = path.posix.join(ARTIFACTS_DIR, `sha256-${sha256}${normalizeArtifactExtension(options.extension)}`);
997
982
  const filePath = this.resolveRunPath(runDir, relativePath);
998
- await fs.mkdir(path.dirname(filePath), { recursive: true });
999
983
  try {
1000
984
  await fs.access(filePath);
1001
985
  } catch {
1002
- await fs.writeFile(filePath, buffer);
986
+ await writePrivateFile(filePath, buffer);
1003
987
  }
1004
988
  const artifact = {
1005
989
  path: relativePath,
@@ -1020,8 +1004,11 @@ var FlowRunStore = class {
1020
1004
  }
1021
1005
  async ensureSessionBundle(runDir, state, binding, record) {
1022
1006
  const sessionDir = this.resolveRunPath(runDir, sessionDirPath(binding.bundleId));
1023
- await fs.mkdir(sessionDir, { recursive: true });
1024
- await writeJsonAtomic(path.join(sessionDir, "binding.json"), binding);
1007
+ await fs.mkdir(sessionDir, {
1008
+ recursive: true,
1009
+ mode: 448
1010
+ });
1011
+ await writePrivateJsonFile(path.join(sessionDir, "binding.json"), binding);
1025
1012
  await ensureFile(path.join(sessionDir, "events.ndjson"));
1026
1013
  if (record) await this.writeSessionRecord(runDir, state, binding, record);
1027
1014
  const manifest = this.getManifest(runDir, state);
@@ -1035,7 +1022,7 @@ var FlowRunStore = class {
1035
1022
  eventsPath: path.posix.join(sessionDirPath(binding.bundleId), "events.ndjson")
1036
1023
  };
1037
1024
  manifest.sessions.push(entry);
1038
- await writeJsonAtomic(this.resolveRunPath(runDir, MANIFEST_PATH), manifest);
1025
+ await writePrivateJsonFile(this.resolveRunPath(runDir, MANIFEST_PATH), manifest);
1039
1026
  }
1040
1027
  if (isNew) await this.appendTrace(runDir, state, {
1041
1028
  scope: "session",
@@ -1054,7 +1041,7 @@ var FlowRunStore = class {
1054
1041
  }
1055
1042
  async writeSessionRecord(runDir, _state, binding, record) {
1056
1043
  const bundledRecord = createBundledSessionRecord(binding, record, this.sessionSeqByBundle.get(`${runDir}::${binding.bundleId}`) ?? 0);
1057
- await writeJsonAtomic(this.resolveRunPath(runDir, path.posix.join(sessionDirPath(binding.bundleId), "record.json")), bundledRecord);
1044
+ await writePrivateJsonFile(this.resolveRunPath(runDir, path.posix.join(sessionDirPath(binding.bundleId), "record.json")), bundledRecord);
1058
1045
  }
1059
1046
  async appendSessionEvent(runDir, binding, direction, message) {
1060
1047
  const sessionKey = `${runDir}::${binding.bundleId}`;
@@ -1079,33 +1066,13 @@ var FlowRunStore = class {
1079
1066
  existing.runTitle = state.runTitle;
1080
1067
  return existing;
1081
1068
  }
1082
- const created = {
1083
- schema: FLOW_BUNDLE_SCHEMA,
1084
- runId: state.runId,
1085
- flowName: state.flowName,
1086
- runTitle: state.runTitle,
1087
- flowPath: state.flowPath,
1088
- startedAt: state.startedAt,
1089
- finishedAt: state.finishedAt,
1090
- status: state.status,
1091
- traceSchema: FLOW_TRACE_SCHEMA,
1092
- paths: {
1093
- flow: FLOW_SNAPSHOT_PATH,
1094
- trace: TRACE_PATH,
1095
- runProjection: RUN_PROJECTION_PATH,
1096
- liveProjection: LIVE_PROJECTION_PATH,
1097
- stepsProjection: STEPS_PROJECTION_PATH,
1098
- sessionsDir: SESSIONS_DIR,
1099
- artifactsDir: ARTIFACTS_DIR
1100
- },
1101
- sessions: []
1102
- };
1069
+ const created = createRunManifest(state);
1103
1070
  this.manifestByRun.set(runDir, created);
1104
1071
  return created;
1105
1072
  }
1106
1073
  async writeManifest(runDir, state) {
1107
1074
  const manifest = this.getManifest(runDir, state);
1108
- await writeJsonAtomic(this.resolveRunPath(runDir, MANIFEST_PATH), manifest);
1075
+ await writePrivateJsonFile(this.resolveRunPath(runDir, MANIFEST_PATH), manifest);
1109
1076
  }
1110
1077
  nextTraceSeq(runDir) {
1111
1078
  const next = (this.traceSeqByRun.get(runDir) ?? 0) + 1;
@@ -1117,8 +1084,15 @@ var FlowRunStore = class {
1117
1084
  }
1118
1085
  async appendJsonLine(filePath, value) {
1119
1086
  const tracked = (this.appendChainByPath.get(filePath) ?? Promise.resolve()).then(async () => {
1120
- await fs.mkdir(path.dirname(filePath), { recursive: true });
1121
- await fs.appendFile(filePath, `${JSON.stringify(value)}\n`, "utf8");
1087
+ await fs.mkdir(path.dirname(filePath), {
1088
+ recursive: true,
1089
+ mode: 448
1090
+ });
1091
+ await appendRegularFile({
1092
+ filePath,
1093
+ content: `${JSON.stringify(value)}\n`,
1094
+ mode: 384
1095
+ });
1122
1096
  }).finally(() => {
1123
1097
  if (this.appendChainByPath.get(filePath) === tracked) this.appendChainByPath.delete(filePath);
1124
1098
  });
@@ -1126,6 +1100,29 @@ var FlowRunStore = class {
1126
1100
  await tracked;
1127
1101
  }
1128
1102
  };
1103
+ function createRunManifest(state) {
1104
+ return {
1105
+ schema: FLOW_BUNDLE_SCHEMA,
1106
+ runId: state.runId,
1107
+ flowName: state.flowName,
1108
+ runTitle: state.runTitle,
1109
+ flowPath: state.flowPath,
1110
+ startedAt: state.startedAt,
1111
+ finishedAt: state.finishedAt,
1112
+ status: state.status,
1113
+ traceSchema: FLOW_TRACE_SCHEMA,
1114
+ paths: {
1115
+ flow: FLOW_SNAPSHOT_PATH,
1116
+ trace: TRACE_PATH,
1117
+ runProjection: RUN_PROJECTION_PATH,
1118
+ liveProjection: LIVE_PROJECTION_PATH,
1119
+ stepsProjection: STEPS_PROJECTION_PATH,
1120
+ sessionsDir: SESSIONS_DIR,
1121
+ artifactsDir: ARTIFACTS_DIR
1122
+ },
1123
+ sessions: []
1124
+ };
1125
+ }
1129
1126
  function createLiveState(state) {
1130
1127
  return {
1131
1128
  runId: state.runId,
@@ -1225,16 +1222,12 @@ function createBundledSessionRecord(binding, record, bundleLastSeq) {
1225
1222
  }
1226
1223
  };
1227
1224
  }
1228
- async function writeJsonAtomic(filePath, value) {
1229
- const tempPath = `${filePath}.${process.pid}.${Date.now()}.${randomUUID()}.tmp`;
1230
- const payload = JSON.stringify(value, null, 2);
1231
- await fs.mkdir(path.dirname(filePath), { recursive: true });
1232
- await fs.writeFile(tempPath, `${payload}\n`, "utf8");
1233
- await fs.rename(tempPath, filePath);
1234
- }
1235
1225
  async function ensureFile(filePath) {
1236
- await fs.mkdir(path.dirname(filePath), { recursive: true });
1237
- await fs.appendFile(filePath, "", "utf8");
1226
+ await appendRegularFile({
1227
+ filePath,
1228
+ content: "",
1229
+ mode: 384
1230
+ });
1238
1231
  }
1239
1232
  async function fileSha256(filePath) {
1240
1233
  const payload = await fs.readFile(filePath);
@@ -1264,16 +1257,8 @@ const DEFAULT_FLOW_STEP_TIMEOUT_MS = 9e5;
1264
1257
  var FlowRunner = class {
1265
1258
  resolveAgent;
1266
1259
  defaultCwd;
1267
- permissionMode;
1268
- mcpServers;
1269
- nonInteractivePermissions;
1270
- permissionPolicy;
1271
- authCredentials;
1272
- authPolicy;
1273
- fs;
1274
- timeoutMs;
1260
+ connectionOptions;
1275
1261
  defaultNodeTimeoutMs;
1276
- verbose;
1277
1262
  suppressSdkConsoleErrors;
1278
1263
  sessionOptions;
1279
1264
  services;
@@ -1285,16 +1270,17 @@ var FlowRunner = class {
1285
1270
  constructor(options) {
1286
1271
  this.resolveAgent = options.resolveAgent;
1287
1272
  this.defaultCwd = options.resolveAgent(void 0).cwd;
1288
- this.permissionMode = options.permissionMode;
1289
- this.mcpServers = options.mcpServers;
1290
- this.nonInteractivePermissions = options.nonInteractivePermissions;
1291
- this.permissionPolicy = options.permissionPolicy;
1292
- this.authCredentials = options.authCredentials;
1293
- this.authPolicy = options.authPolicy;
1294
- this.fs = options.fs;
1295
- this.timeoutMs = options.timeoutMs;
1273
+ this.connectionOptions = {
1274
+ permissionMode: options.permissionMode,
1275
+ mcpServers: options.mcpServers,
1276
+ nonInteractivePermissions: options.nonInteractivePermissions,
1277
+ permissionPolicy: options.permissionPolicy,
1278
+ authCredentials: options.authCredentials,
1279
+ authPolicy: options.authPolicy,
1280
+ fs: options.fs,
1281
+ verbose: options.verbose
1282
+ };
1296
1283
  this.defaultNodeTimeoutMs = options.defaultNodeTimeoutMs ?? options.timeoutMs ?? DEFAULT_FLOW_STEP_TIMEOUT_MS;
1297
- this.verbose = options.verbose;
1298
1284
  this.suppressSdkConsoleErrors = options.suppressSdkConsoleErrors;
1299
1285
  this.sessionOptions = options.sessionOptions;
1300
1286
  this.services = options.services ?? {};
@@ -1432,16 +1418,47 @@ var FlowRunner = class {
1432
1418
  const startedAt = isoNow$1();
1433
1419
  markNodeStarted(state, nodeId, attemptId, node.nodeType, startedAt, node.statusDetail);
1434
1420
  await this.writeNodeStartedSnapshot(runDir, state, nodeId, attemptId, node);
1435
- return await this.executeStartedFlowStep({
1436
- flow,
1437
- input,
1438
- runDir,
1439
- state,
1440
- nodeId,
1441
- node,
1421
+ const context = makeFlowNodeContext(state, input, this.services);
1422
+ let executed;
1423
+ let outcome = "ok";
1424
+ let executionError;
1425
+ try {
1426
+ this.throwIfRunInterrupted(runDir);
1427
+ executed = await this.executeNode(runDir, state, flow, nodeId, node, context);
1428
+ this.throwIfRunInterrupted(runDir);
1429
+ executed.trace = await finalizeStepTrace(this.store, runDir, state, nodeId, attemptId, executed.output, executed.trace);
1430
+ } catch (error) {
1431
+ outcome = outcomeForError(error);
1432
+ executionError = error;
1433
+ executed = {
1434
+ output: void 0,
1435
+ promptText: null,
1436
+ rawText: null,
1437
+ sessionInfo: null,
1438
+ agentInfo: null,
1439
+ trace: await finalizeStepTrace(this.store, runDir, state, nodeId, attemptId, void 0, extractAttachedStepTrace(error) ?? null)
1440
+ };
1441
+ }
1442
+ const nodeResult = createNodeResult({
1442
1443
  attemptId,
1443
- startedAt
1444
+ nodeId,
1445
+ nodeType: node.nodeType,
1446
+ outcome,
1447
+ startedAt,
1448
+ finishedAt: isoNow$1(),
1449
+ ...outcome === "ok" ? { output: executed.output } : { error: executionError instanceof Error ? executionError.message : String(executionError) }
1444
1450
  });
1451
+ state.results[nodeId] = nodeResult;
1452
+ return {
1453
+ ...executed,
1454
+ nodeResult,
1455
+ executionError,
1456
+ attemptId,
1457
+ nodeId,
1458
+ node,
1459
+ startedAt,
1460
+ state
1461
+ };
1445
1462
  }
1446
1463
  async writeNodeStartedSnapshot(runDir, state, nodeId, attemptId, node) {
1447
1464
  await this.store.writeSnapshot(runDir, state, {
@@ -1451,84 +1468,18 @@ var FlowRunner = class {
1451
1468
  attemptId,
1452
1469
  payload: {
1453
1470
  nodeType: node.nodeType,
1454
- ...node.timeoutMs !== void 0 ? { timeoutMs: node.timeoutMs ?? this.defaultNodeTimeoutMs } : { timeoutMs: this.defaultNodeTimeoutMs },
1471
+ timeoutMs: node.timeoutMs ?? this.defaultNodeTimeoutMs,
1455
1472
  ...state.statusDetail ? { statusDetail: state.statusDetail } : {}
1456
1473
  }
1457
1474
  });
1458
1475
  }
1459
- async executeStartedFlowStep(params) {
1460
- const context = makeFlowNodeContext(params.state, params.input, this.services);
1461
- try {
1462
- this.throwIfRunInterrupted(params.runDir);
1463
- const executed = await this.executeNode(params.runDir, params.state, params.flow, params.nodeId, params.node, context);
1464
- this.throwIfRunInterrupted(params.runDir);
1465
- return await this.createSuccessfulFlowStep(params, executed);
1466
- } catch (error) {
1467
- return await this.createFailedFlowStep(params, error);
1468
- }
1469
- }
1470
- async createSuccessfulFlowStep(params, executed) {
1471
- const trace = await finalizeStepTrace(this.store, params.runDir, params.state, params.nodeId, params.attemptId, executed.output, executed.trace);
1472
- const nodeResult = createNodeResult({
1473
- attemptId: params.attemptId,
1474
- nodeId: params.nodeId,
1475
- nodeType: params.node.nodeType,
1476
- outcome: "ok",
1477
- startedAt: params.startedAt,
1478
- finishedAt: isoNow$1(),
1479
- output: executed.output
1480
- });
1481
- params.state.results[params.nodeId] = nodeResult;
1482
- return {
1483
- ...executed,
1484
- trace,
1485
- nodeResult,
1486
- attemptId: params.attemptId,
1487
- nodeId: params.nodeId,
1488
- node: params.node,
1489
- startedAt: params.startedAt,
1490
- state: params.state
1491
- };
1492
- }
1493
- async createFailedFlowStep(params, error) {
1494
- const trace = await finalizeStepTrace(this.store, params.runDir, params.state, params.nodeId, params.attemptId, void 0, extractAttachedStepTrace(error) ?? null);
1495
- const nodeResult = createNodeResult({
1496
- attemptId: params.attemptId,
1497
- nodeId: params.nodeId,
1498
- nodeType: params.node.nodeType,
1499
- outcome: outcomeForError(error),
1500
- startedAt: params.startedAt,
1501
- finishedAt: isoNow$1(),
1502
- error: error instanceof Error ? error.message : String(error)
1503
- });
1504
- params.state.results[params.nodeId] = nodeResult;
1505
- return {
1506
- output: void 0,
1507
- promptText: null,
1508
- rawText: null,
1509
- sessionInfo: null,
1510
- agentInfo: null,
1511
- trace,
1512
- nodeResult,
1513
- executionError: error,
1514
- attemptId: params.attemptId,
1515
- nodeId: params.nodeId,
1516
- node: params.node,
1517
- startedAt: params.startedAt,
1518
- state: params.state
1519
- };
1520
- }
1521
1476
  async maybeCompleteCheckpointStep(runDir, state, step) {
1522
1477
  if (step.nodeResult.outcome !== "ok" || step.node.nodeType !== "checkpoint") return;
1523
1478
  state.outputs[step.nodeId] = step.output;
1524
1479
  state.waitingOn = step.nodeId;
1525
1480
  state.updatedAt = isoNow$1();
1526
1481
  state.status = "waiting";
1527
- await this.recordFlowStepOutcome(runDir, state, step, {
1528
- sessionInfo: null,
1529
- agentInfo: null,
1530
- statusDetail: step.output?.summary ?? step.nodeId
1531
- });
1482
+ await this.recordFlowStepOutcome(runDir, state, step, { statusDetail: step.output?.summary ?? step.nodeId });
1532
1483
  return {
1533
1484
  runDir,
1534
1485
  state
@@ -1539,7 +1490,7 @@ var FlowRunner = class {
1539
1490
  step.state.outputs[step.nodeId] = step.output;
1540
1491
  return resolveNext(flow.edges, step.nodeId, step.output, step.nodeResult);
1541
1492
  }
1542
- const next = resolveNextForOutcome(flow.edges, step.nodeId, step.nodeResult);
1493
+ const next = resolveNext(flow.edges, step.nodeId, void 0, step.nodeResult);
1543
1494
  if (next) return next;
1544
1495
  throw step.executionError;
1545
1496
  }
@@ -1572,8 +1523,8 @@ var FlowRunner = class {
1572
1523
  rawText: step.rawText,
1573
1524
  output: step.output,
1574
1525
  error: step.nodeResult.error,
1575
- session: overrides.sessionInfo ?? step.sessionInfo,
1576
- agent: overrides.agentInfo ?? step.agentInfo,
1526
+ session: step.sessionInfo,
1527
+ agent: step.agentInfo,
1577
1528
  ...step.trace ? { trace: step.trace } : {}
1578
1529
  });
1579
1530
  await this.store.writeSnapshot(runDir, state, {
@@ -1586,34 +1537,28 @@ var FlowRunner = class {
1586
1537
  }
1587
1538
  async executeNode(runDir, state, flow, nodeId, node, context) {
1588
1539
  switch (node.nodeType) {
1589
- case "compute": return await this.executeComputeNode(runDir, state, node, context);
1590
- case "action": return await this.executeActionNode(runDir, state, node, context);
1591
- case "checkpoint": return await this.executeCheckpointNode(runDir, state, nodeId, node, context);
1540
+ case "compute": return await this.executeCallbackNode(runDir, state, nodeId, node, context);
1541
+ case "action": return "run" in node ? await this.executeCallbackNode(runDir, state, nodeId, node, context) : await this.executeShellNode(runDir, state, node, context);
1542
+ case "checkpoint": return await this.executeCallbackNode(runDir, state, nodeId, node, context);
1592
1543
  case "acp": return await this.executeAcpNode(runDir, state, flow, node, context);
1593
1544
  default: throw new Error(`Unsupported flow node: ${String(node)}`);
1594
1545
  }
1595
1546
  }
1596
- async executeComputeNode(runDir, state, node, context) {
1597
- const nodeTimeoutMs = node.timeoutMs ?? this.defaultNodeTimeoutMs;
1547
+ async executeCallbackNode(runDir, state, nodeId, node, context) {
1598
1548
  return {
1599
- output: await this.runWithHeartbeat(runDir, state, state.currentNode ?? "", node, nodeTimeoutMs, async () => await Promise.resolve(node.run(context))),
1549
+ output: node.nodeType === "checkpoint" && typeof node.run !== "function" ? {
1550
+ checkpoint: nodeId,
1551
+ summary: node.summary ?? nodeId
1552
+ } : await this.runWithHeartbeat(runDir, state, nodeId, node, node.timeoutMs ?? this.defaultNodeTimeoutMs, async () => await node.run?.(context)),
1600
1553
  promptText: null,
1601
1554
  rawText: null,
1602
1555
  sessionInfo: null,
1603
1556
  agentInfo: null,
1604
- trace: null
1557
+ trace: node.nodeType === "action" ? { action: { actionType: "function" } } : null
1605
1558
  };
1606
1559
  }
1607
- async executeActionNode(runDir, state, node, context) {
1560
+ async executeShellNode(runDir, state, node, context) {
1608
1561
  const nodeTimeoutMs = node.timeoutMs ?? this.defaultNodeTimeoutMs;
1609
- if ("run" in node) return {
1610
- output: await this.runWithHeartbeat(runDir, state, state.currentNode ?? "", node, nodeTimeoutMs, async () => await Promise.resolve(node.run(context))),
1611
- promptText: null,
1612
- rawText: null,
1613
- sessionInfo: null,
1614
- agentInfo: null,
1615
- trace: { action: { actionType: "function" } }
1616
- };
1617
1562
  const shellAbort = new AbortController();
1618
1563
  let runningOwner;
1619
1564
  const shellControl = {
@@ -1739,20 +1684,6 @@ var FlowRunner = class {
1739
1684
  trace
1740
1685
  };
1741
1686
  }
1742
- async executeCheckpointNode(runDir, state, nodeId, node, context) {
1743
- const nodeTimeoutMs = node.timeoutMs ?? this.defaultNodeTimeoutMs;
1744
- return {
1745
- output: typeof node.run === "function" ? await this.runWithHeartbeat(runDir, state, state.currentNode ?? "", node, nodeTimeoutMs, async () => await Promise.resolve(node.run?.(context))) : {
1746
- checkpoint: nodeId,
1747
- summary: node.summary ?? nodeId
1748
- },
1749
- promptText: null,
1750
- rawText: null,
1751
- sessionInfo: null,
1752
- agentInfo: null,
1753
- trace: null
1754
- };
1755
- }
1756
1687
  async executeAcpNode(runDir, state, flow, node, context) {
1757
1688
  const nodeTimeoutMs = node.timeoutMs ?? this.defaultNodeTimeoutMs;
1758
1689
  let boundSession = null;
@@ -1932,15 +1863,8 @@ var FlowRunner = class {
1932
1863
  agentArgv: agent.agentArgv,
1933
1864
  cwd: agent.cwd,
1934
1865
  name,
1935
- mcpServers: this.mcpServers,
1936
- permissionMode: this.permissionMode,
1937
- nonInteractivePermissions: this.nonInteractivePermissions,
1938
- permissionPolicy: this.permissionPolicy,
1939
- authCredentials: this.authCredentials,
1940
- authPolicy: this.authPolicy,
1941
- fs: this.fs,
1866
+ ...this.connectionOptions,
1942
1867
  timeoutMs,
1943
- verbose: this.verbose,
1944
1868
  sessionOptions: this.sessionOptions
1945
1869
  });
1946
1870
  const binding = {
@@ -1970,40 +1894,68 @@ var FlowRunner = class {
1970
1894
  agentSessionId: record.agentSessionId
1971
1895
  };
1972
1896
  }
1897
+ createPromptEventCapture(runDir, binding) {
1898
+ const pending = [];
1899
+ return {
1900
+ onAcpMessage: (direction, message) => {
1901
+ pending.push(this.store.appendSessionEvent(runDir, binding, direction, message).then((value) => ({
1902
+ status: "fulfilled",
1903
+ value
1904
+ }), (reason) => ({
1905
+ status: "rejected",
1906
+ reason
1907
+ })));
1908
+ },
1909
+ async run(operation) {
1910
+ let result;
1911
+ try {
1912
+ result = {
1913
+ status: "fulfilled",
1914
+ value: await operation()
1915
+ };
1916
+ } catch (reason) {
1917
+ result = {
1918
+ status: "rejected",
1919
+ reason
1920
+ };
1921
+ }
1922
+ const writes = await Promise.all(pending);
1923
+ if (result.status === "rejected") throw result.reason;
1924
+ let eventStartSeq;
1925
+ let eventEndSeq = 0;
1926
+ for (const write of writes) {
1927
+ if (write.status === "rejected") throw write.reason;
1928
+ eventStartSeq = Math.min(eventStartSeq ?? write.value, write.value);
1929
+ eventEndSeq = Math.max(eventEndSeq, write.value);
1930
+ }
1931
+ if (eventStartSeq === void 0) throw new Error(`Missing ACP event capture for session ${binding.bundleId}`);
1932
+ return {
1933
+ result: result.value,
1934
+ eventStartSeq,
1935
+ eventEndSeq
1936
+ };
1937
+ }
1938
+ };
1939
+ }
1973
1940
  async runPersistentPrompt(runDir, state, binding, prompt, timeoutMs) {
1974
1941
  const capture = createQuietCaptureOutput();
1975
1942
  const beforeRecord = await resolveSessionRecord(binding.acpxRecordId);
1976
- let eventStartSeq;
1977
- let eventEndSeq;
1978
- const pendingEventWrites = [];
1943
+ const events = this.createPromptEventCapture(runDir, binding);
1979
1944
  const initialClient = this.pendingPersistentSessionClients.get(binding.key);
1980
1945
  if (initialClient) this.pendingPersistentSessionClients.delete(binding.key);
1981
1946
  try {
1982
- await sendSessionDirect({
1947
+ const { eventStartSeq, eventEndSeq } = await events.run(() => sendSessionDirect({
1983
1948
  sessionId: binding.acpxRecordId,
1984
1949
  prompt,
1985
1950
  resumePolicy: "same-session-only",
1986
- mcpServers: this.mcpServers,
1987
- permissionMode: this.permissionMode,
1988
- nonInteractivePermissions: this.nonInteractivePermissions,
1989
- permissionPolicy: this.permissionPolicy,
1990
- authCredentials: this.authCredentials,
1991
- authPolicy: this.authPolicy,
1992
- fs: this.fs,
1951
+ ...this.connectionOptions,
1993
1952
  outputFormatter: capture.formatter,
1994
- onAcpMessage: (direction, message) => {
1995
- const pending = this.store.appendSessionEvent(runDir, binding, direction, message).then((seq) => {
1996
- eventStartSeq = eventStartSeq === void 0 ? seq : Math.min(eventStartSeq, seq);
1997
- eventEndSeq = eventEndSeq === void 0 ? seq : Math.max(eventEndSeq, seq);
1998
- });
1999
- pendingEventWrites.push(pending);
2000
- },
1953
+ errorEmissionPolicy: { queueErrorAlreadyEmitted: false },
1954
+ onAcpMessage: events.onAcpMessage,
2001
1955
  suppressSdkConsoleErrors: this.suppressSdkConsoleErrors,
2002
1956
  timeoutMs,
2003
- verbose: this.verbose,
2004
1957
  client: initialClient
2005
- });
2006
- await Promise.all(pendingEventWrites);
1958
+ }));
2007
1959
  const sessionInfo = await this.refreshSessionBinding(binding);
2008
1960
  state.sessionBindings[sessionInfo.key] = sessionInfo;
2009
1961
  await this.store.ensureSessionBundle(runDir, state, sessionInfo);
@@ -2017,12 +1969,8 @@ var FlowRunner = class {
2017
1969
  sessionId: sessionInfo.bundleId,
2018
1970
  messageStart: messageStartResolved,
2019
1971
  messageEnd: Math.max(messageStartResolved, afterRecord.messages.length - 1),
2020
- eventStartSeq: eventStartSeq ?? (() => {
2021
- throw new Error(`Missing ACP event capture for session ${sessionInfo.bundleId}`);
2022
- })(),
2023
- eventEndSeq: eventEndSeq ?? (() => {
2024
- throw new Error(`Missing ACP event capture for session ${sessionInfo.bundleId}`);
2025
- })()
1972
+ eventStartSeq,
1973
+ eventEndSeq
2026
1974
  }
2027
1975
  };
2028
1976
  } finally {
@@ -2041,29 +1989,16 @@ var FlowRunner = class {
2041
1989
  const conversation = createSessionConversation(state.currentNodeStartedAt ?? isoNow$1());
2042
1990
  let acpxState;
2043
1991
  recordPromptSubmission(conversation, prompt, state.currentNodeStartedAt ?? isoNow$1());
2044
- let eventStartSeq;
2045
- let eventEndSeq;
2046
- const pendingEventWrites = [];
2047
- const result = await runOnce({
1992
+ const events = this.createPromptEventCapture(runDir, binding);
1993
+ const { result, eventStartSeq, eventEndSeq } = await events.run(() => runOnce({
2048
1994
  agentCommand: agent.agentCommand,
2049
1995
  agentArgv: agent.agentArgv,
2050
1996
  cwd: agent.cwd,
2051
1997
  prompt,
2052
- mcpServers: this.mcpServers,
2053
- permissionMode: this.permissionMode,
2054
- nonInteractivePermissions: this.nonInteractivePermissions,
2055
- permissionPolicy: this.permissionPolicy,
2056
- authCredentials: this.authCredentials,
2057
- authPolicy: this.authPolicy,
2058
- fs: this.fs,
1998
+ ...this.connectionOptions,
2059
1999
  outputFormatter: capture.formatter,
2060
- onAcpMessage: (direction, message) => {
2061
- const pending = this.store.appendSessionEvent(runDir, binding, direction, message).then((seq) => {
2062
- eventStartSeq = eventStartSeq === void 0 ? seq : Math.min(eventStartSeq, seq);
2063
- eventEndSeq = eventEndSeq === void 0 ? seq : Math.max(eventEndSeq, seq);
2064
- });
2065
- pendingEventWrites.push(pending);
2066
- },
2000
+ errorEmissionPolicy: { queueErrorAlreadyEmitted: false },
2001
+ onAcpMessage: events.onAcpMessage,
2067
2002
  onSessionUpdate: (notification) => {
2068
2003
  acpxState = recordSessionUpdate(conversation, acpxState, notification);
2069
2004
  },
@@ -2072,10 +2007,8 @@ var FlowRunner = class {
2072
2007
  },
2073
2008
  suppressSdkConsoleErrors: this.suppressSdkConsoleErrors,
2074
2009
  timeoutMs,
2075
- verbose: this.verbose,
2076
2010
  sessionOptions: this.sessionOptions
2077
- });
2078
- await Promise.all(pendingEventWrites);
2011
+ }));
2079
2012
  const sessionInfo = {
2080
2013
  ...binding,
2081
2014
  acpxRecordId: result.sessionId,
@@ -2088,7 +2021,7 @@ var FlowRunner = class {
2088
2021
  updatedAt: conversation.updated_at,
2089
2022
  conversation,
2090
2023
  acpxState: cloneSessionAcpxState(acpxState),
2091
- lastSeq: eventEndSeq ?? 0
2024
+ lastSeq: eventEndSeq
2092
2025
  });
2093
2026
  await this.store.writeSessionRecord(runDir, state, sessionInfo, syntheticRecord);
2094
2027
  return {
@@ -2098,12 +2031,8 @@ var FlowRunner = class {
2098
2031
  sessionId: sessionInfo.bundleId,
2099
2032
  messageStart: 0,
2100
2033
  messageEnd: Math.max(0, conversation.messages.length - 1),
2101
- eventStartSeq: eventStartSeq ?? (() => {
2102
- throw new Error(`Missing ACP event capture for session ${sessionInfo.bundleId}`);
2103
- })(),
2104
- eventEndSeq: eventEndSeq ?? (() => {
2105
- throw new Error(`Missing ACP event capture for session ${sessionInfo.bundleId}`);
2106
- })()
2034
+ eventStartSeq,
2035
+ eventEndSeq
2107
2036
  }
2108
2037
  };
2109
2038
  }
@@ -2300,4 +2229,4 @@ function formatDecisionPrompt(question, choices, field) {
2300
2229
  //#endregion
2301
2230
  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 };
2302
2231
 
2303
- //# sourceMappingURL=flows-BOI1XkMp.js.map
2232
+ //# sourceMappingURL=flows-CTOdIk-m.js.map