@cadenza.io/core 3.27.0 → 3.28.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
@@ -23,13 +33,16 @@ __export(index_exports, {
23
33
  Actor: () => Actor,
24
34
  DebounceTask: () => DebounceTask,
25
35
  EphemeralTask: () => EphemeralTask,
36
+ GlobalDefinition: () => GlobalDefinition,
26
37
  GraphContext: () => GraphContext,
27
38
  GraphRegistry: () => GraphRegistry,
28
39
  GraphRoutine: () => GraphRoutine,
29
40
  GraphRun: () => GraphRun,
30
41
  GraphRunner: () => GraphRunner,
42
+ HelperDefinition: () => HelperDefinition,
31
43
  InquiryBroker: () => InquiryBroker,
32
44
  META_ACTOR_SESSION_STATE_PERSIST_INTENT: () => META_ACTOR_SESSION_STATE_PERSIST_INTENT,
45
+ RuntimeHost: () => RuntimeHost,
33
46
  SignalBroker: () => SignalBroker,
34
47
  SignalEmitter: () => SignalEmitter,
35
48
  Task: () => Task,
@@ -1281,6 +1294,7 @@ var SignalBroker = class _SignalBroker {
1281
1294
  this.signalObservers = /* @__PURE__ */ new Map();
1282
1295
  this.emittedSignalsRegistry = /* @__PURE__ */ new Set();
1283
1296
  this.signalMetadataRegistry = /* @__PURE__ */ new Map();
1297
+ this.passiveSignalListeners = /* @__PURE__ */ new Map();
1284
1298
  // ── Flush Strategy Management ───────────────────────────────────────
1285
1299
  this.flushStrategies = /* @__PURE__ */ new Map();
1286
1300
  this.strategyData = /* @__PURE__ */ new Map();
@@ -1361,6 +1375,20 @@ var SignalBroker = class _SignalBroker {
1361
1375
  console.log(
1362
1376
  ` \u2022 emittedSignalsRegistry size: ${this.emittedSignalsRegistry.size}`
1363
1377
  );
1378
+ const exactSignalEntries = Array.from(this.signalObservers.entries()).filter(([signal]) => signal.includes(":")).sort((left, right) => {
1379
+ const taskDelta = right[1].tasks.size - left[1].tasks.size;
1380
+ if (taskDelta !== 0) {
1381
+ return taskDelta;
1382
+ }
1383
+ return left[0].localeCompare(right[0]);
1384
+ });
1385
+ console.log(` \u2022 exact signal observer entries: ${exactSignalEntries.length}`);
1386
+ for (const [signal, observer] of exactSignalEntries.slice(0, 8)) {
1387
+ const sampleTaskNames = Array.from(observer.tasks).slice(0, 3).map((task) => task.name);
1388
+ console.log(
1389
+ ` - ${signal} (${observer.tasks.size} tasks) sample=${sampleTaskNames.join(", ")}`
1390
+ );
1391
+ }
1364
1392
  let totalSquashContexts = 0;
1365
1393
  let totalSquashGroups = 0;
1366
1394
  for (const groups of this.strategyData.values()) {
@@ -1774,7 +1802,7 @@ var SignalBroker = class _SignalBroker {
1774
1802
  this.schedule(signal, context, options);
1775
1803
  return;
1776
1804
  }
1777
- this.addSignal(signal);
1805
+ this.validateSignalName(signal);
1778
1806
  this.execute(signal, context);
1779
1807
  }
1780
1808
  /**
@@ -1853,6 +1881,7 @@ var SignalBroker = class _SignalBroker {
1853
1881
  ...context.__metadata,
1854
1882
  __executionTraceId: executionTraceId
1855
1883
  };
1884
+ this.notifyPassiveSignalListeners(signal, context);
1856
1885
  if (this.debug && (!isMetric && !isSubMeta || this.verbose)) {
1857
1886
  console.log(
1858
1887
  `EMITTING ${signal} to listeners ${this.signalObservers.get(signal)?.tasks.size ?? 0} with context ${this.verbose ? JSON.stringify(context) : JSON.stringify(context).slice(0, 100)}`
@@ -1950,11 +1979,37 @@ var SignalBroker = class _SignalBroker {
1950
1979
  this.addSignal(signal, metadata);
1951
1980
  this.signalObservers.get(signal).tasks.add(routineOrTask);
1952
1981
  }
1982
+ addPassiveSignalListener(listener) {
1983
+ const listenerId = (0, import_uuid.v4)();
1984
+ this.passiveSignalListeners.set(listenerId, listener);
1985
+ return () => {
1986
+ this.passiveSignalListeners.delete(listenerId);
1987
+ };
1988
+ }
1989
+ notifyPassiveSignalListeners(signal, context) {
1990
+ if (this.passiveSignalListeners.size === 0) {
1991
+ return;
1992
+ }
1993
+ const metadata = this.getSignalMetadata(signal) ?? null;
1994
+ for (const listener of this.passiveSignalListeners.values()) {
1995
+ try {
1996
+ listener(signal, context, metadata);
1997
+ } catch (error) {
1998
+ if (this.debug) {
1999
+ console.error("Passive signal listener failed", error);
2000
+ }
2001
+ }
2002
+ }
2003
+ }
1953
2004
  registerEmittedSignal(signal, metadata) {
2005
+ const signalKey = this.resolveSignalMetadataKey(signal);
2006
+ if (!signalKey) {
2007
+ return;
2008
+ }
1954
2009
  if (metadata) {
1955
- this.setSignalMetadata(signal, metadata);
2010
+ this.setSignalMetadata(signalKey, metadata);
1956
2011
  }
1957
- this.emittedSignalsRegistry.add(signal);
2012
+ this.emittedSignalsRegistry.add(signalKey);
1958
2013
  }
1959
2014
  /**
1960
2015
  * Unsubscribes a routine/task from a signal.
@@ -2529,6 +2584,38 @@ var GraphNode = class _GraphNode extends SignalEmitter {
2529
2584
  getTag() {
2530
2585
  return this.task.getTag(this.context);
2531
2586
  }
2587
+ classifyBusinessRoutineLifecycle() {
2588
+ const fullContext = this.context?.getFullContext?.() ?? {};
2589
+ const metadata = fullContext.__metadata && typeof fullContext.__metadata === "object" ? fullContext.__metadata : {};
2590
+ if (this.task.isMeta || this.task.isSubMeta || this.task.isHidden) {
2591
+ return false;
2592
+ }
2593
+ if (fullContext.__isInquiry === true || fullContext.__isDeputy === true || metadata.__isInquiry === true || metadata.__isDeputy === true || metadata.__isSubMeta === true) {
2594
+ return false;
2595
+ }
2596
+ return true;
2597
+ }
2598
+ getBusinessRoutineLifecycleDecision() {
2599
+ const fullContext = this.context?.getFullContext?.() ?? {};
2600
+ const metadata = this.context?.getMetadata?.() ?? {};
2601
+ if (typeof metadata.__emitBusinessRoutineLifecycle === "boolean") {
2602
+ return metadata.__emitBusinessRoutineLifecycle;
2603
+ }
2604
+ if (typeof fullContext.__emitBusinessRoutineLifecycle === "boolean") {
2605
+ return fullContext.__emitBusinessRoutineLifecycle;
2606
+ }
2607
+ return this.classifyBusinessRoutineLifecycle();
2608
+ }
2609
+ rememberBusinessRoutineLifecycleDecision(value) {
2610
+ const fullContext = this.context?.getFullContext?.();
2611
+ const metadata = this.context?.getMetadata?.();
2612
+ if (fullContext && typeof fullContext === "object") {
2613
+ fullContext.__emitBusinessRoutineLifecycle = value;
2614
+ }
2615
+ if (metadata && typeof metadata === "object") {
2616
+ metadata.__emitBusinessRoutineLifecycle = value;
2617
+ }
2618
+ }
2532
2619
  /**
2533
2620
  * Schedules the current node/task on the specified graph layer if applicable.
2534
2621
  *
@@ -2654,17 +2741,23 @@ var GraphNode = class _GraphNode extends SignalEmitter {
2654
2741
  this.executionStart = Date.now();
2655
2742
  }
2656
2743
  if (this.previousNodes.length === 0) {
2657
- this.emitMetricsWithMetadata(
2658
- "meta.node.started_routine_execution",
2659
- {
2660
- data: {
2661
- isRunning: true,
2662
- started: formatTimestamp(this.executionStart)
2663
- },
2664
- filter: { uuid: this.routineExecId }
2665
- },
2666
- { squash: true, squashId: this.routineExecId }
2744
+ const shouldEmitBusinessRoutineLifecycle = this.getBusinessRoutineLifecycleDecision();
2745
+ this.rememberBusinessRoutineLifecycleDecision(
2746
+ shouldEmitBusinessRoutineLifecycle
2667
2747
  );
2748
+ if (shouldEmitBusinessRoutineLifecycle) {
2749
+ this.emitMetricsWithMetadata(
2750
+ "meta.node.started_routine_execution",
2751
+ {
2752
+ data: {
2753
+ isRunning: true,
2754
+ started: formatTimestamp(this.executionStart)
2755
+ },
2756
+ filter: { uuid: this.routineExecId }
2757
+ },
2758
+ { squash: true, squashId: this.routineExecId }
2759
+ );
2760
+ }
2668
2761
  }
2669
2762
  if (this.debug && !this.task.isSubMeta && !this.context.getMetadata().__isSubMeta || this.verbose) {
2670
2763
  this.log();
@@ -2733,21 +2826,23 @@ var GraphNode = class _GraphNode extends SignalEmitter {
2733
2826
  `meta.node.graph_completed:${this.routineExecId}`,
2734
2827
  context2
2735
2828
  );
2736
- this.emitMetricsWithMetadata(
2737
- "meta.node.ended_routine_execution",
2738
- {
2739
- data: {
2740
- isRunning: false,
2741
- isComplete: true,
2742
- resultContext: this.context.getContext(),
2743
- metaResultContext: this.context.getMetadata(),
2744
- progress: 1,
2745
- ended: formatTimestamp(end)
2829
+ if (this.getBusinessRoutineLifecycleDecision()) {
2830
+ this.emitMetricsWithMetadata(
2831
+ "meta.node.ended_routine_execution",
2832
+ {
2833
+ data: {
2834
+ isRunning: false,
2835
+ isComplete: true,
2836
+ resultContext: this.context.getContext(),
2837
+ metaResultContext: this.context.getMetadata(),
2838
+ progress: 1,
2839
+ ended: formatTimestamp(end)
2840
+ },
2841
+ filter: { uuid: this.routineExecId }
2746
2842
  },
2747
- filter: { uuid: this.routineExecId }
2748
- },
2749
- { squash: true, squashId: this.routineExecId }
2750
- );
2843
+ { squash: true, squashId: this.routineExecId }
2844
+ );
2845
+ }
2751
2846
  }
2752
2847
  return end;
2753
2848
  }
@@ -3014,16 +3109,17 @@ var GraphNode = class _GraphNode extends SignalEmitter {
3014
3109
  * @return {void} Does not return a value.
3015
3110
  */
3016
3111
  finalize() {
3112
+ const context = this.context?.getFullContext?.() ?? {};
3017
3113
  if (this.nextNodes.length === 0) {
3018
3114
  this.completeSubgraph();
3019
3115
  }
3020
3116
  if (this.errored || this.failed) {
3021
3117
  this.task.mapOnFailSignals(
3022
- (signal) => this.emitWithMetadata(signal, this.context.getFullContext())
3118
+ (signal) => this.emitWithMetadata(signal, { ...context })
3023
3119
  );
3024
3120
  } else if (this.result !== void 0 && this.result !== false) {
3025
3121
  this.task.mapSignals(
3026
- (signal) => this.emitWithMetadata(signal, this.context.getFullContext())
3122
+ (signal) => this.emitWithMetadata(signal, { ...context })
3027
3123
  );
3028
3124
  }
3029
3125
  this.end();
@@ -3037,8 +3133,9 @@ var GraphNode = class _GraphNode extends SignalEmitter {
3037
3133
  */
3038
3134
  onError(error, errorData = {}) {
3039
3135
  const normalizedError = normalizeGraphErrorMessage(error);
3136
+ const context = this.context?.getFullContext?.() ?? {};
3040
3137
  this.result = {
3041
- ...this.context.getFullContext(),
3138
+ ...context,
3042
3139
  __error: `Node error: ${normalizedError}`,
3043
3140
  __retries: this.retries,
3044
3141
  error: `Node error: ${normalizedError}`,
@@ -3632,7 +3729,7 @@ var GraphRunner = class extends SignalEmitter {
3632
3729
  allTasks
3633
3730
  );
3634
3731
  const ctx = new GraphContext(context || {});
3635
- if (!isSubMeta) {
3732
+ if (!isSubMeta && (!isMeta || this.debug)) {
3636
3733
  if (isNewTrace) {
3637
3734
  this.emitMetrics("meta.runner.new_trace", {
3638
3735
  data: {
@@ -3922,7 +4019,13 @@ var Actor = class {
3922
4019
  task(handler, bindingOptions = {}) {
3923
4020
  const mode = bindingOptions.mode ?? "read";
3924
4021
  const taskBindingId = `${this.spec.name}:${++this.nextTaskBindingIndex}`;
3925
- const wrapped = (context, emit, inquire, progressCallback) => {
4022
+ const wrapped = (context, emit, inquire, tools, progressCallback) => {
4023
+ const resolvedTools = tools && typeof tools === "object" && !Array.isArray(tools) && "helpers" in tools && "globals" in tools ? tools : {
4024
+ helpers: {},
4025
+ globals: {}
4026
+ };
4027
+ const resolvedProgressCallback = typeof progressCallback === "function" ? progressCallback : typeof tools === "function" ? tools : () => {
4028
+ };
3926
4029
  const normalizedInput = this.normalizeInputContext(context);
3927
4030
  const invocationOptions = this.resolveInvocationOptions(
3928
4031
  context,
@@ -4042,9 +4145,16 @@ var Actor = class {
4042
4145
  patchRuntimeState,
4043
4146
  reduceRuntimeState,
4044
4147
  emit: (signal, payload = {}) => emit(signal, payload),
4045
- inquire: (inquiryName, inquiryContext = {}, options = {}) => inquire(inquiryName, inquiryContext, options)
4148
+ inquire: (inquiryName, inquiryContext = {}, options = {}) => inquire(inquiryName, inquiryContext, options),
4149
+ tools: resolvedTools
4046
4150
  };
4047
- const handlerResult = await handler(actorContext);
4151
+ const handlerResult = await handler(
4152
+ actorContext,
4153
+ actorContext.emit,
4154
+ actorContext.inquire,
4155
+ resolvedTools,
4156
+ resolvedProgressCallback
4157
+ );
4048
4158
  if (invocationOptions.writeContract === "reducer" && typeof handlerResult === "function") {
4049
4159
  reduceDurableState(handlerResult);
4050
4160
  }
@@ -4069,7 +4179,7 @@ var Actor = class {
4069
4179
  stateRecord.lastRuntimeWriteAt = writeTimestamp;
4070
4180
  }
4071
4181
  this.touchSession(actorKey, invocationOptions.touchSession, Date.now());
4072
- progressCallback(100);
4182
+ resolvedProgressCallback(100);
4073
4183
  if (invocationOptions.writeContract === "reducer" && typeof handlerResult === "function") {
4074
4184
  return cloneForDurableState(stateRecord.durableState);
4075
4185
  }
@@ -4113,6 +4223,13 @@ var Actor = class {
4113
4223
  this.pruneExpiredActorKeys(Date.now());
4114
4224
  return this.ensureStateRecord(key).runtimeState;
4115
4225
  }
4226
+ /**
4227
+ * Lists all currently materialized actor keys.
4228
+ */
4229
+ listActorKeys() {
4230
+ this.pruneExpiredActorKeys(Date.now());
4231
+ return Array.from(this.stateByKey.keys()).sort();
4232
+ }
4116
4233
  /**
4117
4234
  * Alias of `getDurableVersion`.
4118
4235
  */
@@ -4522,6 +4639,176 @@ var Actor = class {
4522
4639
  }
4523
4640
  };
4524
4641
 
4642
+ // src/tools/definitions.ts
4643
+ function validateAlias(alias) {
4644
+ const normalized = String(alias ?? "").trim();
4645
+ if (!normalized) {
4646
+ throw new Error("Tool dependency alias must be a non-empty string");
4647
+ }
4648
+ return normalized;
4649
+ }
4650
+ function serializeGlobalValue(value) {
4651
+ if (value === void 0 || typeof value === "function") {
4652
+ throw new Error("Global values must be JSON-serializable");
4653
+ }
4654
+ try {
4655
+ return JSON.parse(JSON.stringify(value));
4656
+ } catch (error) {
4657
+ throw new Error(
4658
+ `Global values must be JSON-serializable: ${error instanceof Error ? error.message : String(error)}`
4659
+ );
4660
+ }
4661
+ }
4662
+ function deepFreeze(value) {
4663
+ if (!value || typeof value !== "object") {
4664
+ return value;
4665
+ }
4666
+ Object.freeze(value);
4667
+ for (const nested of Object.values(value)) {
4668
+ if (nested && typeof nested === "object" && !Object.isFrozen(nested)) {
4669
+ deepFreeze(nested);
4670
+ }
4671
+ }
4672
+ return value;
4673
+ }
4674
+ var GlobalDefinition = class {
4675
+ constructor(name, value, description = "", isMeta = false) {
4676
+ this.version = 1;
4677
+ this.destroyed = false;
4678
+ this.name = name;
4679
+ this.description = description;
4680
+ this.isMeta = isMeta;
4681
+ this.value = deepFreeze(serializeGlobalValue(value));
4682
+ }
4683
+ destroy() {
4684
+ this.destroyed = true;
4685
+ }
4686
+ export() {
4687
+ return {
4688
+ name: this.name,
4689
+ description: this.description,
4690
+ version: this.version,
4691
+ isMeta: this.isMeta,
4692
+ value: this.value
4693
+ };
4694
+ }
4695
+ };
4696
+ var HelperDefinition = class {
4697
+ constructor(name, helperFunction, description = "", isMeta = false) {
4698
+ this.version = 1;
4699
+ this.helperAliases = /* @__PURE__ */ new Map();
4700
+ this.globalAliases = /* @__PURE__ */ new Map();
4701
+ this.destroyed = false;
4702
+ this.name = name;
4703
+ this.description = description;
4704
+ this.isMeta = isMeta;
4705
+ this.helperFunction = helperFunction;
4706
+ }
4707
+ usesHelpers(helpers) {
4708
+ attachHelperDependency(
4709
+ this,
4710
+ this.name,
4711
+ this.version,
4712
+ helpers,
4713
+ "meta.helper.helper_associated"
4714
+ );
4715
+ return this;
4716
+ }
4717
+ usesGlobals(globals) {
4718
+ attachGlobalDependency(
4719
+ this,
4720
+ this.name,
4721
+ this.version,
4722
+ globals,
4723
+ "meta.helper.global_associated"
4724
+ );
4725
+ return this;
4726
+ }
4727
+ execute(context, emit, inquire, progressCallback) {
4728
+ return Cadenza.executeHelper(
4729
+ this,
4730
+ context,
4731
+ emit,
4732
+ inquire,
4733
+ progressCallback
4734
+ );
4735
+ }
4736
+ destroy() {
4737
+ this.destroyed = true;
4738
+ }
4739
+ export() {
4740
+ return {
4741
+ name: this.name,
4742
+ description: this.description,
4743
+ version: this.version,
4744
+ isMeta: this.isMeta,
4745
+ functionString: this.helperFunction.toString(),
4746
+ helperAliases: Object.fromEntries(this.helperAliases),
4747
+ globalAliases: Object.fromEntries(this.globalAliases)
4748
+ };
4749
+ }
4750
+ };
4751
+ function attachHelperDependency(owner, ownerName, ownerVersion, helpers, signalName) {
4752
+ for (const [alias, helper] of Object.entries(helpers)) {
4753
+ const normalizedAlias = validateAlias(alias);
4754
+ if (!helper) {
4755
+ throw new Error(
4756
+ `Helper dependency "${normalizedAlias}" must reference a helper definition`
4757
+ );
4758
+ }
4759
+ if (helper.isMeta !== owner.isMeta) {
4760
+ throw new Error(
4761
+ `${ownerName} cannot use ${helper.isMeta ? "meta" : "business"} helper "${helper.name}" across layer boundaries`
4762
+ );
4763
+ }
4764
+ owner.helperAliases.set(normalizedAlias, helper.name);
4765
+ Cadenza.emit(signalName, {
4766
+ data: {
4767
+ alias: normalizedAlias,
4768
+ ...signalName === "meta.task.helper_associated" ? {
4769
+ taskName: ownerName,
4770
+ taskVersion: ownerVersion
4771
+ } : {
4772
+ helperName: ownerName,
4773
+ helperVersion: ownerVersion
4774
+ },
4775
+ dependencyHelperName: helper.name,
4776
+ dependencyHelperVersion: helper.version
4777
+ }
4778
+ });
4779
+ }
4780
+ }
4781
+ function attachGlobalDependency(owner, ownerName, ownerVersion, globals, signalName) {
4782
+ for (const [alias, globalDefinition] of Object.entries(globals)) {
4783
+ const normalizedAlias = validateAlias(alias);
4784
+ if (!globalDefinition) {
4785
+ throw new Error(
4786
+ `Global dependency "${normalizedAlias}" must reference a global definition`
4787
+ );
4788
+ }
4789
+ if (globalDefinition.isMeta !== owner.isMeta) {
4790
+ throw new Error(
4791
+ `${ownerName} cannot use ${globalDefinition.isMeta ? "meta" : "business"} global "${globalDefinition.name}" across layer boundaries`
4792
+ );
4793
+ }
4794
+ owner.globalAliases.set(normalizedAlias, globalDefinition.name);
4795
+ Cadenza.emit(signalName, {
4796
+ data: {
4797
+ alias: normalizedAlias,
4798
+ ...signalName === "meta.task.global_associated" ? {
4799
+ taskName: ownerName,
4800
+ taskVersion: ownerVersion
4801
+ } : {
4802
+ helperName: ownerName,
4803
+ helperVersion: ownerVersion
4804
+ },
4805
+ globalName: globalDefinition.name,
4806
+ globalVersion: globalDefinition.version
4807
+ }
4808
+ });
4809
+ }
4810
+ }
4811
+
4525
4812
  // src/graph/definition/Task.ts
4526
4813
  function normalizeSignalDefinition(input) {
4527
4814
  if (typeof input === "string") {
@@ -4598,6 +4885,8 @@ var Task = class _Task extends SignalEmitter {
4598
4885
  this.observedSignals = /* @__PURE__ */ new Set();
4599
4886
  this.handlesIntents = /* @__PURE__ */ new Set();
4600
4887
  this.inquiresIntents = /* @__PURE__ */ new Set();
4888
+ this.helperAliases = /* @__PURE__ */ new Map();
4889
+ this.globalAliases = /* @__PURE__ */ new Map();
4601
4890
  this.name = name;
4602
4891
  this.taskFunction = task;
4603
4892
  this.description = description;
@@ -4633,6 +4922,8 @@ var Task = class _Task extends SignalEmitter {
4633
4922
  "meta.task.relationship_added",
4634
4923
  "meta.task.relationship_removed",
4635
4924
  "meta.task.intent_associated",
4925
+ "meta.task.helper_associated",
4926
+ "meta.task.global_associated",
4636
4927
  "meta.task.layer_index_changed",
4637
4928
  "meta.node.scheduled",
4638
4929
  "meta.node.mapped",
@@ -5146,10 +5437,18 @@ var Task = class _Task extends SignalEmitter {
5146
5437
  * @return {TaskResult} The result of the executed task.
5147
5438
  */
5148
5439
  execute(context, emit, inquire, progressCallback, nodeData) {
5440
+ const executionContext = this.isMeta ? context.getClonedFullContext() : context.getClonedContext();
5149
5441
  return this.taskFunction(
5150
- this.isMeta ? context.getClonedFullContext() : context.getClonedContext(),
5442
+ executionContext,
5151
5443
  emit,
5152
5444
  inquire,
5445
+ Cadenza.resolveToolsForOwner(
5446
+ this,
5447
+ executionContext,
5448
+ emit,
5449
+ inquire,
5450
+ progressCallback
5451
+ ),
5153
5452
  progressCallback
5154
5453
  );
5155
5454
  }
@@ -5163,6 +5462,7 @@ var Task = class _Task extends SignalEmitter {
5163
5462
  * @throws {Error} Throws an error if adding a predecessor creates a cycle in the task structure.
5164
5463
  */
5165
5464
  doAfter(...tasks) {
5465
+ Cadenza.assertGraphMutationAllowed("Task#doAfter");
5166
5466
  for (const pred of tasks) {
5167
5467
  if (!pred) continue;
5168
5468
  if (this.predecessorTasks.has(pred)) continue;
@@ -5194,6 +5494,7 @@ var Task = class _Task extends SignalEmitter {
5194
5494
  * @throws {Error} Throws an error if adding a task causes a cyclic dependency.
5195
5495
  */
5196
5496
  then(...tasks) {
5497
+ Cadenza.assertGraphMutationAllowed("Task#then");
5197
5498
  for (const next of tasks) {
5198
5499
  if (!next) continue;
5199
5500
  if (this.nextTasks.has(next)) continue;
@@ -5357,6 +5658,7 @@ var Task = class _Task extends SignalEmitter {
5357
5658
  * @return {this} The current instance after adding the specified signals.
5358
5659
  */
5359
5660
  doOn(...signals) {
5661
+ Cadenza.assertGraphMutationAllowed("Task#doOn");
5360
5662
  signals.forEach((input) => {
5361
5663
  const { name: signal, metadata } = normalizeSignalDefinition(input);
5362
5664
  if (this.observedSignals.has(signal)) return;
@@ -5381,6 +5683,7 @@ var Task = class _Task extends SignalEmitter {
5381
5683
  * @return {this} The current instance for method chaining.
5382
5684
  */
5383
5685
  emits(...signals) {
5686
+ Cadenza.assertGraphMutationAllowed("Task#emits");
5384
5687
  signals.forEach((input) => {
5385
5688
  const { name: signal } = normalizeSignalDefinition(input);
5386
5689
  if (this.observedSignals.has(signal))
@@ -5400,6 +5703,7 @@ var Task = class _Task extends SignalEmitter {
5400
5703
  * @return {this} Returns the current instance for chaining.
5401
5704
  */
5402
5705
  emitsOnFail(...signals) {
5706
+ Cadenza.assertGraphMutationAllowed("Task#emitsOnFail");
5403
5707
  signals.forEach((input) => {
5404
5708
  const { name: signal } = normalizeSignalDefinition(input);
5405
5709
  this.signalsToEmitOnFail.add(signal);
@@ -5414,6 +5718,7 @@ var Task = class _Task extends SignalEmitter {
5414
5718
  * @return {void} This method does not return a value.
5415
5719
  */
5416
5720
  attachSignal(...signals) {
5721
+ Cadenza.assertGraphMutationAllowed("Task#attachSignal");
5417
5722
  signals.forEach((input) => {
5418
5723
  const { name: signal, metadata } = normalizeSignalDefinition(input);
5419
5724
  this.emitsSignals.add(signal);
@@ -5510,6 +5815,7 @@ var Task = class _Task extends SignalEmitter {
5510
5815
  return this;
5511
5816
  }
5512
5817
  respondsTo(...inquires) {
5818
+ Cadenza.assertGraphMutationAllowed("Task#respondsTo");
5513
5819
  for (const intentName of inquires) {
5514
5820
  if (this.handlesIntents.has(intentName)) {
5515
5821
  continue;
@@ -5545,6 +5851,26 @@ var Task = class _Task extends SignalEmitter {
5545
5851
  }
5546
5852
  return this;
5547
5853
  }
5854
+ usesHelpers(helpers) {
5855
+ attachHelperDependency(
5856
+ this,
5857
+ this.name,
5858
+ this.version,
5859
+ helpers,
5860
+ "meta.task.helper_associated"
5861
+ );
5862
+ return this;
5863
+ }
5864
+ usesGlobals(globals) {
5865
+ attachGlobalDependency(
5866
+ this,
5867
+ this.name,
5868
+ this.version,
5869
+ globals,
5870
+ "meta.task.global_associated"
5871
+ );
5872
+ return this;
5873
+ }
5548
5874
  attachIntents(...intentNames) {
5549
5875
  for (const intent of intentNames) {
5550
5876
  this.inquiresIntents.add(intent);
@@ -5637,6 +5963,7 @@ var Task = class _Task extends SignalEmitter {
5637
5963
  this.nextTasks.clear();
5638
5964
  this.predecessorTasks.clear();
5639
5965
  this.destroyed = true;
5966
+ Cadenza.forgetTask(this.name);
5640
5967
  if (this.register) {
5641
5968
  Cadenza.registry.tasks.delete(this.name);
5642
5969
  this.emitMetricsWithMetadata("meta.task.destroyed", {
@@ -5678,6 +6005,8 @@ var Task = class _Task extends SignalEmitter {
5678
6005
  __validateInputContext: this.validateInputContext,
5679
6006
  __outputSchema: this.outputContextSchema,
5680
6007
  __validateOutputContext: this.validateOutputContext,
6008
+ __helperAliases: Object.fromEntries(this.helperAliases),
6009
+ __globalAliases: Object.fromEntries(this.globalAliases),
5681
6010
  __nextTasks: Array.from(this.nextTasks).map((t) => t.name),
5682
6011
  __previousTasks: Array.from(this.predecessorTasks).map((t) => t.name)
5683
6012
  };
@@ -5924,6 +6253,13 @@ var DebounceTask = class extends Task {
5924
6253
  this.lastContext.getClonedContext(),
5925
6254
  this.lastEmitFunction,
5926
6255
  this.lastInquireFunction,
6256
+ Cadenza.resolveToolsForOwner(
6257
+ this,
6258
+ this.lastContext.getClonedContext(),
6259
+ this.lastEmitFunction,
6260
+ this.lastInquireFunction,
6261
+ this.lastProgressCallback
6262
+ ),
5927
6263
  this.lastProgressCallback
5928
6264
  );
5929
6265
  } catch (error) {
@@ -6078,6 +6414,19 @@ var EphemeralTask = class extends Task {
6078
6414
  progressCallback,
6079
6415
  nodeData
6080
6416
  );
6417
+ if (result instanceof Promise) {
6418
+ return result.then((resolved) => {
6419
+ if (this.once || this.condition(resolved)) {
6420
+ this.destroy();
6421
+ }
6422
+ return resolved;
6423
+ }).catch((error) => {
6424
+ if (this.once || this.condition(error)) {
6425
+ this.destroy();
6426
+ }
6427
+ throw error;
6428
+ });
6429
+ }
6081
6430
  if (this.once || this.condition(result)) {
6082
6431
  this.destroy();
6083
6432
  }
@@ -7068,6 +7417,386 @@ var InquiryBroker = class _InquiryBroker extends SignalEmitter {
7068
7417
  }
7069
7418
  };
7070
7419
 
7420
+ // src/runtime/RuntimeDefinitionRegistry.ts
7421
+ function createLinkKey(predecessorTaskName, successorTaskName) {
7422
+ return `${predecessorTaskName}=>${successorTaskName}`;
7423
+ }
7424
+ function createTaskSignalKey(taskName, signalName) {
7425
+ return `${taskName}=>${signalName}`;
7426
+ }
7427
+ function createTaskIntentKey(taskName, intentName) {
7428
+ return `${taskName}=>${intentName}`;
7429
+ }
7430
+ function createRoutineSignalKey(routineName, signalName) {
7431
+ return `${routineName}=>${signalName}`;
7432
+ }
7433
+ var RuntimeDefinitionRegistry = class {
7434
+ constructor() {
7435
+ this.taskDefinitions = /* @__PURE__ */ new Map();
7436
+ this.helperDefinitions = /* @__PURE__ */ new Map();
7437
+ this.globalDefinitions = /* @__PURE__ */ new Map();
7438
+ this.routineDefinitions = /* @__PURE__ */ new Map();
7439
+ this.intentDefinitions = /* @__PURE__ */ new Map();
7440
+ this.actorDefinitions = /* @__PURE__ */ new Map();
7441
+ this.actorTaskDefinitions = /* @__PURE__ */ new Map();
7442
+ this.taskLinks = /* @__PURE__ */ new Map();
7443
+ this.taskSignalObservations = /* @__PURE__ */ new Map();
7444
+ this.taskSignalEmissions = /* @__PURE__ */ new Map();
7445
+ this.taskIntentBindings = /* @__PURE__ */ new Map();
7446
+ this.taskHelperBindings = /* @__PURE__ */ new Map();
7447
+ this.taskGlobalBindings = /* @__PURE__ */ new Map();
7448
+ this.helperHelperBindings = /* @__PURE__ */ new Map();
7449
+ this.helperGlobalBindings = /* @__PURE__ */ new Map();
7450
+ this.routineSignalObservations = /* @__PURE__ */ new Map();
7451
+ }
7452
+ reset() {
7453
+ this.taskDefinitions.clear();
7454
+ this.helperDefinitions.clear();
7455
+ this.globalDefinitions.clear();
7456
+ this.routineDefinitions.clear();
7457
+ this.intentDefinitions.clear();
7458
+ this.actorDefinitions.clear();
7459
+ this.actorTaskDefinitions.clear();
7460
+ this.taskLinks.clear();
7461
+ this.taskSignalObservations.clear();
7462
+ this.taskSignalEmissions.clear();
7463
+ this.taskIntentBindings.clear();
7464
+ this.taskHelperBindings.clear();
7465
+ this.taskGlobalBindings.clear();
7466
+ this.helperHelperBindings.clear();
7467
+ this.helperGlobalBindings.clear();
7468
+ this.routineSignalObservations.clear();
7469
+ }
7470
+ setTaskDefinition(definition) {
7471
+ this.taskDefinitions.set(definition.name, {
7472
+ ...definition,
7473
+ kind: definition.kind ?? "task",
7474
+ options: definition.options ? { ...definition.options } : void 0
7475
+ });
7476
+ }
7477
+ setHelperDefinition(definition) {
7478
+ this.helperDefinitions.set(definition.name, {
7479
+ ...definition,
7480
+ kind: definition.kind ?? "helper"
7481
+ });
7482
+ }
7483
+ setGlobalDefinition(definition) {
7484
+ this.globalDefinitions.set(definition.name, {
7485
+ ...definition,
7486
+ kind: definition.kind ?? "global",
7487
+ value: definition.value
7488
+ });
7489
+ }
7490
+ setRoutineDefinition(definition) {
7491
+ this.routineDefinitions.set(definition.name, {
7492
+ ...definition,
7493
+ startTaskNames: [...definition.startTaskNames],
7494
+ isMeta: definition.isMeta === true
7495
+ });
7496
+ }
7497
+ setIntentDefinition(definition) {
7498
+ this.intentDefinitions.set(definition.name, {
7499
+ ...definition,
7500
+ input: definition.input ? { ...definition.input } : void 0,
7501
+ output: definition.output ? { ...definition.output } : void 0
7502
+ });
7503
+ }
7504
+ setActorDefinition(definition) {
7505
+ this.actorDefinitions.set(definition.name, {
7506
+ ...definition,
7507
+ state: definition.state ? {
7508
+ ...definition.state,
7509
+ durable: definition.state.durable ? { ...definition.state.durable } : void 0,
7510
+ runtime: definition.state.runtime ? { ...definition.state.runtime } : void 0
7511
+ } : void 0,
7512
+ tasks: definition.tasks ? definition.tasks.map((task) => ({ ...task })) : void 0
7513
+ });
7514
+ }
7515
+ setActorTaskDefinition(definition) {
7516
+ this.actorTaskDefinitions.set(definition.taskName, {
7517
+ ...definition,
7518
+ mode: definition.mode ?? "read",
7519
+ options: definition.options ? { ...definition.options } : void 0
7520
+ });
7521
+ }
7522
+ setTaskLink(definition) {
7523
+ this.taskLinks.set(
7524
+ createLinkKey(
7525
+ definition.predecessorTaskName,
7526
+ definition.successorTaskName
7527
+ ),
7528
+ { ...definition }
7529
+ );
7530
+ }
7531
+ setTaskSignalObservation(definition) {
7532
+ const signalName = typeof definition.signal === "string" ? definition.signal : definition.signal.name;
7533
+ this.taskSignalObservations.set(
7534
+ createTaskSignalKey(definition.taskName, signalName),
7535
+ {
7536
+ taskName: definition.taskName,
7537
+ signal: typeof definition.signal === "string" ? definition.signal : {
7538
+ name: definition.signal.name,
7539
+ deliveryMode: definition.signal.deliveryMode,
7540
+ broadcastFilter: definition.signal.broadcastFilter ?? null
7541
+ }
7542
+ }
7543
+ );
7544
+ }
7545
+ setTaskSignalEmission(definition) {
7546
+ const signalName = typeof definition.signal === "string" ? definition.signal : definition.signal.name;
7547
+ this.taskSignalEmissions.set(
7548
+ `${definition.taskName}=>${definition.mode ?? "after"}=>${signalName}`,
7549
+ {
7550
+ taskName: definition.taskName,
7551
+ mode: definition.mode ?? "after",
7552
+ signal: typeof definition.signal === "string" ? definition.signal : {
7553
+ name: definition.signal.name,
7554
+ deliveryMode: definition.signal.deliveryMode,
7555
+ broadcastFilter: definition.signal.broadcastFilter ?? null
7556
+ }
7557
+ }
7558
+ );
7559
+ }
7560
+ setTaskIntentBinding(definition) {
7561
+ this.taskIntentBindings.set(
7562
+ createTaskIntentKey(definition.taskName, definition.intentName),
7563
+ { ...definition }
7564
+ );
7565
+ }
7566
+ setTaskHelperBinding(definition) {
7567
+ this.taskHelperBindings.set(
7568
+ `${definition.taskName}=>${definition.alias}`,
7569
+ { ...definition }
7570
+ );
7571
+ }
7572
+ setTaskGlobalBinding(definition) {
7573
+ this.taskGlobalBindings.set(
7574
+ `${definition.taskName}=>${definition.alias}`,
7575
+ { ...definition }
7576
+ );
7577
+ }
7578
+ setHelperHelperBinding(definition) {
7579
+ this.helperHelperBindings.set(
7580
+ `${definition.helperName}=>${definition.alias}`,
7581
+ { ...definition }
7582
+ );
7583
+ }
7584
+ setHelperGlobalBinding(definition) {
7585
+ this.helperGlobalBindings.set(
7586
+ `${definition.helperName}=>${definition.alias}`,
7587
+ { ...definition }
7588
+ );
7589
+ }
7590
+ setRoutineSignalObservation(definition) {
7591
+ this.routineSignalObservations.set(
7592
+ createRoutineSignalKey(definition.routineName, definition.signal),
7593
+ { ...definition }
7594
+ );
7595
+ }
7596
+ isRuntimeOwnedTask(taskName) {
7597
+ return this.taskDefinitions.has(taskName) || this.actorTaskDefinitions.has(taskName);
7598
+ }
7599
+ isRuntimeOwnedHelper(helperName) {
7600
+ return this.helperDefinitions.has(helperName);
7601
+ }
7602
+ isRuntimeOwnedGlobal(globalName) {
7603
+ return this.globalDefinitions.has(globalName);
7604
+ }
7605
+ isRuntimeOwnedRoutine(routineName) {
7606
+ return this.routineDefinitions.has(routineName);
7607
+ }
7608
+ isRuntimeOwnedActor(actorName) {
7609
+ return this.actorDefinitions.has(actorName);
7610
+ }
7611
+ };
7612
+ var runtimeDefinitionRegistry = new RuntimeDefinitionRegistry();
7613
+
7614
+ // src/runtime/sandbox.ts
7615
+ var import_node_vm = __toESM(require("vm"));
7616
+ var import_typescript = __toESM(require("typescript"));
7617
+ var FORBIDDEN_SOURCE_PATTERNS = [
7618
+ {
7619
+ pattern: /\bimport\b/,
7620
+ message: "Runtime handler source must not contain import statements"
7621
+ },
7622
+ {
7623
+ pattern: /\bexport\b/,
7624
+ message: "Runtime handler source must not contain export statements"
7625
+ },
7626
+ {
7627
+ pattern: /\brequire\s*\(/,
7628
+ message: "Runtime handler source must not call require()"
7629
+ },
7630
+ {
7631
+ pattern: /\bprocess\b/,
7632
+ message: "Runtime handler source must not access process"
7633
+ },
7634
+ {
7635
+ pattern: /\bFunction\s*\(/,
7636
+ message: "Runtime handler source must not create dynamic functions"
7637
+ },
7638
+ {
7639
+ pattern: /\beval\s*\(/,
7640
+ message: "Runtime handler source must not call eval()"
7641
+ }
7642
+ ];
7643
+ function transpileIfNeeded(source, language, filename) {
7644
+ if (language === "js") {
7645
+ return source;
7646
+ }
7647
+ const result = import_typescript.default.transpileModule(source, {
7648
+ compilerOptions: {
7649
+ target: import_typescript.default.ScriptTarget.ES2020,
7650
+ module: import_typescript.default.ModuleKind.ESNext
7651
+ },
7652
+ fileName: filename,
7653
+ reportDiagnostics: true
7654
+ });
7655
+ const diagnostics = result.diagnostics ?? [];
7656
+ const blockingDiagnostics = diagnostics.filter(
7657
+ (diagnostic) => diagnostic.category === import_typescript.default.DiagnosticCategory.Error
7658
+ );
7659
+ if (blockingDiagnostics.length > 0) {
7660
+ const message = blockingDiagnostics.map((diagnostic) => import_typescript.default.flattenDiagnosticMessageText(diagnostic.messageText, "\n")).join("; ");
7661
+ throw new Error(`TypeScript transpile failed: ${message}`);
7662
+ }
7663
+ return result.outputText;
7664
+ }
7665
+ function createSandbox() {
7666
+ const sandbox = /* @__PURE__ */ Object.create(null);
7667
+ sandbox.global = void 0;
7668
+ sandbox.globalThis = sandbox;
7669
+ sandbox.process = void 0;
7670
+ sandbox.require = void 0;
7671
+ sandbox.module = void 0;
7672
+ sandbox.exports = void 0;
7673
+ sandbox.Buffer = void 0;
7674
+ sandbox.fetch = void 0;
7675
+ sandbox.WebSocket = void 0;
7676
+ sandbox.XMLHttpRequest = void 0;
7677
+ sandbox.setTimeout = void 0;
7678
+ sandbox.setInterval = void 0;
7679
+ sandbox.clearTimeout = void 0;
7680
+ sandbox.clearInterval = void 0;
7681
+ sandbox.queueMicrotask = void 0;
7682
+ return import_node_vm.default.createContext(sandbox);
7683
+ }
7684
+ function compileFunctionFromSource(source, language, filename, label) {
7685
+ const normalizedSource = String(source ?? "").trim();
7686
+ if (!normalizedSource) {
7687
+ throw new Error(`${label} source must be a non-empty string`);
7688
+ }
7689
+ for (const rule of FORBIDDEN_SOURCE_PATTERNS) {
7690
+ if (rule.pattern.test(normalizedSource)) {
7691
+ throw new Error(rule.message);
7692
+ }
7693
+ }
7694
+ const wrappedSource = `const __runtime_handler = ${normalizedSource};
7695
+ __runtime_handler;`;
7696
+ const transpiledSource = transpileIfNeeded(
7697
+ wrappedSource,
7698
+ language,
7699
+ filename
7700
+ ).trim();
7701
+ const sandbox = createSandbox();
7702
+ const script = new import_node_vm.default.Script(transpiledSource, {
7703
+ filename
7704
+ });
7705
+ const compiled = script.runInContext(sandbox, {
7706
+ timeout: 1e3,
7707
+ displayErrors: true,
7708
+ contextCodeGeneration: {
7709
+ strings: false,
7710
+ wasm: false
7711
+ }
7712
+ });
7713
+ if (typeof compiled !== "function") {
7714
+ throw new Error(`${label} source must evaluate to a function`);
7715
+ }
7716
+ return compiled;
7717
+ }
7718
+ function compileRuntimeTaskFunction(definition) {
7719
+ return compileFunctionFromSource(
7720
+ definition.handlerSource,
7721
+ definition.language,
7722
+ `${definition.name}.runtime-task.${definition.language}`,
7723
+ `Task "${definition.name}"`
7724
+ );
7725
+ }
7726
+ function compileRuntimeHelperFunction(definition) {
7727
+ return compileFunctionFromSource(
7728
+ definition.handlerSource,
7729
+ definition.language,
7730
+ `${definition.name}.runtime-helper.${definition.language}`,
7731
+ `Helper "${definition.name}"`
7732
+ );
7733
+ }
7734
+ function compileRuntimeActorTaskHandler(definition) {
7735
+ return compileFunctionFromSource(
7736
+ definition.handlerSource,
7737
+ definition.language,
7738
+ `${definition.actorName}.${definition.taskName}.runtime-actor-task.${definition.language}`,
7739
+ `Actor task "${definition.taskName}"`
7740
+ );
7741
+ }
7742
+
7743
+ // src/runtime/sanitize.ts
7744
+ function isPlainObject2(value) {
7745
+ return typeof value === "object" && value !== null && Object.getPrototypeOf(value) === Object.prototype;
7746
+ }
7747
+ function sanitizeForJson(value, seen = /* @__PURE__ */ new WeakSet()) {
7748
+ if (value === null || value === void 0 || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
7749
+ return value ?? null;
7750
+ }
7751
+ if (typeof value === "bigint") {
7752
+ return value.toString();
7753
+ }
7754
+ if (typeof value === "function") {
7755
+ return `[Function ${value.name || "anonymous"}]`;
7756
+ }
7757
+ if (typeof value === "symbol") {
7758
+ return value.toString();
7759
+ }
7760
+ if (value instanceof Date) {
7761
+ return value.toISOString();
7762
+ }
7763
+ if (value instanceof Set) {
7764
+ return Array.from(value).map((entry) => sanitizeForJson(entry, seen));
7765
+ }
7766
+ if (value instanceof Map) {
7767
+ return Array.from(value.entries()).map(([key, entry]) => [
7768
+ sanitizeForJson(key, seen),
7769
+ sanitizeForJson(entry, seen)
7770
+ ]);
7771
+ }
7772
+ if (Array.isArray(value)) {
7773
+ return value.map((entry) => sanitizeForJson(entry, seen));
7774
+ }
7775
+ if (typeof value === "object") {
7776
+ if (seen.has(value)) {
7777
+ return "[Circular]";
7778
+ }
7779
+ seen.add(value);
7780
+ if (!isPlainObject2(value)) {
7781
+ const clone = {};
7782
+ for (const key of Object.keys(value)) {
7783
+ clone[key] = sanitizeForJson(
7784
+ value[key],
7785
+ seen
7786
+ );
7787
+ }
7788
+ clone.__type = value.constructor?.name ?? "Object";
7789
+ return clone;
7790
+ }
7791
+ const result = {};
7792
+ for (const [key, entry] of Object.entries(value)) {
7793
+ result[key] = sanitizeForJson(entry, seen);
7794
+ }
7795
+ return result;
7796
+ }
7797
+ return String(value);
7798
+ }
7799
+
7071
7800
  // src/Cadenza.ts
7072
7801
  var Cadenza = class {
7073
7802
  /**
@@ -7150,22 +7879,105 @@ var Cadenza = class {
7150
7879
  throw new Error("Task or Routine name must be a non-empty string.");
7151
7880
  }
7152
7881
  }
7153
- static resolveTaskOptionsForActorTask(func, options = {}) {
7154
- const metadata = getActorTaskRuntimeMetadata(func);
7155
- if (!metadata?.forceMeta) {
7156
- return options;
7157
- }
7158
- if (options.isMeta) {
7159
- return options;
7882
+ static assertGraphMutationAllowed(operationName) {
7883
+ if (this.helperExecutionDepth > 0) {
7884
+ throw new Error(
7885
+ `${operationName} is not allowed during helper execution`
7886
+ );
7160
7887
  }
7161
- return {
7162
- ...options,
7163
- isMeta: true
7888
+ }
7889
+ static executeHelper(helper, context, emit, inquire, progressCallback) {
7890
+ const helperContext = context && typeof context === "object" ? context : {};
7891
+ const tools = this.resolveToolsForOwner(
7892
+ helper,
7893
+ helperContext,
7894
+ emit,
7895
+ inquire,
7896
+ progressCallback
7897
+ );
7898
+ this.helperExecutionDepth += 1;
7899
+ try {
7900
+ return helper.helperFunction(
7901
+ helperContext,
7902
+ emit,
7903
+ inquire,
7904
+ tools,
7905
+ progressCallback
7906
+ );
7907
+ } finally {
7908
+ this.helperExecutionDepth = Math.max(0, this.helperExecutionDepth - 1);
7909
+ }
7910
+ }
7911
+ static resolveToolsForOwner(owner, context, emit, inquire, progressCallback) {
7912
+ const helpers = {};
7913
+ const globals = {};
7914
+ for (const [alias, helperName] of owner.helperAliases.entries()) {
7915
+ const helper = this.getHelper(helperName);
7916
+ if (!helper) {
7917
+ continue;
7918
+ }
7919
+ if (helper.isMeta !== owner.isMeta) {
7920
+ throw new Error(
7921
+ `Tool alias "${alias}" resolves across layer boundaries`
7922
+ );
7923
+ }
7924
+ helpers[alias] = (helperContext = context) => this.executeHelper(
7925
+ helper,
7926
+ helperContext,
7927
+ emit,
7928
+ inquire,
7929
+ progressCallback
7930
+ );
7931
+ }
7932
+ for (const [alias, globalName] of owner.globalAliases.entries()) {
7933
+ const globalDefinition = this.getGlobal(globalName);
7934
+ if (!globalDefinition) {
7935
+ continue;
7936
+ }
7937
+ if (globalDefinition.isMeta !== owner.isMeta) {
7938
+ throw new Error(
7939
+ `Global alias "${alias}" resolves across layer boundaries`
7940
+ );
7941
+ }
7942
+ globals[alias] = globalDefinition.value;
7943
+ }
7944
+ return {
7945
+ helpers,
7946
+ globals
7947
+ };
7948
+ }
7949
+ static resolveTaskOptionsForActorTask(func, options = {}) {
7950
+ const metadata = getActorTaskRuntimeMetadata(func);
7951
+ if (!metadata?.forceMeta) {
7952
+ return options;
7953
+ }
7954
+ if (options.isMeta) {
7955
+ return options;
7956
+ }
7957
+ return {
7958
+ ...options,
7959
+ isMeta: true
7164
7960
  };
7165
7961
  }
7166
7962
  static registerActor(actor) {
7167
7963
  this.actorCache.set(actor.spec.name, actor);
7168
7964
  }
7965
+ static getHelper(name) {
7966
+ return this.helperCache.get(name);
7967
+ }
7968
+ static getAllHelpers() {
7969
+ return Array.from(this.helperCache.values()).filter(
7970
+ (helper) => !helper.destroyed
7971
+ );
7972
+ }
7973
+ static getGlobal(name) {
7974
+ return this.globalCache.get(name);
7975
+ }
7976
+ static getAllGlobals() {
7977
+ return Array.from(this.globalCache.values()).filter(
7978
+ (globalDefinition) => !globalDefinition.destroyed
7979
+ );
7980
+ }
7169
7981
  /**
7170
7982
  * Executes the specified task or GraphRoutine with the given context using an internal runner.
7171
7983
  *
@@ -7228,6 +8040,9 @@ var Cadenza = class {
7228
8040
  static get(taskName) {
7229
8041
  return this.registry?.tasks.get(taskName) ?? this.taskCache.get(taskName);
7230
8042
  }
8043
+ static forgetTask(taskName) {
8044
+ this.taskCache.delete(taskName);
8045
+ }
7231
8046
  static getActor(actorName) {
7232
8047
  return this.actorCache.get(actorName);
7233
8048
  }
@@ -7235,9 +8050,10 @@ var Cadenza = class {
7235
8050
  return Array.from(this.actorCache.values());
7236
8051
  }
7237
8052
  static getRoutine(routineName) {
7238
- return this.registry?.routines.get(routineName);
8053
+ return this.registry?.routines.get(routineName) ?? this.routineCache.get(routineName);
7239
8054
  }
7240
8055
  static defineIntent(intent) {
8056
+ this.assertGraphMutationAllowed("Cadenza.defineIntent");
7241
8057
  this.inquiryBroker?.addIntent(intent);
7242
8058
  return intent;
7243
8059
  }
@@ -7391,6 +8207,7 @@ var Cadenza = class {
7391
8207
  * participate in the graph like any other task.
7392
8208
  */
7393
8209
  static createActor(spec, options = {}) {
8210
+ this.assertGraphMutationAllowed("Cadenza.createActor");
7394
8211
  this.bootstrap();
7395
8212
  const actor = new Actor(spec, options);
7396
8213
  this.registerActor(actor);
@@ -7506,6 +8323,7 @@ var Cadenza = class {
7506
8323
  * ```
7507
8324
  */
7508
8325
  static createTask(name, func, description, options = {}) {
8326
+ this.assertGraphMutationAllowed("Cadenza.createTask");
7509
8327
  this.bootstrap();
7510
8328
  this.validateName(name);
7511
8329
  const actorResolvedOptions = this.resolveTaskOptionsForActorTask(
@@ -7555,6 +8373,164 @@ var Cadenza = class {
7555
8373
  this.taskCache.set(name, createdTask);
7556
8374
  return createdTask;
7557
8375
  }
8376
+ static createTaskFromDefinition(definition) {
8377
+ this.bootstrap();
8378
+ this.validateName(definition.name);
8379
+ const existing = this.get(definition.name);
8380
+ if (existing) {
8381
+ if (!runtimeDefinitionRegistry.isRuntimeOwnedTask(definition.name)) {
8382
+ throw new Error(
8383
+ `Task "${definition.name}" already exists and is not runtime-owned`
8384
+ );
8385
+ }
8386
+ existing.destroy();
8387
+ }
8388
+ const taskFunction = compileRuntimeTaskFunction(definition);
8389
+ const createdTask = definition.kind === "metaTask" ? this.createMetaTask(
8390
+ definition.name,
8391
+ taskFunction,
8392
+ definition.description ?? "",
8393
+ definition.options ?? {}
8394
+ ) : this.createTask(
8395
+ definition.name,
8396
+ taskFunction,
8397
+ definition.description ?? "",
8398
+ definition.options ?? {}
8399
+ );
8400
+ runtimeDefinitionRegistry.setTaskDefinition(definition);
8401
+ return createdTask;
8402
+ }
8403
+ static createHelper(name, func, description = "") {
8404
+ this.bootstrap();
8405
+ this.validateName(name);
8406
+ this.assertGraphMutationAllowed("Cadenza.createHelper");
8407
+ if (this.helperCache.has(name)) {
8408
+ throw new Error(`Helper "${name}" already exists`);
8409
+ }
8410
+ const helper = new HelperDefinition(name, func, description, false);
8411
+ this.helperCache.set(name, helper);
8412
+ this.emit("meta.helper.created", {
8413
+ data: {
8414
+ name,
8415
+ version: helper.version,
8416
+ description,
8417
+ functionString: func.toString(),
8418
+ isMeta: false
8419
+ }
8420
+ });
8421
+ return helper;
8422
+ }
8423
+ static createMetaHelper(name, func, description = "") {
8424
+ this.bootstrap();
8425
+ this.validateName(name);
8426
+ this.assertGraphMutationAllowed("Cadenza.createMetaHelper");
8427
+ if (this.helperCache.has(name)) {
8428
+ throw new Error(`Helper "${name}" already exists`);
8429
+ }
8430
+ const helper = new HelperDefinition(name, func, description, true);
8431
+ this.helperCache.set(name, helper);
8432
+ this.emit("meta.helper.created", {
8433
+ data: {
8434
+ name,
8435
+ version: helper.version,
8436
+ description,
8437
+ functionString: func.toString(),
8438
+ isMeta: true
8439
+ }
8440
+ });
8441
+ return helper;
8442
+ }
8443
+ static createHelperFromDefinition(definition) {
8444
+ this.bootstrap();
8445
+ this.validateName(definition.name);
8446
+ const existing = this.getHelper(definition.name);
8447
+ if (existing) {
8448
+ if (!runtimeDefinitionRegistry.isRuntimeOwnedHelper(definition.name)) {
8449
+ throw new Error(
8450
+ `Helper "${definition.name}" already exists and is not runtime-owned`
8451
+ );
8452
+ }
8453
+ existing.destroy();
8454
+ this.helperCache.delete(definition.name);
8455
+ }
8456
+ const helperFunction = compileRuntimeHelperFunction(definition);
8457
+ const helper = definition.kind === "metaHelper" ? this.createMetaHelper(
8458
+ definition.name,
8459
+ helperFunction,
8460
+ definition.description ?? ""
8461
+ ) : this.createHelper(
8462
+ definition.name,
8463
+ helperFunction,
8464
+ definition.description ?? ""
8465
+ );
8466
+ runtimeDefinitionRegistry.setHelperDefinition(definition);
8467
+ return helper;
8468
+ }
8469
+ static createGlobal(name, value, description = "") {
8470
+ this.bootstrap();
8471
+ this.validateName(name);
8472
+ this.assertGraphMutationAllowed("Cadenza.createGlobal");
8473
+ if (this.globalCache.has(name)) {
8474
+ throw new Error(`Global "${name}" already exists`);
8475
+ }
8476
+ const globalDefinition = new GlobalDefinition(name, value, description, false);
8477
+ this.globalCache.set(name, globalDefinition);
8478
+ this.emit("meta.global.created", {
8479
+ data: {
8480
+ name,
8481
+ version: globalDefinition.version,
8482
+ description,
8483
+ isMeta: false,
8484
+ value: globalDefinition.value
8485
+ }
8486
+ });
8487
+ return globalDefinition;
8488
+ }
8489
+ static createMetaGlobal(name, value, description = "") {
8490
+ this.bootstrap();
8491
+ this.validateName(name);
8492
+ this.assertGraphMutationAllowed("Cadenza.createMetaGlobal");
8493
+ if (this.globalCache.has(name)) {
8494
+ throw new Error(`Global "${name}" already exists`);
8495
+ }
8496
+ const globalDefinition = new GlobalDefinition(name, value, description, true);
8497
+ this.globalCache.set(name, globalDefinition);
8498
+ this.emit("meta.global.created", {
8499
+ data: {
8500
+ name,
8501
+ version: globalDefinition.version,
8502
+ description,
8503
+ isMeta: true,
8504
+ value: globalDefinition.value
8505
+ }
8506
+ });
8507
+ return globalDefinition;
8508
+ }
8509
+ static createGlobalFromDefinition(definition) {
8510
+ this.bootstrap();
8511
+ this.validateName(definition.name);
8512
+ const existing = this.getGlobal(definition.name);
8513
+ if (existing) {
8514
+ if (!runtimeDefinitionRegistry.isRuntimeOwnedGlobal(definition.name)) {
8515
+ throw new Error(
8516
+ `Global "${definition.name}" already exists and is not runtime-owned`
8517
+ );
8518
+ }
8519
+ existing.destroy();
8520
+ this.globalCache.delete(definition.name);
8521
+ }
8522
+ const globalDefinition = definition.kind === "metaGlobal" ? this.createMetaGlobal(
8523
+ definition.name,
8524
+ definition.value,
8525
+ definition.description ?? ""
8526
+ ) : this.createGlobal(
8527
+ definition.name,
8528
+ definition.value,
8529
+ definition.description ?? ""
8530
+ );
8531
+ runtimeDefinitionRegistry.setGlobalDefinition(definition);
8532
+ return globalDefinition;
8533
+ }
7558
8534
  /**
7559
8535
  * Creates a meta task with the specified name, functionality, description, and options.
7560
8536
  * This is used for creating tasks that lives on the meta layer.
@@ -7620,6 +8596,7 @@ var Cadenza = class {
7620
8596
  *
7621
8597
  */
7622
8598
  static createUniqueTask(name, func, description, options = {}) {
8599
+ this.assertGraphMutationAllowed("Cadenza.createUniqueTask");
7623
8600
  options.isUnique = true;
7624
8601
  return this.createTask(name, func, description, options);
7625
8602
  }
@@ -7668,6 +8645,7 @@ var Cadenza = class {
7668
8645
  * ```
7669
8646
  */
7670
8647
  static createThrottledTask(name, func, throttledIdGetter = () => "default", description, options = {}) {
8648
+ this.assertGraphMutationAllowed("Cadenza.createThrottledTask");
7671
8649
  options.concurrency = 1;
7672
8650
  options.getTagCallback = throttledIdGetter;
7673
8651
  return this.createTask(name, func, description, options);
@@ -7727,6 +8705,7 @@ var Cadenza = class {
7727
8705
  * ```
7728
8706
  */
7729
8707
  static createDebounceTask(name, func, description, debounceTime = 1e3, options = {}) {
8708
+ this.assertGraphMutationAllowed("Cadenza.createDebounceTask");
7730
8709
  this.bootstrap();
7731
8710
  this.validateName(name);
7732
8711
  const actorResolvedOptions = this.resolveTaskOptionsForActorTask(
@@ -7855,6 +8834,7 @@ var Cadenza = class {
7855
8834
  * ```
7856
8835
  */
7857
8836
  static createEphemeralTask(name, func, description, options = {}) {
8837
+ this.assertGraphMutationAllowed("Cadenza.createEphemeralTask");
7858
8838
  this.bootstrap();
7859
8839
  this.validateName(name);
7860
8840
  const actorResolvedOptions = this.resolveTaskOptionsForActorTask(
@@ -7951,12 +8931,46 @@ var Cadenza = class {
7951
8931
  * ```
7952
8932
  */
7953
8933
  static createRoutine(name, tasks, description = "") {
8934
+ this.assertGraphMutationAllowed("Cadenza.createRoutine");
7954
8935
  this.bootstrap();
7955
8936
  this.validateName(name);
7956
8937
  if (tasks.length === 0) {
7957
8938
  throw new Error(`Routine '${name}' created with no starting tasks.`);
7958
8939
  }
7959
- return new GraphRoutine(name, tasks, description);
8940
+ const createdRoutine = new GraphRoutine(name, tasks, description);
8941
+ this.routineCache.set(name, createdRoutine);
8942
+ return createdRoutine;
8943
+ }
8944
+ static createRoutineFromDefinition(definition) {
8945
+ const existing = this.getRoutine(definition.name);
8946
+ if (existing) {
8947
+ if (!runtimeDefinitionRegistry.isRuntimeOwnedRoutine(definition.name)) {
8948
+ throw new Error(
8949
+ `Routine "${definition.name}" already exists and is not runtime-owned`
8950
+ );
8951
+ }
8952
+ existing.destroy();
8953
+ }
8954
+ const startTasks = definition.startTaskNames.map((taskName) => {
8955
+ const task = this.get(taskName);
8956
+ if (!task) {
8957
+ throw new Error(
8958
+ `Routine "${definition.name}" references missing task "${taskName}"`
8959
+ );
8960
+ }
8961
+ return task;
8962
+ });
8963
+ const routine = definition.isMeta === true ? this.createMetaRoutine(
8964
+ definition.name,
8965
+ startTasks,
8966
+ definition.description ?? ""
8967
+ ) : this.createRoutine(
8968
+ definition.name,
8969
+ startTasks,
8970
+ definition.description ?? ""
8971
+ );
8972
+ runtimeDefinitionRegistry.setRoutineDefinition(definition);
8973
+ return routine;
7960
8974
  }
7961
8975
  /**
7962
8976
  * Creates a meta routine with a given name, tasks, and optional description.
@@ -7971,34 +8985,1418 @@ var Cadenza = class {
7971
8985
  * @throws {Error} If no starting tasks are provided.
7972
8986
  */
7973
8987
  static createMetaRoutine(name, tasks, description = "") {
8988
+ this.assertGraphMutationAllowed("Cadenza.createMetaRoutine");
7974
8989
  this.bootstrap();
7975
8990
  this.validateName(name);
7976
8991
  if (tasks.length === 0) {
7977
8992
  throw new Error(`Routine '${name}' created with no starting tasks.`);
7978
8993
  }
7979
- return new GraphRoutine(name, tasks, description, true);
8994
+ const createdRoutine = new GraphRoutine(name, tasks, description, true);
8995
+ this.routineCache.set(name, createdRoutine);
8996
+ return createdRoutine;
8997
+ }
8998
+ static snapshotRuntime() {
8999
+ const taskMap = /* @__PURE__ */ new Map();
9000
+ for (const task of this.taskCache.values()) {
9001
+ taskMap.set(task.name, task);
9002
+ }
9003
+ for (const task of this.registry?.tasks.values() ?? []) {
9004
+ taskMap.set(task.name, task);
9005
+ }
9006
+ const tasks = Array.from(taskMap.values()).map((task) => {
9007
+ const runtimeTaskDefinition = runtimeDefinitionRegistry.taskDefinitions.get(
9008
+ task.name
9009
+ );
9010
+ const runtimeActorTaskDefinition = runtimeDefinitionRegistry.actorTaskDefinitions.get(task.name);
9011
+ return {
9012
+ name: task.name,
9013
+ version: task.version,
9014
+ description: task.description,
9015
+ kind: runtimeActorTaskDefinition ? "actorTask" : task.isMeta ? "metaTask" : "task",
9016
+ runtimeOwned: runtimeDefinitionRegistry.isRuntimeOwnedTask(task.name) === true,
9017
+ language: runtimeTaskDefinition?.language ?? runtimeActorTaskDefinition?.language ?? null,
9018
+ handlerSource: runtimeTaskDefinition?.handlerSource ?? runtimeActorTaskDefinition?.handlerSource ?? null,
9019
+ concurrency: task.concurrency,
9020
+ timeout: task.timeout,
9021
+ retryCount: task.retryCount,
9022
+ retryDelay: task.retryDelay,
9023
+ retryDelayMax: task.retryDelayMax,
9024
+ retryDelayFactor: task.retryDelayFactor,
9025
+ validateInputContext: task.validateInputContext,
9026
+ validateOutputContext: task.validateOutputContext,
9027
+ inputContextSchema: sanitizeForJson(task.inputContextSchema),
9028
+ outputContextSchema: sanitizeForJson(task.outputContextSchema),
9029
+ nextTaskNames: Array.from(task.nextTasks).map((nextTask) => nextTask.name),
9030
+ predecessorTaskNames: Array.from(task.predecessorTasks).map(
9031
+ (predecessorTask) => predecessorTask.name
9032
+ ),
9033
+ signals: {
9034
+ emits: Array.from(task.emitsSignals),
9035
+ emitsAfter: Array.from(task.signalsToEmitAfter),
9036
+ emitsOnFail: Array.from(task.signalsToEmitOnFail),
9037
+ observed: Array.from(task.observedSignals)
9038
+ },
9039
+ intents: {
9040
+ handles: Array.from(task.handlesIntents),
9041
+ inquires: Array.from(task.inquiresIntents)
9042
+ },
9043
+ tools: {
9044
+ helpers: Object.fromEntries(task.helperAliases),
9045
+ globals: Object.fromEntries(task.globalAliases)
9046
+ },
9047
+ actorName: runtimeActorTaskDefinition?.actorName ?? null,
9048
+ actorMode: runtimeActorTaskDefinition?.mode ?? null
9049
+ };
9050
+ });
9051
+ const helpers = this.getAllHelpers().map((helper) => {
9052
+ const runtimeHelperDefinition = runtimeDefinitionRegistry.helperDefinitions.get(helper.name);
9053
+ return {
9054
+ name: helper.name,
9055
+ version: helper.version,
9056
+ description: helper.description,
9057
+ kind: helper.isMeta ? "metaHelper" : "helper",
9058
+ runtimeOwned: runtimeDefinitionRegistry.isRuntimeOwnedHelper(helper.name),
9059
+ language: runtimeHelperDefinition?.language ?? null,
9060
+ handlerSource: runtimeHelperDefinition?.handlerSource ?? null,
9061
+ tools: {
9062
+ helpers: Object.fromEntries(helper.helperAliases),
9063
+ globals: Object.fromEntries(helper.globalAliases)
9064
+ }
9065
+ };
9066
+ });
9067
+ const globals = this.getAllGlobals().map((globalDefinition) => ({
9068
+ name: globalDefinition.name,
9069
+ version: globalDefinition.version,
9070
+ description: globalDefinition.description,
9071
+ kind: globalDefinition.isMeta ? "metaGlobal" : "global",
9072
+ runtimeOwned: runtimeDefinitionRegistry.isRuntimeOwnedGlobal(
9073
+ globalDefinition.name
9074
+ ),
9075
+ value: sanitizeForJson(globalDefinition.value)
9076
+ }));
9077
+ const routineMap = /* @__PURE__ */ new Map();
9078
+ for (const routine of this.routineCache.values()) {
9079
+ routineMap.set(routine.name, routine);
9080
+ }
9081
+ for (const routine of this.registry?.routines.values() ?? []) {
9082
+ routineMap.set(routine.name, routine);
9083
+ }
9084
+ const routines = Array.from(routineMap.values()).map(
9085
+ (routine) => ({
9086
+ name: routine.name,
9087
+ version: routine.version,
9088
+ description: routine.description,
9089
+ isMeta: routine.isMeta,
9090
+ runtimeOwned: runtimeDefinitionRegistry.isRuntimeOwnedRoutine(routine.name) === true,
9091
+ startTaskNames: Array.from(routine.tasks).map((task) => task.name),
9092
+ observedSignals: Array.from(routine.observedSignals)
9093
+ })
9094
+ );
9095
+ const intents = Array.from(this.inquiryBroker?.intents.values() ?? []).map(
9096
+ (intent) => {
9097
+ const sanitizedIntent = sanitizeForJson(intent);
9098
+ return {
9099
+ ...sanitizedIntent,
9100
+ runtimeOwned: runtimeDefinitionRegistry.intentDefinitions.has(
9101
+ intent.name
9102
+ )
9103
+ };
9104
+ }
9105
+ );
9106
+ const signals = Array.from(
9107
+ this.signalBroker?.emittedSignalsRegistry.values() ?? []
9108
+ ).map((signalName) => ({
9109
+ name: signalName,
9110
+ metadata: sanitizeForJson(
9111
+ this.signalBroker?.signalMetadataRegistry.get(signalName) ?? null
9112
+ ) ?? null
9113
+ }));
9114
+ const actors = this.getAllActors().map((actor) => {
9115
+ const definition = actor.toDefinition();
9116
+ const actorKeys = actor.listActorKeys().map((actorKey) => ({
9117
+ actorKey,
9118
+ durableState: sanitizeForJson(actor.getDurableState(actorKey)),
9119
+ runtimeState: sanitizeForJson(actor.getRuntimeState(actorKey)),
9120
+ durableVersion: actor.getDurableVersion(actorKey),
9121
+ runtimeVersion: actor.getRuntimeVersion(actorKey)
9122
+ }));
9123
+ return {
9124
+ name: actor.spec.name,
9125
+ description: actor.spec.description ?? "",
9126
+ runtimeOwned: runtimeDefinitionRegistry.isRuntimeOwnedActor(
9127
+ actor.spec.name
9128
+ ),
9129
+ definition: sanitizeForJson(definition),
9130
+ actorKeys
9131
+ };
9132
+ });
9133
+ const actorTasks = Array.from(
9134
+ runtimeDefinitionRegistry.actorTaskDefinitions.values()
9135
+ ).map((definition) => ({
9136
+ actorName: definition.actorName,
9137
+ taskName: definition.taskName,
9138
+ description: definition.description ?? "",
9139
+ mode: definition.mode ?? "read",
9140
+ language: definition.language,
9141
+ handlerSource: definition.handlerSource,
9142
+ runtimeOwned: true
9143
+ }));
9144
+ const links = Array.from(runtimeDefinitionRegistry.taskLinks.values()).map(
9145
+ (link) => ({ ...link })
9146
+ );
9147
+ return {
9148
+ runtimeMode: "core",
9149
+ bootstrapped: this.isBootstrapped,
9150
+ mode: this.mode,
9151
+ tasks,
9152
+ helpers,
9153
+ globals,
9154
+ routines,
9155
+ intents,
9156
+ signals,
9157
+ actors,
9158
+ actorTasks,
9159
+ links
9160
+ };
7980
9161
  }
7981
9162
  static reset() {
7982
9163
  this.signalBroker?.reset();
7983
9164
  this.inquiryBroker?.reset();
7984
9165
  this.registry?.reset();
7985
9166
  this.taskCache.clear();
9167
+ this.routineCache.clear();
7986
9168
  this.actorCache.clear();
9169
+ this.helperCache.clear();
9170
+ this.globalCache.clear();
7987
9171
  this.runtimeInquiryDelegate = void 0;
7988
9172
  this.runtimeValidationPolicy = {};
7989
9173
  this.runtimeValidationScopes.clear();
7990
9174
  this.emittedMissingSchemaWarnings.clear();
9175
+ this.helperExecutionDepth = 0;
9176
+ runtimeDefinitionRegistry.reset();
7991
9177
  this.isBootstrapped = false;
7992
9178
  }
7993
9179
  };
7994
9180
  Cadenza.taskCache = /* @__PURE__ */ new Map();
9181
+ Cadenza.routineCache = /* @__PURE__ */ new Map();
7995
9182
  Cadenza.actorCache = /* @__PURE__ */ new Map();
9183
+ Cadenza.helperCache = /* @__PURE__ */ new Map();
9184
+ Cadenza.globalCache = /* @__PURE__ */ new Map();
7996
9185
  Cadenza.runtimeValidationPolicy = {};
7997
9186
  Cadenza.runtimeValidationScopes = /* @__PURE__ */ new Map();
7998
9187
  Cadenza.emittedMissingSchemaWarnings = /* @__PURE__ */ new Set();
9188
+ Cadenza.helperExecutionDepth = 0;
7999
9189
  Cadenza.isBootstrapped = false;
8000
9190
  Cadenza.mode = "production";
8001
9191
 
9192
+ // src/runtime/RuntimeSubscriptionManager.ts
9193
+ var import_uuid8 = require("uuid");
9194
+ function isObject3(value) {
9195
+ return typeof value === "object" && value !== null && !Array.isArray(value);
9196
+ }
9197
+ function asStringOrNull(value) {
9198
+ return typeof value === "string" && value.length > 0 ? value : null;
9199
+ }
9200
+ function asNumberOrNull(value) {
9201
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
9202
+ }
9203
+ function normalizeEventContext(context) {
9204
+ const sanitized = sanitizeForJson(context);
9205
+ return isObject3(sanitized) ? sanitized : { value: sanitized };
9206
+ }
9207
+ function matchesSignalPattern(fullSignal, signalName, patterns) {
9208
+ return patterns.some((pattern) => {
9209
+ if (pattern === "*") {
9210
+ return true;
9211
+ }
9212
+ if (pattern === fullSignal || pattern === signalName) {
9213
+ return true;
9214
+ }
9215
+ if (!pattern.endsWith(".*")) {
9216
+ return false;
9217
+ }
9218
+ const prefix = pattern.slice(0, -2);
9219
+ return signalName === prefix || signalName.startsWith(`${prefix}.`);
9220
+ });
9221
+ }
9222
+ var RuntimeSubscriptionManagerError = class extends Error {
9223
+ constructor(code, message) {
9224
+ super(message);
9225
+ this.code = code;
9226
+ this.name = "RuntimeSubscriptionManagerError";
9227
+ }
9228
+ };
9229
+ var RuntimeSubscriptionManager = class {
9230
+ constructor() {
9231
+ this.subscriptions = /* @__PURE__ */ new Map();
9232
+ this.removeBrokerListener = null;
9233
+ this.nextSequence = 0;
9234
+ this.attach();
9235
+ }
9236
+ dispose() {
9237
+ this.reset();
9238
+ this.removeBrokerListener?.();
9239
+ this.removeBrokerListener = null;
9240
+ }
9241
+ subscribe(signalPatterns, maxQueueSize) {
9242
+ this.attach();
9243
+ const descriptor = {
9244
+ subscriptionId: (0, import_uuid8.v4)(),
9245
+ signalPatterns: [...signalPatterns],
9246
+ maxQueueSize,
9247
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
9248
+ pendingEvents: 0
9249
+ };
9250
+ this.subscriptions.set(descriptor.subscriptionId, {
9251
+ descriptor,
9252
+ events: [],
9253
+ nextWaiter: null
9254
+ });
9255
+ return { ...descriptor };
9256
+ }
9257
+ unsubscribe(subscriptionId) {
9258
+ const subscription = this.requireSubscription(subscriptionId);
9259
+ this.clearWaiter(
9260
+ subscription,
9261
+ new RuntimeSubscriptionManagerError(
9262
+ "not_found",
9263
+ `Subscription "${subscriptionId}" was closed`
9264
+ )
9265
+ );
9266
+ this.subscriptions.delete(subscriptionId);
9267
+ return { ...subscription.descriptor };
9268
+ }
9269
+ async nextEvent(subscriptionId, timeoutMs) {
9270
+ const subscription = this.requireSubscription(subscriptionId);
9271
+ if (subscription.events.length > 0) {
9272
+ const event = subscription.events.shift() ?? null;
9273
+ subscription.descriptor.pendingEvents = subscription.events.length;
9274
+ return {
9275
+ subscriptionId,
9276
+ event,
9277
+ timedOut: false,
9278
+ pendingEvents: subscription.events.length
9279
+ };
9280
+ }
9281
+ if (timeoutMs <= 0) {
9282
+ return {
9283
+ subscriptionId,
9284
+ event: null,
9285
+ timedOut: true,
9286
+ pendingEvents: 0
9287
+ };
9288
+ }
9289
+ if (subscription.nextWaiter) {
9290
+ throw new RuntimeSubscriptionManagerError(
9291
+ "conflict",
9292
+ `Subscription "${subscriptionId}" already has a pending nextEvent request`
9293
+ );
9294
+ }
9295
+ return new Promise((resolve, reject) => {
9296
+ const timer = setTimeout(() => {
9297
+ subscription.nextWaiter = null;
9298
+ resolve({
9299
+ subscriptionId,
9300
+ event: null,
9301
+ timedOut: true,
9302
+ pendingEvents: subscription.events.length
9303
+ });
9304
+ }, timeoutMs);
9305
+ subscription.nextWaiter = {
9306
+ resolve: (result) => {
9307
+ clearTimeout(timer);
9308
+ subscription.nextWaiter = null;
9309
+ resolve(result);
9310
+ },
9311
+ reject: (error) => {
9312
+ clearTimeout(timer);
9313
+ subscription.nextWaiter = null;
9314
+ reject(error);
9315
+ },
9316
+ timer
9317
+ };
9318
+ });
9319
+ }
9320
+ pollEvents(subscriptionId, limit) {
9321
+ const subscription = this.requireSubscription(subscriptionId);
9322
+ const events = subscription.events.splice(0, limit);
9323
+ subscription.descriptor.pendingEvents = subscription.events.length;
9324
+ return {
9325
+ subscriptionId,
9326
+ events,
9327
+ pendingEvents: subscription.events.length
9328
+ };
9329
+ }
9330
+ reset() {
9331
+ for (const subscription of this.subscriptions.values()) {
9332
+ this.clearWaiter(
9333
+ subscription,
9334
+ new RuntimeSubscriptionManagerError(
9335
+ "not_found",
9336
+ `Subscription "${subscription.descriptor.subscriptionId}" was reset`
9337
+ )
9338
+ );
9339
+ subscription.events.length = 0;
9340
+ subscription.descriptor.pendingEvents = 0;
9341
+ }
9342
+ this.subscriptions.clear();
9343
+ }
9344
+ attach() {
9345
+ if (this.removeBrokerListener) {
9346
+ return;
9347
+ }
9348
+ Cadenza.bootstrap();
9349
+ this.removeBrokerListener = Cadenza.signalBroker.addPassiveSignalListener(
9350
+ (signal, context, metadata) => this.captureSignal(signal, context, metadata)
9351
+ );
9352
+ }
9353
+ captureSignal(signal, context, metadata) {
9354
+ if (this.subscriptions.size === 0) {
9355
+ return;
9356
+ }
9357
+ const normalizedContext = normalizeEventContext(context);
9358
+ const emission = isObject3(normalizedContext.__signalEmission) ? normalizedContext.__signalEmission : {};
9359
+ const metadataObject = isObject3(normalizedContext.__metadata) ? normalizedContext.__metadata : {};
9360
+ const fullSignal = signal;
9361
+ const [baseSignalName, ...signalTagParts] = signal.split(":");
9362
+ const signalName = baseSignalName ?? signal;
9363
+ const signalTag = signalTagParts.length > 0 ? signalTagParts.join(":") : null;
9364
+ const eventTemplate = {
9365
+ type: "signal",
9366
+ signal: fullSignal,
9367
+ signalName,
9368
+ signalTag,
9369
+ emittedAt: asStringOrNull(emission.emittedAt),
9370
+ isMeta: emission.isMeta === true || signalName.startsWith("meta."),
9371
+ isSubMeta: normalizedContext.__isSubMeta === true || signalName.startsWith("sub_meta."),
9372
+ metadata: sanitizeForJson(metadata) ?? null,
9373
+ source: {
9374
+ taskName: asStringOrNull(emission.taskName),
9375
+ taskVersion: asNumberOrNull(emission.taskVersion),
9376
+ taskExecutionId: asStringOrNull(emission.taskExecutionId),
9377
+ routineName: asStringOrNull(normalizedContext.__routineName) ?? asStringOrNull(emission.routineName),
9378
+ routineVersion: asNumberOrNull(normalizedContext.__routineVersion) ?? asNumberOrNull(emission.routineVersion),
9379
+ routineExecutionId: asStringOrNull(normalizedContext.__routineExecId) ?? asStringOrNull(emission.routineExecutionId),
9380
+ executionTraceId: asStringOrNull(emission.executionTraceId) ?? asStringOrNull(normalizedContext.__executionTraceId) ?? asStringOrNull(metadataObject.__executionTraceId),
9381
+ consumed: emission.consumed === true,
9382
+ consumedBy: asStringOrNull(emission.consumedBy)
9383
+ },
9384
+ context: normalizedContext
9385
+ };
9386
+ for (const subscription of this.subscriptions.values()) {
9387
+ if (!matchesSignalPattern(
9388
+ fullSignal,
9389
+ signalName,
9390
+ subscription.descriptor.signalPatterns
9391
+ )) {
9392
+ continue;
9393
+ }
9394
+ const event = {
9395
+ id: (0, import_uuid8.v4)(),
9396
+ subscriptionId: subscription.descriptor.subscriptionId,
9397
+ sequence: ++this.nextSequence,
9398
+ ...eventTemplate
9399
+ };
9400
+ if (subscription.nextWaiter) {
9401
+ subscription.nextWaiter.resolve({
9402
+ subscriptionId: subscription.descriptor.subscriptionId,
9403
+ event,
9404
+ timedOut: false,
9405
+ pendingEvents: subscription.events.length
9406
+ });
9407
+ continue;
9408
+ }
9409
+ subscription.events.push(event);
9410
+ if (subscription.events.length > subscription.descriptor.maxQueueSize) {
9411
+ subscription.events.shift();
9412
+ }
9413
+ subscription.descriptor.pendingEvents = subscription.events.length;
9414
+ }
9415
+ }
9416
+ clearWaiter(subscription, error) {
9417
+ if (!subscription.nextWaiter) {
9418
+ return;
9419
+ }
9420
+ if (subscription.nextWaiter.timer) {
9421
+ clearTimeout(subscription.nextWaiter.timer);
9422
+ }
9423
+ subscription.nextWaiter.reject(error);
9424
+ subscription.nextWaiter = null;
9425
+ }
9426
+ requireSubscription(subscriptionId) {
9427
+ const subscription = this.subscriptions.get(subscriptionId);
9428
+ if (!subscription) {
9429
+ throw new RuntimeSubscriptionManagerError(
9430
+ "not_found",
9431
+ `No subscription named "${subscriptionId}" exists`
9432
+ );
9433
+ }
9434
+ return subscription;
9435
+ }
9436
+ };
9437
+
9438
+ // src/runtime/RuntimeHost.ts
9439
+ var SUPPORTED_OPERATIONS = [
9440
+ "runtime.bootstrap",
9441
+ "runtime.info",
9442
+ "runtime.detach",
9443
+ "runtime.shutdown",
9444
+ "runtime.reset",
9445
+ "runtime.snapshot",
9446
+ "runtime.subscribe",
9447
+ "runtime.unsubscribe",
9448
+ "runtime.nextEvent",
9449
+ "runtime.pollEvents",
9450
+ "task.upsert",
9451
+ "helper.upsert",
9452
+ "global.upsert",
9453
+ "task.link",
9454
+ "task.observeSignal",
9455
+ "task.emitSignal",
9456
+ "task.respondToIntent",
9457
+ "task.useHelper",
9458
+ "task.useGlobal",
9459
+ "helper.useHelper",
9460
+ "helper.useGlobal",
9461
+ "routine.upsert",
9462
+ "routine.observeSignal",
9463
+ "intent.upsert",
9464
+ "actor.upsert",
9465
+ "actorTask.upsert",
9466
+ "run",
9467
+ "emit",
9468
+ "inquire"
9469
+ ];
9470
+ var RuntimeProtocolException = class extends Error {
9471
+ constructor(code, message, details) {
9472
+ super(message);
9473
+ this.code = code;
9474
+ this.details = details;
9475
+ this.name = "RuntimeProtocolException";
9476
+ }
9477
+ };
9478
+ function isObject4(value) {
9479
+ return typeof value === "object" && value !== null && !Array.isArray(value);
9480
+ }
9481
+ function assertObject(value, message) {
9482
+ if (!isObject4(value)) {
9483
+ throw new RuntimeProtocolException("invalid_payload", message);
9484
+ }
9485
+ }
9486
+ function assertString(value, fieldName) {
9487
+ if (typeof value !== "string" || !value.trim()) {
9488
+ throw new RuntimeProtocolException(
9489
+ "invalid_payload",
9490
+ `${fieldName} must be a non-empty string`
9491
+ );
9492
+ }
9493
+ return value;
9494
+ }
9495
+ function assertStringArray(value, fieldName) {
9496
+ if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string")) {
9497
+ throw new RuntimeProtocolException(
9498
+ "invalid_payload",
9499
+ `${fieldName} must be an array of strings`
9500
+ );
9501
+ }
9502
+ return value;
9503
+ }
9504
+ function normalizeSignalDefinition2(signal) {
9505
+ if (typeof signal === "string") {
9506
+ return signal;
9507
+ }
9508
+ if (isObject4(signal) && typeof signal.name === "string" && signal.name.trim().length > 0) {
9509
+ return {
9510
+ name: signal.name,
9511
+ deliveryMode: signal.deliveryMode === "single" || signal.deliveryMode === "broadcast" ? signal.deliveryMode : void 0,
9512
+ broadcastFilter: signal.broadcastFilter && isObject4(signal.broadcastFilter) ? signal.broadcastFilter : null
9513
+ };
9514
+ }
9515
+ throw new RuntimeProtocolException(
9516
+ "invalid_payload",
9517
+ "signal must be a signal string or structured signal definition"
9518
+ );
9519
+ }
9520
+ var RuntimeHost = class {
9521
+ constructor(options = {}) {
9522
+ this.pendingControlAction = null;
9523
+ this.subscriptionManager = new RuntimeSubscriptionManager();
9524
+ this.runtimeSharing = options.runtimeSharing ?? "isolated";
9525
+ this.runtimeName = options.runtimeName ?? null;
9526
+ this.sessionId = options.sessionId ?? null;
9527
+ this.sessionRole = options.sessionRole ?? null;
9528
+ this.activeSessionCountProvider = options.activeSessionCountProvider ?? (() => 1);
9529
+ this.daemonProcessId = options.daemonProcessId ?? null;
9530
+ this.onResetRuntime = options.onResetRuntime ?? null;
9531
+ }
9532
+ dispose() {
9533
+ this.subscriptionManager.dispose();
9534
+ }
9535
+ resetSubscriptions() {
9536
+ this.subscriptionManager.reset();
9537
+ }
9538
+ consumeControlAction() {
9539
+ const action = this.pendingControlAction;
9540
+ this.pendingControlAction = null;
9541
+ return action;
9542
+ }
9543
+ handshake() {
9544
+ return {
9545
+ ready: true,
9546
+ protocol: "cadenza-runtime-jsonl",
9547
+ protocolVersion: "1",
9548
+ runtimeMode: "core",
9549
+ runtimeSharing: this.runtimeSharing,
9550
+ runtimeName: this.runtimeName,
9551
+ sessionId: this.sessionId,
9552
+ sessionRole: this.sessionRole,
9553
+ supportedOperations: [...SUPPORTED_OPERATIONS]
9554
+ };
9555
+ }
9556
+ async handle(request) {
9557
+ try {
9558
+ if (!request || typeof request !== "object") {
9559
+ throw new RuntimeProtocolException(
9560
+ "invalid_request",
9561
+ "Request must be an object"
9562
+ );
9563
+ }
9564
+ if (typeof request.operation !== "string" || !SUPPORTED_OPERATIONS.includes(
9565
+ request.operation
9566
+ )) {
9567
+ throw new RuntimeProtocolException(
9568
+ "unsupported_operation",
9569
+ `Unsupported operation: ${String(request.operation ?? "")}`
9570
+ );
9571
+ }
9572
+ const operation = request.operation;
9573
+ this.assertOperationAllowed(operation);
9574
+ const result = await this.dispatch(operation, request.payload);
9575
+ return {
9576
+ id: request.id,
9577
+ operation,
9578
+ ok: true,
9579
+ result: sanitizeForJson(result)
9580
+ };
9581
+ } catch (error) {
9582
+ const normalizedError = this.normalizeError(error);
9583
+ return {
9584
+ id: request?.id,
9585
+ operation: typeof request?.operation === "string" ? request.operation : "runtime.snapshot",
9586
+ ok: false,
9587
+ error: normalizedError
9588
+ };
9589
+ }
9590
+ }
9591
+ normalizeError(error) {
9592
+ if (error instanceof RuntimeSubscriptionManagerError) {
9593
+ return {
9594
+ code: error.code,
9595
+ message: error.message
9596
+ };
9597
+ }
9598
+ if (error instanceof RuntimeProtocolException) {
9599
+ return {
9600
+ code: error.code,
9601
+ message: error.message,
9602
+ details: error.details ? sanitizeForJson(error.details) : void 0
9603
+ };
9604
+ }
9605
+ if (error instanceof Error) {
9606
+ return {
9607
+ code: "runtime_error",
9608
+ message: error.message
9609
+ };
9610
+ }
9611
+ return {
9612
+ code: "runtime_error",
9613
+ message: String(error)
9614
+ };
9615
+ }
9616
+ async dispatch(operation, payload) {
9617
+ switch (operation) {
9618
+ case "runtime.bootstrap":
9619
+ return this.bootstrapRuntime(payload);
9620
+ case "runtime.info":
9621
+ return this.runtimeInfo();
9622
+ case "runtime.detach":
9623
+ return this.detachRuntime();
9624
+ case "runtime.shutdown":
9625
+ return this.shutdownRuntime();
9626
+ case "runtime.reset":
9627
+ return this.resetRuntime();
9628
+ case "runtime.snapshot":
9629
+ return Cadenza.snapshotRuntime();
9630
+ case "runtime.subscribe":
9631
+ return this.subscribe(payload);
9632
+ case "runtime.unsubscribe":
9633
+ return this.unsubscribe(payload);
9634
+ case "runtime.nextEvent":
9635
+ return this.nextEvent(payload);
9636
+ case "runtime.pollEvents":
9637
+ return this.pollEvents(payload);
9638
+ case "task.upsert":
9639
+ return this.upsertTask(payload);
9640
+ case "helper.upsert":
9641
+ return this.upsertHelper(payload);
9642
+ case "global.upsert":
9643
+ return this.upsertGlobal(payload);
9644
+ case "task.link":
9645
+ return this.linkTasks(payload);
9646
+ case "task.observeSignal":
9647
+ return this.observeTaskSignal(payload);
9648
+ case "task.emitSignal":
9649
+ return this.emitTaskSignal(payload);
9650
+ case "task.respondToIntent":
9651
+ return this.bindTaskIntent(payload);
9652
+ case "task.useHelper":
9653
+ return this.bindTaskHelper(payload);
9654
+ case "task.useGlobal":
9655
+ return this.bindTaskGlobal(payload);
9656
+ case "helper.useHelper":
9657
+ return this.bindHelperHelper(payload);
9658
+ case "helper.useGlobal":
9659
+ return this.bindHelperGlobal(payload);
9660
+ case "routine.upsert":
9661
+ return this.upsertRoutine(payload);
9662
+ case "routine.observeSignal":
9663
+ return this.observeRoutineSignal(payload);
9664
+ case "intent.upsert":
9665
+ return this.upsertIntent(payload);
9666
+ case "actor.upsert":
9667
+ return this.upsertActor(payload);
9668
+ case "actorTask.upsert":
9669
+ return this.upsertActorTask(payload);
9670
+ case "run":
9671
+ return this.runTarget(payload);
9672
+ case "emit":
9673
+ return this.emitSignal(payload);
9674
+ case "inquire":
9675
+ return this.inquireIntent(payload);
9676
+ }
9677
+ }
9678
+ assertOperationAllowed(operation) {
9679
+ if (!this.sessionRole) {
9680
+ return;
9681
+ }
9682
+ if (this.sessionRole === "owner") {
9683
+ return;
9684
+ }
9685
+ if (this.sessionRole === "writer") {
9686
+ if (operation === "runtime.reset" || operation === "runtime.shutdown") {
9687
+ throw new RuntimeProtocolException(
9688
+ "forbidden",
9689
+ `Session role "${this.sessionRole}" cannot perform ${operation}`
9690
+ );
9691
+ }
9692
+ return;
9693
+ }
9694
+ const observerOperations = /* @__PURE__ */ new Set([
9695
+ "runtime.info",
9696
+ "runtime.detach",
9697
+ "runtime.snapshot",
9698
+ "runtime.subscribe",
9699
+ "runtime.unsubscribe",
9700
+ "runtime.nextEvent",
9701
+ "runtime.pollEvents",
9702
+ "inquire"
9703
+ ]);
9704
+ if (!observerOperations.has(operation)) {
9705
+ throw new RuntimeProtocolException(
9706
+ "forbidden",
9707
+ `Session role "${this.sessionRole}" cannot perform ${operation}`
9708
+ );
9709
+ }
9710
+ }
9711
+ bootstrapRuntime(payload) {
9712
+ const mode = isObject4(payload) && typeof payload.mode === "string" ? payload.mode : void 0;
9713
+ if (mode) {
9714
+ Cadenza.setMode(mode);
9715
+ } else {
9716
+ Cadenza.bootstrap();
9717
+ }
9718
+ return {
9719
+ bootstrapped: true,
9720
+ mode: Cadenza.mode
9721
+ };
9722
+ }
9723
+ runtimeInfo() {
9724
+ return {
9725
+ runtimeMode: "core",
9726
+ runtimeSharing: this.runtimeSharing,
9727
+ runtimeName: this.runtimeName,
9728
+ sessionId: this.sessionId,
9729
+ sessionRole: this.sessionRole,
9730
+ activeSessionCount: this.activeSessionCountProvider(),
9731
+ daemonProcessId: this.daemonProcessId,
9732
+ bootstrapped: Cadenza.isBootstrapped,
9733
+ mode: Cadenza.mode
9734
+ };
9735
+ }
9736
+ detachRuntime() {
9737
+ this.pendingControlAction = "detach";
9738
+ return {
9739
+ detached: true,
9740
+ runtimeName: this.runtimeName,
9741
+ sessionId: this.sessionId
9742
+ };
9743
+ }
9744
+ shutdownRuntime() {
9745
+ this.pendingControlAction = "shutdown";
9746
+ return {
9747
+ shutdown: true,
9748
+ runtimeName: this.runtimeName
9749
+ };
9750
+ }
9751
+ resetRuntime() {
9752
+ if (this.onResetRuntime) {
9753
+ this.onResetRuntime();
9754
+ } else {
9755
+ Cadenza.reset();
9756
+ this.subscriptionManager.reset();
9757
+ }
9758
+ return {
9759
+ reset: true,
9760
+ bootstrapped: false
9761
+ };
9762
+ }
9763
+ subscribe(payload) {
9764
+ assertObject(payload, "runtime.subscribe payload must be an object");
9765
+ const signalPatterns = this.parseSignalPatterns(payload.signalPatterns);
9766
+ const maxQueueSize = this.parsePositiveInteger(
9767
+ payload.maxQueueSize,
9768
+ "maxQueueSize",
9769
+ 100
9770
+ );
9771
+ return {
9772
+ subscription: this.subscriptionManager.subscribe(signalPatterns, maxQueueSize)
9773
+ };
9774
+ }
9775
+ unsubscribe(payload) {
9776
+ assertObject(payload, "runtime.unsubscribe payload must be an object");
9777
+ const subscriptionId = assertString(payload.subscriptionId, "subscriptionId");
9778
+ return {
9779
+ unsubscribed: true,
9780
+ subscription: this.subscriptionManager.unsubscribe(subscriptionId)
9781
+ };
9782
+ }
9783
+ async nextEvent(payload) {
9784
+ assertObject(payload, "runtime.nextEvent payload must be an object");
9785
+ const subscriptionId = assertString(payload.subscriptionId, "subscriptionId");
9786
+ const timeoutMs = this.parseNonNegativeInteger(
9787
+ payload.timeoutMs,
9788
+ "timeoutMs",
9789
+ 0
9790
+ );
9791
+ return this.subscriptionManager.nextEvent(subscriptionId, timeoutMs);
9792
+ }
9793
+ pollEvents(payload) {
9794
+ assertObject(payload, "runtime.pollEvents payload must be an object");
9795
+ const subscriptionId = assertString(payload.subscriptionId, "subscriptionId");
9796
+ const limit = this.parsePositiveInteger(payload.limit, "limit", 50);
9797
+ return this.subscriptionManager.pollEvents(subscriptionId, limit);
9798
+ }
9799
+ upsertTask(payload) {
9800
+ assertObject(payload, "task.upsert payload must be an object");
9801
+ const definition = payload;
9802
+ definition.name = assertString(definition.name, "name");
9803
+ definition.handlerSource = assertString(
9804
+ definition.handlerSource,
9805
+ "handlerSource"
9806
+ );
9807
+ definition.language = definition.language === "js" || definition.language === "ts" ? definition.language : (() => {
9808
+ throw new RuntimeProtocolException(
9809
+ "invalid_payload",
9810
+ "language must be 'js' or 'ts'"
9811
+ );
9812
+ })();
9813
+ definition.kind = definition.kind === "metaTask" ? "metaTask" : "task";
9814
+ runtimeDefinitionRegistry.setTaskDefinition(definition);
9815
+ const task = Cadenza.createTaskFromDefinition(definition);
9816
+ this.applyTaskDecorations(definition.name);
9817
+ this.applyAllTaskLinks();
9818
+ this.rematerializeRoutinesStartingWith(definition.name);
9819
+ return {
9820
+ task: this.snapshotTask(task)
9821
+ };
9822
+ }
9823
+ upsertHelper(payload) {
9824
+ assertObject(payload, "helper.upsert payload must be an object");
9825
+ const definition = payload;
9826
+ definition.name = assertString(definition.name, "name");
9827
+ definition.handlerSource = assertString(
9828
+ definition.handlerSource,
9829
+ "handlerSource"
9830
+ );
9831
+ definition.language = definition.language === "js" || definition.language === "ts" ? definition.language : (() => {
9832
+ throw new RuntimeProtocolException(
9833
+ "invalid_payload",
9834
+ "language must be 'js' or 'ts'"
9835
+ );
9836
+ })();
9837
+ definition.kind = definition.kind === "metaHelper" ? "metaHelper" : "helper";
9838
+ runtimeDefinitionRegistry.setHelperDefinition(definition);
9839
+ compileRuntimeHelperFunction(definition);
9840
+ Cadenza.createHelperFromDefinition(definition);
9841
+ this.applyHelperDecorations(definition.name);
9842
+ return {
9843
+ helper: this.snapshotHelper(definition.name)
9844
+ };
9845
+ }
9846
+ upsertGlobal(payload) {
9847
+ assertObject(payload, "global.upsert payload must be an object");
9848
+ const definition = {
9849
+ name: assertString(payload.name, "name"),
9850
+ description: typeof payload.description === "string" ? payload.description : "",
9851
+ kind: payload.kind === "metaGlobal" ? "metaGlobal" : "global",
9852
+ value: payload.value
9853
+ };
9854
+ runtimeDefinitionRegistry.setGlobalDefinition(definition);
9855
+ Cadenza.createGlobalFromDefinition(definition);
9856
+ return {
9857
+ global: this.snapshotGlobal(definition.name)
9858
+ };
9859
+ }
9860
+ linkTasks(payload) {
9861
+ assertObject(payload, "task.link payload must be an object");
9862
+ const definition = {
9863
+ predecessorTaskName: assertString(
9864
+ payload.predecessorTaskName,
9865
+ "predecessorTaskName"
9866
+ ),
9867
+ successorTaskName: assertString(
9868
+ payload.successorTaskName,
9869
+ "successorTaskName"
9870
+ )
9871
+ };
9872
+ runtimeDefinitionRegistry.setTaskLink(definition);
9873
+ this.applyAllTaskLinks();
9874
+ return {
9875
+ linked: true,
9876
+ ...definition
9877
+ };
9878
+ }
9879
+ observeTaskSignal(payload) {
9880
+ assertObject(payload, "task.observeSignal payload must be an object");
9881
+ const definition = {
9882
+ taskName: assertString(payload.taskName, "taskName"),
9883
+ signal: normalizeSignalDefinition2(payload.signal)
9884
+ };
9885
+ runtimeDefinitionRegistry.setTaskSignalObservation(definition);
9886
+ this.requireTask(definition.taskName).doOn(definition.signal);
9887
+ return {
9888
+ observed: true,
9889
+ taskName: definition.taskName,
9890
+ signal: typeof definition.signal === "string" ? definition.signal : definition.signal.name
9891
+ };
9892
+ }
9893
+ emitTaskSignal(payload) {
9894
+ assertObject(payload, "task.emitSignal payload must be an object");
9895
+ const mode = payload.mode === "attach" || payload.mode === "onFail" ? payload.mode : "after";
9896
+ const definition = {
9897
+ taskName: assertString(payload.taskName, "taskName"),
9898
+ signal: normalizeSignalDefinition2(payload.signal),
9899
+ mode
9900
+ };
9901
+ runtimeDefinitionRegistry.setTaskSignalEmission(definition);
9902
+ const task = this.requireTask(definition.taskName);
9903
+ if (definition.mode === "attach") {
9904
+ task.attachSignal(definition.signal);
9905
+ } else if (definition.mode === "onFail") {
9906
+ task.emitsOnFail(definition.signal);
9907
+ } else {
9908
+ task.emits(definition.signal);
9909
+ }
9910
+ return {
9911
+ attached: true,
9912
+ taskName: definition.taskName,
9913
+ mode: definition.mode,
9914
+ signal: typeof definition.signal === "string" ? definition.signal : definition.signal.name
9915
+ };
9916
+ }
9917
+ bindTaskIntent(payload) {
9918
+ assertObject(payload, "task.respondToIntent payload must be an object");
9919
+ const taskName = assertString(payload.taskName, "taskName");
9920
+ const intentName = assertString(payload.intentName, "intentName");
9921
+ runtimeDefinitionRegistry.setTaskIntentBinding({
9922
+ taskName,
9923
+ intentName
9924
+ });
9925
+ this.requireTask(taskName).respondsTo(intentName);
9926
+ return {
9927
+ bound: true,
9928
+ taskName,
9929
+ intentName
9930
+ };
9931
+ }
9932
+ bindTaskHelper(payload) {
9933
+ assertObject(payload, "task.useHelper payload must be an object");
9934
+ const definition = {
9935
+ taskName: assertString(payload.taskName, "taskName"),
9936
+ alias: assertString(payload.alias, "alias"),
9937
+ helperName: assertString(payload.helperName, "helperName")
9938
+ };
9939
+ runtimeDefinitionRegistry.setTaskHelperBinding(definition);
9940
+ this.requireTask(definition.taskName).usesHelpers({
9941
+ [definition.alias]: Cadenza.getHelper(definition.helperName)
9942
+ });
9943
+ return {
9944
+ bound: true,
9945
+ ...definition
9946
+ };
9947
+ }
9948
+ bindTaskGlobal(payload) {
9949
+ assertObject(payload, "task.useGlobal payload must be an object");
9950
+ const definition = {
9951
+ taskName: assertString(payload.taskName, "taskName"),
9952
+ alias: assertString(payload.alias, "alias"),
9953
+ globalName: assertString(payload.globalName, "globalName")
9954
+ };
9955
+ runtimeDefinitionRegistry.setTaskGlobalBinding(definition);
9956
+ this.requireTask(definition.taskName).usesGlobals({
9957
+ [definition.alias]: Cadenza.getGlobal(definition.globalName)
9958
+ });
9959
+ return {
9960
+ bound: true,
9961
+ ...definition
9962
+ };
9963
+ }
9964
+ bindHelperHelper(payload) {
9965
+ assertObject(payload, "helper.useHelper payload must be an object");
9966
+ const definition = {
9967
+ helperName: assertString(payload.helperName, "helperName"),
9968
+ alias: assertString(payload.alias, "alias"),
9969
+ dependencyHelperName: assertString(
9970
+ payload.dependencyHelperName,
9971
+ "dependencyHelperName"
9972
+ )
9973
+ };
9974
+ runtimeDefinitionRegistry.setHelperHelperBinding(definition);
9975
+ const helper = Cadenza.getHelper(definition.helperName);
9976
+ if (!helper) {
9977
+ throw new RuntimeProtocolException(
9978
+ "not_found",
9979
+ `No helper named "${definition.helperName}" exists`
9980
+ );
9981
+ }
9982
+ helper.usesHelpers({
9983
+ [definition.alias]: Cadenza.getHelper(definition.dependencyHelperName)
9984
+ });
9985
+ return {
9986
+ bound: true,
9987
+ ...definition
9988
+ };
9989
+ }
9990
+ bindHelperGlobal(payload) {
9991
+ assertObject(payload, "helper.useGlobal payload must be an object");
9992
+ const definition = {
9993
+ helperName: assertString(payload.helperName, "helperName"),
9994
+ alias: assertString(payload.alias, "alias"),
9995
+ globalName: assertString(payload.globalName, "globalName")
9996
+ };
9997
+ runtimeDefinitionRegistry.setHelperGlobalBinding(definition);
9998
+ const helper = Cadenza.getHelper(definition.helperName);
9999
+ if (!helper) {
10000
+ throw new RuntimeProtocolException(
10001
+ "not_found",
10002
+ `No helper named "${definition.helperName}" exists`
10003
+ );
10004
+ }
10005
+ helper.usesGlobals({
10006
+ [definition.alias]: Cadenza.getGlobal(definition.globalName)
10007
+ });
10008
+ return {
10009
+ bound: true,
10010
+ ...definition
10011
+ };
10012
+ }
10013
+ upsertRoutine(payload) {
10014
+ assertObject(payload, "routine.upsert payload must be an object");
10015
+ const definition = {
10016
+ name: assertString(payload.name, "name"),
10017
+ description: typeof payload.description === "string" ? payload.description : "",
10018
+ startTaskNames: assertStringArray(payload.startTaskNames, "startTaskNames"),
10019
+ isMeta: payload.isMeta === true
10020
+ };
10021
+ if (definition.startTaskNames.length === 0) {
10022
+ throw new RuntimeProtocolException(
10023
+ "invalid_payload",
10024
+ "startTaskNames must contain at least one task name"
10025
+ );
10026
+ }
10027
+ runtimeDefinitionRegistry.setRoutineDefinition(definition);
10028
+ const routine = Cadenza.createRoutineFromDefinition(definition);
10029
+ this.applyRoutineDecorations(definition.name);
10030
+ return {
10031
+ routine: this.snapshotRoutine(routine)
10032
+ };
10033
+ }
10034
+ observeRoutineSignal(payload) {
10035
+ assertObject(payload, "routine.observeSignal payload must be an object");
10036
+ const routineName = assertString(payload.routineName, "routineName");
10037
+ const signal = assertString(payload.signal, "signal");
10038
+ runtimeDefinitionRegistry.setRoutineSignalObservation({
10039
+ routineName,
10040
+ signal
10041
+ });
10042
+ this.requireRoutine(routineName).doOn(signal);
10043
+ return {
10044
+ observed: true,
10045
+ routineName,
10046
+ signal
10047
+ };
10048
+ }
10049
+ upsertIntent(payload) {
10050
+ assertObject(payload, "intent.upsert payload must be an object");
10051
+ const intent = {
10052
+ name: assertString(payload.name, "name"),
10053
+ description: typeof payload.description === "string" ? payload.description : "",
10054
+ input: isObject4(payload.input) ? payload.input : { type: "object" },
10055
+ output: isObject4(payload.output) ? payload.output : { type: "object" }
10056
+ };
10057
+ runtimeDefinitionRegistry.setIntentDefinition(intent);
10058
+ Cadenza.defineIntent(intent);
10059
+ return {
10060
+ intent: sanitizeForJson(intent)
10061
+ };
10062
+ }
10063
+ upsertActor(payload) {
10064
+ assertObject(payload, "actor.upsert payload must be an object");
10065
+ const definition = payload;
10066
+ definition.name = assertString(definition.name, "name");
10067
+ definition.description = assertString(definition.description, "description");
10068
+ definition.defaultKey = assertString(definition.defaultKey, "defaultKey");
10069
+ runtimeDefinitionRegistry.setActorDefinition(definition);
10070
+ const actor = Cadenza.createActorFromDefinition(definition);
10071
+ this.rematerializeActorTasksFor(definition.name);
10072
+ return {
10073
+ actor: sanitizeForJson({
10074
+ name: actor.spec.name,
10075
+ description: actor.spec.description ?? "",
10076
+ defaultKey: actor.spec.defaultKey
10077
+ })
10078
+ };
10079
+ }
10080
+ upsertActorTask(payload) {
10081
+ assertObject(payload, "actorTask.upsert payload must be an object");
10082
+ const definition = {
10083
+ actorName: assertString(payload.actorName, "actorName"),
10084
+ taskName: assertString(payload.taskName, "taskName"),
10085
+ description: typeof payload.description === "string" ? payload.description : "",
10086
+ mode: payload.mode === "write" || payload.mode === "meta" ? payload.mode : "read",
10087
+ handlerSource: assertString(payload.handlerSource, "handlerSource"),
10088
+ language: payload.language === "js" || payload.language === "ts" ? payload.language : (() => {
10089
+ throw new RuntimeProtocolException(
10090
+ "invalid_payload",
10091
+ "language must be 'js' or 'ts'"
10092
+ );
10093
+ })(),
10094
+ options: isObject4(payload.options) ? { ...payload.options } : void 0
10095
+ };
10096
+ runtimeDefinitionRegistry.setActorTaskDefinition(definition);
10097
+ const task = this.materializeActorTask(definition.taskName);
10098
+ this.applyTaskDecorations(definition.taskName);
10099
+ this.applyAllTaskLinks();
10100
+ this.rematerializeRoutinesStartingWith(definition.taskName);
10101
+ return {
10102
+ actorTask: this.snapshotTask(task)
10103
+ };
10104
+ }
10105
+ async runTarget(payload) {
10106
+ assertObject(payload, "run payload must be an object");
10107
+ const targetName = assertString(payload.targetName, "targetName");
10108
+ const context = isObject4(payload.context) ? payload.context : {};
10109
+ let target = Cadenza.getRoutine(targetName);
10110
+ if (!target) {
10111
+ const routineDefinition = runtimeDefinitionRegistry.routineDefinitions.get(targetName);
10112
+ if (routineDefinition) {
10113
+ target = Cadenza.createRoutineFromDefinition(routineDefinition);
10114
+ this.applyRoutineDecorations(targetName);
10115
+ }
10116
+ }
10117
+ target = target ?? Cadenza.get(targetName);
10118
+ if (!target) {
10119
+ throw new RuntimeProtocolException(
10120
+ "not_found",
10121
+ `No task or routine named "${targetName}" exists`
10122
+ );
10123
+ }
10124
+ const runner = "isMeta" in target && target.isMeta ? Cadenza.metaRunner : Cadenza.runner;
10125
+ const runResult = runner.run(target, context);
10126
+ const completedRun = await Promise.resolve(runResult);
10127
+ return {
10128
+ targetName,
10129
+ run: completedRun.export()
10130
+ };
10131
+ }
10132
+ emitSignal(payload) {
10133
+ assertObject(payload, "emit payload must be an object");
10134
+ const signal = assertString(payload.signal, "signal");
10135
+ const context = isObject4(payload.context) ? payload.context : {};
10136
+ const options = isObject4(payload.options) ? payload.options : {};
10137
+ Cadenza.emit(signal, context, options);
10138
+ return {
10139
+ emitted: true,
10140
+ signal
10141
+ };
10142
+ }
10143
+ async inquireIntent(payload) {
10144
+ assertObject(payload, "inquire payload must be an object");
10145
+ const inquiry = assertString(payload.intent, "intent");
10146
+ const context = isObject4(payload.context) ? payload.context : {};
10147
+ const options = isObject4(payload.options) ? payload.options : {};
10148
+ const response = await Cadenza.inquire(inquiry, context, options);
10149
+ return {
10150
+ inquiry,
10151
+ response
10152
+ };
10153
+ }
10154
+ requireTask(taskName) {
10155
+ const task = Cadenza.get(taskName);
10156
+ if (!task) {
10157
+ throw new RuntimeProtocolException(
10158
+ "not_found",
10159
+ `No task named "${taskName}" exists`
10160
+ );
10161
+ }
10162
+ return task;
10163
+ }
10164
+ requireRoutine(routineName) {
10165
+ const routine = Cadenza.getRoutine(routineName);
10166
+ if (!routine) {
10167
+ throw new RuntimeProtocolException(
10168
+ "not_found",
10169
+ `No routine named "${routineName}" exists`
10170
+ );
10171
+ }
10172
+ return routine;
10173
+ }
10174
+ applyTaskDecorations(taskName) {
10175
+ const task = this.requireTask(taskName);
10176
+ for (const observation of runtimeDefinitionRegistry.taskSignalObservations.values()) {
10177
+ if (observation.taskName !== taskName) {
10178
+ continue;
10179
+ }
10180
+ task.doOn(observation.signal);
10181
+ }
10182
+ for (const emission of runtimeDefinitionRegistry.taskSignalEmissions.values()) {
10183
+ if (emission.taskName !== taskName) {
10184
+ continue;
10185
+ }
10186
+ if (emission.mode === "attach") {
10187
+ task.attachSignal(emission.signal);
10188
+ } else if (emission.mode === "onFail") {
10189
+ task.emitsOnFail(emission.signal);
10190
+ } else {
10191
+ task.emits(emission.signal);
10192
+ }
10193
+ }
10194
+ for (const binding of runtimeDefinitionRegistry.taskIntentBindings.values()) {
10195
+ if (binding.taskName !== taskName) {
10196
+ continue;
10197
+ }
10198
+ task.respondsTo(binding.intentName);
10199
+ }
10200
+ for (const binding of runtimeDefinitionRegistry.taskHelperBindings.values()) {
10201
+ if (binding.taskName !== taskName) {
10202
+ continue;
10203
+ }
10204
+ task.usesHelpers({
10205
+ [binding.alias]: Cadenza.getHelper(binding.helperName)
10206
+ });
10207
+ }
10208
+ for (const binding of runtimeDefinitionRegistry.taskGlobalBindings.values()) {
10209
+ if (binding.taskName !== taskName) {
10210
+ continue;
10211
+ }
10212
+ task.usesGlobals({
10213
+ [binding.alias]: Cadenza.getGlobal(binding.globalName)
10214
+ });
10215
+ }
10216
+ }
10217
+ applyHelperDecorations(helperName) {
10218
+ const helper = Cadenza.getHelper(helperName);
10219
+ if (!helper) {
10220
+ throw new RuntimeProtocolException(
10221
+ "not_found",
10222
+ `No helper named "${helperName}" exists`
10223
+ );
10224
+ }
10225
+ for (const binding of runtimeDefinitionRegistry.helperHelperBindings.values()) {
10226
+ if (binding.helperName !== helperName) {
10227
+ continue;
10228
+ }
10229
+ helper.usesHelpers({
10230
+ [binding.alias]: Cadenza.getHelper(binding.dependencyHelperName)
10231
+ });
10232
+ }
10233
+ for (const binding of runtimeDefinitionRegistry.helperGlobalBindings.values()) {
10234
+ if (binding.helperName !== helperName) {
10235
+ continue;
10236
+ }
10237
+ helper.usesGlobals({
10238
+ [binding.alias]: Cadenza.getGlobal(binding.globalName)
10239
+ });
10240
+ }
10241
+ }
10242
+ applyAllTaskLinks() {
10243
+ for (const link of runtimeDefinitionRegistry.taskLinks.values()) {
10244
+ const predecessor = Cadenza.get(link.predecessorTaskName);
10245
+ const successor = Cadenza.get(link.successorTaskName);
10246
+ if (!predecessor || !successor) {
10247
+ continue;
10248
+ }
10249
+ predecessor.then(successor);
10250
+ }
10251
+ }
10252
+ applyRoutineDecorations(routineName) {
10253
+ const routine = this.requireRoutine(routineName);
10254
+ for (const observation of runtimeDefinitionRegistry.routineSignalObservations.values()) {
10255
+ if (observation.routineName !== routineName) {
10256
+ continue;
10257
+ }
10258
+ routine.doOn(observation.signal);
10259
+ }
10260
+ }
10261
+ rematerializeRoutinesStartingWith(taskName) {
10262
+ for (const definition of runtimeDefinitionRegistry.routineDefinitions.values()) {
10263
+ if (!definition.startTaskNames.includes(taskName)) {
10264
+ continue;
10265
+ }
10266
+ const recreated = Cadenza.createRoutineFromDefinition(definition);
10267
+ this.applyRoutineDecorations(recreated.name);
10268
+ }
10269
+ }
10270
+ rematerializeActorTasksFor(actorName) {
10271
+ for (const definition of runtimeDefinitionRegistry.actorTaskDefinitions.values()) {
10272
+ if (definition.actorName !== actorName) {
10273
+ continue;
10274
+ }
10275
+ this.materializeActorTask(definition.taskName);
10276
+ this.applyTaskDecorations(definition.taskName);
10277
+ this.applyAllTaskLinks();
10278
+ this.rematerializeRoutinesStartingWith(definition.taskName);
10279
+ }
10280
+ }
10281
+ materializeActorTask(taskName) {
10282
+ const definition = runtimeDefinitionRegistry.actorTaskDefinitions.get(taskName);
10283
+ if (!definition) {
10284
+ throw new RuntimeProtocolException(
10285
+ "not_found",
10286
+ `No actor task definition named "${taskName}" exists`
10287
+ );
10288
+ }
10289
+ const actor = Cadenza.getActor(definition.actorName);
10290
+ if (!actor) {
10291
+ throw new RuntimeProtocolException(
10292
+ "not_found",
10293
+ `No actor named "${definition.actorName}" exists`
10294
+ );
10295
+ }
10296
+ const existingTask = Cadenza.get(definition.taskName);
10297
+ if (existingTask && !runtimeDefinitionRegistry.isRuntimeOwnedTask(existingTask.name)) {
10298
+ throw new RuntimeProtocolException(
10299
+ "conflict",
10300
+ `Task "${definition.taskName}" already exists and is not runtime-owned`
10301
+ );
10302
+ }
10303
+ existingTask?.destroy();
10304
+ const handler = compileRuntimeActorTaskHandler(definition);
10305
+ return Cadenza.createTask(
10306
+ definition.taskName,
10307
+ actor.task(handler, { mode: definition.mode }),
10308
+ definition.description ?? "",
10309
+ definition.options ?? {}
10310
+ );
10311
+ }
10312
+ snapshotTask(task) {
10313
+ const snapshot = Cadenza.snapshotRuntime();
10314
+ const existing = snapshot.tasks.find((entry) => entry.name === task.name);
10315
+ if (existing) {
10316
+ return existing;
10317
+ }
10318
+ const runtimeTaskDefinition = runtimeDefinitionRegistry.taskDefinitions.get(
10319
+ task.name
10320
+ );
10321
+ const runtimeActorTaskDefinition = runtimeDefinitionRegistry.actorTaskDefinitions.get(task.name);
10322
+ return {
10323
+ name: task.name,
10324
+ version: task.version,
10325
+ description: task.description,
10326
+ kind: runtimeActorTaskDefinition ? "actorTask" : task.isMeta ? "metaTask" : "task",
10327
+ runtimeOwned: runtimeDefinitionRegistry.isRuntimeOwnedTask(task.name),
10328
+ language: runtimeTaskDefinition?.language ?? runtimeActorTaskDefinition?.language ?? null,
10329
+ handlerSource: runtimeTaskDefinition?.handlerSource ?? runtimeActorTaskDefinition?.handlerSource ?? null,
10330
+ tools: {
10331
+ helpers: Object.fromEntries(task.helperAliases),
10332
+ globals: Object.fromEntries(task.globalAliases)
10333
+ }
10334
+ };
10335
+ }
10336
+ snapshotHelper(helperName) {
10337
+ const snapshot = Cadenza.snapshotRuntime();
10338
+ return snapshot.helpers.find((entry) => entry.name === helperName) ?? {
10339
+ name: helperName
10340
+ };
10341
+ }
10342
+ snapshotGlobal(globalName) {
10343
+ const snapshot = Cadenza.snapshotRuntime();
10344
+ return snapshot.globals.find((entry) => entry.name === globalName) ?? {
10345
+ name: globalName
10346
+ };
10347
+ }
10348
+ snapshotRoutine(routine) {
10349
+ const snapshot = Cadenza.snapshotRuntime();
10350
+ return snapshot.routines.find((entry) => entry.name === routine.name) ?? {
10351
+ name: routine.name,
10352
+ version: routine.version,
10353
+ description: routine.description,
10354
+ isMeta: routine.isMeta,
10355
+ runtimeOwned: runtimeDefinitionRegistry.isRuntimeOwnedRoutine(
10356
+ routine.name
10357
+ ),
10358
+ startTaskNames: Array.from(routine.tasks).map((task) => task.name),
10359
+ observedSignals: Array.from(routine.observedSignals)
10360
+ };
10361
+ }
10362
+ parseSignalPatterns(value) {
10363
+ if (value === void 0) {
10364
+ return ["*"];
10365
+ }
10366
+ if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string" || entry.trim().length === 0)) {
10367
+ throw new RuntimeProtocolException(
10368
+ "invalid_payload",
10369
+ "signalPatterns must be an array of non-empty strings"
10370
+ );
10371
+ }
10372
+ return Array.from(new Set(value.map((entry) => entry.trim())));
10373
+ }
10374
+ parsePositiveInteger(value, fieldName, fallback) {
10375
+ if (value === void 0) {
10376
+ return fallback;
10377
+ }
10378
+ if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) {
10379
+ throw new RuntimeProtocolException(
10380
+ "invalid_payload",
10381
+ `${fieldName} must be a positive integer`
10382
+ );
10383
+ }
10384
+ return value;
10385
+ }
10386
+ parseNonNegativeInteger(value, fieldName, fallback) {
10387
+ if (value === void 0) {
10388
+ return fallback;
10389
+ }
10390
+ if (typeof value !== "number" || !Number.isInteger(value) || value < 0) {
10391
+ throw new RuntimeProtocolException(
10392
+ "invalid_payload",
10393
+ `${fieldName} must be a non-negative integer`
10394
+ );
10395
+ }
10396
+ return value;
10397
+ }
10398
+ };
10399
+
8002
10400
  // src/index.ts
8003
10401
  var index_default = Cadenza;
8004
10402
  // Annotate the CommonJS export names for ESM import in node:
@@ -8006,13 +10404,16 @@ var index_default = Cadenza;
8006
10404
  Actor,
8007
10405
  DebounceTask,
8008
10406
  EphemeralTask,
10407
+ GlobalDefinition,
8009
10408
  GraphContext,
8010
10409
  GraphRegistry,
8011
10410
  GraphRoutine,
8012
10411
  GraphRun,
8013
10412
  GraphRunner,
10413
+ HelperDefinition,
8014
10414
  InquiryBroker,
8015
10415
  META_ACTOR_SESSION_STATE_PERSIST_INTENT,
10416
+ RuntimeHost,
8016
10417
  SignalBroker,
8017
10418
  SignalEmitter,
8018
10419
  Task,