yaml-flow 2.8.0 → 3.0.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 (39) hide show
  1. package/README.md +168 -3
  2. package/dist/{constants-BEbO2_OK.d.ts → constants-B_ftYTTE.d.ts} +36 -6
  3. package/dist/{constants-BNjeIlZ8.d.cts → constants-CiyHX8L-.d.cts} +36 -6
  4. package/dist/continuous-event-graph/index.cjs +399 -42
  5. package/dist/continuous-event-graph/index.cjs.map +1 -1
  6. package/dist/continuous-event-graph/index.d.cts +124 -5
  7. package/dist/continuous-event-graph/index.d.ts +124 -5
  8. package/dist/continuous-event-graph/index.js +396 -43
  9. package/dist/continuous-event-graph/index.js.map +1 -1
  10. package/dist/event-graph/index.cjs +6784 -44
  11. package/dist/event-graph/index.cjs.map +1 -1
  12. package/dist/event-graph/index.d.cts +5 -5
  13. package/dist/event-graph/index.d.ts +5 -5
  14. package/dist/event-graph/index.js +6777 -43
  15. package/dist/event-graph/index.js.map +1 -1
  16. package/dist/index.cjs +946 -91
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.cts +5 -5
  19. package/dist/index.d.ts +5 -5
  20. package/dist/index.js +938 -91
  21. package/dist/index.js.map +1 -1
  22. package/dist/inference/index.cjs +17 -8
  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 +17 -8
  27. package/dist/inference/index.js.map +1 -1
  28. package/dist/step-machine/index.cjs +6600 -0
  29. package/dist/step-machine/index.cjs.map +1 -1
  30. package/dist/step-machine/index.d.cts +26 -1
  31. package/dist/step-machine/index.d.ts +26 -1
  32. package/dist/step-machine/index.js +6596 -1
  33. package/dist/step-machine/index.js.map +1 -1
  34. package/dist/{types-DAI_a2as.d.ts → types-BpWrH1sf.d.cts} +16 -7
  35. package/dist/{types-DAI_a2as.d.cts → types-BpWrH1sf.d.ts} +16 -7
  36. package/dist/{types-mS_pPftm.d.ts → types-BuEo3wVG.d.ts} +1 -1
  37. package/dist/{types-C2lOwquM.d.cts → types-CxJg9Jrt.d.cts} +1 -1
  38. package/package.json +1 -1
  39. package/schema/event-graph.schema.json +254 -0
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
- import { execFile } from 'child_process';
2
1
  import addFormats from 'ajv-formats';
2
+ import { existsSync, writeFileSync, appendFileSync, readFileSync } from 'fs';
3
+ import { execFile } from 'child_process';
3
4
 
4
5
  var __create = Object.create;
5
6
  var __defProp = Object.defineProperty;
@@ -3911,7 +3912,7 @@ var require_core = __commonJS({
3911
3912
  uriResolver
3912
3913
  };
3913
3914
  }
