@codemation/core 1.0.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/CHANGELOG.md +293 -0
  2. package/dist/{EngineRuntimeRegistration.types-kxQA5NLt.d.ts → EngineRuntimeRegistration.types-D1fyApMI.d.ts} +2 -2
  3. package/dist/{EngineWorkflowRunnerService-Ba2AvBnL.d.cts → EngineRuntimeRegistration.types-pB3FnzqR.d.cts} +17 -17
  4. package/dist/{InMemoryRunDataFactory-Ou4tQUOS.d.cts → InMemoryRunDataFactory-Xw7v4-sj.d.cts} +31 -29
  5. package/dist/InMemoryRunEventBusRegistry-VM3OWnHo.cjs +47 -0
  6. package/dist/InMemoryRunEventBusRegistry-VM3OWnHo.cjs.map +1 -0
  7. package/dist/InMemoryRunEventBusRegistry-sM4z4n_i.js +41 -0
  8. package/dist/InMemoryRunEventBusRegistry-sM4z4n_i.js.map +1 -0
  9. package/dist/{RunIntentService-dteLjNiT.d.ts → RunIntentService-BE9CAkbf.d.ts} +602 -213
  10. package/dist/{RunIntentService-Dyh_dH0k.d.cts → RunIntentService-siBSjaaY.d.cts} +430 -125
  11. package/dist/bootstrap/index.cjs +5 -2
  12. package/dist/bootstrap/index.d.cts +212 -135
  13. package/dist/bootstrap/index.d.ts +4 -4
  14. package/dist/bootstrap/index.js +3 -3
  15. package/dist/{bootstrap-Cko6udwL.cjs → bootstrap-Cm5ruQxx.cjs} +253 -3
  16. package/dist/bootstrap-Cm5ruQxx.cjs.map +1 -0
  17. package/dist/{bootstrap-CL68rqWg.js → bootstrap-D3r505ko.js} +236 -4
  18. package/dist/bootstrap-D3r505ko.js.map +1 -0
  19. package/dist/{index-CyfGTfU1.d.ts → index-DeLl1Tne.d.ts} +574 -242
  20. package/dist/index.cjs +328 -180
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +441 -103
  23. package/dist/index.d.ts +3 -3
  24. package/dist/index.js +305 -163
  25. package/dist/index.js.map +1 -1
  26. package/dist/{runtime-284ok0cm.js → runtime-BGNbRnqs.js} +764 -75
  27. package/dist/runtime-BGNbRnqs.js.map +1 -0
  28. package/dist/{runtime-B3Og-_St.cjs → runtime-DKXJwTNv.cjs} +841 -80
  29. package/dist/runtime-DKXJwTNv.cjs.map +1 -0
  30. package/dist/testing.cjs +4 -4
  31. package/dist/testing.cjs.map +1 -1
  32. package/dist/testing.d.cts +2 -2
  33. package/dist/testing.d.ts +2 -2
  34. package/dist/testing.js +3 -3
  35. package/package.json +7 -2
  36. package/src/authoring/DefinedCollectionRegistry.ts +17 -0
  37. package/src/authoring/defineCollection.types.ts +181 -0
  38. package/src/authoring/definePollingTrigger.types.ts +396 -0
  39. package/src/authoring/definePollingTriggerInternals.ts +74 -0
  40. package/src/authoring/index.ts +19 -0
  41. package/src/bootstrap/index.ts +9 -0
  42. package/src/bootstrap/runtime/EngineRuntimeRegistrar.ts +5 -1
  43. package/src/contracts/assertionTypes.ts +63 -0
  44. package/src/contracts/baseTypes.ts +12 -0
  45. package/src/contracts/collectionTypes.ts +44 -0
  46. package/src/contracts/credentialTypes.ts +23 -1
  47. package/src/contracts/index.ts +4 -0
  48. package/src/contracts/runTypes.ts +27 -1
  49. package/src/contracts/runtimeTypes.ts +34 -0
  50. package/src/contracts/testTriggerTypes.ts +66 -0
  51. package/src/contracts/workflowTypes.ts +30 -7
  52. package/src/contracts.ts +59 -0
  53. package/src/events/runEvents.ts +49 -0
  54. package/src/execution/ChildExecutionScopeFactory.ts +4 -7
  55. package/src/execution/DefaultExecutionContextFactory.ts +6 -0
  56. package/src/execution/NodeInstanceFactory.ts +13 -1
  57. package/src/execution/NodeInstantiationError.ts +16 -0
  58. package/src/execution/WorkflowRunExecutionContextFactory.ts +3 -0
  59. package/src/execution/index.ts +1 -0
  60. package/src/index.ts +7 -0
  61. package/src/orchestration/AbortControllerFactory.ts +9 -0
  62. package/src/orchestration/NodeExecutionRequestHandlerService.ts +1 -0
  63. package/src/orchestration/RunContinuationService.ts +3 -0
  64. package/src/orchestration/RunStartService.ts +114 -2
  65. package/src/orchestration/TestSuiteOrchestrator.ts +350 -0
  66. package/src/orchestration/TestSuiteRunIdFactory.ts +11 -0
  67. package/src/orchestration/TriggerRuntimeService.ts +34 -7
  68. package/src/orchestration/index.ts +9 -0
  69. package/src/runtime/EngineFactory.ts +11 -0
  70. package/src/triggers/polling/PollingTriggerDedupWindow.ts +23 -0
  71. package/src/triggers/polling/PollingTriggerLogger.ts +18 -0
  72. package/src/triggers/polling/PollingTriggerRuntime.ts +122 -0
  73. package/src/triggers/polling/index.ts +5 -0
  74. package/src/types/index.ts +12 -9
  75. package/src/workflow/dsl/NodeIdSlugifier.ts +18 -0
  76. package/src/workflow/dsl/WorkflowBuilder.ts +71 -3
  77. package/src/workflow/dsl/WorkflowDefinitionError.ts +15 -0
  78. package/src/workflow/index.ts +2 -0
  79. package/dist/InMemoryRunEventBusRegistry-B0_C4OnP.cjs +0 -262
  80. package/dist/InMemoryRunEventBusRegistry-B0_C4OnP.cjs.map +0 -1
  81. package/dist/InMemoryRunEventBusRegistry-C2U83Hmv.js +0 -238
  82. package/dist/InMemoryRunEventBusRegistry-C2U83Hmv.js.map +0 -1
  83. package/dist/bootstrap-CL68rqWg.js.map +0 -1
  84. package/dist/bootstrap-Cko6udwL.cjs.map +0 -1
  85. package/dist/runtime-284ok0cm.js.map +0 -1
  86. package/dist/runtime-B3Og-_St.cjs.map +0 -1
@@ -164,6 +164,56 @@ function chatModel(options = {}) {
164
164
  return InjectableRuntimeDecoratorComposer.compose("chatModel", options, require("url").pathToFileURL(__filename).href);
165
165
  }
166
166
 
167
+ //#endregion
168
+ //#region src/ai/NodeBackedToolConfig.ts
169
+ var NodeBackedToolConfig = class {
170
+ type;
171
+ toolKind = "nodeBacked";
172
+ description;
173
+ presentation;
174
+ inputSchemaValue;
175
+ outputSchemaValue;
176
+ mapInputValue;
177
+ mapOutputValue;
178
+ constructor(name, node$1, options) {
179
+ this.name = name;
180
+ this.node = node$1;
181
+ this.type = node$1.type;
182
+ this.description = options.description;
183
+ this.presentation = options.presentation;
184
+ this.inputSchemaValue = options.inputSchema;
185
+ this.outputSchemaValue = options.outputSchema;
186
+ this.mapInputValue = options.mapInput;
187
+ this.mapOutputValue = options.mapOutput;
188
+ }
189
+ getCredentialRequirements() {
190
+ return this.node.getCredentialRequirements?.() ?? [];
191
+ }
192
+ getInputSchema() {
193
+ return this.inputSchemaValue;
194
+ }
195
+ getOutputSchema() {
196
+ return this.outputSchemaValue;
197
+ }
198
+ toNodeItem(args) {
199
+ const mapped = this.mapInputValue?.(args) ?? args.input;
200
+ if (this.isItem(mapped)) return mapped;
201
+ return { json: mapped };
202
+ }
203
+ toToolOutput(args) {
204
+ const raw = this.mapOutputValue?.(args) ?? this.readDefaultToolOutput(args.outputs);
205
+ return this.outputSchemaValue.parse(raw);
206
+ }
207
+ readDefaultToolOutput(outputs) {
208
+ const firstMainItem = outputs.main?.[0];
209
+ if (!firstMainItem) throw new Error(`Node-backed tool "${this.name}" did not produce a main output item.`);
210
+ return firstMainItem.json;
211
+ }
212
+ isItem(value) {
213
+ return typeof value === "object" && value !== null && "json" in value;
214
+ }
215
+ };
216
+
167
217
  //#endregion
