yaml-flow 3.0.0 → 3.1.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 (34) hide show
  1. package/README.md +44 -23
  2. package/dist/{constants-B_ftYTTE.d.ts → constants-B2zqu10b.d.ts} +7 -57
  3. package/dist/{constants-CiyHX8L-.d.cts → constants-DJZU1pwJ.d.cts} +7 -57
  4. package/dist/continuous-event-graph/index.cjs +1161 -182
  5. package/dist/continuous-event-graph/index.cjs.map +1 -1
  6. package/dist/continuous-event-graph/index.d.cts +567 -48
  7. package/dist/continuous-event-graph/index.d.ts +567 -48
  8. package/dist/continuous-event-graph/index.js +1151 -183
  9. package/dist/continuous-event-graph/index.js.map +1 -1
  10. package/dist/event-graph/index.cjs +35 -11
  11. package/dist/event-graph/index.cjs.map +1 -1
  12. package/dist/event-graph/index.d.cts +14 -5
  13. package/dist/event-graph/index.d.ts +14 -5
  14. package/dist/event-graph/index.js +34 -11
  15. package/dist/event-graph/index.js.map +1 -1
  16. package/dist/index.cjs +945 -414
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.cts +5 -4
  19. package/dist/index.d.ts +5 -4
  20. package/dist/index.js +936 -415
  21. package/dist/index.js.map +1 -1
  22. package/dist/inference/index.cjs +31 -7
  23. package/dist/inference/index.cjs.map +1 -1
  24. package/dist/inference/index.d.cts +2 -2
  25. package/dist/inference/index.d.ts +2 -2
  26. package/dist/inference/index.js +31 -7
  27. package/dist/inference/index.js.map +1 -1
  28. package/dist/{types-CxJg9Jrt.d.cts → types-BwvgvlOO.d.cts} +2 -2
  29. package/dist/{types-BuEo3wVG.d.ts → types-ClRA8hzC.d.ts} +2 -2
  30. package/dist/{types-BpWrH1sf.d.cts → types-DEj7OakX.d.cts} +14 -4
  31. package/dist/{types-BpWrH1sf.d.ts → types-DEj7OakX.d.ts} +14 -4
  32. package/dist/validate-DEZ2Ymdb.d.ts +53 -0
  33. package/dist/validate-DqKTZg_o.d.cts +53 -0
  34. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import addFormats from 'ajv-formats';
2
2
  import { existsSync, writeFileSync, appendFileSync, readFileSync } from 'fs';
3
- import { execFile } from 'child_process';
3
+ import { createHash } from 'crypto';
4
+ import { exec, execFile } from 'child_process';
4
5
 
5
6
  var __create = Object.create;
6
7
  var __defProp = Object.defineProperty;
@@ -7225,7 +7226,7 @@ function addDynamicTask(graph, taskName, taskConfig) {
7225
7226
  }
7226
7227
  };
7227
7228
  }