3914
- var Ajv2 = class {
3915
+ var Ajv4 = class {
3915
3916
  constructor(opts = {}) {
3916
3917
  this.schemas = {};
3917
3918
  this.refs = {};
@@ -4281,9 +4282,9 @@ var require_core = __commonJS({
4281
4282
  }
4282
4283
  }
4283
4284
  };
4284
- Ajv2.ValidationError = validation_error_1.default;
4285
- Ajv2.MissingRefError = ref_error_1.default;
4286
- exports$1.default = Ajv2;
4285
+ Ajv4.ValidationError = validation_error_1.default;
4286
+ Ajv4.MissingRefError = ref_error_1.default;
4287
+ exports$1.default = Ajv4;
4287
4288
  function checkOptions(checkOpts, options, msg, log = "error") {
4288
4289
  for (const key in checkOpts) {
4289
4290
  const opt = key;
@@ -6354,7 +6355,7 @@ var require_ajv = __commonJS({
6354
6355
  var draft7MetaSchema = require_json_schema_draft_07();
6355
6356
  var META_SUPPORT_DATA = ["/properties"];
6356
6357
  var META_SCHEMA_ID = "http://json-schema.org/draft-07/schema";
6357
- var Ajv2 = class extends core_1.default {
6358
+ var Ajv4 = class extends core_1.default {
6358
6359
  _addVocabularies() {
6359
6360
  super._addVocabularies();
6360
6361
  draft7_1.default.forEach((v) => this.addVocabulary(v));
@@ -6373,11 +6374,11 @@ var require_ajv = __commonJS({
6373
6374
  return this.opts.defaultMeta = super.defaultMeta() || (this.getSchema(META_SCHEMA_ID) ? META_SCHEMA_ID : void 0);
6374
6375
  }
6375
6376
  };
6376
- exports$1.Ajv = Ajv2;
6377
- module.exports = exports$1 = Ajv2;
6378
- module.exports.Ajv = Ajv2;
6377
+ exports$1.Ajv = Ajv4;
6378
+ module.exports = exports$1 = Ajv4;
6379
+ module.exports.Ajv = Ajv4;
6379
6380
  Object.defineProperty(exports$1, "__esModule", { value: true });
6380
- exports$1.default = Ajv2;
6381
+ exports$1.default = Ajv4;
6381
6382
  var validate_1 = require_validate();
6382
6383
  Object.defineProperty(exports$1, "KeywordCxt", { enumerable: true, get: function() {
6383
6384
  return validate_1.KeywordCxt;
@@ -6911,6 +6912,188 @@ async function loadStepFlow(source) {
6911
6912
  return flow;
6912
6913
  }
6913
6914
 
6915
+ // schema/flow.schema.json
6916
+ var flow_schema_default = {
6917
+ $schema: "http://json-schema.org/draft-07/schema#",
6918
+ $id: "https://github.com/yaml-flow/schema/flow.json",
6919
+ title: "YamlFlow Configuration",
6920
+ description: "Schema for yaml-flow workflow definitions",
6921
+ type: "object",
6922
+ required: ["settings", "steps", "terminal_states"],
6923
+ properties: {
6924
+ id: {
6925
+ type: "string",
6926
+ description: "Optional flow identifier"
6927
+ },
6928
+ settings: {
6929
+ type: "object",
6930
+ description: "Flow-level settings",
6931
+ required: ["start_step"],
6932
+ properties: {
6933
+ start_step: {
6934
+ type: "string",
6935
+ description: "Step to start execution from"
6936
+ },
6937
+ max_total_steps: {
6938
+ type: "integer",
6939
+ minimum: 1,
6940
+ default: 100,
6941
+ description: "Maximum steps before forced termination"
6942
+ },
6943
+ timeout_ms: {
6944
+ type: "integer",
6945
+ minimum: 0,
6946
+ description: "Flow timeout in milliseconds"
6947
+ }
6948
+ },
6949
+ additionalProperties: false
6950
+ },
6951
+ steps: {
6952
+ type: "object",
6953
+ description: "Step definitions",
6954
+ minProperties: 1,
6955
+ additionalProperties: {
6956
+ $ref: "#/definitions/step"
6957
+ }
6958
+ },
6959
+ terminal_states: {
6960
+ type: "object",
6961
+ description: "Terminal state definitions",
6962
+ minProperties: 1,
6963
+ additionalProperties: {
6964
+ $ref: "#/definitions/terminal_state"
6965
+ }
6966
+ }
6967
+ },
6968
+ additionalProperties: false,
6969
+ definitions: {
6970
+ step: {
6971
+ type: "object",
6972
+ description: "Individual step configuration",
6973
+ required: ["transitions"],
6974
+ properties: {
6975
+ description: {
6976
+ type: "string",
6977
+ description: "Human-readable description"
6978
+ },
6979
+ expects_data: {
6980
+ type: "array",
6981
+ items: { type: "string" },
6982
+ description: "Data keys this step expects as input"
6983
+ },
6984
+ produces_data: {
6985
+ type: "array",
6986
+ items: { type: "string" },
6987
+ description: "Data keys this step produces as output"
6988
+ },
6989
+ transitions: {
6990
+ type: "object",
6991
+ description: "Mapping of result -> next step name",
6992
+ additionalProperties: { type: "string" },
6993
+ minProperties: 1
6994
+ },
6995
+ retry: {
6996
+ $ref: "#/definitions/retry_config"
6997
+ },
6998
+ circuit_breaker: {
6999
+ $ref: "#/definitions/circuit_breaker_config"
7000
+ }
7001
+ },
7002
+ additionalProperties: false
7003
+ },
7004
+ terminal_state: {
7005
+ type: "object",
7006
+ description: "Terminal state configuration",
7007
+ required: ["return_intent"],
7008
+ properties: {
7009
+ description: {
7010
+ type: "string",
7011
+ description: "Human-readable description"
7012
+ },
7013
+ return_intent: {
7014
+ type: "string",
7015
+ description: "Intent/status to return (e.g., 'success', 'error')"
7016
+ },
7017
+ return_artifacts: {
7018
+ oneOf: [
7019
+ { type: "string" },
7020
+ { type: "array", items: { type: "string" } },
7021
+ { type: "boolean", const: false }
7022
+ ],
7023
+ description: "Data key(s) to include in result, or false to exclude"
7024
+ },
7025
+ expects_data: {
7026
+ type: "array",
7027
+ items: { type: "string" },
7028
+ description: "Data keys this terminal state expects"
7029
+ }
7030
+ },
7031
+ additionalProperties: false
7032
+ },
7033
+ retry_config: {
7034
+ type: "object",
7035
+ description: "Retry configuration for step failures",
7036
+ required: ["max_attempts"],
7037
+ properties: {
7038
+ max_attempts: {
7039
+ type: "integer",
7040
+ minimum: 1,
7041
+ description: "Maximum retry attempts"
7042
+ },
7043
+ delay_ms: {
7044
+ type: "integer",
7045
+ minimum: 0,
7046
+ description: "Delay between retries in ms"
7047
+ },
7048
+ backoff_multiplier: {
7049
+ type: "number",
7050
+ minimum: 1,
7051
+ description: "Backoff multiplier (e.g., 2 for exponential)"
7052
+ }
7053
+ },
7054
+ additionalProperties: false
7055
+ },
7056
+ circuit_breaker_config: {
7057
+ type: "object",
7058
+ description: "Circuit breaker configuration for loops",
7059
+ required: ["max_iterations", "on_open"],
7060
+ properties: {
7061
+ max_iterations: {
7062
+ type: "integer",
7063
+ minimum: 1,
7064
+ description: "Maximum iterations before circuit opens"
7065
+ },
7066
+ on_open: {
7067
+ type: "string",
7068
+ description: "Step to transition to when circuit opens"
7069
+ }
7070
+ },
7071
+ additionalProperties: false
7072
+ }
7073
+ }
7074
+ };
7075
+
7076
+ // src/step-machine/schema-validator.ts
7077
+ var import_ajv = __toESM(require_ajv());
7078
+ var _compiled = null;
7079
+ function getValidator() {
7080
+ if (_compiled) return _compiled;
7081
+ const ajv = new import_ajv.default({ allErrors: true });
7082
+ addFormats(ajv);
7083
+ _compiled = ajv.compile(flow_schema_default);
7084
+ return _compiled;
7085
+ }
7086
+ function validateFlowSchema(config) {
7087
+ const validate = getValidator();
7088
+ const valid = validate(config);
7089
+ if (valid) return { ok: true, errors: [] };
7090
+ const errors = (validate.errors ?? []).map((e) => {
7091
+ const path = e.instancePath || "/";
7092
+ return `${path}: ${e.message ?? "unknown error"}`;
7093
+ });
7094
+ return { ok: false, errors };
7095
+ }
7096
+
6914
7097
  // src/event-graph/constants.ts
6915
7098
  var TASK_STATUS = {
6916
7099
  NOT_STARTED: "not-started",
@@ -6987,15 +7170,14 @@ function isTaskCompleted(taskState) {
6987
7170
  function isTaskRunning(taskState) {
6988
7171
  return taskState?.status === TASK_STATUS.RUNNING;
6989
7172
  }
6990
- function isRepeatableTask(taskConfig) {
6991
- return taskConfig.repeatable === true || typeof taskConfig.repeatable === "object" && taskConfig.repeatable !== null;
7173
+ function getRefreshStrategy(taskConfig, graphSettings) {
7174
+ return taskConfig.refreshStrategy ?? graphSettings?.refreshStrategy ?? "data-changed";
6992
7175
  }
6993
- function getRepeatableMax(taskConfig) {
6994
- if (taskConfig.repeatable === true) return void 0;
6995
- if (typeof taskConfig.repeatable === "object" && taskConfig.repeatable !== null) {
6996
- return taskConfig.repeatable.max;
6997
- }
6998
- return void 0;
7176
+ function isRerunnable(taskConfig, graphSettings) {
7177
+ return getRefreshStrategy(taskConfig, graphSettings) !== "once";
7178
+ }
7179
+ function getMaxExecutions(taskConfig) {
7180
+ return taskConfig.maxExecutions;
6999
7181
  }
7000
7182
  function computeAvailableOutputs(graph, taskStates) {
7001
7183
  const outputs = /* @__PURE__ */ new Set();
@@ -7427,48 +7609,88 @@ function getCandidateTasks(graph, state) {
7427
7609
  const candidates = [];
7428
7610
  for (const [taskName, taskConfig] of Object.entries(graphTasks)) {
7429
7611
  const taskState = state.tasks[taskName];
7430
- if (!isRepeatableTask(taskConfig)) {
7431
- if (taskState?.status === TASK_STATUS.COMPLETED || taskState?.status === TASK_STATUS.RUNNING || isNonActiveTask(taskState)) {
7432
- continue;
7433
- }
7434
- } else {
7435
- if (taskState?.status === TASK_STATUS.RUNNING || isNonActiveTask(taskState)) {
7436
- continue;
7437
- }
7438
- const maxExec = getRepeatableMax(taskConfig);
7439
- if (maxExec !== void 0 && taskState && taskState.executionCount >= maxExec) {
7612
+ const strategy = getRefreshStrategy(taskConfig, graph.settings);
7613
+ const rerunnable = strategy !== "once";
7614
+ if (taskState?.status === TASK_STATUS.RUNNING || isNonActiveTask(taskState)) {
7615
+ continue;
7616
+ }
7617
+ const maxExec = getMaxExecutions(taskConfig);
7618
+ if (maxExec !== void 0 && taskState && taskState.executionCount >= maxExec) {
7619
+ continue;
7620
+ }
7621
+ if (taskConfig.circuit_breaker && taskState && taskState.executionCount >= taskConfig.circuit_breaker.max_executions) {
7622
+ continue;
7623
+ }
7624
+ if (!rerunnable) {
7625
+ if (taskState?.status === TASK_STATUS.COMPLETED) {
7440
7626
  continue;
7441
7627
  }
7442
- if (taskConfig.circuit_breaker) {
7443
- if (taskState && taskState.executionCount >= taskConfig.circuit_breaker.max_executions) {
7444
- continue;
7628
+ }
7629
+ if (rerunnable && taskState?.status === TASK_STATUS.COMPLETED) {
7630
+ const requires2 = getRequires(taskConfig);
7631
+ switch (strategy) {
7632
+ case "data-changed": {
7633
+ if (requires2.length > 0) {
7634
+ const hasChangedData = requires2.some((req) => {
7635
+ for (const [otherName, otherConfig] of Object.entries(graphTasks)) {
7636
+ if (getProvides(otherConfig).includes(req)) {
7637
+ const otherState = state.tasks[otherName];
7638
+ if (!otherState) continue;
7639
+ const consumed = taskState.lastConsumedHashes?.[req];
7640
+ if (otherState.lastDataHash == null) {
7641
+ return otherState.executionCount > taskState.lastEpoch;
7642
+ }
7643
+ return otherState.lastDataHash !== consumed;
7644
+ }
7645
+ }
7646
+ return false;
7647
+ });
7648
+ if (!hasChangedData) continue;
7649
+ } else {
7650
+ continue;
7651
+ }
7652
+ break;
7445
7653
  }
7446
- }
7447
- if (taskState?.status === TASK_STATUS.COMPLETED) {
7448
- const requires2 = getRequires(taskConfig);
7449
- if (requires2.length > 0) {
7450
- const hasRefreshedInputs = requires2.some((req) => {
7451
- for (const [otherName, otherConfig] of Object.entries(graphTasks)) {
7452
- if (getProvides(otherConfig).includes(req)) {
7453
- const otherState = state.tasks[otherName];
7454
- if (otherState && otherState.executionCount > taskState.lastEpoch) {
7455
- return true;
7654
+ case "epoch-changed": {
7655
+ if (requires2.length > 0) {
7656
+ const hasRefreshedInputs = requires2.some((req) => {
7657
+ for (const [otherName, otherConfig] of Object.entries(graphTasks)) {
7658
+ if (getProvides(otherConfig).includes(req)) {
7659
+ const otherState = state.tasks[otherName];
7660
+ if (otherState && otherState.executionCount > taskState.lastEpoch) {
7661
+ return true;
7662
+ }
7456
7663
  }
7457
7664
  }
7458
- }
7459
- return false;
7460
- });
7461
- if (!hasRefreshedInputs) continue;
7462
- } else {
7665
+ return false;
7666
+ });
7667
+ if (!hasRefreshedInputs) continue;
7668
+ } else {
7669
+ continue;
7670
+ }
7671
+ break;
7672
+ }
7673
+ case "time-based": {
7674
+ const interval = taskConfig.refreshInterval ?? 0;
7675
+ if (interval <= 0) continue;
7676
+ const completedAt = taskState.completedAt;
7677
+ if (!completedAt) continue;
7678
+ const elapsedSec = (Date.now() - Date.parse(completedAt)) / 1e3;
7679
+ if (elapsedSec < interval) continue;
7680
+ break;
7681
+ }
7682
+ case "manual": {
7463
7683
  continue;
7464
7684
  }
7685
+ default:
7686
+ continue;
7465
7687
  }
7466
7688
  }
7467
7689
  const requires = getRequires(taskConfig);
7468
7690
  if (!requires.every((req) => availableOutputs.includes(req))) {
7469
7691
  continue;
7470
7692
  }
7471
- if (!isRepeatableTask(taskConfig)) {
7693
+ if (!rerunnable) {
7472
7694
  const provides = getProvides(taskConfig);
7473
7695
  const allAlreadyAvailable = provides.length > 0 && provides.every((output) => availableOutputs.includes(output));
7474
7696
  if (allAlreadyAvailable) continue;
@@ -7552,7 +7774,7 @@ function applyTaskStart(state, taskName) {
7552
7774
  lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
7553
7775
  };
7554
7776
  }
7555
- function applyTaskCompletion(state, graph, taskName, result) {
7777
+ function applyTaskCompletion(state, graph, taskName, result, dataHash) {
7556
7778
  const existingTask = state.tasks[taskName] ?? createDefaultTaskState2();
7557
7779
  const taskConfig = graph.tasks[taskName];
7558
7780
  if (!taskConfig) {
@@ -7564,6 +7786,19 @@ function applyTaskCompletion(state, graph, taskName, result) {
7564
7786
  } else {
7565
7787
  outputTokens = getProvides(taskConfig);
7566
7788
  }
7789
+ const lastConsumedHashes = { ...existingTask.lastConsumedHashes };
7790
+ const requires = taskConfig.requires ?? [];
7791
+ for (const token of requires) {
7792
+ for (const [otherName, otherConfig] of Object.entries(graph.tasks)) {
7793
+ if (getProvides(otherConfig).includes(token)) {
7794
+ const otherState = state.tasks[otherName];
7795
+ if (otherState?.lastDataHash) {
7796
+ lastConsumedHashes[token] = otherState.lastDataHash;
7797
+ }
7798
+ break;
7799
+ }
7800
+ }
7801
+ }
7567
7802
  const updatedTask = {
7568
7803
  ...existingTask,
7569
7804
  status: "completed",
@@ -7571,11 +7806,10 @@ function applyTaskCompletion(state, graph, taskName, result) {
7571
7806
  lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
7572
7807
  executionCount: existingTask.executionCount + 1,
7573
7808
  lastEpoch: existingTask.executionCount + 1,
7809
+ lastDataHash: dataHash,
7810
+ lastConsumedHashes,
7574
7811
  error: void 0
7575
7812
  };
7576
- if (isRepeatableTask(taskConfig)) {
7577
- updatedTask.status = "not-started";
7578
- }
7579
7813
  const newOutputs = [.../* @__PURE__ */ new Set([...state.availableOutputs, ...outputTokens])];
7580
7814
  return {
7581
7815
  ...state,
@@ -7664,7 +7898,7 @@ function apply(state, event, graph) {
7664
7898
  case "task-started":
7665
7899
  return applyTaskStart(state, event.taskName);
7666
7900
  case "task-completed":
7667
- return applyTaskCompletion(state, graph, event.taskName, event.result);
7901
+ return applyTaskCompletion(state, graph, event.taskName, event.result, event.dataHash);
7668
7902
  case "task-failed":
7669
7903
  return applyTaskFailure(state, graph, event.taskName, event.error);
7670
7904
  case "task-progress":
@@ -8354,6 +8588,276 @@ function buildResult(issues) {
8354
8588
  };
8355
8589
  }
8356
8590
 
8591
+ // schema/event-graph.schema.json
8592
+ var event_graph_schema_default = {
8593
+ $schema: "http://json-schema.org/draft-07/schema#",
8594
+ $id: "https://github.com/yaml-flow/schema/event-graph.json",
8595
+ title: "Event Graph Configuration",
8596
+ description: "Schema for stateless event-graph (DAG) workflow definitions in yaml-flow",
8597
+ type: "object",
8598
+ required: ["settings", "tasks"],
8599
+ additionalProperties: false,
8600
+ properties: {
8601
+ id: {
8602
+ type: "string",
8603
+ description: "Optional graph identifier"
8604
+ },
8605
+ settings: {
8606
+ $ref: "#/definitions/settings"
8607
+ },
8608
+ tasks: {
8609
+ type: "object",
8610
+ description: "Task definitions keyed by name",
8611
+ minProperties: 1,
8612
+ additionalProperties: {
8613
+ $ref: "#/definitions/task"
8614
+ }
8615
+ }
8616
+ },
8617
+ definitions: {
8618
+ settings: {
8619
+ type: "object",
8620
+ required: ["completion"],
8621
+ properties: {
8622
+ completion: {
8623
+ type: "string",
8624
+ enum: [
8625
+ "all-tasks-done",
8626
+ "all-outputs-done",
8627
+ "only-resolved",
8628
+ "goal-reached",
8629
+ "manual"
8630
+ ],
8631
+ description: "Completion strategy"
8632
+ },
8633
+ conflict_strategy: {
8634
+ type: "string",
8635
+ enum: [
8636
+ "alphabetical",
8637
+ "priority-first",
8638
+ "duration-first",
8639
+ "cost-optimized",
8640
+ "resource-aware",
8641
+ "random-select",
8642
+ "user-choice",
8643
+ "parallel-all",
8644
+ "skip-conflicts",
8645
+ "round-robin"
8646
+ ],
8647
+ description: "Conflict resolution strategy"
8648
+ },
8649
+ execution_mode: {
8650
+ type: "string",
8651
+ enum: ["dependency-mode", "eligibility-mode"],
8652
+ description: "Execution mode"
8653
+ },
8654
+ goal: {
8655
+ type: "array",
8656
+ items: { type: "string" },
8657
+ minItems: 1,
8658
+ description: "Goal outputs \u2014 required when completion is 'goal-reached'"
8659
+ },
8660
+ max_iterations: {
8661
+ type: "integer",
8662
+ minimum: 1,
8663
+ description: "Max scheduler iterations (safety limit, default: 1000)"
8664
+ },
8665
+ timeout_ms: {
8666
+ type: "integer",
8667
+ minimum: 0,
8668
+ description: "Timeout in ms (declared for drivers, not enforced by pure engine)"
8669
+ },
8670
+ refreshStrategy: {
8671
+ $ref: "#/definitions/refresh_strategy",
8672
+ description: "Default refresh strategy for all tasks (default: 'data-changed')"
8673
+ }
8674
+ },
8675
+ additionalProperties: false,
8676
+ if: {
8677
+ properties: { completion: { const: "goal-reached" } }
8678
+ },
8679
+ then: {
8680
+ required: ["completion", "goal"]
8681
+ }
8682
+ },
8683
+ task: {
8684
+ type: "object",
8685
+ required: ["provides"],
8686
+ properties: {
8687
+ requires: {
8688
+ type: "array",
8689
+ items: { type: "string" },
8690
+ description: "Tokens this task needs to become eligible"
8691
+ },
8692
+ provides: {
8693
+ type: "array",
8694
+ items: { type: "string" },
8695
+ description: "Tokens this task produces on successful completion"
8696
+ },
8697
+ on: {
8698
+ type: "object",
8699
+ description: "Conditional provides based on handler result key",
8700
+ additionalProperties: {
8701
+ type: "array",
8702
+ items: { type: "string" }
8703
+ }
8704
+ },
8705
+ on_failure: {
8706
+ type: "array",
8707
+ items: { type: "string" },
8708
+ description: "Tokens to inject when this task fails"
8709
+ },
8710
+ method: {
8711
+ type: "string",
8712
+ description: "Task execution method (informational \u2014 driver concern)"
8713
+ },
8714
+ config: {
8715
+ type: "object",
8716
+ description: "Arbitrary task configuration (driver concern)"
8717
+ },
8718
+ priority: {
8719
+ type: "number",
8720
+ description: "Higher = preferred in conflict resolution"
8721
+ },
8722
+ estimatedDuration: {
8723
+ type: "number",
8724
+ minimum: 0,
8725
+ description: "Estimated duration in ms (used by duration-first strategy)"
8726
+ },
8727
+ estimatedCost: {
8728
+ type: "number",
8729
+ minimum: 0,
8730
+ description: "Estimated cost (used by cost-optimized strategy)"
8731
+ },
8732
+ estimatedResources: {
8733
+ type: "object",
8734
+ additionalProperties: { type: "number" },
8735
+ description: "Resource requirements (used by resource-aware strategy)"
8736
+ },
8737
+ retry: {
8738
+ $ref: "#/definitions/task_retry"
8739
+ },
8740
+ refreshStrategy: {
8741
+ $ref: "#/definitions/refresh_strategy",
8742
+ description: "Task-level refresh strategy (overrides settings default)"
8743
+ },
8744
+ refreshInterval: {
8745
+ type: "number",
8746
+ minimum: 0,
8747
+ description: "Interval in seconds for time-based refresh strategy"
8748
+ },
8749
+ maxExecutions: {
8750
+ type: "integer",
8751
+ minimum: 1,
8752
+ description: "Maximum number of times this task can execute"
8753
+ },
8754
+ circuit_breaker: {
8755
+ $ref: "#/definitions/task_circuit_breaker"
8756
+ },
8757
+ description: {
8758
+ type: "string",
8759
+ description: "Human-readable description"
8760
+ },
8761
+ inference: {
8762
+ $ref: "#/definitions/inference_hints"
8763
+ }
8764
+ },
8765
+ additionalProperties: false
8766
+ },
8767
+ task_retry: {
8768
+ type: "object",
8769
+ required: ["max_attempts"],
8770
+ properties: {
8771
+ max_attempts: {
8772
+ type: "integer",
8773
+ minimum: 1,
8774
+ description: "Maximum retry attempts"
8775
+ },
8776
+ delay_ms: {
8777
+ type: "integer",
8778
+ minimum: 0,
8779
+ description: "Delay between retries in ms"
8780
+ },
8781
+ backoff_multiplier: {
8782
+ type: "number",
8783
+ minimum: 1,
8784
+ description: "Backoff multiplier (e.g., 2 for exponential)"
8785
+ }
8786
+ },
8787
+ additionalProperties: false
8788
+ },
8789
+ refresh_strategy: {
8790
+ type: "string",
8791
+ enum: ["data-changed", "epoch-changed", "time-based", "manual", "once"],
8792
+ description: "Strategy for determining when a completed task should re-run"
8793
+ },
8794
+ task_circuit_breaker: {
8795
+ type: "object",
8796
+ required: ["max_executions", "on_break"],
8797
+ properties: {
8798
+ max_executions: {
8799
+ type: "integer",
8800
+ minimum: 1,
8801
+ description: "Max executions before breaker trips"
8802
+ },
8803
+ on_break: {
8804
+ type: "array",
8805
+ items: { type: "string" },
8806
+ minItems: 1,
8807
+ description: "Tokens to inject when breaker trips"
8808
+ }
8809
+ },
8810
+ additionalProperties: false
8811
+ },
8812
+ inference_hints: {
8813
+ type: "object",
8814
+ description: "LLM inference hints \u2014 opt-in metadata for AI-assisted completion detection",
8815
+ properties: {
8816
+ criteria: {
8817
+ type: "string",
8818
+ description: "Human-readable completion criteria"
8819
+ },
8820
+ keywords: {
8821
+ type: "array",
8822
+ items: { type: "string" },
8823
+ description: "Keywords to help the LLM understand the domain"
8824
+ },
8825
+ suggestedChecks: {
8826
+ type: "array",
8827
+ items: { type: "string" },
8828
+ description: "Suggested checks for verification"
8829
+ },
8830
+ autoDetectable: {
8831
+ type: "boolean",
8832
+ description: "Whether the LLM should attempt to auto-detect completion (default: false)"
8833
+ }
8834
+ },
8835
+ additionalProperties: false
8836
+ }
8837
+ }
8838
+ };
8839
+
8840
+ // src/event-graph/schema-validator.ts
8841
+ var import_ajv2 = __toESM(require_ajv());
8842
+ var _compiled2 = null;
8843
+ function getValidator2() {
8844
+ if (_compiled2) return _compiled2;
8845
+ const ajv = new import_ajv2.default({ allErrors: true });
8846
+ addFormats(ajv);
8847
+ _compiled2 = ajv.compile(event_graph_schema_default);
8848
+ return _compiled2;
8849
+ }
8850
+ function validateGraphSchema(config) {
8851
+ const validate = getValidator2();
8852
+ const valid = validate(config);
8853
+ if (valid) return { ok: true, errors: [] };
8854
+ const errors = (validate.errors ?? []).map((e) => {
8855
+ const path = e.instancePath || "/";
8856
+ return `${path}: ${e.message ?? "unknown error"}`;
8857
+ });
8858
+ return { ok: false, errors };
8859
+ }
8860
+
8357
8861
  // src/stores/localStorage.ts
8358
8862
  var LocalStorageStore = class {
8359
8863
  prefix;
@@ -8747,7 +9251,7 @@ function applyEvent(live, event) {
8747
9251
  newState = applyTaskStart(state, event.taskName);
8748
9252
  break;
8749
9253
  case "task-completed":
8750
- newState = applyTaskCompletion(state, config, event.taskName, event.result);
9254
+ newState = applyTaskCompletion(state, config, event.taskName, event.result, event.dataHash);
8751
9255
  break;
8752
9256
  case "task-failed":
8753
9257
  newState = applyTaskFailure(state, config, event.taskName, event.error);
@@ -8770,6 +9274,9 @@ function applyEvent(live, event) {
8770
9274
  }
8771
9275
  return { config, state: newState };
8772
9276
  }
9277
+ function applyEvents(live, events) {
9278
+ return events.reduce((current, event) => applyEvent(current, event), live);
9279
+ }
8773
9280
  function addNode(live, name, taskConfig) {
8774
9281
  if (live.config.tasks[name]) return live;
8775
9282
  return {
@@ -9014,38 +9521,84 @@ function schedule(live) {
9014
9521
  const blocked = [];
9015
9522
  for (const [taskName, taskConfig] of Object.entries(graphTasks)) {
9016
9523
  const taskState = state.tasks[taskName];
9017
- if (!isRepeatableTask(taskConfig)) {
9018
- if (taskState?.status === TASK_STATUS.COMPLETED || taskState?.status === TASK_STATUS.RUNNING || isNonActiveTask(taskState)) {
9019
- continue;
9020
- }
9021
- } else {
9022
- if (taskState?.status === TASK_STATUS.RUNNING || isNonActiveTask(taskState)) {
9023
- continue;
9024
- }
9025
- const maxExec = getRepeatableMax(taskConfig);
9026
- if (maxExec !== void 0 && taskState && taskState.executionCount >= maxExec) {
9027
- continue;
9028
- }
9029
- if (taskConfig.circuit_breaker && taskState && taskState.executionCount >= taskConfig.circuit_breaker.max_executions) {
9030
- continue;
9031
- }
9032
- if (taskState?.status === TASK_STATUS.COMPLETED) {
9033
- const requires2 = getRequires(taskConfig);
9034
- if (requires2.length > 0) {
9035
- const hasRefreshed = requires2.some((req) => {
9036
- for (const [otherName, otherConfig] of Object.entries(graphTasks)) {
9037
- if (getProvides(otherConfig).includes(req)) {
9038
- const otherState = state.tasks[otherName];
9039
- if (otherState && otherState.executionCount > taskState.lastEpoch) return true;
9524
+ const strategy = getRefreshStrategy(taskConfig, config.settings);
9525
+ const rerunnable = strategy !== "once";
9526
+ if (taskState?.status === TASK_STATUS.RUNNING || isNonActiveTask(taskState)) {
9527
+ continue;
9528
+ }
9529
+ const maxExec = getMaxExecutions(taskConfig);
9530
+ if (maxExec !== void 0 && taskState && taskState.executionCount >= maxExec) {
9531
+ continue;
9532
+ }
9533
+ if (taskConfig.circuit_breaker && taskState && taskState.executionCount >= taskConfig.circuit_breaker.max_executions) {
9534
+ continue;
9535
+ }
9536
+ if (!rerunnable && taskState?.status === TASK_STATUS.COMPLETED) {
9537
+ continue;
9538
+ }
9539
+ if (rerunnable && taskState?.status === TASK_STATUS.COMPLETED) {
9540
+ const requires2 = getRequires(taskConfig);
9541
+ let shouldSkip = false;
9542
+ switch (strategy) {
9543
+ case "data-changed": {
9544
+ if (requires2.length > 0) {
9545
+ const hasChangedData = requires2.some((req) => {
9546
+ for (const [otherName, otherConfig] of Object.entries(graphTasks)) {
9547
+ if (getProvides(otherConfig).includes(req)) {
9548
+ const otherState = state.tasks[otherName];
9549
+ if (!otherState) continue;
9550
+ const consumed = taskState.lastConsumedHashes?.[req];
9551
+ if (otherState.lastDataHash == null) {
9552
+ return otherState.executionCount > taskState.lastEpoch;
9553
+ }
9554
+ return otherState.lastDataHash !== consumed;
9555
+ }
9040
9556
  }
9041
- }
9042
- return false;
9043
- });
9044
- if (!hasRefreshed) continue;
9045
- } else {
9046
- continue;
9557
+ return false;
9558
+ });
9559
+ if (!hasChangedData) shouldSkip = true;
9560
+ } else {
9561
+ shouldSkip = true;
9562
+ }
9563
+ break;
9047
9564
  }
9565
+ case "epoch-changed": {
9566
+ if (requires2.length > 0) {
9567
+ const hasRefreshed = requires2.some((req) => {
9568
+ for (const [otherName, otherConfig] of Object.entries(graphTasks)) {
9569
+ if (getProvides(otherConfig).includes(req)) {
9570
+ const otherState = state.tasks[otherName];
9571
+ if (otherState && otherState.executionCount > taskState.lastEpoch) return true;
9572
+ }
9573
+ }
9574
+ return false;
9575
+ });
9576
+ if (!hasRefreshed) shouldSkip = true;
9577
+ } else {
9578
+ shouldSkip = true;
9579
+ }
9580
+ break;
9581
+ }
9582
+ case "time-based": {
9583
+ const interval = taskConfig.refreshInterval ?? 0;
9584
+ if (interval <= 0) {
9585
+ shouldSkip = true;
9586
+ break;
9587
+ }
9588
+ const completedAt = taskState.completedAt;
9589
+ if (!completedAt) {
9590
+ shouldSkip = true;
9591
+ break;
9592
+ }
9593
+ const elapsedSec = (Date.now() - Date.parse(completedAt)) / 1e3;
9594
+ if (elapsedSec < interval) shouldSkip = true;
9595
+ break;
9596
+ }
9597
+ case "manual":
9598
+ shouldSkip = true;
9599
+ break;
9048
9600
  }
9601
+ if (shouldSkip) continue;
9049
9602
  }
9050
9603
  const requires = getRequires(taskConfig);
9051
9604
  if (requires.length === 0) {
@@ -9440,6 +9993,300 @@ function getDownstream(live, nodeName) {
9440
9993
  }));
9441
9994
  return { nodeName, nodes, tokens: [...tokenSet] };
9442
9995
  }
9996
+ var MemoryJournal = class {
9997
+ buffer = [];
9998
+ append(event) {
9999
+ this.buffer.push(event);
10000
+ }
10001
+ drain() {
10002
+ const events = this.buffer;
10003
+ this.buffer = [];
10004
+ return events;
10005
+ }
10006
+ get size() {
10007
+ return this.buffer.length;
10008
+ }
10009
+ };
10010
+ var FileJournal = class {
10011
+ constructor(path) {
10012
+ this.path = path;
10013
+ if (!existsSync(path)) {
10014
+ writeFileSync(path, "", "utf-8");
10015
+ }
10016
+ }
10017
+ path;
10018
+ pending = 0;
10019
+ append(event) {
10020
+ appendFileSync(this.path, JSON.stringify(event) + "\n", "utf-8");
10021
+ this.pending++;
10022
+ }
10023
+ drain() {
10024
+ const content = readFileSync(this.path, "utf-8").trim();
10025
+ writeFileSync(this.path, "", "utf-8");
10026
+ this.pending = 0;
10027
+ if (!content) return [];
10028
+ return content.split("\n").map((line) => JSON.parse(line));
10029
+ }
10030
+ get size() {
10031
+ try {
10032
+ const content = readFileSync(this.path, "utf-8").trim();
10033
+ if (!content) return 0;
10034
+ return content.split("\n").length;
10035
+ } catch {
10036
+ return this.pending;
10037
+ }
10038
+ }
10039
+ };
10040
+
10041
+ // src/continuous-event-graph/reactive.ts
10042
+ function createReactiveGraph(config, options, executionId) {
10043
+ const {
10044
+ handlers: initialHandlers,
10045
+ maxDispatchRetries = 3,
10046
+ defaultTimeoutMs = 3e4,
10047
+ journal = new MemoryJournal(),
10048
+ onDispatchFailed,
10049
+ onAbandoned,
10050
+ onDrain
10051
+ } = options;
10052
+ let live = createLiveGraph(config, executionId);
10053
+ let disposed = false;
10054
+ const handlers = new Map(Object.entries(initialHandlers));
10055
+ const dispatched = /* @__PURE__ */ new Map();
10056
+ const timeoutTimers = /* @__PURE__ */ new Map();
10057
+ let draining = false;
10058
+ let drainQueued = false;
10059
+ function drain() {
10060
+ if (disposed) return;
10061
+ if (draining) {
10062
+ drainQueued = true;
10063
+ return;
10064
+ }
10065
+ draining = true;
10066
+ try {
10067
+ do {
10068
+ drainQueued = false;
10069
+ drainOnce();
10070
+ } while (drainQueued);
10071
+ } finally {
10072
+ draining = false;
10073
+ }
10074
+ }
10075
+ function drainOnce() {
10076
+ sweepTimeouts();
10077
+ 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
+ if (events.length > 0) {
10087
+ live = applyEvents(live, events);
10088
+ }
10089
+ const result = schedule(live);
10090
+ if (onDrain && events.length > 0) {
10091
+ onDrain(events, live, result);
10092
+ }
10093
+ for (const taskName of result.eligible) {
10094
+ if (dispatched.has(taskName)) continue;
10095
+ dispatchTask(taskName);
10096
+ }
10097
+ for (const [taskName, entry] of dispatched) {
10098
+ if (entry.status === "retry-queued") {
10099
+ dispatchTask(taskName);
10100
+ }
10101
+ }
10102
+ }
10103
+ 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;
10132
+ return;
10133
+ }
10134
+ dispatched.set(taskName, {
10135
+ status: "initiated",
10136
+ dispatchedAt: Date.now(),
10137
+ dispatchAttempts: attempt
10138
+ });
10139
+ journal.append({
10140
+ type: "task-started",
10141
+ taskName,
10142
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
10143
+ });
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"
10218
+ });
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
+ }
10245
+ }
10246
+ return {
10247
+ push(event) {
10248
+ if (disposed) return;
10249
+ live = applyEvent(live, event);
10250
+ drain();
10251
+ },
10252
+ pushAll(events) {
10253
+ if (disposed) return;
10254
+ if (events.length === 0) return;
10255
+ live = applyEvents(live, events);
10256
+ drain();
10257
+ },
10258
+ addNode(name, taskConfig, handler) {
10259
+ if (disposed) return;
10260
+ live = addNode(live, name, taskConfig);
10261
+ handlers.set(name, handler);
10262
+ drain();
10263
+ },
10264
+ removeNode(name) {
10265
+ if (disposed) return;
10266
+ live = removeNode(live, name);
10267
+ handlers.delete(name);
10268
+ dispatched.delete(name);
10269
+ clearTimeout(timeoutTimers.get(name));
10270
+ timeoutTimers.delete(name);
10271
+ },
10272
+ getState() {
10273
+ return live;
10274
+ },
10275
+ getSchedule() {
10276
+ return schedule(live);
10277
+ },
10278
+ getDispatchState() {
10279
+ return dispatched;
10280
+ },
10281
+ dispose() {
10282
+ disposed = true;
10283
+ for (const timer of timeoutTimers.values()) {
10284
+ clearTimeout(timer);
10285
+ }
10286
+ timeoutTimers.clear();
10287
+ }
10288
+ };
10289
+ }
9443
10290
 
9444
10291
  // src/inference/core.ts
9445
10292
  var DEFAULT_THRESHOLD = 0.5;
@@ -10005,17 +10852,17 @@ var live_cards_schema_default = {
10005
10852
  };
10006
10853
 
10007
10854
  // src/card-compute/schema-validator.ts
10008
- var import_ajv = __toESM(require_ajv());
10009
- var _compiled = null;
10010
- function getValidator() {
10011
- if (_compiled) return _compiled;
10012
- const ajv = new import_ajv.default({ allErrors: true });
10855
+ var import_ajv3 = __toESM(require_ajv());
10856
+ var _compiled3 = null;
10857
+ function getValidator3() {
10858
+ if (_compiled3) return _compiled3;
10859
+ const ajv = new import_ajv3.default({ allErrors: true });
10013
10860
  addFormats(ajv);
10014
- _compiled = ajv.compile(live_cards_schema_default);
10015
- return _compiled;
10861
+ _compiled3 = ajv.compile(live_cards_schema_default);
10862
+ return _compiled3;
10016
10863
  }
10017
10864
  function validateLiveCardSchema(node) {
10018
- const validate = getValidator();
10865
+ const validate = getValidator3();
10019
10866
  const valid = validate(node);
10020
10867
  if (valid) return { ok: true, errors: [] };
10021
10868
  const errors = (validate.errors ?? []).map((e) => {
@@ -10472,6 +11319,6 @@ var CardCompute = {
10472
11319
  }
10473
11320
  };
10474
11321
 
10475
- export { COMPLETION_STRATEGIES, CONFLICT_STRATEGIES, CardCompute, DEFAULTS, EXECUTION_MODES, EXECUTION_STATUS, FileStore, StepMachine as FlowEngine, LocalStorageStore, MemoryStore, StepMachine, TASK_STATUS, addDynamicTask, addNode, addProvides, addRequires, apply, applyAll, applyEvent, applyInferences, applyStepResult, batch, buildInferencePrompt, checkCircuitBreaker, computeAvailableOutputs, computeStepInput, createCliAdapter, createDefaultTaskState, createStepMachine as createEngine, createHttpAdapter, createInitialExecutionState, createInitialState, createLiveGraph, createStepMachine, detectStuckState, disableNode, drainTokens, enableNode, exportGraphConfig, exportGraphConfigToFile, extractReturnData, flowToMermaid, getAllTasks, getCandidateTasks, getDownstream, getNode, getProvides, getRequires, getTask, getUnreachableNodes, getUnreachableTokens, getUpstream, graphToMermaid, hasTask, inferAndApply, inferCompletions, injectTokens, inspect, isExecutionComplete, isNonActiveTask, isRepeatableTask, isTaskCompleted, isTaskRunning, loadGraphConfig, loadStepFlow, next, planExecution, removeNode, removeProvides, removeRequires, resetNode, resolveConfigTemplates, resolveVariables, restore, schedule, snapshot, validateGraph, validateGraphConfig, validateLiveCardSchema, validateStepFlowConfig };
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 };
10476
11323
  //# sourceMappingURL=index.js.map
10477
11324
  //# sourceMappingURL=index.js.map