168
218
  //#region src/contracts/itemExpr.ts
169
219
  const ITEM_EXPR_BRAND = Symbol.for("codemation.itemExpr");
@@ -232,6 +282,27 @@ async function resolveItemExprsForExecution(config, nodeCtx, item, itemIndex, it
232
282
  return await resolveItemExprsInUnknown(config, exprArgs);
233
283
  }
234
284
 
285
+ //#endregion
286
+ //#region src/ai/AgentConfigInspectorFactory.ts
287
+ var AgentConfigInspector = class {
288
+ static isAgentNodeConfig(config) {
289
+ if (!config) return false;
290
+ const candidate = config;
291
+ return !!candidate.chatModel && this.hasCompatibleMessageConfiguration(candidate);
292
+ }
293
+ static hasCompatibleMessageConfiguration(candidate) {
294
+ const messages = candidate.messages;
295
+ if (messages === void 0 || messages === null) return false;
296
+ if (Array.isArray(messages)) return messages.length > 0;
297
+ if (typeof messages === "object") {
298
+ if (isItemExpr(messages)) return true;
299
+ const o = messages;
300
+ return Array.isArray(o.prompt) && o.prompt.length > 0 || typeof o.buildMessages === "function";
301
+ }
302
+ return false;
303
+ }
304
+ };
305
+
235
306
  //#endregion
236
307
  //#region src/workflow/definition/ConnectionNodeIdFactory.ts