7228
- function createDefaultTaskState() {
7229
+ function createDefaultGraphEngineStore() {
7229
7230
  return {
7230
7231
  status: "not-started",
7231
7232
  executionCount: 0,
@@ -7238,7 +7239,7 @@ function createDefaultTaskState() {
7238
7239
  function createInitialExecutionState(graph, executionId) {
7239
7240
  const tasks = {};
7240
7241
  for (const taskName of Object.keys(graph.tasks)) {
7241
- tasks[taskName] = createDefaultTaskState();
7242
+ tasks[taskName] = createDefaultGraphEngineStore();
7242
7243
  }
7243
7244
  return {
7244
7245
  status: "running",
@@ -7759,7 +7760,7 @@ function selectOptimalTasks(candidates, graph, state, conflictStrategy) {
7759
7760
 
7760
7761
  // src/event-graph/task-transitions.ts
7761
7762
  function applyTaskStart(state, taskName) {
7762
- const existingTask = state.tasks[taskName] ?? createDefaultTaskState2();
7763
+ const existingTask = state.tasks[taskName] ?? createDefaultGraphEngineStore2();
7763
7764
  const updatedTask = {
7764
7765
  ...existingTask,
7765
7766
  status: "running",
@@ -7774,8 +7775,8 @@ function applyTaskStart(state, taskName) {
7774
7775
  lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
7775
7776
  };
7776
7777
  }
7777
- function applyTaskCompletion(state, graph, taskName, result, dataHash) {
7778
- const existingTask = state.tasks[taskName] ?? createDefaultTaskState2();
7778
+ function applyTaskCompletion(state, graph, taskName, result, dataHash, data) {
7779
+ const existingTask = state.tasks[taskName] ?? createDefaultGraphEngineStore2();
7779
7780
  const taskConfig = graph.tasks[taskName];
7780
7781
  if (!taskConfig) {
7781
7782
  throw new Error(`Task "${taskName}" not found in graph`);
@@ -7807,6 +7808,7 @@ function applyTaskCompletion(state, graph, taskName, result, dataHash) {
7807
7808
  executionCount: existingTask.executionCount + 1,
7808
7809
  lastEpoch: existingTask.executionCount + 1,
7809
7810
  lastDataHash: dataHash,
7811
+ data,
7810
7812
  lastConsumedHashes,
7811
7813
  error: void 0
7812
7814
  };
@@ -7819,7 +7821,7 @@ function applyTaskCompletion(state, graph, taskName, result, dataHash) {
7819
7821
  };
7820
7822
  }
7821
7823
  function applyTaskFailure(state, graph, taskName, error) {
7822
- const existingTask = state.tasks[taskName] ?? createDefaultTaskState2();
7824
+ const existingTask = state.tasks[taskName] ?? createDefaultGraphEngineStore2();
7823
7825
  const taskConfig = graph.tasks[taskName];
7824
7826
  if (taskConfig?.retry) {
7825
7827
  const retryCount = existingTask.retryCount + 1;
@@ -7862,7 +7864,7 @@ function applyTaskFailure(state, graph, taskName, error) {
7862
7864
  };
7863
7865
  }
7864
7866
  function applyTaskProgress(state, taskName, message, progress) {
7865
- const existingTask = state.tasks[taskName] ?? createDefaultTaskState2();
7867
+ const existingTask = state.tasks[taskName] ?? createDefaultGraphEngineStore2();
7866
7868
  const updatedTask = {
7867
7869
  ...existingTask,
7868
7870
  progress: typeof progress === "number" ? progress : existingTask.progress,
@@ -7878,7 +7880,27 @@ function applyTaskProgress(state, taskName, message, progress) {
7878
7880
  lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
7879
7881
  };
7880
7882
  }
7881
- function createDefaultTaskState2() {
7883
+ function applyTaskRestart(state, taskName) {
7884
+ const existingTask = state.tasks[taskName];
7885
+ if (!existingTask) return state;
7886
+ const updatedTask = {
7887
+ ...existingTask,
7888
+ status: "not-started",
7889
+ startedAt: void 0,
7890
+ completedAt: void 0,
7891
+ failedAt: void 0,
7892
+ error: void 0,
7893
+ data: void 0,
7894
+ progress: null,
7895
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
7896
+ };
7897
+ return {
7898
+ ...state,
7899
+ tasks: { ...state.tasks, [taskName]: updatedTask },
7900
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
7901
+ };
7902
+ }
7903
+ function createDefaultGraphEngineStore2() {
7882
7904
  return {
7883
7905
  status: "not-started",
7884
7906
  executionCount: 0,
@@ -7898,11 +7920,13 @@ function apply(state, event, graph) {
7898
7920
  case "task-started":
7899
7921
  return applyTaskStart(state, event.taskName);
7900
7922
  case "task-completed":
7901
- return applyTaskCompletion(state, graph, event.taskName, event.result, event.dataHash);
7923
+ return applyTaskCompletion(state, graph, event.taskName, event.result, event.dataHash, event.data);
7902
7924
  case "task-failed":
7903
7925
  return applyTaskFailure(state, graph, event.taskName, event.error);
7904
7926
  case "task-progress":
7905
7927
  return applyTaskProgress(state, event.taskName, event.message, event.progress);
7928
+ case "task-restart":
7929
+ return applyTaskRestart(state, event.taskName);
7906
7930
  case "inject-tokens":
7907
7931
  return applyInjectTokens(state, event.tokens);
7908
7932
  case "agent-action":
@@ -7973,7 +7997,7 @@ function applyTaskCreation(state, taskName, taskConfig) {
7973
7997
  ...state,
7974
7998
  tasks: {
7975
7999
  ...state.tasks,
7976
- [taskName]: createDefaultTaskState()
8000
+ [taskName]: createDefaultGraphEngineStore()
7977
8001
  },
7978
8002
  lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
7979
8003
  };
@@ -9223,7 +9247,7 @@ function createLiveGraph(config, executionId) {
9223
9247
  const id = executionId ?? `live-${Date.now()}`;
9224
9248
  const tasks = {};
9225
9249
  for (const taskName of Object.keys(config.tasks)) {
9226
- tasks[taskName] = createDefaultTaskState3();
9250
+ tasks[taskName] = createDefaultGraphEngineStore3();
9227
9251
  }
9228
9252
  const state = {
9229
9253
  status: "running",
@@ -9251,7 +9275,7 @@ function applyEvent(live, event) {
9251
9275
  newState = applyTaskStart(state, event.taskName);
9252
9276
  break;
9253
9277
  case "task-completed":
9254
- newState = applyTaskCompletion(state, config, event.taskName, event.result, event.dataHash);
9278
+ newState = applyTaskCompletion(state, config, event.taskName, event.result, event.dataHash, event.data);
9255
9279
  break;
9256
9280
  case "task-failed":
9257
9281
  newState = applyTaskFailure(state, config, event.taskName, event.error);
@@ -9259,6 +9283,9 @@ function applyEvent(live, event) {
9259
9283
  case "task-progress":
9260
9284
  newState = applyTaskProgress(state, event.taskName, event.message, event.progress);
9261
9285
  break;
9286
+ case "task-restart":
9287
+ newState = applyTaskRestart(state, event.taskName);
9288
+ break;
9262
9289
  case "inject-tokens":
9263
9290
  newState = {
9264
9291
  ...state,
@@ -9286,7 +9313,7 @@ function addNode(live, name, taskConfig) {
9286
9313
  },
9287
9314
  state: {
9288
9315
  ...live.state,
9289
- tasks: { ...live.state.tasks, [name]: createDefaultTaskState3() },
9316
+ tasks: { ...live.state.tasks, [name]: createDefaultGraphEngineStore3() },
9290
9317
  lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
9291
9318
  }
9292
9319
  };
@@ -9403,7 +9430,7 @@ function resetNode(live, name) {
9403
9430
  ...live.state,
9404
9431
  tasks: {
9405
9432
  ...live.state.tasks,
9406
- [name]: createDefaultTaskState3()
9433
+ [name]: createDefaultGraphEngineStore3()
9407
9434
  },
9408
9435
  lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
9409
9436
  }
@@ -9442,7 +9469,7 @@ function enableNode(live, name) {
9442
9469
  function getNode(live, name) {
9443
9470
  const config = live.config.tasks[name];
9444
9471
  if (!config) return void 0;
9445
- const state = live.state.tasks[name] ?? createDefaultTaskState3();
9472
+ const state = live.state.tasks[name] ?? createDefaultGraphEngineStore3();
9446
9473
  return { name, config, state };
9447
9474
  }
9448
9475
  function snapshot(live) {
@@ -9480,7 +9507,7 @@ function restore(data) {
9480
9507
  }
9481
9508
  return { config, state };
9482
9509
  }
9483
- function createDefaultTaskState3() {
9510
+ function createDefaultGraphEngineStore3() {
9484
9511
  return {
9485
9512
  status: "not-started",
9486
9513
  executionCount: 0,
@@ -10037,23 +10064,43 @@ var FileJournal = class {
10037
10064
  }
10038
10065
  }
10039
10066
  };
10040
-
10041
- // src/continuous-event-graph/reactive.ts
10067
+ function computeDataHash(data) {
10068
+ const json = stableStringify(data);
10069
+ return createHash("sha256").update(json).digest("hex").slice(0, 16);
10070
+ }
10071
+ function stableStringify(value) {
10072
+ if (value === null || value === void 0 || typeof value !== "object") {
10073
+ return JSON.stringify(value);
10074
+ }
10075
+ if (Array.isArray(value)) {
10076
+ return "[" + value.map(stableStringify).join(",") + "]";
10077
+ }
10078
+ const obj = value;
10079
+ const keys = Object.keys(obj).sort();
10080
+ return "{" + keys.map((k) => JSON.stringify(k) + ":" + stableStringify(obj[k])).join(",") + "}";
10081
+ }
10082
+ function encodeCallbackToken(taskName) {
10083
+ const payload = JSON.stringify({ t: taskName, n: Date.now().toString(36) + Math.random().toString(36).slice(2, 6) });
10084
+ return Buffer.from(payload).toString("base64url");
10085
+ }
10086
+ function decodeCallbackToken(token) {
10087
+ try {
10088
+ const payload = JSON.parse(Buffer.from(token, "base64url").toString());
10089
+ if (typeof payload?.t === "string") return { taskName: payload.t };
10090
+ return null;
10091
+ } catch {
10092
+ return null;
10093
+ }
10094
+ }
10042
10095
  function createReactiveGraph(config, options, executionId) {
10043
10096
  const {
10044
10097
  handlers: initialHandlers,
10045
- maxDispatchRetries = 3,
10046
- defaultTimeoutMs = 3e4,
10047
10098
  journal = new MemoryJournal(),
10048
- onDispatchFailed,
10049
- onAbandoned,
10050
10099
  onDrain
10051
10100
  } = options;
10052
10101
  let live = createLiveGraph(config, executionId);
10053
10102
  let disposed = false;
10054
10103
  const handlers = new Map(Object.entries(initialHandlers));
10055
- const dispatched = /* @__PURE__ */ new Map();
10056
- const timeoutTimers = /* @__PURE__ */ new Map();
10057
10104
  let draining = false;
10058
10105
  let drainQueued = false;
10059
10106
  function drain() {
@@ -10073,201 +10120,183 @@ function createReactiveGraph(config, options, executionId) {
10073
10120
  }
10074
10121
  }
10075
10122
  function drainOnce() {
10076
- sweepTimeouts();
10077
10123
  const events = journal.drain();
10078
- for (const event of events) {
10079
- if (event.type === "task-completed" || event.type === "task-failed") {
10080
- const taskName = event.taskName;
10081
- dispatched.delete(taskName);
10082
- clearTimeout(timeoutTimers.get(taskName));
10083
- timeoutTimers.delete(taskName);
10084
- }
10085
- }
10086
10124
  if (events.length > 0) {
10087
10125
  live = applyEvents(live, events);
10088
10126
  }
10089
10127
  const result = schedule(live);
10090
- if (onDrain && events.length > 0) {
10091
- onDrain(events, live, result);
10128
+ if (events.length > 0) {
10129
+ onDrain?.(events, live, result);
10092
10130
  }
10093
10131
  for (const taskName of result.eligible) {
10094
- if (dispatched.has(taskName)) continue;
10095
10132
  dispatchTask(taskName);
10096
10133
  }
10097
- for (const [taskName, entry] of dispatched) {
10098
- if (entry.status === "retry-queued") {
10099
- dispatchTask(taskName);
10134
+ }
10135
+ function resolveUpstreamState(taskName) {
10136
+ const taskConfig = live.config.tasks[taskName];
10137
+ const requires = taskConfig.requires ?? [];
10138
+ const tokenToTask = /* @__PURE__ */ new Map();
10139
+ for (const [name, cfg] of Object.entries(live.config.tasks)) {
10140
+ for (const token of cfg.provides ?? []) {
10141
+ tokenToTask.set(token, name);
10142
+ }
10143
+ }
10144
+ const state = {};
10145
+ for (const token of requires) {
10146
+ const producerTask = tokenToTask.get(token);
10147
+ if (producerTask) {
10148
+ state[token] = live.state.tasks[producerTask]?.data;
10149
+ } else {
10150
+ state[token] = void 0;
10151
+ }
10152
+ }
10153
+ return state;
10154
+ }
10155
+ async function runPipeline(taskName, callbackToken) {
10156
+ const taskConfig = live.config.tasks[taskName];
10157
+ const handlerNames = taskConfig.taskHandlers ?? [];
10158
+ const upstreamState = resolveUpstreamState(taskName);
10159
+ for (const handlerName of handlerNames) {
10160
+ const handler = handlers.get(handlerName);
10161
+ if (!handler) {
10162
+ throw new Error(`Handler '${handlerName}' not found in registry (task '${taskName}')`);
10163
+ }
10164
+ const input = {
10165
+ nodeId: taskName,
10166
+ state: upstreamState,
10167
+ taskState: live.state.tasks[taskName],
10168
+ config: taskConfig,
10169
+ callbackToken
10170
+ };
10171
+ const status = await handler(input);
10172
+ if (status === "task-initiate-failure") {
10173
+ throw new Error(`Handler '${handlerName}' returned task-initiate-failure (task '${taskName}')`);
10100
10174
  }
10101
10175
  }
10102
10176
  }
10103
10177
  function dispatchTask(taskName) {
10104
- const handler = handlers.get(taskName);
10105
- if (!handler) {
10106
- journal.append({
10107
- type: "task-failed",
10108
- taskName,
10109
- error: `No handler registered for task "${taskName}"`,
10110
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
10111
- });
10112
- drainQueued = true;
10113
- return;
10114
- }
10115
- const existing = dispatched.get(taskName);
10116
- const attempt = existing ? existing.dispatchAttempts + 1 : 1;
10117
- if (attempt > maxDispatchRetries) {
10118
- dispatched.set(taskName, {
10119
- status: "abandoned",
10120
- dispatchedAt: existing?.dispatchedAt ?? Date.now(),
10121
- dispatchAttempts: attempt - 1,
10122
- lastError: existing?.lastError
10123
- });
10124
- onAbandoned?.(taskName);
10125
- journal.append({
10126
- type: "task-failed",
10127
- taskName,
10128
- error: `dispatch-abandoned: handler unreachable after ${attempt - 1} attempts${existing?.lastError ? ` (${existing.lastError})` : ""}`,
10129
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
10130
- });
10131
- drainQueued = true;
10178
+ const taskConfig = live.config.tasks[taskName];
10179
+ const handlerNames = taskConfig?.taskHandlers;
10180
+ if (!handlerNames || handlerNames.length === 0) {
10132
10181
  return;
10133
10182
  }
10134
- dispatched.set(taskName, {
10135
- status: "initiated",
10136
- dispatchedAt: Date.now(),
10137
- dispatchAttempts: attempt
10138
- });
10139
10183
  journal.append({
10140
10184
  type: "task-started",
10141
10185
  taskName,
10142
10186
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
10143
10187
  });
10144
- if (defaultTimeoutMs > 0) {
10145
- const timer = setTimeout(() => {
10146
- if (disposed) return;
10147
- const entry = dispatched.get(taskName);
10148
- if (entry?.status === "initiated") {
10149
- dispatched.set(taskName, {
10150
- ...entry,
10151
- status: "timed-out"
10152
- });
10153
- dispatched.set(taskName, {
10154
- ...entry,
10155
- status: entry.dispatchAttempts >= maxDispatchRetries ? "abandoned" : "retry-queued"
10156
- });
10157
- if (entry.dispatchAttempts >= maxDispatchRetries) {
10158
- onAbandoned?.(taskName);
10159
- journal.append({
10160
- type: "task-failed",
10161
- taskName,
10162
- error: `dispatch-timeout: no callback after ${defaultTimeoutMs}ms (${entry.dispatchAttempts} attempts)`,
10163
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
10164
- });
10165
- }
10166
- drain();
10167
- }
10168
- }, defaultTimeoutMs);
10169
- timeoutTimers.set(taskName, timer);
10170
- }
10171
- const ctx = {
10172
- taskName,
10173
- live,
10174
- config: live.config.tasks[taskName]
10175
- };
10176
- try {
10177
- const promise = handler(ctx);
10178
- promise.then(
10179
- (handlerResult) => {
10180
- if (disposed) return;
10181
- clearTimeout(timeoutTimers.get(taskName));
10182
- timeoutTimers.delete(taskName);
10183
- journal.append({
10184
- type: "task-completed",
10185
- taskName,
10186
- result: handlerResult.result,
10187
- data: handlerResult.data,
10188
- dataHash: handlerResult.dataHash,
10189
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
10190
- });
10191
- drain();
10192
- },
10193
- (error) => {
10194
- if (disposed) return;
10195
- clearTimeout(timeoutTimers.get(taskName));
10196
- timeoutTimers.delete(taskName);
10197
- journal.append({
10198
- type: "task-failed",
10199
- taskName,
10200
- error: error.message ?? String(error),
10201
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
10202
- });
10203
- drain();
10204
- }
10205
- );
10206
- } catch (syncError) {
10207
- const err = syncError instanceof Error ? syncError : new Error(String(syncError));
10208
- dispatched.set(taskName, {
10209
- status: "dispatch-failed",
10210
- dispatchedAt: Date.now(),
10211
- dispatchAttempts: attempt,
10212
- lastError: err.message
10213
- });
10214
- onDispatchFailed?.(taskName, err, attempt);
10215
- dispatched.set(taskName, {
10216
- ...dispatched.get(taskName),
10217
- status: "retry-queued"
10188
+ const callbackToken = encodeCallbackToken(taskName);
10189
+ runPipeline(taskName, callbackToken).catch((error) => {
10190
+ if (disposed) return;
10191
+ journal.append({
10192
+ type: "task-failed",
10193
+ taskName,
10194
+ error: error.message ?? String(error),
10195
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
10218
10196
  });
10219
- drainQueued = true;
10220
- }
10221
- }
10222
- function sweepTimeouts() {
10223
- const now = Date.now();
10224
- for (const [taskName, entry] of dispatched) {
10225
- if (entry.status !== "initiated") continue;
10226
- if (defaultTimeoutMs <= 0) continue;
10227
- if (now - entry.dispatchedAt >= defaultTimeoutMs) {
10228
- dispatched.set(taskName, {
10229
- ...entry,
10230
- status: entry.dispatchAttempts >= maxDispatchRetries ? "abandoned" : "retry-queued"
10231
- });
10232
- if (entry.dispatchAttempts >= maxDispatchRetries) {
10233
- onAbandoned?.(taskName);
10234
- journal.append({
10235
- type: "task-failed",
10236
- taskName,
10237
- error: `dispatch-timeout: no callback after ${defaultTimeoutMs}ms (${entry.dispatchAttempts} attempts)`,
10238
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
10239
- });
10240
- }
10241
- clearTimeout(timeoutTimers.get(taskName));
10242
- timeoutTimers.delete(taskName);
10243
- }
10244
- }
10197
+ drain();
10198
+ });
10245
10199
  }
10246
10200
  return {
10247
10201
  push(event) {
10248
10202
  if (disposed) return;
10249
- live = applyEvent(live, event);
10203
+ if (event.type === "task-completed" && event.data && !event.dataHash) {
10204
+ event = { ...event, dataHash: computeDataHash(event.data) };
10205
+ }
10206
+ journal.append(event);
10250
10207
  drain();
10251
10208
  },
10252
10209
  pushAll(events) {
10253
10210
  if (disposed) return;
10254
- if (events.length === 0) return;
10255
- live = applyEvents(live, events);
10211
+ for (const event of events) {
10212
+ if (event.type === "task-completed" && event.data && !event.dataHash) {
10213
+ journal.append({ ...event, dataHash: computeDataHash(event.data) });
10214
+ } else {
10215
+ journal.append(event);
10216
+ }
10217
+ }
10218
+ drain();
10219
+ },
10220
+ resolveCallback(callbackToken, data, errors) {
10221
+ if (disposed) return;
10222
+ const decoded = decodeCallbackToken(callbackToken);
10223
+ if (!decoded) return;
10224
+ const { taskName } = decoded;
10225
+ if (!live.config.tasks[taskName]) return;
10226
+ if (errors && errors.length > 0) {
10227
+ journal.append({
10228
+ type: "task-failed",
10229
+ taskName,
10230
+ error: errors.join("; "),
10231
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
10232
+ });
10233
+ } else {
10234
+ const dataHash = data && Object.keys(data).length > 0 ? computeDataHash(data) : void 0;
10235
+ journal.append({
10236
+ type: "task-completed",
10237
+ taskName,
10238
+ data,
10239
+ dataHash,
10240
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
10241
+ });
10242
+ }
10256
10243
  drain();
10257
10244
  },
10258
- addNode(name, taskConfig, handler) {
10245
+ addNode(name, taskConfig) {
10259
10246
  if (disposed) return;
10260
10247
  live = addNode(live, name, taskConfig);
10261
- handlers.set(name, handler);
10262
10248
  drain();
10263
10249
  },
10264
10250
  removeNode(name) {
10265
10251
  if (disposed) return;
10266
10252
  live = removeNode(live, name);
10253
+ },
10254
+ addRequires(nodeName, tokens) {
10255
+ if (disposed) return;
10256
+ live = addRequires(live, nodeName, tokens);
10257
+ drain();
10258
+ },
10259
+ removeRequires(nodeName, tokens) {
10260
+ if (disposed) return;
10261
+ live = removeRequires(live, nodeName, tokens);
10262
+ drain();
10263
+ },
10264
+ addProvides(nodeName, tokens) {
10265
+ if (disposed) return;
10266
+ live = addProvides(live, nodeName, tokens);
10267
+ drain();
10268
+ },
10269
+ removeProvides(nodeName, tokens) {
10270
+ if (disposed) return;
10271
+ live = removeProvides(live, nodeName, tokens);
10272
+ },
10273
+ registerHandler(name, fn) {
10274
+ handlers.set(name, fn);
10275
+ },
10276
+ unregisterHandler(name) {
10267
10277
  handlers.delete(name);
10268
- dispatched.delete(name);
10269
- clearTimeout(timeoutTimers.get(name));
10270
- timeoutTimers.delete(name);
10278
+ },
10279
+ retrigger(taskName) {
10280
+ if (disposed) return;
10281
+ if (!live.config.tasks[taskName]) return;
10282
+ journal.append({
10283
+ type: "task-restart",
10284
+ taskName,
10285
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
10286
+ });
10287
+ drain();
10288
+ },
10289
+ retriggerAll(taskNames) {
10290
+ if (disposed) return;
10291
+ for (const name of taskNames) {
10292
+ if (!live.config.tasks[name]) continue;
10293
+ journal.append({
10294
+ type: "task-restart",
10295
+ taskName: name,
10296
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
10297
+ });
10298
+ }
10299
+ drain();
10271
10300
  },
10272
10301
  getState() {
10273
10302
  return live;
@@ -10275,267 +10304,360 @@ function createReactiveGraph(config, options, executionId) {
10275
10304
  getSchedule() {
10276
10305
  return schedule(live);
10277
10306
  },
10278
- getDispatchState() {
10279
- return dispatched;
10280
- },
10281
10307
  dispose() {
10282
10308
  disposed = true;
10283
- for (const timer of timeoutTimers.values()) {
10284
- clearTimeout(timer);
10285
- }
10286
- timeoutTimers.clear();
10287
10309
  }
10288
10310
  };
10289
10311
  }
10290
10312
 
10291
- // src/inference/core.ts
10292
- var DEFAULT_THRESHOLD = 0.5;
10293
- var DEFAULT_SYSTEM_PROMPT = `You are a workflow completion analyzer. Given a graph of tasks with their current states, evidence, and inference hints, determine which tasks appear to be completed based on the available evidence.
10294
-
10295
- For each task you analyze, provide a JSON response. Be conservative \u2014 only mark tasks as completed when the evidence strongly supports it.`;
10296
- function buildInferencePrompt(live, options = {}) {
10297
- const { scope, context, systemPrompt } = options;
10298
- const graphTasks = getAllTasks(live.config);
10299
- const { state } = live;
10300
- const candidates = getAnalyzableCandidates(live, scope);
10301
- if (candidates.length === 0) {
10302
- return "";
10313
+ // src/continuous-event-graph/validate.ts
10314
+ function validateLiveGraph(live) {
10315
+ const issues = [];
10316
+ const { config, state } = live;
10317
+ const tasks = getAllTasks(config);
10318
+ const taskNames = Object.keys(tasks);
10319
+ for (const name of taskNames) {
10320
+ if (!state.tasks[name]) {
10321
+ issues.push({
10322
+ severity: "error",
10323
+ code: "MISSING_STATE",
10324
+ message: `Task "${name}" exists in config but has no state entry`,
10325
+ tasks: [name]
10326
+ });
10327
+ }
10303
10328
  }
10304
- const lines = [];
10305
- lines.push(systemPrompt || DEFAULT_SYSTEM_PROMPT);
10306
- lines.push("");
10307
- lines.push("## Graph State");
10308
- lines.push("");
10309
- lines.push(`Available tokens: ${state.availableOutputs.length > 0 ? state.availableOutputs.join(", ") : "(none)"}`);
10310
- lines.push("");
10311
- const completedTasks = Object.entries(state.tasks).filter(([_, ts]) => ts.status === "completed").map(([name]) => name);
10312
- if (completedTasks.length > 0) {
10313
- lines.push(`Completed tasks: ${completedTasks.join(", ")}`);
10314
- lines.push("");
10329
+ for (const name of Object.keys(state.tasks)) {
10330
+ if (!tasks[name]) {
10331
+ issues.push({
10332
+ severity: "warning",
10333
+ code: "ORPHAN_STATE",
10334
+ message: `State entry "${name}" has no corresponding task config`,
10335
+ tasks: [name]
10336
+ });
10337
+ }
10315
10338
  }
10316
- lines.push("## Tasks to Analyze");
10317
- lines.push("");
10318
- for (const taskName of candidates) {
10319
- const taskConfig = graphTasks[taskName];
10320
- const taskState = state.tasks[taskName];
10321
- lines.push(`### ${taskName}`);
10322
- if (taskConfig.description) {
10323
- lines.push(`Description: ${taskConfig.description}`);
10339
+ for (const name of taskNames) {
10340
+ const ts = state.tasks[name];
10341
+ if (!ts) continue;
10342
+ if (ts.status === TASK_STATUS.RUNNING && !ts.startedAt) {
10343
+ issues.push({
10344
+ severity: "warning",
10345
+ code: "RUNNING_WITHOUT_START",
10346
+ message: `Task "${name}" is running but has no startedAt timestamp`,
10347
+ tasks: [name]
10348
+ });
10324
10349
  }
10325
- const requires = getRequires(taskConfig);
10326
- const provides = getProvides(taskConfig);
10327
- if (requires.length > 0) lines.push(`Requires: ${requires.join(", ")}`);
10328
- if (provides.length > 0) lines.push(`Provides: ${provides.join(", ")}`);
10329
- lines.push(`Current status: ${taskState?.status || "not-started"}`);
10330
- const hints = taskConfig.inference;
10331
- if (hints) {
10332
- if (hints.criteria) lines.push(`Completion criteria: ${hints.criteria}`);
10333
- if (hints.keywords?.length) lines.push(`Keywords: ${hints.keywords.join(", ")}`);
10334
- if (hints.suggestedChecks?.length) lines.push(`Suggested checks: ${hints.suggestedChecks.join("; ")}`);
10350
+ if (ts.status === TASK_STATUS.COMPLETED && !ts.completedAt) {
10351
+ issues.push({
10352
+ severity: "warning",
10353
+ code: "COMPLETED_WITHOUT_TIMESTAMP",
10354
+ message: `Task "${name}" is completed but has no completedAt timestamp`,
10355
+ tasks: [name]
10356
+ });
10357
+ }
10358
+ if (ts.status === TASK_STATUS.FAILED) {
10359
+ if (!ts.failedAt) {
10360
+ issues.push({
10361
+ severity: "warning",
10362
+ code: "FAILED_WITHOUT_INFO",
10363
+ message: `Task "${name}" is failed but has no failedAt timestamp`,
10364
+ tasks: [name]
10365
+ });
10366
+ }
10367
+ if (!ts.error) {
10368
+ issues.push({
10369
+ severity: "info",
10370
+ code: "FAILED_WITHOUT_INFO",
10371
+ message: `Task "${name}" is failed but has no error message`,
10372
+ tasks: [name]
10373
+ });
10374
+ }
10335
10375
  }
10336
- lines.push("");
10337
10376
  }
10338
- if (context) {
10339
- lines.push("## Additional Context / Evidence");
10340
- lines.push("");
10341
- lines.push(context);
10342
- lines.push("");
10377
+ const expectedOutputs = /* @__PURE__ */ new Set();
10378
+ for (const name of taskNames) {
10379
+ const ts = state.tasks[name];
10380
+ if (ts?.status === TASK_STATUS.COMPLETED) {
10381
+ for (const token of getProvides(tasks[name])) {
10382
+ expectedOutputs.add(token);
10383
+ }
10384
+ }
10343
10385
  }
10344
- lines.push("## Response Format");
10345
- lines.push("");
10346
- lines.push("Respond with a JSON array of objects, one per task you have evidence for:");
10347
- lines.push("```json");
10348
- lines.push("[");
10349
- lines.push(" {");
10350
- lines.push(' "taskName": "task-name",');
10351
- lines.push(' "confidence": 0.0 to 1.0,');
10352
- lines.push(' "reasoning": "explanation of why you believe this task is complete or not"');
10353
- lines.push(" }");
10354
- lines.push("]");
10355
- lines.push("```");
10356
- lines.push("");
10357
- lines.push("Rules:");
10358
- lines.push('- Only include tasks from the "Tasks to Analyze" section');
10359
- lines.push("- confidence 0.0 = no evidence of completion, 1.0 = certain it is complete");
10360
- lines.push("- If you have no evidence for a task, omit it from the array");
10361
- lines.push("- Be conservative \u2014 require clear evidence before high confidence");
10362
- lines.push("- Respond ONLY with the JSON array, no additional text");
10363
- return lines.join("\n");
10364
- }
10365
- async function inferCompletions(live, adapter, options = {}) {
10366
- options.threshold ?? DEFAULT_THRESHOLD;
10367
- const analyzedNodes = getAnalyzableCandidates(live, options.scope);
10368
- if (analyzedNodes.length === 0) {
10369
- return { suggestions: [], promptUsed: "", rawResponse: "", analyzedNodes: [] };
10386
+ const actualOutputs = new Set(state.availableOutputs);
10387
+ const allProducible = /* @__PURE__ */ new Set();
10388
+ for (const taskConfig of Object.values(tasks)) {
10389
+ for (const t of getProvides(taskConfig)) allProducible.add(t);
10390
+ if (taskConfig.on) {
10391
+ for (const tokens of Object.values(taskConfig.on)) {
10392
+ for (const t of tokens) allProducible.add(t);
10393
+ }
10394
+ }
10395
+ if (taskConfig.on_failure) {
10396
+ for (const t of taskConfig.on_failure) allProducible.add(t);
10397
+ }
10370
10398
  }
10371
- const prompt = buildInferencePrompt(live, options);
10372
- const rawResponse = await adapter.analyze(prompt);
10373
- const suggestions = parseInferenceResponse(rawResponse, analyzedNodes);
10374
- return {
10375
- suggestions,
10376
- promptUsed: prompt,
10377
- rawResponse,
10378
- analyzedNodes
10379
- };
10380
- }
10381
- function applyInferences(live, result, threshold = DEFAULT_THRESHOLD) {
10382
- let current = live;
10383
- for (const suggestion of result.suggestions) {
10384
- if (suggestion.confidence < threshold) continue;
10385
- const taskState = current.state.tasks[suggestion.taskName];
10386
- if (!taskState) continue;
10387
- if (taskState.status === "completed" || taskState.status === "running") continue;
10388
- const now = (/* @__PURE__ */ new Date()).toISOString();
10389
- current = applyEvent(current, {
10390
- type: "task-started",
10391
- taskName: suggestion.taskName,
10392
- timestamp: now
10393
- });
10394
- current = applyEvent(current, {
10395
- type: "task-completed",
10396
- taskName: suggestion.taskName,
10397
- timestamp: now,
10398
- result: "llm-inferred"
10399
- });
10399
+ for (const token of actualOutputs) {
10400
+ if (!expectedOutputs.has(token) && !allProducible.has(token)) {
10401
+ issues.push({
10402
+ severity: "info",
10403
+ code: "INJECTED_TOKEN",
10404
+ message: `Token "${token}" is available but no task in the graph can produce it (likely injected)`,
10405
+ tokens: [token]
10406
+ });
10407
+ }
10400
10408
  }
10401
- return current;
10402
- }
10403
- async function inferAndApply(live, adapter, options = {}) {
10404
- const threshold = options.threshold ?? DEFAULT_THRESHOLD;
10405
- const inference = await inferCompletions(live, adapter, options);
10406
- const updated = applyInferences(live, inference, threshold);
10407
- const applied = inference.suggestions.filter((s) => s.confidence >= threshold);
10408
- const skipped = inference.suggestions.filter((s) => s.confidence < threshold);
10409
- return {
10410
- live: updated,
10411
- inference,
10412
- applied,
10413
- skipped
10414
- };
10415
- }
10416
- function getAnalyzableCandidates(live, scope) {
10417
- const graphTasks = getAllTasks(live.config);
10418
- const { state } = live;
10419
- const candidates = [];
10420
- for (const [name, config] of Object.entries(graphTasks)) {
10421
- const taskState = state.tasks[name];
10422
- if (taskState?.status === "completed" || taskState?.status === "running") continue;
10423
- if (scope) {
10424
- if (scope.includes(name)) candidates.push(name);
10425
- } else {
10426
- if (config.inference?.autoDetectable) candidates.push(name);
10409
+ for (const token of expectedOutputs) {
10410
+ if (!actualOutputs.has(token)) {
10411
+ issues.push({
10412
+ severity: "warning",
10413
+ code: "MISSING_OUTPUT",
10414
+ message: `Token "${token}" should be available (its producer completed) but is not in availableOutputs`,
10415
+ tokens: [token]
10416
+ });
10427
10417
  }
10428
10418
  }
10429
- return candidates;
10430
- }
10431
- function parseInferenceResponse(rawResponse, validNodes, _threshold) {
10432
- const validSet = new Set(validNodes);
10433
- try {
10434
- const jsonStr = extractJson(rawResponse);
10435
- if (!jsonStr) return [];
10436
- const parsed = JSON.parse(jsonStr);
10437
- if (!Array.isArray(parsed)) return [];
10438
- const suggestions = [];
10439
- for (const item of parsed) {
10440
- if (!item || typeof item !== "object") continue;
10441
- if (typeof item.taskName !== "string") continue;
10442
- if (typeof item.confidence !== "number") continue;
10443
- if (!validSet.has(item.taskName)) continue;
10444
- const confidence = Math.max(0, Math.min(1, item.confidence));
10445
- suggestions.push({
10446
- taskName: item.taskName,
10447
- confidence,
10448
- reasoning: typeof item.reasoning === "string" ? item.reasoning : "",
10449
- detectionMethod: "llm-inferred"
10419
+ for (const name of taskNames) {
10420
+ const ts = state.tasks[name];
10421
+ if (!ts) continue;
10422
+ if (ts.executionCount < 0) {
10423
+ issues.push({
10424
+ severity: "error",
10425
+ code: "INVALID_EXECUTION_COUNT",
10426
+ message: `Task "${name}" has negative execution count: ${ts.executionCount}`,
10427
+ tasks: [name]
10428
+ });
10429
+ }
10430
+ const maxExec = tasks[name].maxExecutions;
10431
+ if (maxExec !== void 0 && ts.executionCount > maxExec) {
10432
+ issues.push({
10433
+ severity: "error",
10434
+ code: "EXCEEDED_MAX_EXECUTIONS",
10435
+ message: `Task "${name}" executed ${ts.executionCount} times, exceeding maxExecutions of ${maxExec}`,
10436
+ tasks: [name]
10450
10437
  });
10451
10438
  }
10452
- return suggestions;
10453
- } catch {
10454
- return [];
10455
10439
  }
10440
+ return buildResult2(issues);
10456
10441
  }
10457
- function extractJson(text) {
10458
- if (!text || typeof text !== "string") return null;
10459
- const trimmed = text.trim();
10460
- const fenceMatch = trimmed.match(/```(?:json)?\s*\n?([\s\S]*?)\n?\s*```/);
10461
- if (fenceMatch) return fenceMatch[1].trim();
10462
- const firstBracket = trimmed.indexOf("[");
10463
- const lastBracket = trimmed.lastIndexOf("]");
10464
- if (firstBracket !== -1 && lastBracket > firstBracket) {
10465
- return trimmed.slice(firstBracket, lastBracket + 1);
10442
+ function validateReactiveGraph(input) {
10443
+ const { graph, handlers } = input;
10444
+ const live = graph.getState();
10445
+ const issues = [];
10446
+ const tasks = getAllTasks(live.config);
10447
+ const taskNames = Object.keys(tasks);
10448
+ const handlerNames = new Set(Object.keys(handlers));
10449
+ const referencedHandlers = /* @__PURE__ */ new Set();
10450
+ for (const name of taskNames) {
10451
+ const taskHandlers = tasks[name].taskHandlers;
10452
+ if (taskHandlers) {
10453
+ for (const h of taskHandlers) {
10454
+ referencedHandlers.add(h);
10455
+ }
10456
+ }
10466
10457
  }
10467
- if (trimmed.startsWith("[")) return trimmed;
10468
- return null;
10469
- }
10470
- function createCliAdapter(opts) {
10471
- const timeout = opts.timeout ?? 6e4;
10472
- return {
10473
- analyze: (prompt) => {
10474
- return new Promise((resolve2, reject) => {
10475
- const args = opts.args(prompt);
10476
- const child = execFile(
10477
- opts.command,
10478
- opts.stdin ? opts.args("") : args,
10479
- {
10480
- timeout,
10481
- cwd: opts.cwd,
10482
- env: opts.env ? { ...process.env, ...opts.env } : void 0,
10483
- maxBuffer: 10 * 1024 * 1024
10484
- // 10MB
10485
- },
10486
- (error, stdout, stderr) => {
10487
- if (error) {
10488
- reject(new Error(
10489
- `CLI adapter failed: ${opts.command} exited with ${error.code ?? "error"}` + (stderr ? `
10490
- stderr: ${stderr.slice(0, 500)}` : "") + `
10491
- ${error.message}`
10492
- ));
10493
- } else {
10494
- resolve2(stdout);
10495
- }
10496
- }
10497
- );
10498
- if (opts.stdin && child.stdin) {
10499
- child.stdin.write(prompt);
10500
- child.stdin.end();
10501
- }
10458
+ for (const name of taskNames) {
10459
+ const taskHandlers = tasks[name].taskHandlers;
10460
+ if (!taskHandlers) continue;
10461
+ for (const h of taskHandlers) {
10462
+ if (!handlers[h]) {
10463
+ issues.push({
10464
+ severity: "error",
10465
+ code: "MISSING_HANDLER",
10466
+ message: `Task "${name}" references handler "${h}" but it is not in the registry`,
10467
+ tasks: [name]
10468
+ });
10469
+ }
10470
+ }
10471
+ }
10472
+ for (const name of handlerNames) {
10473
+ if (!referencedHandlers.has(name)) {
10474
+ issues.push({
10475
+ severity: "warning",
10476
+ code: "ORPHAN_HANDLER",
10477
+ message: `Handler "${name}" is registered but not referenced by any task's taskHandlers`,
10478
+ tasks: [name]
10502
10479
  });
10503
10480
  }
10504
- };
10481
+ }
10482
+ const liveResult = validateLiveGraph(live);
10483
+ issues.push(...liveResult.issues);
10484
+ return buildResult2(issues);
10505
10485
  }
10506
- function createHttpAdapter(opts) {
10507
- const timeout = opts.timeout ?? 6e4;
10486
+ function buildResult2(issues) {
10487
+ const errors = issues.filter((i) => i.severity === "error");
10488
+ const warnings = issues.filter((i) => i.severity === "warning");
10508
10489
  return {
10509
- analyze: async (prompt) => {
10510
- const body = opts.buildBody ? opts.buildBody(prompt) : { prompt };
10511
- const controller = new AbortController();
10512
- const timer = setTimeout(() => controller.abort(), timeout);
10513
- try {
10514
- const response = await fetch(opts.url, {
10515
- method: "POST",
10516
- headers: {
10517
- "Content-Type": "application/json",
10518
- ...opts.headers ?? {}
10519
- },
10520
- body: JSON.stringify(body),
10521
- signal: controller.signal
10522
- });
10523
- if (!response.ok) {
10524
- const text = await response.text().catch(() => "");
10525
- throw new Error(`HTTP ${response.status}: ${text.slice(0, 500)}`);
10490
+ valid: errors.length === 0,
10491
+ issues,
10492
+ errors,
10493
+ warnings
10494
+ };
10495
+ }
10496
+
10497
+ // src/continuous-event-graph/mutate.ts
10498
+ function mutateGraph(live, mutations) {
10499
+ let current = live;
10500
+ for (const mutation of mutations) {
10501
+ current = applySingleMutation(current, mutation);
10502
+ }
10503
+ return current;
10504
+ }
10505
+ function applySingleMutation(live, mutation) {
10506
+ switch (mutation.type) {
10507
+ case "add-node":
10508
+ return addNode(live, mutation.name, mutation.config);
10509
+ case "remove-node":
10510
+ return removeNode(live, mutation.name);
10511
+ case "add-requires":
10512
+ return addRequires(live, mutation.taskName, mutation.tokens);
10513
+ case "remove-requires":
10514
+ return removeRequires(live, mutation.taskName, mutation.tokens);
10515
+ case "add-provides":
10516
+ return addProvides(live, mutation.taskName, mutation.tokens);
10517
+ case "remove-provides":
10518
+ return removeProvides(live, mutation.taskName, mutation.tokens);
10519
+ case "inject-tokens":
10520
+ return injectTokens(live, mutation.tokens);
10521
+ case "drain-tokens":
10522
+ return drainTokens(live, mutation.tokens);
10523
+ case "reset-node":
10524
+ return resetNode(live, mutation.name);
10525
+ case "disable-node":
10526
+ return disableNode(live, mutation.name);
10527
+ case "enable-node":
10528
+ return enableNode(live, mutation.name);
10529
+ case "apply-events":
10530
+ return applyEvents(live, mutation.events);
10531
+ default:
10532
+ throw new Error(`Unknown mutation type: ${mutation.type}`);
10533
+ }
10534
+ }
10535
+ function createCallbackHandler(fn, getResolve) {
10536
+ return async (input) => {
10537
+ const { callbackToken } = input;
10538
+ Promise.resolve(fn(input)).then((data) => getResolve()(callbackToken, data)).catch((err) => getResolve()(callbackToken, {}, [err instanceof Error ? err.message : String(err)]));
10539
+ return "task-initiated";
10540
+ };
10541
+ }
10542
+ function createFireAndForgetHandler(fn, getResolve) {
10543
+ return async (input) => {
10544
+ const { callbackToken } = input;
10545
+ Promise.resolve(fn(input)).then(() => getResolve()(callbackToken, {})).catch(() => getResolve()(callbackToken, {}));
10546
+ return "task-initiated";
10547
+ };
10548
+ }
10549
+ function createShellHandler(options) {
10550
+ const {
10551
+ command: commandTemplate,
10552
+ cwd,
10553
+ env,
10554
+ timeoutMs = 3e4,
10555
+ exitCodeMap,
10556
+ captureOutput = false,
10557
+ getResolve
10558
+ } = options;
10559
+ return async (input) => {
10560
+ const { callbackToken, nodeId } = input;
10561
+ const command = commandTemplate.replace(/\$\{taskName\}/g, nodeId);
10562
+ exec(
10563
+ command,
10564
+ {
10565
+ cwd,
10566
+ env: env ? { ...process.env, ...env } : void 0,
10567
+ timeout: timeoutMs,
10568
+ maxBuffer: 10 * 1024 * 1024
10569
+ // 10MB
10570
+ },
10571
+ (error, stdout, stderr) => {
10572
+ const exitCode = error?.code ?? (error ? 1 : 0);
10573
+ if (exitCode !== 0 && !exitCodeMap?.[exitCode]) {
10574
+ getResolve()(callbackToken, {}, [`Command exited with code ${exitCode}: ${stderr || error?.message}`]);
10575
+ return;
10526
10576
  }
10527
- const json = await response.json();
10528
- if (opts.extractResponse) {
10529
- return opts.extractResponse(json);
10577
+ const data = {};
10578
+ if (captureOutput) {
10579
+ data.stdout = stdout;
10580
+ data.stderr = stderr;
10581
+ data.exitCode = exitCode;
10530
10582
  }
10531
- if (typeof json.response === "string") return json.response;
10532
- if (typeof json.text === "string") return json.text;
10533
- if (typeof json.content === "string") return json.content;
10534
- return JSON.stringify(json);
10535
- } finally {
10536
- clearTimeout(timer);
10583
+ getResolve()(callbackToken, data);
10537
10584
  }
10538
- }
10585
+ );
10586
+ return "task-initiated";
10587
+ };
10588
+ }
10589
+ function detectRuntime(scriptPath) {
10590
+ if (scriptPath.endsWith(".js") || scriptPath.endsWith(".mjs") || scriptPath.endsWith(".ts")) return "node";
10591
+ if (scriptPath.endsWith(".py")) return "python3";
10592
+ if (scriptPath.endsWith(".sh")) return "bash";
10593
+ return "bash";
10594
+ }
10595
+ function createScriptHandler(options) {
10596
+ const {
10597
+ scriptPath,
10598
+ runtime,
10599
+ args = [],
10600
+ cwd,
10601
+ timeoutMs = 6e4,
10602
+ captureOutput = false,
10603
+ getResolve
10604
+ } = options;
10605
+ const resolvedRuntime = runtime ?? detectRuntime(scriptPath);
10606
+ const shellArgs = [ctx_taskName_placeholder, ...args].join(" ");
10607
+ const command = `${resolvedRuntime} ${scriptPath} ${shellArgs}`;
10608
+ return createShellHandler({
10609
+ command: command.replace(ctx_taskName_placeholder, "${taskName}"),
10610
+ cwd,
10611
+ timeoutMs,
10612
+ captureOutput,
10613
+ getResolve
10614
+ });
10615
+ }
10616
+ var ctx_taskName_placeholder = "__TASK_NAME__";
10617
+ function createWebhookHandler(options) {
10618
+ const {
10619
+ url: urlTemplate,
10620
+ method = "POST",
10621
+ headers = {},
10622
+ timeoutMs = 3e4,
10623
+ failOnNon2xx = true,
10624
+ getResolve
10625
+ } = options;
10626
+ return async (input) => {
10627
+ const { callbackToken, nodeId, config } = input;
10628
+ const url = urlTemplate.replace(/\$\{taskName\}/g, nodeId);
10629
+ const body = JSON.stringify({
10630
+ taskName: nodeId,
10631
+ callbackToken,
10632
+ config
10633
+ });
10634
+ const controller = new AbortController();
10635
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
10636
+ fetch(url, {
10637
+ method,
10638
+ headers: { "Content-Type": "application/json", ...headers },
10639
+ body,
10640
+ signal: controller.signal
10641
+ }).then(async (response) => {
10642
+ clearTimeout(timer);
10643
+ if (failOnNon2xx && !response.ok) {
10644
+ const text = await response.text().catch(() => "");
10645
+ getResolve()(callbackToken, {}, [`HTTP ${response.status}: ${text}`]);
10646
+ return;
10647
+ }
10648
+ const data = await response.json().catch(() => ({}));
10649
+ getResolve()(callbackToken, data);
10650
+ }).catch((err) => {
10651
+ clearTimeout(timer);
10652
+ getResolve()(callbackToken, {}, [err instanceof Error ? err.message : String(err)]);
10653
+ });
10654
+ return "task-initiated";
10655
+ };
10656
+ }
10657
+ function createNoopHandler(getResolve, staticData) {
10658
+ return async (input) => {
10659
+ getResolve()(input.callbackToken, staticData ?? {});
10660
+ return "task-initiated";
10539
10661
  };
10540
10662
  }
10541
10663
 
@@ -11319,6 +11441,405 @@ var CardCompute = {
11319
11441
  }
11320
11442
  };
11321
11443
 
11322
- export { COMPLETION_STRATEGIES, CONFLICT_STRATEGIES, CardCompute, DEFAULTS, EXECUTION_MODES, EXECUTION_STATUS, FileJournal, FileStore, StepMachine as FlowEngine, LocalStorageStore, MemoryJournal, MemoryStore, StepMachine, TASK_STATUS, addDynamicTask, addNode, addProvides, addRequires, apply, applyAll, applyEvent, applyEvents, applyInferences, applyStepResult, batch, buildInferencePrompt, checkCircuitBreaker, computeAvailableOutputs, computeStepInput, createCliAdapter, createDefaultTaskState, createStepMachine as createEngine, createHttpAdapter, createInitialExecutionState, createInitialState, createLiveGraph, createReactiveGraph, createStepMachine, detectStuckState, disableNode, drainTokens, enableNode, exportGraphConfig, exportGraphConfigToFile, extractReturnData, flowToMermaid, getAllTasks, getCandidateTasks, getDownstream, getMaxExecutions, getNode, getProvides, getRefreshStrategy, getRequires, getTask, getUnreachableNodes, getUnreachableTokens, getUpstream, graphToMermaid, hasTask, inferAndApply, inferCompletions, injectTokens, inspect, isExecutionComplete, isNonActiveTask, isRerunnable, isTaskCompleted, isTaskRunning, loadGraphConfig, loadStepFlow, next, planExecution, removeNode, removeProvides, removeRequires, resetNode, resolveConfigTemplates, resolveVariables, restore, schedule, snapshot, validateFlowSchema, validateGraph, validateGraphConfig, validateGraphSchema, validateLiveCardSchema, validateStepFlowConfig };
11444
+ // src/continuous-event-graph/live-cards-bridge.ts
11445
+ function liveCardsToReactiveGraph(input, options = {}) {
11446
+ let cards;
11447
+ let boardSettings = {};
11448
+ let boardId;
11449
+ if (!Array.isArray(input) && "nodes" in input) {
11450
+ const board = input;
11451
+ cards = board.nodes;
11452
+ boardId = board.id;
11453
+ boardSettings = board.settings ?? {};
11454
+ } else {
11455
+ cards = input;
11456
+ }
11457
+ const {
11458
+ sourceHandlers = {},
11459
+ defaultSourceHandler,
11460
+ cardHandlers = {},
11461
+ reactiveOptions = {},
11462
+ graphSettings = {},
11463
+ executionId
11464
+ } = options;
11465
+ const cardMap = /* @__PURE__ */ new Map();
11466
+ for (const card of cards) {
11467
+ if (cardMap.has(card.id)) {
11468
+ throw new Error(`Duplicate card ID: "${card.id}"`);
11469
+ }
11470
+ cardMap.set(card.id, card);
11471
+ }
11472
+ const sharedState = options.sharedState ?? /* @__PURE__ */ new Map();
11473
+ const tasks = {};
11474
+ for (const card of cards) {
11475
+ const requires = card.data?.requires ?? [];
11476
+ for (const req of requires) {
11477
+ if (!cardMap.has(req)) {
11478
+ throw new Error(`Card "${card.id}" requires "${req}" but no card with that ID exists`);
11479
+ }
11480
+ }
11481
+ tasks[card.id] = {
11482
+ requires: requires.length > 0 ? requires : void 0,
11483
+ provides: [card.id],
11484
+ taskHandlers: [card.id],
11485
+ // each card has a named handler matching its ID
11486
+ description: card.meta?.title ?? `${card.type}: ${card.id}`
11487
+ };
11488
+ }
11489
+ const config = {
11490
+ id: boardId ?? `live-cards-${Date.now()}`,
11491
+ settings: {
11492
+ completion: "manual",
11493
+ execution_mode: "eligibility-mode",
11494
+ ...boardSettings,
11495
+ ...graphSettings
11496
+ },
11497
+ tasks
11498
+ };
11499
+ const handlers = {};
11500
+ let graphRef = null;
11501
+ const getResolve = () => (token, data, errors) => {
11502
+ graphRef.resolveCallback(token, data, errors);
11503
+ };
11504
+ for (const card of cards) {
11505
+ if (card.type === "source") {
11506
+ handlers[card.id] = buildSourceHandler(card, sourceHandlers, defaultSourceHandler, sharedState, getResolve);
11507
+ } else {
11508
+ handlers[card.id] = buildCardHandler(card, cardHandlers, sharedState, cardMap, getResolve);
11509
+ }
11510
+ }
11511
+ const graph = createReactiveGraph(
11512
+ config,
11513
+ {
11514
+ ...reactiveOptions,
11515
+ handlers
11516
+ },
11517
+ executionId
11518
+ );
11519
+ graphRef = graph;
11520
+ return { graph, config, handlers, cards: cardMap, sharedState };
11521
+ }
11522
+ function buildSourceHandler(card, sourceHandlers, defaultSourceHandler, sharedState, getResolve) {
11523
+ if (sourceHandlers[card.id]) {
11524
+ const userHandler = sourceHandlers[card.id];
11525
+ return async (input) => {
11526
+ return userHandler(input);
11527
+ };
11528
+ }
11529
+ if (defaultSourceHandler) {
11530
+ const factoryHandler = defaultSourceHandler(card);
11531
+ return async (input) => {
11532
+ return factoryHandler(input);
11533
+ };
11534
+ }
11535
+ return async (input) => {
11536
+ const state = { ...card.state };
11537
+ sharedState.set(card.id, state);
11538
+ getResolve()(input.callbackToken, state);
11539
+ return "task-initiated";
11540
+ };
11541
+ }
11542
+ function buildCardHandler(card, cardHandlers, sharedState, cardMap, getResolve) {
11543
+ if (cardHandlers[card.id]) {
11544
+ const userHandler = cardHandlers[card.id];
11545
+ return async (input) => {
11546
+ return userHandler(input);
11547
+ };
11548
+ }
11549
+ return async (input) => {
11550
+ const computeNode = {
11551
+ id: card.id,
11552
+ state: { ...card.state },
11553
+ compute: card.compute
11554
+ };
11555
+ const requires = card.data?.requires ?? [];
11556
+ for (const upstreamId of requires) {
11557
+ const upstreamState = sharedState.get(upstreamId);
11558
+ if (upstreamState) {
11559
+ computeNode.state[upstreamId] = upstreamState;
11560
+ }
11561
+ const upstreamCard = cardMap.get(upstreamId);
11562
+ if (upstreamCard?.data?.provides && upstreamState) {
11563
+ for (const [key, bindRef] of Object.entries(upstreamCard.data.provides)) {
11564
+ if (typeof bindRef === "string" && bindRef.startsWith("state.")) {
11565
+ const path = bindRef.slice(6);
11566
+ const value = deepGet2(upstreamState, path);
11567
+ if (value !== void 0) {
11568
+ computeNode.state[key] = value;
11569
+ }
11570
+ }
11571
+ }
11572
+ }
11573
+ }
11574
+ CardCompute.run(computeNode);
11575
+ const resultState = { ...computeNode.state };
11576
+ sharedState.set(card.id, resultState);
11577
+ getResolve()(input.callbackToken, resultState);
11578
+ return "task-initiated";
11579
+ };
11580
+ }
11581
+ function deepGet2(obj, path) {
11582
+ if (!path || !obj) return void 0;
11583
+ const parts = path.split(".");
11584
+ let cur = obj;
11585
+ for (const part of parts) {
11586
+ if (cur == null) return void 0;
11587
+ cur = cur[part];
11588
+ }
11589
+ return cur;
11590
+ }
11591
+
11592
+ // src/inference/core.ts
11593
+ var DEFAULT_THRESHOLD = 0.5;
11594
+ var DEFAULT_SYSTEM_PROMPT = `You are a workflow completion analyzer. Given a graph of tasks with their current states, evidence, and inference hints, determine which tasks appear to be completed based on the available evidence.
11595
+
11596
+ For each task you analyze, provide a JSON response. Be conservative \u2014 only mark tasks as completed when the evidence strongly supports it.`;
11597
+ function buildInferencePrompt(live, options = {}) {
11598
+ const { scope, context, systemPrompt } = options;
11599
+ const graphTasks = getAllTasks(live.config);
11600
+ const { state } = live;
11601
+ const candidates = getAnalyzableCandidates(live, scope);
11602
+ if (candidates.length === 0) {
11603
+ return "";
11604
+ }
11605
+ const lines = [];
11606
+ lines.push(systemPrompt || DEFAULT_SYSTEM_PROMPT);
11607
+ lines.push("");
11608
+ lines.push("## Graph State");
11609
+ lines.push("");
11610
+ lines.push(`Available tokens: ${state.availableOutputs.length > 0 ? state.availableOutputs.join(", ") : "(none)"}`);
11611
+ lines.push("");
11612
+ const completedTasks = Object.entries(state.tasks).filter(([_, ts]) => ts.status === "completed").map(([name]) => name);
11613
+ if (completedTasks.length > 0) {
11614
+ lines.push(`Completed tasks: ${completedTasks.join(", ")}`);
11615
+ lines.push("");
11616
+ }
11617
+ lines.push("## Tasks to Analyze");
11618
+ lines.push("");
11619
+ for (const taskName of candidates) {
11620
+ const taskConfig = graphTasks[taskName];
11621
+ const taskState = state.tasks[taskName];
11622
+ lines.push(`### ${taskName}`);
11623
+ if (taskConfig.description) {
11624
+ lines.push(`Description: ${taskConfig.description}`);
11625
+ }
11626
+ const requires = getRequires(taskConfig);
11627
+ const provides = getProvides(taskConfig);
11628
+ if (requires.length > 0) lines.push(`Requires: ${requires.join(", ")}`);
11629
+ if (provides.length > 0) lines.push(`Provides: ${provides.join(", ")}`);
11630
+ lines.push(`Current status: ${taskState?.status || "not-started"}`);
11631
+ const hints = taskConfig.inference;
11632
+ if (hints) {
11633
+ if (hints.criteria) lines.push(`Completion criteria: ${hints.criteria}`);
11634
+ if (hints.keywords?.length) lines.push(`Keywords: ${hints.keywords.join(", ")}`);
11635
+ if (hints.suggestedChecks?.length) lines.push(`Suggested checks: ${hints.suggestedChecks.join("; ")}`);
11636
+ }
11637
+ lines.push("");
11638
+ }
11639
+ if (context) {
11640
+ lines.push("## Additional Context / Evidence");
11641
+ lines.push("");
11642
+ lines.push(context);
11643
+ lines.push("");
11644
+ }
11645
+ lines.push("## Response Format");
11646
+ lines.push("");
11647
+ lines.push("Respond with a JSON array of objects, one per task you have evidence for:");
11648
+ lines.push("```json");
11649
+ lines.push("[");
11650
+ lines.push(" {");
11651
+ lines.push(' "taskName": "task-name",');
11652
+ lines.push(' "confidence": 0.0 to 1.0,');
11653
+ lines.push(' "reasoning": "explanation of why you believe this task is complete or not"');
11654
+ lines.push(" }");
11655
+ lines.push("]");
11656
+ lines.push("```");
11657
+ lines.push("");
11658
+ lines.push("Rules:");
11659
+ lines.push('- Only include tasks from the "Tasks to Analyze" section');
11660
+ lines.push("- confidence 0.0 = no evidence of completion, 1.0 = certain it is complete");
11661
+ lines.push("- If you have no evidence for a task, omit it from the array");
11662
+ lines.push("- Be conservative \u2014 require clear evidence before high confidence");
11663
+ lines.push("- Respond ONLY with the JSON array, no additional text");
11664
+ return lines.join("\n");
11665
+ }
11666
+ async function inferCompletions(live, adapter, options = {}) {
11667
+ options.threshold ?? DEFAULT_THRESHOLD;
11668
+ const analyzedNodes = getAnalyzableCandidates(live, options.scope);
11669
+ if (analyzedNodes.length === 0) {
11670
+ return { suggestions: [], promptUsed: "", rawResponse: "", analyzedNodes: [] };
11671
+ }
11672
+ const prompt = buildInferencePrompt(live, options);
11673
+ const rawResponse = await adapter.analyze(prompt);
11674
+ const suggestions = parseInferenceResponse(rawResponse, analyzedNodes);
11675
+ return {
11676
+ suggestions,
11677
+ promptUsed: prompt,
11678
+ rawResponse,
11679
+ analyzedNodes
11680
+ };
11681
+ }
11682
+ function applyInferences(live, result, threshold = DEFAULT_THRESHOLD) {
11683
+ let current = live;
11684
+ for (const suggestion of result.suggestions) {
11685
+ if (suggestion.confidence < threshold) continue;
11686
+ const taskState = current.state.tasks[suggestion.taskName];
11687
+ if (!taskState) continue;
11688
+ if (taskState.status === "completed" || taskState.status === "running") continue;
11689
+ const now = (/* @__PURE__ */ new Date()).toISOString();
11690
+ current = applyEvent(current, {
11691
+ type: "task-started",
11692
+ taskName: suggestion.taskName,
11693
+ timestamp: now
11694
+ });
11695
+ current = applyEvent(current, {
11696
+ type: "task-completed",
11697
+ taskName: suggestion.taskName,
11698
+ timestamp: now,
11699
+ result: "llm-inferred"
11700
+ });
11701
+ }
11702
+ return current;
11703
+ }
11704
+ async function inferAndApply(live, adapter, options = {}) {
11705
+ const threshold = options.threshold ?? DEFAULT_THRESHOLD;
11706
+ const inference = await inferCompletions(live, adapter, options);
11707
+ const updated = applyInferences(live, inference, threshold);
11708
+ const applied = inference.suggestions.filter((s) => s.confidence >= threshold);
11709
+ const skipped = inference.suggestions.filter((s) => s.confidence < threshold);
11710
+ return {
11711
+ live: updated,
11712
+ inference,
11713
+ applied,
11714
+ skipped
11715
+ };
11716
+ }
11717
+ function getAnalyzableCandidates(live, scope) {
11718
+ const graphTasks = getAllTasks(live.config);
11719
+ const { state } = live;
11720
+ const candidates = [];
11721
+ for (const [name, config] of Object.entries(graphTasks)) {
11722
+ const taskState = state.tasks[name];
11723
+ if (taskState?.status === "completed" || taskState?.status === "running") continue;
11724
+ if (scope) {
11725
+ if (scope.includes(name)) candidates.push(name);
11726
+ } else {
11727
+ if (config.inference?.autoDetectable) candidates.push(name);
11728
+ }
11729
+ }
11730
+ return candidates;
11731
+ }
11732
+ function parseInferenceResponse(rawResponse, validNodes, _threshold) {
11733
+ const validSet = new Set(validNodes);
11734
+ try {
11735
+ const jsonStr = extractJson(rawResponse);
11736
+ if (!jsonStr) return [];
11737
+ const parsed = JSON.parse(jsonStr);
11738
+ if (!Array.isArray(parsed)) return [];
11739
+ const suggestions = [];
11740
+ for (const item of parsed) {
11741
+ if (!item || typeof item !== "object") continue;
11742
+ if (typeof item.taskName !== "string") continue;
11743
+ if (typeof item.confidence !== "number") continue;
11744
+ if (!validSet.has(item.taskName)) continue;
11745
+ const confidence = Math.max(0, Math.min(1, item.confidence));
11746
+ suggestions.push({
11747
+ taskName: item.taskName,
11748
+ confidence,
11749
+ reasoning: typeof item.reasoning === "string" ? item.reasoning : "",
11750
+ detectionMethod: "llm-inferred"
11751
+ });
11752
+ }
11753
+ return suggestions;
11754
+ } catch {
11755
+ return [];
11756
+ }
11757
+ }
11758
+ function extractJson(text) {
11759
+ if (!text || typeof text !== "string") return null;
11760
+ const trimmed = text.trim();
11761
+ const fenceMatch = trimmed.match(/```(?:json)?\s*\n?([\s\S]*?)\n?\s*```/);
11762
+ if (fenceMatch) return fenceMatch[1].trim();
11763
+ const firstBracket = trimmed.indexOf("[");
11764
+ const lastBracket = trimmed.lastIndexOf("]");
11765
+ if (firstBracket !== -1 && lastBracket > firstBracket) {
11766
+ return trimmed.slice(firstBracket, lastBracket + 1);
11767
+ }
11768
+ if (trimmed.startsWith("[")) return trimmed;
11769
+ return null;
11770
+ }
11771
+ function createCliAdapter(opts) {
11772
+ const timeout = opts.timeout ?? 6e4;
11773
+ return {
11774
+ analyze: (prompt) => {
11775
+ return new Promise((resolve2, reject) => {
11776
+ const args = opts.args(prompt);
11777
+ const child = execFile(
11778
+ opts.command,
11779
+ opts.stdin ? opts.args("") : args,
11780
+ {
11781
+ timeout,
11782
+ cwd: opts.cwd,
11783
+ env: opts.env ? { ...process.env, ...opts.env } : void 0,
11784
+ maxBuffer: 10 * 1024 * 1024
11785
+ // 10MB
11786
+ },
11787
+ (error, stdout, stderr) => {
11788
+ if (error) {
11789
+ reject(new Error(
11790
+ `CLI adapter failed: ${opts.command} exited with ${error.code ?? "error"}` + (stderr ? `
11791
+ stderr: ${stderr.slice(0, 500)}` : "") + `
11792
+ ${error.message}`
11793
+ ));
11794
+ } else {
11795
+ resolve2(stdout);
11796
+ }
11797
+ }
11798
+ );
11799
+ if (opts.stdin && child.stdin) {
11800
+ child.stdin.write(prompt);
11801
+ child.stdin.end();
11802
+ }
11803
+ });
11804
+ }
11805
+ };
11806
+ }
11807
+ function createHttpAdapter(opts) {
11808
+ const timeout = opts.timeout ?? 6e4;
11809
+ return {
11810
+ analyze: async (prompt) => {
11811
+ const body = opts.buildBody ? opts.buildBody(prompt) : { prompt };
11812
+ const controller = new AbortController();
11813
+ const timer = setTimeout(() => controller.abort(), timeout);
11814
+ try {
11815
+ const response = await fetch(opts.url, {
11816
+ method: "POST",
11817
+ headers: {
11818
+ "Content-Type": "application/json",
11819
+ ...opts.headers ?? {}
11820
+ },
11821
+ body: JSON.stringify(body),
11822
+ signal: controller.signal
11823
+ });
11824
+ if (!response.ok) {
11825
+ const text = await response.text().catch(() => "");
11826
+ throw new Error(`HTTP ${response.status}: ${text.slice(0, 500)}`);
11827
+ }
11828
+ const json = await response.json();
11829
+ if (opts.extractResponse) {
11830
+ return opts.extractResponse(json);
11831
+ }
11832
+ if (typeof json.response === "string") return json.response;
11833
+ if (typeof json.text === "string") return json.text;
11834
+ if (typeof json.content === "string") return json.content;
11835
+ return JSON.stringify(json);
11836
+ } finally {
11837
+ clearTimeout(timer);
11838
+ }
11839
+ }
11840
+ };
11841
+ }
11842
+
11843
+ export { COMPLETION_STRATEGIES, CONFLICT_STRATEGIES, CardCompute, DEFAULTS, EXECUTION_MODES, EXECUTION_STATUS, FileJournal, FileStore, StepMachine as FlowEngine, LocalStorageStore, MemoryJournal, MemoryStore, StepMachine, TASK_STATUS, addDynamicTask, addNode, addProvides, addRequires, apply, applyAll, applyEvent, applyEvents, applyInferences, applyStepResult, batch, buildInferencePrompt, checkCircuitBreaker, computeAvailableOutputs, computeStepInput, createCallbackHandler, createCliAdapter, createDefaultGraphEngineStore, createStepMachine as createEngine, createFireAndForgetHandler, createHttpAdapter, createInitialExecutionState, createInitialState, createLiveGraph, createNoopHandler, createReactiveGraph, createScriptHandler, createShellHandler, createStepMachine, createWebhookHandler, detectStuckState, disableNode, drainTokens, enableNode, exportGraphConfig, exportGraphConfigToFile, extractReturnData, flowToMermaid, getAllTasks, getCandidateTasks, getDownstream, getMaxExecutions, getNode, getProvides, getRefreshStrategy, getRequires, getTask, getUnreachableNodes, getUnreachableTokens, getUpstream, graphToMermaid, hasTask, inferAndApply, inferCompletions, injectTokens, inspect, isExecutionComplete, isNonActiveTask, isRerunnable, isTaskCompleted, isTaskRunning, liveCardsToReactiveGraph, loadGraphConfig, loadStepFlow, mutateGraph, next, planExecution, removeNode, removeProvides, removeRequires, resetNode, resolveConfigTemplates, resolveVariables, restore, schedule, snapshot, validateFlowSchema, validateGraph, validateGraphConfig, validateGraphSchema, validateLiveCardSchema, validateLiveGraph, validateReactiveGraph, validateStepFlowConfig };
11323
11844
  //# sourceMappingURL=index.js.map
11324
11845
  //# sourceMappingURL=index.js.map