237
308
  /**
@@ -282,6 +353,346 @@ var ConnectionNodeIdFactory = class {
282
353
  }
283
354
  };
284
355
 
356
+ //#endregion
357
+ //#region src/ai/AgentConnectionNodeCollector.ts
358
+ const AgentConnectionNodeCollector = new class {
359
+ collect(parentNodeId, agentConfig) {
360
+ const collected = [];
361
+ this.collectInto(parentNodeId, agentConfig, collected);
362
+ return collected;
363
+ }
364
+ collectInto(parentNodeId, agentConfig, collected) {
365
+ collected.push({
366
+ nodeId: ConnectionNodeIdFactory.languageModelConnectionNodeId(parentNodeId),
367
+ parentNodeId,
368
+ connectionName: "llm",
369
+ role: "languageModel",
370
+ name: agentConfig.chatModel.presentation?.label ?? agentConfig.chatModel.name,
371
+ typeName: agentConfig.chatModel.name,
372
+ icon: agentConfig.chatModel.presentation?.icon,
373
+ credentialSource: agentConfig.chatModel
374
+ });
375
+ for (const tool$1 of agentConfig.tools ?? []) {
376
+ const toolNodeId = ConnectionNodeIdFactory.toolConnectionNodeId(parentNodeId, tool$1.name);
377
+ const isNestedAgent = this.isNodeBackedAgentTool(tool$1);
378
+ collected.push({
379
+ nodeId: toolNodeId,
380
+ parentNodeId,
381
+ connectionName: "tools",
382
+ role: isNestedAgent ? "nestedAgent" : "tool",
383
+ name: tool$1.presentation?.label ?? tool$1.name,
384
+ typeName: tool$1.name,
385
+ icon: tool$1.presentation?.icon,
386
+ credentialSource: tool$1
387
+ });
388
+ this.collectNestedAgentTools(toolNodeId, tool$1, collected);
389
+ }
390
+ }
391
+ collectNestedAgentTools(toolNodeId, tool$1, collected) {
392
+ if (!this.isNodeBackedAgentTool(tool$1)) return;
393
+ const innerAgent = tool$1 instanceof NodeBackedToolConfig ? tool$1.node : tool$1.node;
394
+ this.collectInto(toolNodeId, innerAgent, collected);
395
+ }
396
+ /**
397
+ * After JSON round-trip (persisted snapshots), tools are plain objects — `instanceof NodeBackedToolConfig` fails.
398
+ * Detect node-backed tools structurally via {@link NodeBackedToolConfig#toolKind}.
399
+ */
400
+ isNodeBackedAgentTool(tool$1) {
401
+ if (tool$1 instanceof NodeBackedToolConfig) return AgentConfigInspector.isAgentNodeConfig(tool$1.node);
402
+ if (!tool$1 || typeof tool$1 !== "object") return false;
403
+ const t = tool$1;
404
+ if (t.toolKind !== "nodeBacked") return false;
405
+ return AgentConfigInspector.isAgentNodeConfig(t.node);
406
+ }
407
+ }();
408
+
409
+ //#endregion
410
+ //#region src/workflow/dsl/WhenBuilder.ts
411
+ var WhenBuilder = class WhenBuilder {
412
+ constructor(wf, from, branchPort) {
413
+ this.wf = wf;
414
+ this.from = from;
415
+ this.branchPort = branchPort;
416
+ }
417
+ addBranch(steps) {
418
+ const created = [];
419
+ let prev = null;
420
+ for (const cfg of steps) {
421
+ const ref = this.wf.add(cfg);
422
+ created.push(ref);
423
+ if (!prev) this.wf.connect(this.from, ref, this.branchPort, "in");
424
+ else this.wf.connect(prev, ref, "main", "in");
425
+ prev = ref;
426
+ }
427
+ for (const cfg of steps) {
428
+ const maybe = cfg;
429
+ if (!Array.isArray(maybe.upstreamRefs) || maybe.upstreamRefs.length === 0) continue;
430
+ maybe.upstreamRefs = maybe.upstreamRefs.map((r) => {
431
+ if (typeof r !== "string") return r;
432
+ const nodeId = created[parseInt(r.slice(1), 10)]?.id;
433
+ return nodeId ? { nodeId } : { nodeId: r };
434
+ });
435
+ }
436
+ return this;
437
+ }
438
+ when = (branch, steps, ...more) => {
439
+ const list = Array.isArray(steps) ? steps : [steps, ...more];
440
+ const port = branch ? "true" : "false";
441
+ const b = new WhenBuilder(this.wf, this.from, port);
442
+ b.addBranch(list);
443
+ return b;
444
+ };
445
+ build() {
446
+ return this.wf.build();
447
+ }
448
+ };
449
+
450
+ //#endregion
451
+ //#region src/workflow/dsl/ChainCursorResolver.ts
452
+ var ChainCursor = class ChainCursor {
453
+ constructor(wf, endpoints) {
454
+ this.wf = wf;
455
+ this.endpoints = endpoints;
456
+ }
457
+ then(config) {
458
+ const next = this.wf.add(config);
459
+ const inputPortHint = this.resolveSharedInputPortHint();
460
+ for (const e of this.endpoints) this.wf.connect(e.node, next, e.output);
461
+ return new ChainCursor(this.wf, [{
462
+ node: next,
463
+ output: "main",
464
+ ...inputPortHint ? { inputPortHint } : {}
465
+ }]);
466
+ }
467
+ thenIntoInputHints(config) {
468
+ const next = this.wf.add(config);
469
+ for (const e of this.endpoints) this.wf.connect(e.node, next, e.output, e.inputPortHint ?? "in");
470
+ return new ChainCursor(this.wf, [{
471
+ node: next,
472
+ output: "main"
473
+ }]);
474
+ }
475
+ when = ((arg1, steps, ...more) => {
476
+ if (this.endpoints.length !== 1) throw new Error("ChainCursor.when(...) is only supported from a single cursor endpoint");
477
+ const cursor = this.endpoints[0].node;
478
+ if (typeof arg1 === "boolean") {
479
+ const list = Array.isArray(steps) ? steps : steps ? [steps, ...more] : more;
480
+ const port = arg1 ? "true" : "false";
481
+ const b = new WhenBuilder(this.wf, cursor, port);
482
+ b.addBranch(list);
483
+ return b;
484
+ }
485
+ const branches = arg1;
486
+ const wfAny = this.wf;
487
+ const buildBranch = (port, branchSteps) => {
488
+ const list = branchSteps ?? [];
489
+ let prev = null;
490
+ for (const cfg of list) {
491
+ const ref = wfAny.add(cfg);
492
+ if (!prev) wfAny.connect(cursor, ref, port, "in");
493
+ else wfAny.connect(prev, ref, "main", "in");
494
+ prev = ref;
495
+ }
496
+ if (!prev) return {
497
+ end: cursor,
498
+ endOutput: port,
499
+ inputPortHint: port
500
+ };
501
+ return {
502
+ end: prev,
503
+ endOutput: "main",
504
+ inputPortHint: port
505
+ };
506
+ };
507
+ const t = buildBranch("true", branches.true);
508
+ const f = buildBranch("false", branches.false);
509
+ return new ChainCursor(this.wf, [{
510
+ node: t.end,
511
+ output: t.endOutput,
512
+ inputPortHint: t.inputPortHint
513
+ }, {
514
+ node: f.end,
515
+ output: f.endOutput,
516
+ inputPortHint: f.inputPortHint
517
+ }]);
518
+ });
519
+ route(branches) {
520
+ if (this.endpoints.length !== 1) throw new Error("ChainCursor.route(...) is only supported from a single cursor endpoint");
521
+ const cursor = this.endpoints[0];
522
+ const nextEndpoints = [];
523
+ for (const [port, branchFactory] of Object.entries(branches)) {
524
+ if (!branchFactory) continue;
525
+ const builtBranch = branchFactory(new ChainCursor(this.wf, [{
526
+ node: cursor.node,
527
+ output: port,
528
+ inputPortHint: port
529
+ }]));
530
+ if (!builtBranch) continue;
531
+ nextEndpoints.push(...builtBranch.endpoints);
532
+ }
533
+ return new ChainCursor(this.wf, nextEndpoints);
534
+ }
535
+ build() {
536
+ return this.wf.build();
537
+ }
538
+ resolveSharedInputPortHint() {
539
+ const first = this.endpoints[0]?.inputPortHint;
540
+ if (!first) return;
541
+ return this.endpoints.every((endpoint) => endpoint.inputPortHint === first) ? first : void 0;
542
+ }
543
+ };
544
+
545
+ //#endregion
546
+ //#region src/workflow/dsl/NodeIdSlugifier.ts
547
+ /**
548
+ * Converts a human-readable node label into a stable, URL-safe identifier segment.
549
+ *
550
+ * Rules:
551
+ * - Lowercase the entire string.
552
+ * - Replace every run of characters outside `[a-z0-9]` with a single `-`.
553
+ * - Strip any leading or trailing `-` characters.
554
+ * - Return `""` for blank/empty input.
555
+ */
556
+ const NodeIdSlugifier = { slugify(label) {
557
+ if (!label) return "";
558
+ return label.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
559
+ } };
560
+
561
+ //#endregion
562
+ //#region src/workflow/dsl/WorkflowDefinitionError.ts
563
+ /**
564
+ * Thrown by {@link WorkflowBuilder.build} when the workflow definition is structurally invalid.
565
+ *
566
+ * Common causes:
567
+ * - A node has an empty effective id (label is blank and no explicit `id` was given).
568
+ * - Two or more nodes share the same effective id (label slugs collide or explicit ids clash).
569
+ *
570
+ * Fix: provide an explicit `id:` on the offending node configs.
571
+ */
572
+ var WorkflowDefinitionError = class extends Error {
573
+ constructor(message) {
574
+ super(message);
575
+ this.name = "WorkflowDefinitionError";
576
+ }
577
+ };
578
+
579
+ //#endregion
580
+ //#region src/workflow/dsl/WorkflowBuilder.ts
581
+ var WorkflowBuilder = class {
582
+ nodes = [];
583
+ edges = [];
584
+ constructor(meta, options) {
585
+ this.meta = meta;
586
+ this.options = options;
587
+ }
588
+ add(config) {
589
+ const id = config.id ?? NodeIdSlugifier.slugify(config.name ?? "");
590
+ this.nodes.push({
591
+ id,
592
+ kind: config.kind,
593
+ type: config.type,
594
+ name: config.name,
595
+ config
596
+ });
597
+ return {
598
+ id,
599
+ kind: config.kind,
600
+ name: config.name
601
+ };
602
+ }
603
+ connect(from, to, fromOutput = "main", toInput = "in") {
604
+ this.edges.push({
605
+ from: {
606
+ nodeId: from.id,
607
+ output: fromOutput
608
+ },
609
+ to: {
610
+ nodeId: to.id,
611
+ input: toInput
612
+ }
613
+ });
614
+ }
615
+ trigger(config) {
616
+ const ref = this.add(config);
617
+ return new ChainCursor(this, [{
618
+ node: ref,
619
+ output: "main"
620
+ }]);
621
+ }
622
+ start(config) {
623
+ const ref = this.add(config);
624
+ return new ChainCursor(this, [{
625
+ node: ref,
626
+ output: "main"
627
+ }]);
628
+ }
629
+ build() {
630
+ this.validateNodeIds();
631
+ return {
632
+ ...this.meta,
633
+ nodes: this.nodes,
634
+ edges: this.edges
635
+ };
636
+ }
637
+ validateNodeIds() {
638
+ const entries = [];
639
+ for (const node$1 of this.nodes) {
640
+ const tokenName = typeof node$1.type === "function" ? node$1.type.name : String(node$1.type);
641
+ entries.push({
642
+ nodeId: node$1.id,
643
+ tokenName,
644
+ label: node$1.name ?? ""
645
+ });
646
+ if (AgentConfigInspector.isAgentNodeConfig(node$1.config)) for (const child of AgentConnectionNodeCollector.collect(node$1.id, node$1.config)) entries.push({
647
+ nodeId: child.nodeId,
648
+ tokenName: child.typeName,
649
+ label: child.name
650
+ });
651
+ }
652
+ const emptyIds = [];
653
+ const seenIds = /* @__PURE__ */ new Map();
654
+ const duplicateIds = [];
655
+ for (const entry of entries) {
656
+ if (!entry.nodeId) {
657
+ emptyIds.push(entry);
658
+ continue;
659
+ }
660
+ const existing = seenIds.get(entry.nodeId);
661
+ if (existing) {
662
+ if (!duplicateIds.includes(existing)) duplicateIds.push(existing);
663
+ duplicateIds.push(entry);
664
+ } else seenIds.set(entry.nodeId, entry);
665
+ }
666
+ if (emptyIds.length === 0 && duplicateIds.length === 0) return;
667
+ const lines = ["WorkflowBuilder.build() found invalid node ids:"];
668
+ if (emptyIds.length > 0) {
669
+ lines.push(" Empty ids (label is blank and no explicit id was given):");
670
+ for (const e of emptyIds) lines.push(` - type "${e.tokenName}" label "${e.label}"`);
671
+ }
672
+ if (duplicateIds.length > 0) {
673
+ lines.push(" Duplicate ids:");
674
+ for (const e of duplicateIds) lines.push(` - id "${e.nodeId}" type "${e.tokenName}" label "${e.label}"`);
675
+ }
676
+ lines.push(" Fix: set an explicit `id:` on each offending node config.");
677
+ throw new WorkflowDefinitionError(lines.join("\n"));
678
+ }
679
+ };
680
+
681
+ //#endregion
682
+ //#region src/workflow/definition/ConnectionInvocationIdFactory.ts
683
+ /**
684
+ * Unique ids for persisted connection invocation history rows (LLM/tool calls under an owning node).
685
+ */
686
+ var ConnectionInvocationIdFactory = class {
687
+ static create() {
688
+ return `cinv_${(0, node_crypto.randomUUID)()}`;
689
+ }
690
+ /** Deterministic id for tests when a stable sequence is needed. */
691
+ static createForTest(runId, connectionNodeId, sequence) {
692
+ return `cinv_${runId}_${connectionNodeId}_${sequence}`;
693
+ }
694
+ };
695
+
285
696
  //#endregion
286
697
  //#region src/workflow/definition/NodeIterationIdFactory.ts
287
698
  /**
@@ -365,6 +776,35 @@ var WorkflowExecutableNodeClassifierFactory = class {
365
776
  }
366
777
  };
367
778
 
779
+ //#endregion
780
+ //#region src/workflow/graph/ExecutableGraph.ts
781
+ var ExecutableGraph = class {
782
+ outgoingByNodeAndPort = /* @__PURE__ */ new Map();
783
+ constructor(def) {
784
+ for (const e of def.edges) {
785
+ const byPort = this.outgoingByNodeAndPort.get(e.from.nodeId) ?? /* @__PURE__ */ new Map();
786
+ const next = byPort.get(e.from.output) ?? [];
787
+ next.push({
788
+ nodeId: e.to.nodeId,
789
+ input: e.to.input
790
+ });
791
+ byPort.set(e.from.output, next);
792
+ this.outgoingByNodeAndPort.set(e.from.nodeId, byPort);
793
+ }
794
+ }
795
+ next(nodeId, output) {
796
+ return this.outgoingByNodeAndPort.get(nodeId)?.get(output) ?? [];
797
+ }
798
+ };
799
+
800
+ //#endregion
801
+ //#region src/workflow/graph/DefaultWorkflowGraphFactory.ts
802
+ var DefaultWorkflowGraphFactory = class {
803
+ create(def) {
804
+ return new ExecutableGraph(def);
805
+ }
806
+ };
807
+
368
808
  //#endregion
369
809
  //#region src/events/ConnectionInvocationEventPublisher.ts
370
810
  /**
@@ -419,15 +859,6 @@ var NodeEventPublisher = class {
419
859
  }
420
860
  };
421
861
 
422
- //#endregion
423
- //#region \0@oxc-project+runtime@0.95.0/helpers/decorate.js
424
- function __decorate(decorators, target, key, desc) {
425
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
426
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
427
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
428
- return c > 3 && r && Object.defineProperty(target, key, r), r;
429
- }
430
-
431
862
  //#endregion
432
863
  //#region src/binaries/DefaultNodeBinaryAttachmentServiceFactory.ts
433
864
  var DefaultNodeBinaryAttachmentService = class DefaultNodeBinaryAttachmentService {
@@ -726,23 +1157,22 @@ var ActivationEnqueueService = class {
726
1157
  }
727
1158
  };
728
1159
 
729
- //#endregion
730
- //#region \0@oxc-project+runtime@0.95.0/helpers/decorateMetadata.js
731
- function __decorateMetadata(k, v) {
732
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
733
- }
734
-
735
- //#endregion
736
- //#region \0@oxc-project+runtime@0.95.0/helpers/decorateParam.js
737
- function __decorateParam(paramIndex, decorator) {
738
- return function(target, key) {
739
- decorator(target, key, paramIndex);
740
- };
741
- }
742
-
743
1160
  //#endregion
744
1161
  //#region src/execution/ChildExecutionScopeFactory.ts
745
- let ChildExecutionScopeFactory = class ChildExecutionScopeFactory$1 {
1162
+ /**
1163
+ * Builds a re-rooted child execution context for sub-agent (and other deeply-nested) invocations.
1164
+ *
1165
+ * At the orchestrator's `agent.tool.call` boundary the inner runtime needs a ctx whose:
1166
+ * - `nodeId` is the tool's connection node id (so inner LLM/tool connection ids derive correctly),
1167
+ * - `activationId` is fresh (so its connection-invocation rows are uniquely identifiable),
1168
+ * - `telemetry` parents children under the tool-call span (not the orchestrator's node span),
1169
+ * - `binary` is scoped to the new (nodeId, activationId),
1170
+ * - `parentInvocationId` points back to the tool-call invocation for downstream lineage.
1171
+ *
1172
+ * Registered via factory in {@link EngineRuntimeRegistrar} so constructors stay free of parameter
1173
+ * decorators (Next/SWC and coverage tooling cannot parse them on in-repo sources).
1174
+ */
1175
+ var ChildExecutionScopeFactory = class {
746
1176
  constructor(activationIdFactory) {
747
1177
  this.activationIdFactory = activationIdFactory;
748
1178
  }
@@ -768,11 +1198,6 @@ let ChildExecutionScopeFactory = class ChildExecutionScopeFactory$1 {
768
1198
  };
769
1199
  }
770
1200
  };
771
- ChildExecutionScopeFactory = __decorate([
772
- (0, tsyringe.injectable)(),
773
- __decorateParam(0, (0, tsyringe.inject)(CoreTokens.ActivationIdFactory)),
774
- __decorateMetadata("design:paramtypes", [Object])
775
- ], ChildExecutionScopeFactory);
776
1201
 
777
1202
  //#endregion
778
1203
  //#region src/contracts/itemMeta.ts
@@ -914,6 +1339,20 @@ var NodeActivationRequestInputPreparer = class {
914
1339
  }
915
1340
  };
916
1341
 
1342
+ //#endregion
1343
+ //#region src/execution/NodeInstantiationError.ts
1344
+ var NodeInstantiationError = class extends Error {
1345
+ name = "NodeInstantiationError";
1346
+ originalError;
1347
+ constructor(nodeId, nodeType, originalError) {
1348
+ super(`Failed to instantiate node "${nodeId}" (type ${nodeType}): ${originalError.message}`);
1349
+ this.nodeId = nodeId;
1350
+ this.nodeType = nodeType;
1351
+ this.originalError = originalError;
1352
+ this.stack = originalError.stack;
1353
+ }
1354
+ };
1355
+
917
1356
  //#endregion
918
1357
  //#region src/execution/CredentialResolverFactory.ts
919
1358
  var CredentialResolverFactory = class {
@@ -1149,6 +1588,28 @@ var NoOpExecutionTelemetryFactory = class {
1149
1588
  }
1150
1589
  };
1151
1590
 
1591
+ //#endregion
1592
+ //#region src/contracts/runFinishedAtFactory.ts
1593
+ /** Derives workflow end time from persisted run root or node snapshots for run listings. */
1594
+ var RunFinishedAtFactory = class {
1595
+ static resolveIso(state) {
1596
+ if (state.finishedAt && state.status !== "running" && state.status !== "pending") return state.finishedAt;
1597
+ if (state.status === "running" || state.status === "pending") return;
1598
+ let max;
1599
+ for (const snap of Object.values(state.nodeSnapshotsByNodeId)) if (snap?.finishedAt && (!max || snap.finishedAt > max)) max = snap.finishedAt;
1600
+ return max;
1601
+ }
1602
+ };
1603
+
1604
+ //#endregion
1605
+ //#region src/contracts/workflowActivationPolicy.ts
1606
+ /** Default for tests and harnesses: every workflow is treated as active (legacy behavior). */
1607
+ var AllWorkflowsActiveWorkflowActivationPolicy = class {
1608
+ isActive(_workflowId) {
1609
+ return true;
1610
+ }
1611
+ };
1612
+
1152
1613
  //#endregion
1153
1614
  //#region src/contracts/CodemationTelemetryAttributeNames.ts
1154
1615
  var CodemationTelemetryAttributeNames = class {
@@ -1193,19 +1654,6 @@ var CodemationTelemetryMetricNames = class {
1193
1654
  static gmailAttachmentBytes = "codemation.gmail.attachment_bytes";
1194
1655
  };
1195
1656
 
1196
- //#endregion
1197
- //#region src/contracts/runFinishedAtFactory.ts
1198
- /** Derives workflow end time from persisted run root or node snapshots for run listings. */
1199
- var RunFinishedAtFactory = class {
1200
- static resolveIso(state) {
1201
- if (state.finishedAt && state.status !== "running" && state.status !== "pending") return state.finishedAt;
1202
- if (state.status === "running" || state.status === "pending") return;
1203
- let max;
1204
- for (const snap of Object.values(state.nodeSnapshotsByNodeId)) if (snap?.finishedAt && (!max || snap.finishedAt > max)) max = snap.finishedAt;
1205
- return max;
1206
- }
1207
- };
1208
-
1209
1657
  //#endregion
1210
1658
  //#region src/contracts/workflowTypes.ts
1211
1659
  function nodeRef(nodeId) {
@@ -1213,15 +1661,6 @@ function nodeRef(nodeId) {
1213
1661
  }
1214
1662
  const branchRef = (index) => `$${index}`;
1215
1663
 
1216
- //#endregion
1217
- //#region src/contracts/workflowActivationPolicy.ts
1218
- /** Default for tests and harnesses: every workflow is treated as active (legacy behavior). */
1219
- var AllWorkflowsActiveWorkflowActivationPolicy = class {
1220
- isActive(_workflowId) {
1221
- return true;
1222
- }
1223
- };
1224
-
1225
1664
  //#endregion
1226
1665
  //#region src/execution/ExecutionTelemetryCostTrackingDecoratorFactory.ts
1227
1666
  var ExecutionTelemetryCostTrackingDecoratorFactory = class {
@@ -1295,11 +1734,12 @@ var ExecutionTelemetryCostTrackingDecoratorFactory = class {
1295
1734
  //#region src/execution/DefaultExecutionContextFactory.ts
1296
1735
  var DefaultExecutionContextFactory = class {
1297
1736
  telemetryDecoratorFactory = new ExecutionTelemetryCostTrackingDecoratorFactory();
1298
- constructor(binaryStorage = new UnavailableBinaryStorage(), telemetryFactory = new NoOpExecutionTelemetryFactory(), costTrackingFactory = new NoOpCostTrackingTelemetryFactory(), currentDate = () => /* @__PURE__ */ new Date()) {
1737
+ constructor(binaryStorage = new UnavailableBinaryStorage(), telemetryFactory = new NoOpExecutionTelemetryFactory(), costTrackingFactory = new NoOpCostTrackingTelemetryFactory(), currentDate = () => /* @__PURE__ */ new Date(), collections) {
1299
1738
  this.binaryStorage = binaryStorage;
1300
1739
  this.telemetryFactory = telemetryFactory;
1301
1740
  this.costTrackingFactory = costTrackingFactory;
1302
1741
  this.currentDate = currentDate;
1742
+ this.collections = collections;
1303
1743
  }
1304
1744
  create(args) {
1305
1745
  const baseTelemetry = args.telemetry ?? this.telemetryFactory.create({
@@ -1324,7 +1764,9 @@ var DefaultExecutionContextFactory = class {
1324
1764
  nodeState: args.nodeState,
1325
1765
  telemetry,
1326
1766
  binary: new DefaultExecutionBinaryService(this.binaryStorage, args.workflowId, args.runId, this.currentDate),
1327
- getCredential: args.getCredential
1767
+ getCredential: args.getCredential,
1768
+ testContext: args.testContext,
1769
+ collections: this.collections
1328
1770
  };
1329
1771
  }
1330
1772
  };
@@ -2161,7 +2603,12 @@ var NodeInstanceFactory = class {
2161
2603
  }
2162
2604
  createNodes(workflow) {
2163
2605
  const nodeInstances = /* @__PURE__ */ new Map();
2164
- for (const definition of workflow.nodes) nodeInstances.set(definition.id, this.createNode(definition));
2606
+ for (const definition of workflow.nodes) try {
2607
+ nodeInstances.set(definition.id, this.createNode(definition));
2608
+ } catch (err) {
2609
+ if (err instanceof NodeInstantiationError) throw err;
2610
+ throw new NodeInstantiationError(definition.id, typeof definition.type === "function" ? definition.type.name : String(definition.type), err instanceof Error ? err : new Error(String(err)));
2611
+ }
2165
2612
  return nodeInstances;
2166
2613
  }
2167
2614
  createNode(definition) {
@@ -2460,7 +2907,8 @@ var WorkflowRunExecutionContextFactory = class {
2460
2907
  engineMaxSubworkflowDepth: args.engineMaxSubworkflowDepth,
2461
2908
  data: args.data,
2462
2909
  nodeState: args.nodeState,
2463
- getCredential: this.credentialResolverFactory.create(args.workflowId, args.nodeId)
2910
+ getCredential: this.credentialResolverFactory.create(args.workflowId, args.nodeId),
2911
+ testContext: args.testContext
2464
2912
  });
2465
2913
  }
2466
2914
  };
@@ -2627,7 +3075,8 @@ var RunContinuationService = class {
2627
3075
  engineMaxNodeActivations: limits.engineMaxNodeActivations,
2628
3076
  engineMaxSubworkflowDepth: limits.engineMaxSubworkflowDepth,
2629
3077
  data,
2630
- nodeState: this.nodeStatePublisherFactory.create(state.runId, state.workflowId, state.parent)
3078
+ nodeState: this.nodeStatePublisherFactory.create(state.runId, state.workflowId, state.parent),
3079
+ testContext: state.executionOptions?.testContext
2631
3080
  });
2632
3081
  data.setOutputs(args.nodeId, args.outputs);
2633
3082
  const completedAt = (/* @__PURE__ */ new Date()).toISOString();
@@ -3148,7 +3597,8 @@ var RunContinuationService = class {
3148
3597
  engineMaxNodeActivations: webhookLimits.engineMaxNodeActivations,
3149
3598
  engineMaxSubworkflowDepth: webhookLimits.engineMaxSubworkflowDepth,
3150
3599
  data,
3151
- nodeState: this.nodeStatePublisherFactory.create(args.state.runId, args.state.workflowId, args.state.parent)
3600
+ nodeState: this.nodeStatePublisherFactory.create(args.state.runId, args.state.workflowId, args.state.parent),
3601
+ testContext: args.state.executionOptions?.testContext
3152
3602
  });
3153
3603
  const request = this.nodeActivationRequestComposer.createFromPlannedActivation({
3154
3604
  next,
@@ -3239,7 +3689,8 @@ var RunContinuationService = class {
3239
3689
  engineMaxNodeActivations: limits.engineMaxNodeActivations,
3240
3690
  engineMaxSubworkflowDepth: limits.engineMaxSubworkflowDepth,
3241
3691
  data,
3242
- nodeState: this.nodeStatePublisherFactory.create(state.runId, state.workflowId, state.parent)
3692
+ nodeState: this.nodeStatePublisherFactory.create(state.runId, state.workflowId, state.parent),
3693
+ testContext: state.executionOptions?.testContext
3243
3694
  });
3244
3695
  const activationId = pendingExecution.activationId;
3245
3696
  return {
@@ -3631,7 +4082,7 @@ var RunPolicySnapshotFactory = class {
3631
4082
  //#endregion
3632
4083
  //#region src/orchestration/RunStartService.ts
3633
4084
  var RunStartService = class {
3634
- constructor(runIdFactory, workflowExecutionRepository, runDataFactory, workflowSnapshotFactory, planningFactory, nodeStatePublisherFactory, runExecutionContextFactory, nodeActivationRequestComposer, activationEnqueueService, semantics, waiters, workflowPolicyRuntimeDefaults, executionLimitsPolicy) {
4085
+ constructor(runIdFactory, workflowExecutionRepository, runDataFactory, workflowSnapshotFactory, planningFactory, nodeStatePublisherFactory, runExecutionContextFactory, nodeActivationRequestComposer, activationEnqueueService, semantics, waiters, workflowPolicyRuntimeDefaults, executionLimitsPolicy, nodeEventPublisher, persistedRunStateTerminalBuilder) {
3635
4086
  this.runIdFactory = runIdFactory;
3636
4087
  this.workflowExecutionRepository = workflowExecutionRepository;
3637
4088
  this.runDataFactory = runDataFactory;
@@ -3645,6 +4096,8 @@ var RunStartService = class {
3645
4096
  this.waiters = waiters;
3646
4097
  this.workflowPolicyRuntimeDefaults = workflowPolicyRuntimeDefaults;
3647
4098
  this.executionLimitsPolicy = executionLimitsPolicy;
4099
+ this.nodeEventPublisher = nodeEventPublisher;
4100
+ this.persistedRunStateTerminalBuilder = persistedRunStateTerminalBuilder;
3648
4101
  }
3649
4102
  async runWorkflow(workflow, startAt, items, parent, executionOptions, persistedStateOverrides) {
3650
4103
  const runId = this.runIdFactory.makeRunId();
@@ -3675,9 +4128,28 @@ var RunStartService = class {
3675
4128
  engineMaxNodeActivations: mergedExecutionOptions.maxNodeActivations,
3676
4129
  engineMaxSubworkflowDepth: mergedExecutionOptions.maxSubworkflowDepth,
3677
4130
  data,
3678
- nodeState: this.nodeStatePublisherFactory.create(runId, workflow.id, parent)
4131
+ nodeState: this.nodeStatePublisherFactory.create(runId, workflow.id, parent),
4132
+ testContext: mergedExecutionOptions.testContext
3679
4133
  });
3680
- const { topology, planner } = this.planningFactory.create(workflow);
4134
+ let planning;
4135
+ try {
4136
+ planning = this.planningFactory.create(workflow);
4137
+ } catch (err) {
4138
+ if (err instanceof NodeInstantiationError) return await this.failRunDuringPlanning({
4139
+ runId,
4140
+ workflowId: workflow.id,
4141
+ startedAt,
4142
+ parent,
4143
+ executionOptions: mergedExecutionOptions,
4144
+ control: void 0,
4145
+ workflowSnapshot,
4146
+ mutableState,
4147
+ policySnapshot,
4148
+ err
4149
+ });
4150
+ throw err;
4151
+ }
4152
+ const { topology, planner } = planning;
3681
4153
  const startDefinition = topology.defsById.get(startAt);
3682
4154
  if (!startDefinition) throw new Error(`Unknown start nodeId: ${startAt}`);
3683
4155
  const initialNodeSnapshotsByNodeId = {};
@@ -3756,7 +4228,25 @@ var RunStartService = class {
3756
4228
  policySnapshot,
3757
4229
  engineCounters: { completedNodeActivations: 0 }
3758
4230
  });
3759
- const { topology, planner } = this.planningFactory.create(request.workflow);
4231
+ let planningFromState;
4232
+ try {
4233
+ planningFromState = this.planningFactory.create(request.workflow);
4234
+ } catch (err) {
4235
+ if (err instanceof NodeInstantiationError) return await this.failRunDuringPlanning({
4236
+ runId,
4237
+ workflowId: request.workflow.id,
4238
+ startedAt,
4239
+ parent: request.parent,
4240
+ executionOptions: mergedExecutionOptions,
4241
+ control,
4242
+ workflowSnapshot,
4243
+ mutableState,
4244
+ policySnapshot,
4245
+ err
4246
+ });
4247
+ throw err;
4248
+ }
4249
+ const { topology, planner } = planningFromState;
3760
4250
  const plan = CurrentStateFrontierPlanner.createFromTopology(topology).plan({
3761
4251
  currentState: this.createRunCurrentState(request.currentState, mutableState),
3762
4252
  stopCondition: control.stopCondition,
@@ -3774,7 +4264,8 @@ var RunStartService = class {
3774
4264
  engineMaxNodeActivations: mergedExecutionOptions.maxNodeActivations,
3775
4265
  engineMaxSubworkflowDepth: mergedExecutionOptions.maxSubworkflowDepth,
3776
4266
  data,
3777
- nodeState: this.nodeStatePublisherFactory.create(runId, request.workflow.id, request.parent)
4267
+ nodeState: this.nodeStatePublisherFactory.create(runId, request.workflow.id, request.parent),
4268
+ testContext: mergedExecutionOptions.testContext
3778
4269
  });
3779
4270
  return await this.scheduleInitialPlan({
3780
4271
  runId,
@@ -3949,6 +4440,57 @@ var RunStartService = class {
3949
4440
  this.waiters.resolveRunCompletion(result);
3950
4441
  return result;
3951
4442
  }
4443
+ async failRunDuringPlanning(args) {
4444
+ const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
4445
+ const failedSnapshot = NodeExecutionSnapshotFactory.failed({
4446
+ previous: void 0,
4447
+ runId: args.runId,
4448
+ workflowId: args.workflowId,
4449
+ nodeId: args.err.nodeId,
4450
+ activationId: "planning_failure",
4451
+ parent: args.parent,
4452
+ finishedAt,
4453
+ inputsByPort: {},
4454
+ error: args.err
4455
+ });
4456
+ const failedState = this.persistedRunStateTerminalBuilder.mergeTerminal({
4457
+ state: {
4458
+ runId: args.runId,
4459
+ workflowId: args.workflowId,
4460
+ startedAt: args.startedAt,
4461
+ parent: args.parent,
4462
+ executionOptions: args.executionOptions,
4463
+ control: args.control,
4464
+ workflowSnapshot: args.workflowSnapshot,
4465
+ mutableState: args.mutableState,
4466
+ policySnapshot: args.policySnapshot,
4467
+ engineCounters: { completedNodeActivations: 0 },
4468
+ status: "pending",
4469
+ pending: void 0,
4470
+ queue: [],
4471
+ outputsByNode: {},
4472
+ nodeSnapshotsByNodeId: {},
4473
+ connectionInvocations: []
4474
+ },
4475
+ engineCounters: { completedNodeActivations: 0 },
4476
+ status: "failed",
4477
+ queue: [],
4478
+ outputsByNode: {},
4479
+ nodeSnapshotsByNodeId: { [args.err.nodeId]: failedSnapshot },
4480
+ finishedAtIso: finishedAt
4481
+ });
4482
+ await this.workflowExecutionRepository.save(failedState);
4483
+ await this.nodeEventPublisher.publish("nodeFailed", failedSnapshot);
4484
+ const result = {
4485
+ runId: args.runId,
4486
+ workflowId: args.workflowId,
4487
+ startedAt: args.startedAt,
4488
+ status: "failed",
4489
+ error: { message: args.err.message }
4490
+ };
4491
+ this.waiters.resolveRunCompletion(result);
4492
+ return result;
4493
+ }
3952
4494
  };
3953
4495
 
3954
4496
  //#endregion
@@ -4422,6 +4964,128 @@ var InMemoryRunDataFactory = class {
4422
4964
  }
4423
4965
  };
4424
4966
 
4967
+ //#endregion
4968
+ //#region src/triggers/polling/PollingTriggerDedupWindow.ts
4969
+ /**
4970
+ * Merges processed-ID windows for polling triggers, capping the total to avoid unbounded growth.
4971
+ * Plugin code receives an instance of this class via {@link PollingTriggerHandle.dedup}.
4972
+ */
4973
+ var PollingTriggerDedupWindow = class PollingTriggerDedupWindow {
4974
+ static defaultCapN = 2e3;
4975
+ merge(previous, incoming, capN = PollingTriggerDedupWindow.defaultCapN) {
4976
+ const merged = new Set(previous);
4977
+ for (const id of incoming) merged.add(id);
4978
+ const result = [...merged];
4979
+ if (result.length <= capN) return result;
4980
+ return result.slice(result.length - capN);
4981
+ }
4982
+ };
4983
+
4984
+ //#endregion
4985
+ //#region src/triggers/polling/PollingTriggerRuntime.ts
4986
+ /**
4987
+ * Generic polling-trigger runtime. Owns the set-interval loop, overlap guard, and persistence.
4988
+ * Constructed by {@link import("../../runtime/EngineFactory").EngineFactory} and exposed to plugin
4989
+ * authors via {@link import("../../contracts/runtimeTypes").TriggerSetupContext}.polling.
4990
+ */
4991
+ var PollingTriggerRuntime = class {
4992
+ activeTriggers = /* @__PURE__ */ new Set();
4993
+ intervalsByTrigger = /* @__PURE__ */ new Map();
4994
+ busyTriggers = /* @__PURE__ */ new Set();
4995
+ constructor(triggerSetupStateRepository, logger) {
4996
+ this.triggerSetupStateRepository = triggerSetupStateRepository;
4997
+ this.logger = logger;
4998
+ }
4999
+ async start(args) {
5000
+ let first;
5001
+ try {
5002
+ first = await this.runCycle(args, { seedState: args.seedState });
5003
+ } catch (err) {
5004
+ this.logError(`Polling trigger initial cycle failed for ${this.describe(args.trigger)}`, err);
5005
+ }
5006
+ this.ensureLoop(args);
5007
+ return first;
5008
+ }
5009
+ async stop(trigger) {
5010
+ const key = this.toKey(trigger);
5011
+ const interval = this.intervalsByTrigger.get(key);
5012
+ if (interval !== void 0) {
5013
+ clearInterval(interval);
5014
+ this.intervalsByTrigger.delete(key);
5015
+ }
5016
+ this.busyTriggers.delete(key);
5017
+ this.activeTriggers.delete(key);
5018
+ this.logger.debug(`Polling trigger stopped for ${this.describe(trigger)}`);
5019
+ }
5020
+ ensureLoop(args) {
5021
+ const key = this.toKey(args.trigger);
5022
+ if (this.activeTriggers.has(key)) {
5023
+ this.logger.debug(`Polling trigger already active for ${this.describe(args.trigger)}`);
5024
+ return;
5025
+ }
5026
+ this.activeTriggers.add(key);
5027
+ const intervalMs = Math.max(args.intervalMs, 25);
5028
+ const interval = setInterval(() => {
5029
+ this.runCycle(args, { seedState: void 0 }).catch((err) => {
5030
+ this.logError(`Polling trigger cycle failed for ${this.describe(args.trigger)}`, err);
5031
+ });
5032
+ }, intervalMs);
5033
+ this.intervalsByTrigger.set(key, interval);
5034
+ this.logger.info(`Polling trigger started for ${this.describe(args.trigger)} (interval ${intervalMs}ms)`);
5035
+ }
5036
+ async runCycle(args, opts) {
5037
+ const key = this.toKey(args.trigger);
5038
+ if (this.busyTriggers.has(key)) {
5039
+ this.logger.debug(`Polling trigger skipping overlapping tick for ${this.describe(args.trigger)}`);
5040
+ return;
5041
+ }
5042
+ this.busyTriggers.add(key);
5043
+ try {
5044
+ const loaded = await this.triggerSetupStateRepository.load(args.trigger);
5045
+ const previousState = loaded !== void 0 ? loaded.state : opts.seedState;
5046
+ const controller = new AbortController();
5047
+ const { items, nextState } = await args.runCycle({
5048
+ previousState,
5049
+ signal: controller.signal
5050
+ });
5051
+ await this.triggerSetupStateRepository.save({
5052
+ trigger: args.trigger,
5053
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
5054
+ state: nextState
5055
+ });
5056
+ if (items.length > 0) {
5057
+ this.logger.info(`Polling trigger emitting ${items.length} item(s) for ${this.describe(args.trigger)}`);
5058
+ await args.emit(items);
5059
+ }
5060
+ return nextState;
5061
+ } finally {
5062
+ this.busyTriggers.delete(key);
5063
+ }
5064
+ }
5065
+ toKey(trigger) {
5066
+ return `${trigger.workflowId}:${trigger.nodeId}`;
5067
+ }
5068
+ describe(trigger) {
5069
+ return `${trigger.workflowId}.${trigger.nodeId}`;
5070
+ }
5071
+ logError(message, error) {
5072
+ if (error instanceof Error) {
5073
+ this.logger.error(message, error);
5074
+ return;
5075
+ }
5076
+ this.logger.error(`${message}: ${String(error)}`);
5077
+ }
5078
+ };
5079
+
5080
+ //#endregion
5081
+ //#region src/triggers/polling/PollingTriggerLogger.ts
5082
+ var NoOpPollingTriggerLogger = class {
5083
+ info() {}
5084
+ warn() {}
5085
+ error() {}
5086
+ debug() {}
5087
+ };
5088
+
4425
5089
  //#endregion
4426
5090
  //#region src/orchestration/NodeExecutionRequestHandlerService.ts
4427
5091
  var NodeExecutionRequestHandlerService = class {
@@ -4461,7 +5125,8 @@ var NodeExecutionRequestHandlerService = class {
4461
5125
  engineMaxNodeActivations: limits.engineMaxNodeActivations,
4462
5126
  engineMaxSubworkflowDepth: limits.engineMaxSubworkflowDepth,
4463
5127
  data,
4464
- nodeState: this.nodeStatePublisherFactory.create(state.runId, state.workflowId, resolvedParent)
5128
+ nodeState: this.nodeStatePublisherFactory.create(state.runId, state.workflowId, resolvedParent),
5129
+ testContext: state.executionOptions?.testContext
4465
5130
  });
4466
5131
  const inputsByPort = pendingExecution.inputsByPort;
4467
5132
  const portKeys = Object.keys(inputsByPort);
@@ -4851,7 +5516,7 @@ var EngineWorkflowPlanningFactory = class {
4851
5516
  var TriggerRuntimeService = class {
4852
5517
  credentialResolverFactory;
4853
5518
  triggerCleanupHandlesByKey = /* @__PURE__ */ new Map();
4854
- constructor(workflowRepository, workflowActivationPolicy, runIdFactory, runDataFactory, executionContextFactory, credentialResolverFactory, nodeExecutionStatePublisherFactory, nodeResolver, triggerSetupStateRepository, emitHandler, executionLimitsPolicy, diagnostics) {
5519
+ constructor(workflowRepository, workflowActivationPolicy, runIdFactory, runDataFactory, executionContextFactory, credentialResolverFactory, nodeExecutionStatePublisherFactory, nodeResolver, triggerSetupStateRepository, emitHandler, executionLimitsPolicy, diagnostics, pollingTriggerRuntime, pollingTriggerDedupWindow) {
4855
5520
  this.workflowRepository = workflowRepository;
4856
5521
  this.workflowActivationPolicy = workflowActivationPolicy;
4857
5522
  this.runIdFactory = runIdFactory;
@@ -4863,6 +5528,8 @@ var TriggerRuntimeService = class {
4863
5528
  this.emitHandler = emitHandler;
4864
5529
  this.executionLimitsPolicy = executionLimitsPolicy;
4865
5530
  this.diagnostics = diagnostics;
5531
+ this.pollingTriggerRuntime = pollingTriggerRuntime;
5532
+ this.pollingTriggerDedupWindow = pollingTriggerDedupWindow;
4866
5533
  this.credentialResolverFactory = credentialResolverFactory;
4867
5534
  }
4868
5535
  async startTriggers() {
@@ -4918,6 +5585,7 @@ var TriggerRuntimeService = class {
4918
5585
  async startTriggersForWorkflow(wf) {
4919
5586
  for (const def of wf.nodes) {
4920
5587
  if (def.kind !== "trigger") continue;
5588
+ if (def.config.triggerKind === "test") continue;
4921
5589
  const node$1 = this.nodeResolver.resolve(def.type);
4922
5590
  const data = this.runDataFactory.create();
4923
5591
  const triggerRunId = this.runIdFactory.makeRunId();
@@ -4927,6 +5595,9 @@ var TriggerRuntimeService = class {
4927
5595
  };
4928
5596
  await this.stopTrigger(trigger);
4929
5597
  const previousState = await this.triggerSetupStateRepository.load(trigger);
5598
+ const emit = this.emitHandler.emit.bind(this.emitHandler, wf, def.id);
5599
+ const registerCleanup = this.registerTriggerCleanupHandle.bind(this, trigger);
5600
+ const polling = this.buildPollingHandle(trigger, emit);
4930
5601
  let nextState;
4931
5602
  try {
4932
5603
  nextState = await node$1.setup({
@@ -4939,12 +5610,9 @@ var TriggerRuntimeService = class {
4939
5610
  trigger,
4940
5611
  config: def.config,
4941
5612
  previousState: previousState?.state,
4942
- registerCleanup: (cleanup) => {
4943
- this.registerTriggerCleanupHandle(trigger, cleanup);
4944
- },
4945
- emit: async (items) => {
4946
- await this.emitHandler.emit(wf, def.id, items);
4947
- }
5613
+ registerCleanup,
5614
+ emit,
5615
+ polling
4948
5616
  });
4949
5617
  } catch (triggerError) {
4950
5618
  await this.stopTrigger(trigger);
@@ -4963,6 +5631,7 @@ var TriggerRuntimeService = class {
4963
5631
  async stopTriggersForWorkflow(workflow) {
4964
5632
  for (const node$1 of workflow.nodes) {
4965
5633
  if (node$1.kind !== "trigger") continue;
5634
+ if (node$1.config.triggerKind === "test") continue;
4966
5635
  await this.stopTrigger({
4967
5636
  workflowId: workflow.id,
4968
5637
  nodeId: node$1.id
@@ -5003,6 +5672,7 @@ var TriggerRuntimeService = class {
5003
5672
  const out = [];
5004
5673
  for (const def of wf.nodes) {
5005
5674
  if (def.kind !== "trigger") continue;
5675
+ if (def.config.triggerKind === "test") continue;
5006
5676
  out.push(this.describeTriggerNode(def));
5007
5677
  }
5008
5678
  return out;
@@ -5020,6 +5690,22 @@ var TriggerRuntimeService = class {
5020
5690
  if (this.diagnostics) this.diagnostics.warn(message);
5021
5691
  else console.warn(`[engine] ${message}`);
5022
5692
  }
5693
+ buildPollingHandle(trigger, emit) {
5694
+ const runtime = this.pollingTriggerRuntime;
5695
+ return {
5696
+ dedup: this.pollingTriggerDedupWindow,
5697
+ start: async (args) => {
5698
+ this.registerTriggerCleanupHandle(trigger, { stop: async () => {
5699
+ await runtime.stop(trigger);
5700
+ } });
5701
+ return runtime.start({
5702
+ trigger,
5703
+ emit,
5704
+ ...args
5705
+ });
5706
+ }
5707
+ };
5708
+ }
5023
5709
  isTestableTriggerNode(node$1) {
5024
5710
  return typeof node$1.getTestItems === "function";
5025
5711
  }
@@ -5171,12 +5857,15 @@ var EngineFactory = class {
5171
5857
  const storagePolicyEvaluator = new WorkflowStoragePolicyEvaluator(deps.nodeResolver);
5172
5858
  const terminalPersistence = new RunTerminalPersistenceCoordinator(deps.workflowExecutionRepository, storagePolicyEvaluator);
5173
5859
  const policyErrorServices = new WorkflowPolicyErrorServices(deps.nodeResolver);
5174
- const runStartService = new RunStartService(deps.runIdFactory, deps.workflowExecutionRepository, deps.runDataFactory, workflowSnapshotCodec, planningFactory, nodeStatePublisherFactory, runExecutionContextFactory, nodeActivationRequestComposer, activationEnqueueService, semantics, waiters, deps.workflowPolicyRuntimeDefaults, executionLimitsPolicy);
5860
+ const runStartService = new RunStartService(deps.runIdFactory, deps.workflowExecutionRepository, deps.runDataFactory, workflowSnapshotCodec, planningFactory, nodeStatePublisherFactory, runExecutionContextFactory, nodeActivationRequestComposer, activationEnqueueService, semantics, waiters, deps.workflowPolicyRuntimeDefaults, executionLimitsPolicy, nodeEventPublisher, persistedRunStateTerminalBuilder);
5175
5861
  const runContinuationService = new RunContinuationService(deps.activationIdFactory, deps.workflowExecutionRepository, deps.runDataFactory, runExecutionContextFactory, workflowSnapshotResolver, planningFactory, nodeStatePublisherFactory, credentialResolverFactory, nodeActivationRequestComposer, persistedRunStateTerminalBuilder, activationEnqueueService, nodeEventPublisher, semantics, waiters, policyErrorServices, terminalPersistence, executionLimitsPolicy);
5176
5862
  const nodeExecutionRequestHandler = new NodeExecutionRequestHandlerService(deps.workflowExecutionRepository, workflowSnapshotResolver, deps.runDataFactory, runExecutionContextFactory, nodeStatePublisherFactory, nodeActivationRequestComposer, deps.nodeExecutor, runContinuationService, executionLimitsPolicy);
5863
+ const pollingTriggerLogger = deps.pollingTriggerLogger ?? new NoOpPollingTriggerLogger();
5864
+ const pollingTriggerDedupWindow = new PollingTriggerDedupWindow();
5865
+ const pollingTriggerRuntime = new PollingTriggerRuntime(deps.triggerSetupStateRepository, pollingTriggerLogger);
5177
5866
  const triggerRuntime = new TriggerRuntimeService(deps.workflowRepository, deps.workflowActivationPolicy, deps.runIdFactory, deps.runDataFactory, deps.executionContextFactory, credentialResolverFactory, nodeStatePublisherFactory, deps.nodeResolver, deps.triggerSetupStateRepository, { emit: async (workflow, triggerNodeId, items) => {
5178
5867
  await runStartService.runWorkflow(workflow, triggerNodeId, items, void 0);
5179
- } }, executionLimitsPolicy, deps.triggerRuntimeDiagnostics);
5868
+ } }, executionLimitsPolicy, deps.triggerRuntimeDiagnostics, pollingTriggerRuntime, pollingTriggerDedupWindow);
5180
5869
  const engine = new Engine({
5181
5870
  liveWorkflowRepository: deps.liveWorkflowRepository,
5182
5871
  tokenRegistry: deps.tokenRegistry,
@@ -5467,6 +6156,18 @@ var WorkflowRepositoryWebhookTriggerMatcherFactory = class {
5467
6156
  };
5468
6157
 
5469
6158
  //#endregion
6159
+ Object.defineProperty(exports, 'AgentConfigInspector', {
6160
+ enumerable: true,
6161
+ get: function () {
6162
+ return AgentConfigInspector;
6163
+ }
6164
+ });
6165
+ Object.defineProperty(exports, 'AgentConnectionNodeCollector', {
6166
+ enumerable: true,
6167
+ get: function () {
6168
+ return AgentConnectionNodeCollector;
6169
+ }
6170
+ });
5470
6171
  Object.defineProperty(exports, 'AllWorkflowsActiveWorkflowActivationPolicy', {
5471
6172
  enumerable: true,
5472
6173
  get: function () {
@@ -5479,6 +6180,12 @@ Object.defineProperty(exports, 'CatalogBackedCostTrackingTelemetryFactory', {
5479
6180
  return CatalogBackedCostTrackingTelemetryFactory;
5480
6181
  }
5481
6182
  });
6183
+ Object.defineProperty(exports, 'ChainCursor', {
6184
+ enumerable: true,
6185
+ get: function () {
6186
+ return ChainCursor;
6187
+ }
6188
+ });
5482
6189
  Object.defineProperty(exports, 'ChildExecutionScopeFactory', {
5483
6190
  enumerable: true,
5484
6191
  get: function () {
@@ -5509,6 +6216,12 @@ Object.defineProperty(exports, 'ConnectionInvocationEventPublisher', {
5509
6216
  return ConnectionInvocationEventPublisher;
5510
6217
  }
5511
6218
  });
6219
+ Object.defineProperty(exports, 'ConnectionInvocationIdFactory', {
6220
+ enumerable: true,
6221
+ get: function () {
6222
+ return ConnectionInvocationIdFactory;
6223
+ }
6224
+ });
5512
6225
  Object.defineProperty(exports, 'ConnectionNodeIdFactory', {
5513
6226
  enumerable: true,
5514
6227
  get: function () {
@@ -5569,6 +6282,12 @@ Object.defineProperty(exports, 'DefaultExecutionContextFactory', {
5569
6282
  return DefaultExecutionContextFactory;
5570
6283
  }
5571
6284
  });
6285
+ Object.defineProperty(exports, 'DefaultWorkflowGraphFactory', {
6286
+ enumerable: true,
6287
+ get: function () {
6288
+ return DefaultWorkflowGraphFactory;
6289
+ }
6290
+ });
5572
6291
  Object.defineProperty(exports, 'ENGINE_EXECUTION_LIMITS_DEFAULTS', {
5573
6292
  enumerable: true,
5574
6293
  get: function () {
@@ -5713,6 +6432,12 @@ Object.defineProperty(exports, 'NoOpNodeExecutionTelemetry', {
5713
6432
  return NoOpNodeExecutionTelemetry;
5714
6433
  }
5715
6434
  });
6435
+ Object.defineProperty(exports, 'NoOpPollingTriggerLogger', {
6436
+ enumerable: true,
6437
+ get: function () {
6438
+ return NoOpPollingTriggerLogger;
6439
+ }
6440
+ });
5716
6441
  Object.defineProperty(exports, 'NoOpTelemetryArtifactReference', {
5717
6442
  enumerable: true,
5718
6443
  get: function () {
@@ -5731,6 +6456,12 @@ Object.defineProperty(exports, 'NoRetryPolicy', {
5731
6456
  return NoRetryPolicy;
5732
6457
  }
5733
6458
  });
6459
+ Object.defineProperty(exports, 'NodeBackedToolConfig', {
6460
+ enumerable: true,
6461
+ get: function () {
6462
+ return NodeBackedToolConfig;
6463
+ }
6464
+ });
5734
6465
  Object.defineProperty(exports, 'NodeEventPublisher', {
5735
6466
  enumerable: true,
5736
6467
  get: function () {
@@ -5749,6 +6480,12 @@ Object.defineProperty(exports, 'NodeExecutorFactory', {
5749
6480
  return NodeExecutorFactory;
5750
6481
  }
5751
6482
  });
6483
+ Object.defineProperty(exports, 'NodeIdSlugifier', {
6484
+ enumerable: true,
6485
+ get: function () {
6486
+ return NodeIdSlugifier;
6487
+ }
6488
+ });
5752
6489
  Object.defineProperty(exports, 'NodeInstanceFactory', {
5753
6490
  enumerable: true,
5754
6491
  get: function () {
@@ -5791,6 +6528,18 @@ Object.defineProperty(exports, 'PersistedWorkflowTokenRegistry', {
5791
6528
  return PersistedWorkflowTokenRegistry;
5792
6529
  }
5793
6530
  });
6531
+ Object.defineProperty(exports, 'PollingTriggerDedupWindow', {
6532
+ enumerable: true,
6533
+ get: function () {
6534
+ return PollingTriggerDedupWindow;
6535
+ }
6536
+ });
6537
+ Object.defineProperty(exports, 'PollingTriggerRuntime', {
6538
+ enumerable: true,
6539
+ get: function () {
6540
+ return PollingTriggerRuntime;
6541
+ }
6542
+ });
5794
6543
  Object.defineProperty(exports, 'RetryPolicy', {
5795
6544
  enumerable: true,
5796
6545
  get: function () {
@@ -5851,6 +6600,24 @@ Object.defineProperty(exports, 'UnavailableBinaryStorage', {
5851
6600
  return UnavailableBinaryStorage;
5852
6601
  }
5853
6602
  });
6603
+ Object.defineProperty(exports, 'WhenBuilder', {
6604
+ enumerable: true,
6605
+ get: function () {
6606
+ return WhenBuilder;
6607
+ }
6608
+ });
6609
+ Object.defineProperty(exports, 'WorkflowBuilder', {
6610
+ enumerable: true,
6611
+ get: function () {
6612
+ return WorkflowBuilder;
6613
+ }
6614
+ });
6615
+ Object.defineProperty(exports, 'WorkflowDefinitionError', {
6616
+ enumerable: true,
6617
+ get: function () {
6618
+ return WorkflowDefinitionError;
6619
+ }
6620
+ });
5854
6621
  Object.defineProperty(exports, 'WorkflowExecutableNodeClassifier', {
5855
6622
  enumerable: true,
5856
6623
  get: function () {
@@ -5893,12 +6660,6 @@ Object.defineProperty(exports, 'WorkflowStoragePolicyEvaluator', {
5893
6660
  return WorkflowStoragePolicyEvaluator;
5894
6661
  }
5895
6662
  });
5896
- Object.defineProperty(exports, '__decorate', {
5897
- enumerable: true,
5898
- get: function () {
5899
- return __decorate;
5900
- }
5901
- });
5902
6663
  Object.defineProperty(exports, '__toESM', {
5903
6664
  enumerable: true,
5904
6665
  get: function () {
@@ -5989,4 +6750,4 @@ Object.defineProperty(exports, 'tool', {
5989
6750
  return tool;
5990
6751
  }
5991
6752
  });
5992
- //# sourceMappingURL=runtime-B3Og-_St.cjs.map
6753
+ //# sourceMappingURL=runtime-DKXJwTNv.cjs.map