@ai-setting/roy-agent-core 1.4.11 → 1.4.13

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.
@@ -0,0 +1,3140 @@
1
+ import {
2
+ AgentComponentAdapter,
3
+ AskUserError,
4
+ createNodeInterruptEvent,
5
+ init_agent_component_adapter,
6
+ init_workflow_hil
7
+ } from "./chunk-0q6s9wm6.js";
8
+ import {
9
+ createLogger,
10
+ getMaxOutput,
11
+ init_logger,
12
+ simplifyFilePath
13
+ } from "./chunk-a9qmy3sc.js";
14
+ import {
15
+ getTracerProvider,
16
+ init_tracer_provider
17
+ } from "./chunk-q9j99fsm.js";
18
+ import {
19
+ __esm,
20
+ __export,
21
+ __legacyDecorateClassTS,
22
+ __require
23
+ } from "./chunk-wbkh7wat.js";
24
+
25
+ // src/env/workflow/engine/event-bus.ts
26
+ class EventBus {
27
+ handlers = new Map;
28
+ wildcardHandlers = new Set;
29
+ constructor() {}
30
+ on(eventType, handler) {
31
+ let handlers = this.handlers.get(eventType);
32
+ if (!handlers) {
33
+ handlers = new Set;
34
+ this.handlers.set(eventType, handlers);
35
+ }
36
+ handlers.add(handler);
37
+ return () => this.off(eventType, handler);
38
+ }
39
+ once(eventType, handler) {
40
+ let executed = false;
41
+ const wrappedHandler = async (event) => {
42
+ if (executed) {
43
+ return;
44
+ }
45
+ executed = true;
46
+ try {
47
+ await handler(event);
48
+ } catch (error) {
49
+ console.error("Event handler error:", error);
50
+ }
51
+ this.off(eventType, wrappedHandler);
52
+ };
53
+ return this.on(eventType, wrappedHandler);
54
+ }
55
+ off(eventType, handler) {
56
+ const handlers = this.handlers.get(eventType);
57
+ if (handlers) {
58
+ handlers.delete(handler);
59
+ if (handlers.size === 0) {
60
+ this.handlers.delete(eventType);
61
+ }
62
+ }
63
+ }
64
+ onAny(handler) {
65
+ this.wildcardHandlers.add(handler);
66
+ return () => {
67
+ this.wildcardHandlers.delete(handler);
68
+ };
69
+ }
70
+ async publish(event, waitForHandlers = false) {
71
+ const handlers = this.handlers.get(event.type);
72
+ const handlerPromises = [];
73
+ if (handlers) {
74
+ for (const handler of handlers) {
75
+ const promise = this.executeHandler(handler, event);
76
+ handlerPromises.push(promise);
77
+ }
78
+ }
79
+ for (const handler of this.wildcardHandlers) {
80
+ const promise = this.executeHandler(handler, event);
81
+ handlerPromises.push(promise);
82
+ }
83
+ if (waitForHandlers && handlerPromises.length > 0) {
84
+ await Promise.allSettled(handlerPromises);
85
+ }
86
+ }
87
+ async executeHandler(handler, event) {
88
+ try {
89
+ await handler(event);
90
+ } catch (error) {
91
+ console.error("Event handler error:", error);
92
+ }
93
+ }
94
+ clear() {
95
+ this.handlers.clear();
96
+ this.wildcardHandlers.clear();
97
+ }
98
+ getStats() {
99
+ let totalHandlers = 0;
100
+ for (const handlers of this.handlers.values()) {
101
+ totalHandlers += handlers.size;
102
+ }
103
+ totalHandlers += this.wildcardHandlers.size;
104
+ return {
105
+ eventTypes: this.handlers.size,
106
+ wildcardHandlers: this.wildcardHandlers.size,
107
+ totalHandlers
108
+ };
109
+ }
110
+ }
111
+ var init_event_bus = () => {};
112
+
113
+ // src/env/workflow/engine/dag-manager.ts
114
+ class DAGManager {
115
+ workflow;
116
+ nodeMap;
117
+ extendedDefinition = null;
118
+ cachedAnalysis = null;
119
+ constructor(workflow) {
120
+ if (!workflow.nodes || workflow.nodes.length === 0) {
121
+ throw new Error("At least one node is required");
122
+ }
123
+ this.workflow = workflow;
124
+ this.nodeMap = new Map;
125
+ for (const node of workflow.nodes) {
126
+ if (node.id === "") {
127
+ throw new Error("Node ID cannot be empty");
128
+ }
129
+ if (this.nodeMap.has(node.id)) {
130
+ throw new Error(`Duplicate node ID: ${node.id}`);
131
+ }
132
+ this.nodeMap.set(node.id, node);
133
+ }
134
+ }
135
+ getExtendedDefinition() {
136
+ if (this.extendedDefinition) {
137
+ return this.extendedDefinition;
138
+ }
139
+ const analysis = this.analyze();
140
+ this.extendedDefinition = {
141
+ ...this.workflow,
142
+ computedEntry: analysis.entryNodes,
143
+ nodeMap: this.nodeMap,
144
+ topologicalOrder: this.getTopologicalOrder()
145
+ };
146
+ return this.extendedDefinition;
147
+ }
148
+ analyze() {
149
+ if (this.cachedAnalysis) {
150
+ return this.cachedAnalysis;
151
+ }
152
+ const dependencies = this.buildDependenciesMap();
153
+ const dependents = this.buildDependentsMap(dependencies);
154
+ const entryNodes = this.findEntryNodes(dependencies);
155
+ const exitNodes = this.findExitNodes(dependents);
156
+ const levels = this.computeLevels(dependencies);
157
+ const criticalPath = this.findCriticalPath(levels, dependencies);
158
+ this.cachedAnalysis = {
159
+ entryNodes,
160
+ exitNodes,
161
+ levels,
162
+ dependencies,
163
+ dependents,
164
+ criticalPath
165
+ };
166
+ return this.cachedAnalysis;
167
+ }
168
+ buildDependenciesMap() {
169
+ const dependencies = new Map;
170
+ for (const node of this.workflow.nodes) {
171
+ const deps = node.depends_on || [];
172
+ dependencies.set(node.id, [...deps]);
173
+ }
174
+ return dependencies;
175
+ }
176
+ buildDependentsMap(dependencies) {
177
+ const dependentsMap = new Map;
178
+ for (const nodeId of dependencies.keys()) {
179
+ dependentsMap.set(nodeId, []);
180
+ }
181
+ for (const [nodeId, deps] of dependencies.entries()) {
182
+ for (const dep of deps) {
183
+ const nodeDependents = dependentsMap.get(dep) || [];
184
+ nodeDependents.push(nodeId);
185
+ dependentsMap.set(dep, nodeDependents);
186
+ }
187
+ }
188
+ return dependentsMap;
189
+ }
190
+ findEntryNodes(dependencies) {
191
+ const entryNodes = [];
192
+ for (const [nodeId, deps] of dependencies.entries()) {
193
+ if (deps.length === 0) {
194
+ entryNodes.push(nodeId);
195
+ }
196
+ }
197
+ return entryNodes;
198
+ }
199
+ findExitNodes(dependents) {
200
+ const exitNodes = [];
201
+ for (const [nodeId, deps] of dependents.entries()) {
202
+ if (deps.length === 0) {
203
+ exitNodes.push(nodeId);
204
+ }
205
+ }
206
+ return exitNodes;
207
+ }
208
+ computeLevels(dependencies) {
209
+ const levels = [];
210
+ const assigned = new Set;
211
+ const nodeLevels = new Map;
212
+ const dependentsMap = this.buildDependentsMap(dependencies);
213
+ const entryNodes = this.findEntryNodes(dependencies);
214
+ const queue = [];
215
+ for (const entry of entryNodes) {
216
+ queue.push({ nodeId: entry, level: 0 });
217
+ nodeLevels.set(entry, 0);
218
+ }
219
+ while (queue.length > 0) {
220
+ const { nodeId, level } = queue.shift();
221
+ if (assigned.has(nodeId)) {
222
+ const currentLevel = nodeLevels.get(nodeId) || 0;
223
+ if (level > currentLevel) {
224
+ nodeLevels.set(nodeId, level);
225
+ }
226
+ continue;
227
+ }
228
+ assigned.add(nodeId);
229
+ nodeLevels.set(nodeId, level);
230
+ const dependentsOfNode = dependentsMap.get(nodeId) || [];
231
+ for (const dependent of dependentsOfNode) {
232
+ if (!assigned.has(dependent)) {
233
+ queue.push({ nodeId: dependent, level: level + 1 });
234
+ }
235
+ }
236
+ }
237
+ for (const nodeId of dependencies.keys()) {
238
+ if (!nodeLevels.has(nodeId)) {
239
+ nodeLevels.set(nodeId, 0);
240
+ }
241
+ }
242
+ const maxLevel = Math.max(...nodeLevels.values(), 0);
243
+ for (let i = 0;i <= maxLevel; i++) {
244
+ levels.push([]);
245
+ }
246
+ for (const [nodeId, level] of nodeLevels.entries()) {
247
+ levels[level].push(nodeId);
248
+ }
249
+ return levels;
250
+ }
251
+ findCriticalPath(levels, dependencies) {
252
+ if (levels.length === 0) {
253
+ return [];
254
+ }
255
+ const longestPath = new Map;
256
+ const allNodes = [];
257
+ for (const level of levels) {
258
+ allNodes.push(...level);
259
+ }
260
+ for (const nodeId of allNodes) {
261
+ const deps = dependencies.get(nodeId) || [];
262
+ if (deps.length === 0) {
263
+ longestPath.set(nodeId, { length: 1, path: [nodeId] });
264
+ } else {
265
+ let maxLength2 = 0;
266
+ let maxPath = [];
267
+ for (const dep of deps) {
268
+ const depInfo = longestPath.get(dep);
269
+ if (depInfo && depInfo.length > maxLength2) {
270
+ maxLength2 = depInfo.length;
271
+ maxPath = depInfo.path;
272
+ }
273
+ }
274
+ longestPath.set(nodeId, {
275
+ length: maxLength2 + 1,
276
+ path: [...maxPath, nodeId]
277
+ });
278
+ }
279
+ }
280
+ let maxLength = 0;
281
+ let criticalPath = [];
282
+ for (const [, info] of longestPath.entries()) {
283
+ if (info.length > maxLength) {
284
+ maxLength = info.length;
285
+ criticalPath = info.path;
286
+ }
287
+ }
288
+ return criticalPath;
289
+ }
290
+ getTopologicalOrder() {
291
+ const dependencies = this.buildDependenciesMap();
292
+ const dependents = this.buildDependentsMap(dependencies);
293
+ const inDegree = new Map;
294
+ for (const nodeId of dependencies.keys()) {
295
+ inDegree.set(nodeId, dependencies.get(nodeId)?.length || 0);
296
+ }
297
+ const queue = [];
298
+ for (const [nodeId, degree] of inDegree.entries()) {
299
+ if (degree === 0) {
300
+ queue.push(nodeId);
301
+ }
302
+ }
303
+ const result = [];
304
+ while (queue.length > 0) {
305
+ const nodeId = queue.shift();
306
+ result.push(nodeId);
307
+ const nodeDependents = dependents.get(nodeId) || [];
308
+ for (const dependent of nodeDependents) {
309
+ const currentDegree = inDegree.get(dependent) || 0;
310
+ inDegree.set(dependent, currentDegree - 1);
311
+ if (currentDegree - 1 === 0) {
312
+ queue.push(dependent);
313
+ }
314
+ }
315
+ }
316
+ return result;
317
+ }
318
+ getReadyNodes(completedNodes) {
319
+ const dependencies = this.buildDependenciesMap();
320
+ const ready = [];
321
+ for (const nodeId of dependencies.keys()) {
322
+ if (completedNodes.has(nodeId)) {
323
+ continue;
324
+ }
325
+ if (this.areDependenciesMet(nodeId, completedNodes)) {
326
+ ready.push(nodeId);
327
+ }
328
+ }
329
+ return ready;
330
+ }
331
+ areDependenciesMet(nodeId, completedNodes) {
332
+ const node = this.nodeMap.get(nodeId);
333
+ if (!node) {
334
+ return false;
335
+ }
336
+ const dependencies = node.depends_on || [];
337
+ for (const dep of dependencies) {
338
+ if (!completedNodes.has(dep)) {
339
+ return false;
340
+ }
341
+ }
342
+ return true;
343
+ }
344
+ isCyclic() {
345
+ const dependencies = this.buildDependenciesMap();
346
+ const order = this.getTopologicalOrderInternal(dependencies);
347
+ return order.length !== this.workflow.nodes.length;
348
+ }
349
+ getTopologicalOrderInternal(dependencies) {
350
+ const dependents = this.buildDependentsMap(dependencies);
351
+ const inDegree = new Map;
352
+ for (const nodeId of dependencies.keys()) {
353
+ inDegree.set(nodeId, dependencies.get(nodeId)?.length || 0);
354
+ }
355
+ const queue = [];
356
+ for (const [nodeId, degree] of inDegree.entries()) {
357
+ if (degree === 0) {
358
+ queue.push(nodeId);
359
+ }
360
+ }
361
+ const result = [];
362
+ while (queue.length > 0) {
363
+ const nodeId = queue.shift();
364
+ result.push(nodeId);
365
+ const nodeDependents = dependents.get(nodeId) || [];
366
+ for (const dependent of nodeDependents) {
367
+ const currentDegree = inDegree.get(dependent) || 0;
368
+ inDegree.set(dependent, currentDegree - 1);
369
+ if (currentDegree - 1 === 0) {
370
+ queue.push(dependent);
371
+ }
372
+ }
373
+ }
374
+ return result;
375
+ }
376
+ validate() {
377
+ const errors = [];
378
+ const nodeIds = new Set;
379
+ for (const node of this.workflow.nodes) {
380
+ if (node.id === "") {
381
+ errors.push("Node ID cannot be empty");
382
+ continue;
383
+ }
384
+ if (nodeIds.has(node.id)) {
385
+ errors.push(`Duplicate node ID: ${node.id}`);
386
+ }
387
+ nodeIds.add(node.id);
388
+ }
389
+ for (const node of this.workflow.nodes) {
390
+ const deps = node.depends_on || [];
391
+ for (const dep of deps) {
392
+ if (!nodeIds.has(dep)) {
393
+ errors.push(`Node '${node.id}' depends on non-existent node '${dep}'`);
394
+ }
395
+ }
396
+ }
397
+ if (this.isCyclic()) {
398
+ errors.push("Workflow contains a cycle");
399
+ }
400
+ return {
401
+ valid: errors.length === 0,
402
+ errors
403
+ };
404
+ }
405
+ addNode(node) {
406
+ if (!node.id || node.id.trim() === "") {
407
+ throw new Error("Node ID cannot be empty");
408
+ }
409
+ if (this.nodeMap.has(node.id)) {
410
+ throw new Error(`Node with ID '${node.id}' already exists`);
411
+ }
412
+ const deps = node.depends_on || [];
413
+ for (const dep of deps) {
414
+ if (!this.nodeMap.has(dep)) {
415
+ throw new Error(`Cannot add node '${node.id}': depends on non-existent node '${dep}'`);
416
+ }
417
+ }
418
+ const originalNodes = [...this.workflow.nodes];
419
+ this.workflow.nodes.push(node);
420
+ if (this.isCyclic()) {
421
+ this.workflow.nodes = originalNodes;
422
+ throw new Error(`Cannot add node '${node.id}': would create a cycle in the workflow`);
423
+ }
424
+ this.nodeMap.set(node.id, node);
425
+ this.cachedAnalysis = null;
426
+ this.extendedDefinition = null;
427
+ }
428
+ removeNode(nodeId) {
429
+ if (!this.nodeMap.has(nodeId)) {
430
+ throw new Error(`Node '${nodeId}' does not exist`);
431
+ }
432
+ const dependents = this.getDependents(nodeId);
433
+ if (dependents.length > 0) {
434
+ throw new Error(`Cannot remove node '${nodeId}': other nodes depend on it: ${dependents.join(", ")}`);
435
+ }
436
+ this.workflow.nodes = this.workflow.nodes.filter((n) => n.id !== nodeId);
437
+ this.nodeMap.delete(nodeId);
438
+ this.cachedAnalysis = null;
439
+ this.extendedDefinition = null;
440
+ }
441
+ getDependents(nodeId) {
442
+ const analysis = this.analyze();
443
+ return analysis.dependents.get(nodeId) || [];
444
+ }
445
+ getDefinition() {
446
+ return this.workflow;
447
+ }
448
+ getNode(nodeId) {
449
+ return this.nodeMap.get(nodeId);
450
+ }
451
+ getNodeIds() {
452
+ return Array.from(this.nodeMap.keys());
453
+ }
454
+ getNodeCount() {
455
+ return this.nodeMap.size;
456
+ }
457
+ }
458
+ var init_dag_manager = () => {};
459
+
460
+ // src/env/workflow/engine/scheduler.ts
461
+ class Scheduler {
462
+ dagManager;
463
+ options;
464
+ pending = new Set;
465
+ ready = new Set;
466
+ running = new Set;
467
+ completed = new Set;
468
+ failed = new Set;
469
+ skipped = new Set;
470
+ constructor(dagManager, options) {
471
+ this.dagManager = dagManager;
472
+ const parallelLimit = options?.parallelLimit;
473
+ this.options = {
474
+ parallelLimit: parallelLimit === undefined ? 1 : parallelLimit
475
+ };
476
+ const analysis = dagManager.analyze();
477
+ for (const nodeId of analysis.dependencies.keys()) {
478
+ this.pending.add(nodeId);
479
+ }
480
+ this.updateReadyNodes(new Set);
481
+ }
482
+ getReadyNodes(completedNodes) {
483
+ const allCompleted = new Set(completedNodes);
484
+ for (const nodeId of this.completed) {
485
+ allCompleted.add(nodeId);
486
+ }
487
+ const readyFromDag = this.dagManager.getReadyNodes(allCompleted);
488
+ const ready = [];
489
+ for (const nodeId of readyFromDag) {
490
+ const isProcessed = this.running.has(nodeId) || this.completed.has(nodeId) || this.failed.has(nodeId) || this.skipped.has(nodeId);
491
+ if (!isProcessed) {
492
+ ready.push(nodeId);
493
+ }
494
+ }
495
+ return ready.sort();
496
+ }
497
+ getRunningCount() {
498
+ return this.running.size;
499
+ }
500
+ canStartMore() {
501
+ if (this.options.parallelLimit === null) {
502
+ return true;
503
+ }
504
+ if (this.options.parallelLimit <= 0) {
505
+ return false;
506
+ }
507
+ return this.running.size < this.options.parallelLimit;
508
+ }
509
+ markStarted(nodeId) {
510
+ if (!this.running.has(nodeId)) {
511
+ this.running.add(nodeId);
512
+ this.ready.delete(nodeId);
513
+ this.pending.delete(nodeId);
514
+ }
515
+ }
516
+ isRunning(nodeId) {
517
+ return this.running.has(nodeId);
518
+ }
519
+ isCompleted(nodeId) {
520
+ return this.completed.has(nodeId);
521
+ }
522
+ isFailed(nodeId) {
523
+ return this.failed.has(nodeId);
524
+ }
525
+ isPending(nodeId) {
526
+ return this.pending.has(nodeId);
527
+ }
528
+ isReady(nodeId) {
529
+ return this.ready.has(nodeId);
530
+ }
531
+ markCompleted(nodeId) {
532
+ this.running.delete(nodeId);
533
+ this.ready.delete(nodeId);
534
+ this.pending.delete(nodeId);
535
+ this.failed.delete(nodeId);
536
+ this.skipped.delete(nodeId);
537
+ this.completed.add(nodeId);
538
+ }
539
+ markFailed(nodeId) {
540
+ this.running.delete(nodeId);
541
+ this.ready.delete(nodeId);
542
+ this.pending.delete(nodeId);
543
+ this.completed.delete(nodeId);
544
+ this.skipped.delete(nodeId);
545
+ this.failed.add(nodeId);
546
+ }
547
+ markSkipped(nodeId) {
548
+ if (this.running.has(nodeId)) {
549
+ this.running.delete(nodeId);
550
+ }
551
+ if (this.ready.has(nodeId)) {
552
+ this.ready.delete(nodeId);
553
+ }
554
+ if (this.pending.has(nodeId)) {
555
+ this.pending.delete(nodeId);
556
+ }
557
+ this.skipped.add(nodeId);
558
+ }
559
+ reset() {
560
+ this.running.clear();
561
+ this.completed.clear();
562
+ this.failed.clear();
563
+ this.skipped.clear();
564
+ const analysis = this.dagManager.analyze();
565
+ this.pending.clear();
566
+ this.ready.clear();
567
+ for (const nodeId of analysis.dependencies.keys()) {
568
+ this.pending.add(nodeId);
569
+ }
570
+ this.updateReadyNodes(new Set);
571
+ }
572
+ getState() {
573
+ this.updateReadyNodes(new Set);
574
+ return {
575
+ pending: Array.from(this.pending).sort(),
576
+ ready: Array.from(this.ready).sort(),
577
+ running: Array.from(this.running).sort(),
578
+ completed: Array.from(this.completed).sort(),
579
+ failed: Array.from(this.failed).sort(),
580
+ skipped: Array.from(this.skipped).sort()
581
+ };
582
+ }
583
+ updateReadyNodes(completedNodes) {
584
+ const allCompleted = new Set(completedNodes);
585
+ for (const nodeId of this.completed) {
586
+ allCompleted.add(nodeId);
587
+ }
588
+ const analysis = this.dagManager.analyze();
589
+ const allNodeIds = Array.from(analysis.dependencies.keys());
590
+ this.ready.clear();
591
+ for (const nodeId of allNodeIds) {
592
+ if (this.running.has(nodeId) || this.completed.has(nodeId) || this.failed.has(nodeId) || this.skipped.has(nodeId)) {
593
+ continue;
594
+ }
595
+ if (this.dagManager.areDependenciesMet(nodeId, allCompleted)) {
596
+ this.ready.add(nodeId);
597
+ }
598
+ }
599
+ }
600
+ getParallelLimit() {
601
+ return this.options.parallelLimit;
602
+ }
603
+ setParallelLimit(limit) {
604
+ this.options.parallelLimit = limit;
605
+ }
606
+ }
607
+ var init_scheduler = () => {};
608
+
609
+ // src/env/workflow/types/event.ts
610
+ import { z } from "zod";
611
+ function createWorkflowEvent(type, runId, data) {
612
+ return {
613
+ type,
614
+ run_id: runId,
615
+ timestamp: Date.now(),
616
+ ...data
617
+ };
618
+ }
619
+ var BaseEventSchema, WorkflowStartedEventSchema, WorkflowPausedEventSchema, WorkflowResumedEventSchema, WorkflowStoppedEventSchema, WorkflowCompletedEventSchema, WorkflowFailedEventSchema, WorkflowOutputEventSchema, NodeScheduledEventSchema, NodeStartedEventSchema, NodeProgressEventSchema, NodeCompletedEventSchema, NodeFailedEventSchema, NodeSkippedEventSchema, NodeDataEventSchema, NodeAddedEventSchema, NodeRemovedEventSchema, ControlPauseEventSchema, ControlResumeEventSchema, ControlStopEventSchema, NodeInterruptEventSchema, WorkflowAskUserEventSchema, WorkflowEventSchema;
620
+ var init_event = __esm(() => {
621
+ BaseEventSchema = z.object({
622
+ type: z.string(),
623
+ run_id: z.string(),
624
+ timestamp: z.number()
625
+ });
626
+ WorkflowStartedEventSchema = BaseEventSchema.extend({
627
+ type: z.literal("workflow.started"),
628
+ workflow_name: z.string(),
629
+ input: z.record(z.string(), z.unknown()).optional()
630
+ });
631
+ WorkflowPausedEventSchema = BaseEventSchema.extend({
632
+ type: z.literal("workflow.paused")
633
+ });
634
+ WorkflowResumedEventSchema = BaseEventSchema.extend({
635
+ type: z.literal("workflow.resumed")
636
+ });
637
+ WorkflowStoppedEventSchema = BaseEventSchema.extend({
638
+ type: z.literal("workflow.stopped"),
639
+ reason: z.string()
640
+ });
641
+ WorkflowCompletedEventSchema = BaseEventSchema.extend({
642
+ type: z.literal("workflow.completed"),
643
+ result: z.record(z.string(), z.unknown()).optional(),
644
+ duration_ms: z.number()
645
+ });
646
+ WorkflowFailedEventSchema = BaseEventSchema.extend({
647
+ type: z.literal("workflow.failed"),
648
+ error: z.object({
649
+ message: z.string(),
650
+ stack: z.string().optional()
651
+ }),
652
+ failed_at: z.string()
653
+ });
654
+ WorkflowOutputEventSchema = BaseEventSchema.extend({
655
+ type: z.literal("workflow.output"),
656
+ output: z.record(z.string(), z.unknown())
657
+ });
658
+ NodeScheduledEventSchema = BaseEventSchema.extend({
659
+ type: z.literal("node.scheduled"),
660
+ node_id: z.string()
661
+ });
662
+ NodeStartedEventSchema = BaseEventSchema.extend({
663
+ type: z.literal("node.started"),
664
+ node_id: z.string(),
665
+ input: z.any(),
666
+ agentSessionId: z.string().optional(),
667
+ userResponse: z.string().optional()
668
+ });
669
+ NodeProgressEventSchema = BaseEventSchema.extend({
670
+ type: z.literal("node.progress"),
671
+ node_id: z.string(),
672
+ progress: z.number(),
673
+ message: z.string().optional()
674
+ });
675
+ NodeCompletedEventSchema = BaseEventSchema.extend({
676
+ type: z.literal("node.completed"),
677
+ node_id: z.string(),
678
+ output: z.any(),
679
+ duration_ms: z.number()
680
+ });
681
+ NodeFailedEventSchema = BaseEventSchema.extend({
682
+ type: z.literal("node.failed"),
683
+ node_id: z.string(),
684
+ error: z.object({
685
+ message: z.string(),
686
+ stack: z.string().optional()
687
+ })
688
+ });
689
+ NodeSkippedEventSchema = BaseEventSchema.extend({
690
+ type: z.literal("node.skipped"),
691
+ node_id: z.string(),
692
+ reason: z.string()
693
+ });
694
+ NodeDataEventSchema = BaseEventSchema.extend({
695
+ type: z.literal("node.data"),
696
+ from_node: z.string(),
697
+ to_node: z.string(),
698
+ data: z.any()
699
+ });
700
+ NodeAddedEventSchema = BaseEventSchema.extend({
701
+ type: z.literal("node.added"),
702
+ node_id: z.string(),
703
+ node: z.any()
704
+ });
705
+ NodeRemovedEventSchema = BaseEventSchema.extend({
706
+ type: z.literal("node.removed"),
707
+ node_id: z.string()
708
+ });
709
+ ControlPauseEventSchema = BaseEventSchema.extend({
710
+ type: z.literal("control.pause")
711
+ });
712
+ ControlResumeEventSchema = BaseEventSchema.extend({
713
+ type: z.literal("control.resume")
714
+ });
715
+ ControlStopEventSchema = BaseEventSchema.extend({
716
+ type: z.literal("control.stop")
717
+ });
718
+ NodeInterruptEventSchema = BaseEventSchema.extend({
719
+ type: z.literal("node.interrupt"),
720
+ node_id: z.string(),
721
+ node_type: z.string(),
722
+ query: z.string()
723
+ });
724
+ WorkflowAskUserEventSchema = BaseEventSchema.extend({
725
+ type: z.literal("workflow.ask-user"),
726
+ session_id: z.string(),
727
+ node_id: z.string(),
728
+ node_type: z.string(),
729
+ query: z.string()
730
+ });
731
+ WorkflowEventSchema = z.union([
732
+ WorkflowStartedEventSchema,
733
+ WorkflowPausedEventSchema,
734
+ WorkflowResumedEventSchema,
735
+ WorkflowStoppedEventSchema,
736
+ WorkflowCompletedEventSchema,
737
+ WorkflowFailedEventSchema,
738
+ WorkflowOutputEventSchema,
739
+ NodeScheduledEventSchema,
740
+ NodeStartedEventSchema,
741
+ NodeProgressEventSchema,
742
+ NodeCompletedEventSchema,
743
+ NodeFailedEventSchema,
744
+ NodeSkippedEventSchema,
745
+ NodeDataEventSchema,
746
+ NodeAddedEventSchema,
747
+ NodeRemovedEventSchema,
748
+ ControlPauseEventSchema,
749
+ ControlResumeEventSchema,
750
+ ControlStopEventSchema,
751
+ NodeInterruptEventSchema,
752
+ WorkflowAskUserEventSchema
753
+ ]);
754
+ });
755
+
756
+ // src/env/workflow/types/workflow.ts
757
+ import { z as z2 } from "zod";
758
+ var DependsOnSchema, RetryConfigSchema, NodeDefinitionSchema, WorkflowConfigSchema, OutputDefinitionSchema, WorkflowMetadataSchema, WorkflowDefinitionSchema;
759
+ var init_workflow = __esm(() => {
760
+ DependsOnSchema = z2.array(z2.string());
761
+ RetryConfigSchema = z2.object({
762
+ max_attempts: z2.number().min(1).default(1),
763
+ backoff: z2.enum(["fixed", "exponential"]).default("exponential"),
764
+ initial_delay: z2.number().min(0).default(1000)
765
+ });
766
+ NodeDefinitionSchema = z2.object({
767
+ id: z2.string().min(1, "Node ID is required"),
768
+ type: z2.string().min(1, "Node type is required"),
769
+ name: z2.string().optional(),
770
+ config: z2.record(z2.string(), z2.unknown()).optional().default({}),
771
+ depends_on: z2.array(z2.string()).optional(),
772
+ condition: z2.string().optional(),
773
+ retry: RetryConfigSchema.optional(),
774
+ timeout: z2.number().optional()
775
+ });
776
+ WorkflowConfigSchema = z2.object({
777
+ parallel_limit: z2.number().nullable().optional(),
778
+ timeout: z2.number().nullable().optional(),
779
+ retry: RetryConfigSchema.optional(),
780
+ debug: z2.boolean().optional()
781
+ });
782
+ OutputDefinitionSchema = z2.object({
783
+ name: z2.string(),
784
+ source: z2.string(),
785
+ path: z2.string()
786
+ });
787
+ WorkflowMetadataSchema = z2.object({
788
+ author: z2.string().optional(),
789
+ taskId: z2.number().optional(),
790
+ tags: z2.array(z2.string()).optional().default([]),
791
+ created_at: z2.string().optional(),
792
+ updated_at: z2.string().optional()
793
+ });
794
+ WorkflowDefinitionSchema = z2.object({
795
+ name: z2.string().min(1, "Workflow name is required"),
796
+ version: z2.string().default("1.0"),
797
+ description: z2.string().optional(),
798
+ config: WorkflowConfigSchema.optional().default({}),
799
+ nodes: z2.array(NodeDefinitionSchema).min(1, "At least one node is required"),
800
+ entry: z2.union([z2.string(), z2.array(z2.string())]).default("__default_entry__"),
801
+ outputs: z2.array(OutputDefinitionSchema).optional().default([]),
802
+ metadata: WorkflowMetadataSchema.optional().default({})
803
+ });
804
+ });
805
+
806
+ // src/env/workflow/types/workflow-message.ts
807
+ import { z as z3 } from "zod";
808
+ var WorkflowMessageRoleSchema;
809
+ var init_workflow_message = __esm(() => {
810
+ init_workflow_hil();
811
+ WorkflowMessageRoleSchema = z3.enum([
812
+ "workflow.node.call",
813
+ "workflow.node.interrupt",
814
+ "workflow.node.result",
815
+ "workflow.node.resume"
816
+ ]);
817
+ });
818
+
819
+ // src/env/workflow/types/workflow-session.ts
820
+ var init_workflow_session = () => {};
821
+
822
+ // src/env/workflow/types/context.ts
823
+ var init_context = () => {};
824
+
825
+ // src/env/workflow/types/run.ts
826
+ import { z as z4 } from "zod";
827
+ var RunStatusSchema, NodeStatusSchema;
828
+ var init_run = __esm(() => {
829
+ init_workflow_message();
830
+ RunStatusSchema = z4.enum([
831
+ "idle",
832
+ "running",
833
+ "paused",
834
+ "stopped",
835
+ "completed",
836
+ "failed"
837
+ ]);
838
+ NodeStatusSchema = z4.enum([
839
+ "pending",
840
+ "scheduled",
841
+ "started",
842
+ "running",
843
+ "completed",
844
+ "failed",
845
+ "skipped"
846
+ ]);
847
+ });
848
+
849
+ // src/env/workflow/types/index.ts
850
+ var init_types = __esm(() => {
851
+ init_run();
852
+ init_workflow();
853
+ init_workflow_message();
854
+ init_workflow_session();
855
+ init_context();
856
+ init_workflow_hil();
857
+ init_event();
858
+ init_run();
859
+ });
860
+
861
+ // src/env/log-trace/decorator.ts
862
+ function Traced(options) {
863
+ return function(target, propertyKey, descriptor) {
864
+ const originalFn = descriptor.value;
865
+ const spanName = options?.name || propertyKey;
866
+ descriptor.value = wrapFunction(originalFn, spanName, {
867
+ recordParams: options?.recordParams ?? true,
868
+ recordResult: options?.recordResult ?? false,
869
+ recordError: options?.recordError ?? true,
870
+ log: options?.log ?? false,
871
+ maxLogSize: options?.maxLogSize,
872
+ paramFilter: options?.paramFilter
873
+ });
874
+ return descriptor;
875
+ };
876
+ }
877
+ function TracedAs(name, options) {
878
+ return Traced({ name, ...options });
879
+ }
880
+ function TracedLightweight(options) {
881
+ return Traced({ recordParams: false, recordResult: false, log: options?.log ?? false, maxLogSize: options?.maxLogSize });
882
+ }
883
+ function wrapFunction(fn, name, options) {
884
+ const shouldLog = options?.log ?? false;
885
+ const getMaxLogSize = () => {
886
+ if (options?.maxLogSize !== undefined) {
887
+ return options.maxLogSize;
888
+ }
889
+ const configMaxOutput = getMaxOutput();
890
+ return configMaxOutput !== undefined ? configMaxOutput : 500;
891
+ };
892
+ const truncate = (obj) => {
893
+ if (obj === undefined)
894
+ return;
895
+ if (obj === null)
896
+ return null;
897
+ const maxLogSize = getMaxLogSize();
898
+ let str;
899
+ try {
900
+ str = typeof obj === "string" ? obj : JSON.stringify(obj, null, 0).replace(/\n/g, "");
901
+ } catch (e) {
902
+ str = `[Object with circular reference: ${e instanceof Error ? e.message : String(e)}]`;
903
+ }
904
+ if (maxLogSize > 0 && str.length > maxLogSize) {
905
+ return str.slice(0, maxLogSize) + " [TRUNCATED]";
906
+ }
907
+ try {
908
+ return JSON.parse(str);
909
+ } catch {
910
+ return str;
911
+ }
912
+ };
913
+ const truncateString = (obj) => {
914
+ if (obj === undefined)
915
+ return "undefined";
916
+ if (obj === null)
917
+ return "null";
918
+ const maxLogSize = getMaxLogSize();
919
+ let str;
920
+ try {
921
+ str = typeof obj === "string" ? obj : JSON.stringify(obj, null, 0).replace(/\n/g, "");
922
+ } catch (e) {
923
+ str = `[Object with circular reference: ${e instanceof Error ? e.message : String(e)}]`;
924
+ }
925
+ return maxLogSize > 0 && str.length > maxLogSize ? str.slice(0, maxLogSize) + " [TRUNCATED]" : str;
926
+ };
927
+ const TRACE_LOG_PREFIX = "[TRACE]";
928
+ const getCallerLocation = () => {
929
+ const originalLimit = Error.stackTraceLimit;
930
+ Error.stackTraceLimit = 15;
931
+ const err = new Error;
932
+ Error.captureStackTrace(err, getCallerLocation);
933
+ const stack = err.stack?.split(`
934
+ `) || [];
935
+ Error.stackTraceLimit = originalLimit;
936
+ for (let i = 1;i < stack.length; i++) {
937
+ const line = stack[i];
938
+ if (line.includes("decorator.ts") || line.includes("decorator.js") || line.includes("logFn") || line.includes("getCallerLocation"))
939
+ continue;
940
+ const match = line.match(/at\s+.+\s+\((.+):(\d+):\d+\)/) || line.match(/at\s+(.+):(\d+):\d+/);
941
+ if (match) {
942
+ const filePath = match[1];
943
+ if (!filePath || filePath === "native")
944
+ continue;
945
+ const relativePath = simplifyFilePath(filePath);
946
+ return `${relativePath}:${match[2]}`;
947
+ }
948
+ }
949
+ return "";
950
+ };
951
+ const logFn = (event2, argsOrData, callerLocation) => {
952
+ if (!shouldLog)
953
+ return;
954
+ const logger = createLogger("traced:" + name);
955
+ const tag = event2 === "enter" ? ">>>" : event2 === "quit" ? "<<<" : "!!!";
956
+ const prefix = `${TRACE_LOG_PREFIX} ${tag} ${name}`;
957
+ const originalFnLocation = callerLocation || getCallerLocation();
958
+ const logMessage = (msg, data) => {
959
+ if (data !== undefined) {
960
+ logger.info(`${prefix} ${msg}: ${truncateString(data)}`, { callerLocation: originalFnLocation });
961
+ } else {
962
+ logger.info(`${prefix} ${msg}`, { callerLocation: originalFnLocation });
963
+ }
964
+ };
965
+ if (event2 === "enter") {
966
+ logMessage("enter", argsOrData);
967
+ } else if (event2 === "quit") {
968
+ logMessage("quit", options?.recordResult ? argsOrData : undefined);
969
+ } else {
970
+ logMessage("error", argsOrData);
971
+ }
972
+ };
973
+ return function(...args) {
974
+ const tracer = getTracerProvider().getTracer("roy-tracer");
975
+ const attributes = {};
976
+ if (options?.recordParams !== false) {
977
+ if (options?.paramFilter) {
978
+ attributes["params"] = truncate(options.paramFilter(args));
979
+ } else {
980
+ attributes["params"] = truncate(args);
981
+ }
982
+ }
983
+ const callerLocation = getCallerLocation();
984
+ logFn("enter", args, callerLocation);
985
+ const span = tracer.startSpan(name, { attributes });
986
+ try {
987
+ const result = fn.call(this, ...args);
988
+ if (result && typeof result === "object" && typeof result.then === "function") {
989
+ return result.then((resolved) => {
990
+ span.setAttribute("result", JSON.stringify(truncate(resolved)));
991
+ span.end(resolved);
992
+ logFn("quit", options?.recordResult ? resolved : undefined, callerLocation);
993
+ return resolved;
994
+ }, (rejected) => {
995
+ span.setAttribute("error", String(rejected));
996
+ span.end(undefined, rejected instanceof Error ? rejected : new Error(String(rejected)));
997
+ logFn("error", rejected.message, callerLocation);
998
+ throw rejected;
999
+ });
1000
+ }
1001
+ span.setAttribute("result", JSON.stringify(truncate(result)));
1002
+ span.end(result);
1003
+ logFn("quit", options?.recordResult ? result : undefined, callerLocation);
1004
+ return result;
1005
+ } catch (error) {
1006
+ span.setAttribute("error", String(error));
1007
+ span.end(undefined, error instanceof Error ? error : new Error(String(error)));
1008
+ logFn("error", error.message, callerLocation);
1009
+ throw error;
1010
+ }
1011
+ };
1012
+ }
1013
+ var init_decorator = __esm(() => {
1014
+ init_tracer_provider();
1015
+ init_logger();
1016
+ });
1017
+
1018
+ // src/env/workflow/engine/executor.ts
1019
+ var Executor;
1020
+ var init_executor = __esm(() => {
1021
+ init_event();
1022
+ init_types();
1023
+ init_decorator();
1024
+ Executor = class Executor {
1025
+ nodeRegistry;
1026
+ eventBus;
1027
+ options;
1028
+ sessionComponent;
1029
+ abortControllers = new Map;
1030
+ constructor(nodeRegistry, eventBus, options, sessionComponent) {
1031
+ this.nodeRegistry = nodeRegistry;
1032
+ this.eventBus = eventBus;
1033
+ this.options = options;
1034
+ this.sessionComponent = sessionComponent;
1035
+ }
1036
+ async executeNode(definition, context2) {
1037
+ const nodeId = definition.id;
1038
+ const nodeType = definition.type;
1039
+ const agentSessionId = context2.agentSessionId;
1040
+ await this.eventBus.publish(createWorkflowEvent("node.started", context2.runId, {
1041
+ node_id: nodeId,
1042
+ input: context2.input
1043
+ }));
1044
+ await this.writeNodeCall(context2.sessionId, nodeId, nodeType, context2.input, agentSessionId);
1045
+ const abortController = new AbortController;
1046
+ this.abortControllers.set(nodeId, abortController);
1047
+ const timeout = definition.timeout ?? this.options.globalTimeout ?? undefined;
1048
+ const retryConfig = definition.retry ?? this.options.globalRetry;
1049
+ try {
1050
+ let result;
1051
+ if (retryConfig && retryConfig.max_attempts > 1) {
1052
+ result = await this.executeWithRetry(definition, context2, abortController.signal, timeout);
1053
+ } else {
1054
+ result = await this.executeWithTimeout(definition, context2, abortController.signal, timeout);
1055
+ }
1056
+ if (result.error instanceof AskUserError) {
1057
+ const interruptEvent = createNodeInterruptEvent(context2.runId, nodeId, nodeType, result.error.query, result.error.agentSessionId || agentSessionId);
1058
+ await this.eventBus.publish(interruptEvent);
1059
+ await this.writeNodeInterrupt(context2.sessionId, nodeId, nodeType, result.error.query, result.error.agentSessionId || agentSessionId);
1060
+ throw result.error;
1061
+ }
1062
+ if (result.error) {
1063
+ const errorMessage = result.error instanceof Error ? result.error.message : String(result.error);
1064
+ const errorStack = result.error instanceof Error ? result.error.stack : undefined;
1065
+ await this.eventBus.publish(createWorkflowEvent("node.failed", context2.runId, {
1066
+ node_id: nodeId,
1067
+ error: {
1068
+ message: errorMessage,
1069
+ stack: errorStack
1070
+ }
1071
+ }));
1072
+ await this.writeNodeResult(context2.sessionId, nodeId, nodeType, result.output, errorMessage, result.durationMs ?? 0);
1073
+ } else {
1074
+ await this.eventBus.publish(createWorkflowEvent("node.completed", context2.runId, {
1075
+ node_id: nodeId,
1076
+ output: result.output,
1077
+ duration_ms: result.durationMs ?? 0
1078
+ }));
1079
+ await this.writeNodeResult(context2.sessionId, nodeId, nodeType, result.output, undefined, result.durationMs ?? 0);
1080
+ }
1081
+ return result;
1082
+ } finally {
1083
+ this.abortControllers.delete(nodeId);
1084
+ }
1085
+ }
1086
+ async executeWithTimeout(definition, context2, signal, timeout) {
1087
+ const startTime = Date.now();
1088
+ const nodeContext = {
1089
+ runId: context2.runId,
1090
+ workflowName: context2.workflowName,
1091
+ eventBus: this.eventBus,
1092
+ debug: context2.debug
1093
+ };
1094
+ const node = this.nodeRegistry.createNode(definition, nodeContext);
1095
+ if (timeout) {
1096
+ const timeoutPromise = new Promise((_, reject) => {
1097
+ const handle = setTimeout(() => {
1098
+ reject(new Error(`Node execution timeout: ${timeout}ms`));
1099
+ }, timeout);
1100
+ signal.addEventListener("abort", () => clearTimeout(handle));
1101
+ });
1102
+ try {
1103
+ const result = await Promise.race([
1104
+ node.execute(context2),
1105
+ timeoutPromise
1106
+ ]);
1107
+ return {
1108
+ output: result.output,
1109
+ error: result.error ?? undefined,
1110
+ durationMs: Date.now() - startTime
1111
+ };
1112
+ } catch (error) {
1113
+ if (error instanceof AskUserError) {
1114
+ throw error;
1115
+ }
1116
+ return {
1117
+ output: undefined,
1118
+ error: error instanceof Error ? error : new Error(String(error)),
1119
+ durationMs: Date.now() - startTime
1120
+ };
1121
+ }
1122
+ } else {
1123
+ try {
1124
+ const result = await node.execute(context2);
1125
+ return {
1126
+ output: result.output,
1127
+ durationMs: Date.now() - startTime
1128
+ };
1129
+ } catch (error) {
1130
+ if (error instanceof AskUserError) {
1131
+ throw error;
1132
+ }
1133
+ return {
1134
+ output: undefined,
1135
+ error: error instanceof Error ? error : new Error(String(error)),
1136
+ durationMs: Date.now() - startTime
1137
+ };
1138
+ }
1139
+ }
1140
+ }
1141
+ async executeWithRetry(definition, context2, signal, timeout) {
1142
+ const retryConfig = definition.retry;
1143
+ let lastError;
1144
+ let delay = retryConfig.initial_delay;
1145
+ for (let attempt = 1;attempt <= retryConfig.max_attempts; attempt++) {
1146
+ if (signal.aborted) {
1147
+ return {
1148
+ output: undefined,
1149
+ error: new Error("Execution aborted"),
1150
+ durationMs: 0
1151
+ };
1152
+ }
1153
+ const attemptAbort = new AbortController;
1154
+ const combinedSignal = this.combineAbortSignals(signal, attemptAbort.signal);
1155
+ try {
1156
+ const result = await this.executeWithTimeout(definition, context2, combinedSignal, timeout);
1157
+ if (!result.error) {
1158
+ return result;
1159
+ }
1160
+ lastError = result.error instanceof Error ? result.error : new Error(String(result.error));
1161
+ } catch (error) {
1162
+ lastError = error instanceof Error ? error : new Error(String(error));
1163
+ }
1164
+ if (attempt < retryConfig.max_attempts) {
1165
+ await this.sleep(delay);
1166
+ if (retryConfig.backoff === "exponential") {
1167
+ delay *= 2;
1168
+ }
1169
+ }
1170
+ }
1171
+ return {
1172
+ output: undefined,
1173
+ error: lastError ?? new Error("Unknown error after retries"),
1174
+ durationMs: 0
1175
+ };
1176
+ }
1177
+ cancelNode(nodeId) {
1178
+ const controller = this.abortControllers.get(nodeId);
1179
+ if (controller) {
1180
+ controller.abort();
1181
+ this.abortControllers.delete(nodeId);
1182
+ }
1183
+ }
1184
+ cancelAll() {
1185
+ for (const controller of this.abortControllers.values()) {
1186
+ controller.abort();
1187
+ }
1188
+ this.abortControllers.clear();
1189
+ }
1190
+ combineAbortSignals(signal1, signal2) {
1191
+ const controller = new AbortController;
1192
+ signal1.addEventListener("abort", () => controller.abort());
1193
+ signal2.addEventListener("abort", () => controller.abort());
1194
+ return controller.signal;
1195
+ }
1196
+ sleep(ms) {
1197
+ return new Promise((resolve) => setTimeout(resolve, ms));
1198
+ }
1199
+ async writeNodeCall(sessionId, nodeId, nodeType, input, agentSessionId) {
1200
+ if (!this.sessionComponent)
1201
+ return;
1202
+ const startTime = Date.now();
1203
+ const part = {
1204
+ type: "workflow-node-call",
1205
+ nodeId,
1206
+ nodeType,
1207
+ input,
1208
+ startTime,
1209
+ ...agentSessionId ? { agentSessionId } : {}
1210
+ };
1211
+ const contentSummary = this.summarizeCall(nodeType, nodeId, input);
1212
+ await this.sessionComponent.addMessage(sessionId, {
1213
+ role: "workflow.node.call",
1214
+ content: contentSummary,
1215
+ parts: [part],
1216
+ metadata: {
1217
+ _workflowNodeMetadata: true,
1218
+ type: "workflow.node.call",
1219
+ workflowNodeId: nodeId,
1220
+ workflowNodeType: nodeType,
1221
+ ...agentSessionId ? { agentSessionId } : {}
1222
+ }
1223
+ });
1224
+ }
1225
+ summarizeCall(nodeType, nodeId, input) {
1226
+ if (input === undefined || input === null) {
1227
+ return `[${nodeType}] ${nodeId} started`;
1228
+ }
1229
+ if (typeof input === "object") {
1230
+ const keys = Object.keys(input);
1231
+ if (keys.length === 0) {
1232
+ return `[${nodeType}] ${nodeId} started`;
1233
+ }
1234
+ const summary = keys.slice(0, 3).map((k) => `${k}: ${JSON.stringify(input[k])}`).join(", ");
1235
+ return `[${nodeType}] ${nodeId}: ${summary}`;
1236
+ }
1237
+ return `[${nodeType}] ${nodeId}: ${String(input)}`;
1238
+ }
1239
+ async writeNodeInterrupt(sessionId, nodeId, nodeType, query, agentSessionId) {
1240
+ if (!this.sessionComponent)
1241
+ return;
1242
+ const timestamp = Date.now();
1243
+ const part = {
1244
+ type: "workflow-node-interrupt",
1245
+ nodeId,
1246
+ nodeType,
1247
+ query,
1248
+ timestamp,
1249
+ ...agentSessionId ? { agentSessionId } : {}
1250
+ };
1251
+ await this.sessionComponent.addMessage(sessionId, {
1252
+ role: "workflow.node.interrupt",
1253
+ content: query,
1254
+ parts: [part],
1255
+ metadata: {
1256
+ _workflowNodeMetadata: true,
1257
+ type: "workflow.node.interrupt",
1258
+ workflowNodeId: nodeId,
1259
+ workflowNodeType: nodeType,
1260
+ query,
1261
+ agentSessionId
1262
+ }
1263
+ });
1264
+ }
1265
+ async writeNodeResult(sessionId, nodeId, nodeType, output, error, durationMs) {
1266
+ if (!this.sessionComponent)
1267
+ return;
1268
+ const part = {
1269
+ type: "workflow-node-result",
1270
+ nodeId,
1271
+ nodeType,
1272
+ output,
1273
+ error,
1274
+ durationMs
1275
+ };
1276
+ const contentSummary = this.summarizeResult(nodeId, output, error, durationMs);
1277
+ await this.sessionComponent.addMessage(sessionId, {
1278
+ role: "workflow.node.result",
1279
+ content: contentSummary,
1280
+ parts: [part],
1281
+ metadata: {
1282
+ _workflowNodeMetadata: true,
1283
+ type: "workflow.node.result",
1284
+ workflowNodeId: nodeId,
1285
+ workflowNodeType: nodeType,
1286
+ success: !error
1287
+ }
1288
+ });
1289
+ }
1290
+ summarizeResult(nodeId, output, error, durationMs) {
1291
+ if (error) {
1292
+ return `❌ ${nodeId} failed: ${error}`;
1293
+ }
1294
+ if (output === undefined || output === null) {
1295
+ return `✅ ${nodeId} completed (${durationMs}ms)`;
1296
+ }
1297
+ if (typeof output === "object") {
1298
+ const keys = Object.keys(output);
1299
+ if (keys.length === 0) {
1300
+ return `✅ ${nodeId} completed (${durationMs}ms)`;
1301
+ }
1302
+ const summary = keys.slice(0, 3).join(", ");
1303
+ return `✅ ${nodeId}: ${summary} (${durationMs}ms)`;
1304
+ }
1305
+ const strOutput = String(output);
1306
+ const truncated = strOutput.length > 100 ? strOutput.substring(0, 100) + "..." : strOutput;
1307
+ return `✅ ${nodeId}: ${truncated} (${durationMs}ms)`;
1308
+ }
1309
+ async writeNodeResume(sessionId, response) {
1310
+ if (!this.sessionComponent)
1311
+ return;
1312
+ const timestamp = Date.now();
1313
+ const part = {
1314
+ type: "workflow-node-resume",
1315
+ response,
1316
+ timestamp
1317
+ };
1318
+ await this.sessionComponent.addMessage(sessionId, {
1319
+ role: "workflow.node.resume",
1320
+ content: response,
1321
+ parts: [part],
1322
+ metadata: {
1323
+ _workflowNodeMetadata: true
1324
+ }
1325
+ });
1326
+ }
1327
+ };
1328
+ __legacyDecorateClassTS([
1329
+ TracedAs("workflow.executor.executeNode", { recordParams: true, recordResult: true, log: true })
1330
+ ], Executor.prototype, "executeNode", null);
1331
+ __legacyDecorateClassTS([
1332
+ TracedAs("workflow.executor.writeNodeCall", { recordParams: true, recordResult: true, log: true })
1333
+ ], Executor.prototype, "writeNodeCall", null);
1334
+ __legacyDecorateClassTS([
1335
+ TracedAs("workflow.executor.writeNodeInterrupt", { recordParams: true, recordResult: true, log: true })
1336
+ ], Executor.prototype, "writeNodeInterrupt", null);
1337
+ __legacyDecorateClassTS([
1338
+ TracedAs("workflow.executor.writeNodeResult", { recordParams: true, recordResult: true, log: true })
1339
+ ], Executor.prototype, "writeNodeResult", null);
1340
+ __legacyDecorateClassTS([
1341
+ TracedAs("workflow.executor.writeNodeResume", { recordParams: true, recordResult: true, log: true })
1342
+ ], Executor.prototype, "writeNodeResume", null);
1343
+ });
1344
+
1345
+ // src/env/workflow/nodes/tool-node.ts
1346
+ class ToolNode {
1347
+ definition;
1348
+ toolRegistry;
1349
+ type = "tool";
1350
+ id;
1351
+ constructor(definition, toolRegistry) {
1352
+ this.definition = definition;
1353
+ this.toolRegistry = toolRegistry;
1354
+ this.id = definition.id;
1355
+ }
1356
+ async execute(context2) {
1357
+ const startTime = Date.now();
1358
+ try {
1359
+ const toolName = this.definition.config?.tool ?? this.definition.config?.toolName;
1360
+ if (!toolName) {
1361
+ throw new Error("Tool name is required. Please specify config.tool or config.toolName in the node definition.");
1362
+ }
1363
+ let tool;
1364
+ if (this.toolRegistry.getTool) {
1365
+ const result = this.toolRegistry.getTool(toolName);
1366
+ if (!result) {
1367
+ throw new Error(`Tool not found: ${toolName}`);
1368
+ }
1369
+ if ("tool" in result) {
1370
+ tool = result.tool;
1371
+ } else {
1372
+ tool = result;
1373
+ }
1374
+ } else if (this.toolRegistry.getToolByName) {
1375
+ tool = this.toolRegistry.getToolByName(toolName);
1376
+ }
1377
+ if (!tool) {
1378
+ throw new Error(`Tool not found: ${toolName}`);
1379
+ }
1380
+ let input;
1381
+ if (this.definition.config?.command !== undefined) {
1382
+ const commandTemplate = this.definition.config.command;
1383
+ const resolvedCommand = this.resolveTemplateReferences(commandTemplate, context2.previousOutputs, context2.input);
1384
+ input = { command: resolvedCommand };
1385
+ console.log(`[ToolNode] command input: ${resolvedCommand}`);
1386
+ } else if (this.definition.config?.message !== undefined && Object.keys(this.definition.config).length === 1) {
1387
+ const messageTemplate = this.definition.config.message;
1388
+ const resolvedMessage = this.resolveTemplateReferences(messageTemplate, context2.previousOutputs, context2.input);
1389
+ input = { message: resolvedMessage };
1390
+ console.log(`[ToolNode] message input: ${resolvedMessage}`);
1391
+ } else {
1392
+ input = this.definition.config?.input ?? this.definition.config?.args ?? {};
1393
+ input = this.resolveTemplateReferences(input, context2.previousOutputs, context2.input);
1394
+ }
1395
+ let output;
1396
+ try {
1397
+ const toolContext = {
1398
+ session_id: context2.sessionId || `workflow_${context2.runId}`,
1399
+ message_id: context2.nodeId,
1400
+ metadata: {
1401
+ workflowRunId: context2.runId,
1402
+ workflowName: context2.workflowName,
1403
+ nodeId: context2.nodeId
1404
+ }
1405
+ };
1406
+ const executePromise = tool.execute(input, toolContext);
1407
+ const timeoutPromise = new Promise((_, reject) => {
1408
+ setTimeout(() => reject(new Error(`Tool ${toolName} execution timeout after 30s`)), 30000);
1409
+ });
1410
+ output = await Promise.race([executePromise, timeoutPromise]);
1411
+ } catch (err) {
1412
+ console.log(`[ToolNode] Tool ${toolName} doesn't support context, retrying without context...`);
1413
+ output = await tool.execute(input);
1414
+ }
1415
+ return {
1416
+ output,
1417
+ error: undefined,
1418
+ durationMs: Date.now() - startTime
1419
+ };
1420
+ } catch (error) {
1421
+ return {
1422
+ output: undefined,
1423
+ error: error instanceof Error ? error : new Error(String(error)),
1424
+ durationMs: Date.now() - startTime
1425
+ };
1426
+ }
1427
+ }
1428
+ resolveTemplateReferences(input, previousOutputs, workflowInput) {
1429
+ if (typeof input === "string") {
1430
+ const pureTemplate = this.extractPureTemplate(input) || this.extractDollarTemplate(input);
1431
+ if (pureTemplate) {
1432
+ return this.resolvePureTemplate(pureTemplate, previousOutputs, workflowInput);
1433
+ }
1434
+ return this.resolveStringTemplate(input, previousOutputs, workflowInput);
1435
+ }
1436
+ if (Array.isArray(input)) {
1437
+ return input.map((item) => this.resolveTemplateReferences(item, previousOutputs, workflowInput));
1438
+ }
1439
+ if (input !== null && typeof input === "object") {
1440
+ const resolved = {};
1441
+ for (const [key, value] of Object.entries(input)) {
1442
+ resolved[key] = this.resolveTemplateReferences(value, previousOutputs, workflowInput);
1443
+ }
1444
+ return resolved;
1445
+ }
1446
+ return input;
1447
+ }
1448
+ extractPureTemplate(str) {
1449
+ const trimmed = str.trim();
1450
+ if (trimmed.startsWith("{{") && trimmed.endsWith("}}") && trimmed.length > 4) {
1451
+ const content = trimmed.slice(2, -2).trim();
1452
+ if (!content.includes("{{") && !content.includes("}}")) {
1453
+ return content;
1454
+ }
1455
+ }
1456
+ return null;
1457
+ }
1458
+ extractDollarTemplate(str) {
1459
+ const trimmed = str.trim();
1460
+ if (trimmed.startsWith("${") && trimmed.endsWith("}") && trimmed.length > 3) {
1461
+ const content = trimmed.slice(2, -1).trim();
1462
+ if (!content.includes("${") && !content.includes("}")) {
1463
+ return content;
1464
+ }
1465
+ }
1466
+ return null;
1467
+ }
1468
+ resolvePureTemplate(templateContent, previousOutputs, workflowInput) {
1469
+ const trimmed = templateContent.trim();
1470
+ const originalTemplate = `{{${templateContent}}}`;
1471
+ if (trimmed.startsWith("input.")) {
1472
+ const value = this.getNestedValue(workflowInput, trimmed.slice(6));
1473
+ return value !== undefined ? value : originalTemplate;
1474
+ }
1475
+ if (trimmed.startsWith("nodes.")) {
1476
+ const path = trimmed.slice(6);
1477
+ const segments = path.split(".");
1478
+ const nodeId = segments[0];
1479
+ const restPath = segments.slice(1).join(".") || undefined;
1480
+ const value = this.resolvePath(nodeId, restPath, previousOutputs);
1481
+ return value !== undefined ? value : originalTemplate;
1482
+ }
1483
+ if (trimmed !== "input" && trimmed !== "nodes") {
1484
+ const segments = trimmed.split(".");
1485
+ const nodeId = segments[0];
1486
+ const restPath = segments.slice(1).join(".") || undefined;
1487
+ const value = this.resolvePath(nodeId, restPath, previousOutputs);
1488
+ return value !== undefined ? value : originalTemplate;
1489
+ }
1490
+ return originalTemplate;
1491
+ }
1492
+ resolveStringTemplate(template, previousOutputs, workflowInput) {
1493
+ let resolved = template;
1494
+ resolved = resolved.replace(/\{\{input\.([^}]+)\}\}/g, (match, path) => {
1495
+ const value = this.getNestedValue(workflowInput, path.trim());
1496
+ return this.stringifyValue(value, match);
1497
+ });
1498
+ resolved = resolved.replace(/\$\{input\.([^}]+)\}/g, (match, path) => {
1499
+ const value = this.getNestedValue(workflowInput, path.trim());
1500
+ return this.stringifyValue(value, match);
1501
+ });
1502
+ resolved = resolved.replace(/\{\{([^:.{}][^}]*?)\}\}/g, (match, path) => {
1503
+ if (path.trim().startsWith("nodes.") || path.trim().startsWith("input.")) {
1504
+ return match;
1505
+ }
1506
+ const segments = path.trim().split(".");
1507
+ const nodeId = segments[0];
1508
+ const restPath = segments.slice(1).join(".") || undefined;
1509
+ const value = this.resolvePath(nodeId, restPath, previousOutputs);
1510
+ return this.stringifyValue(value, match);
1511
+ });
1512
+ resolved = resolved.replace(/\$\{([^}]+)\}/g, (match, path) => {
1513
+ if (path.trim().startsWith("nodes.") || path.trim().startsWith("input.")) {
1514
+ return match;
1515
+ }
1516
+ const segments = path.trim().split(".");
1517
+ const nodeId = segments[0];
1518
+ const restPath = segments.slice(1).join(".") || undefined;
1519
+ const value = this.resolvePath(nodeId, restPath, previousOutputs);
1520
+ return this.stringifyValue(value, match);
1521
+ });
1522
+ resolved = resolved.replace(/\{\{nodes\.([^}]+)\}\}/g, (match, path) => {
1523
+ const segments = path.trim().split(".");
1524
+ const nodeId = segments[0];
1525
+ const restPath = segments.slice(1).join(".") || undefined;
1526
+ const nodeOutput = this.resolvePath(nodeId, undefined, previousOutputs);
1527
+ let extractedValue = this.extractFromWrapper(nodeOutput);
1528
+ if (typeof extractedValue === "string" && restPath === "output") {
1529
+ return this.stringifyValue(extractedValue, match);
1530
+ }
1531
+ if (restPath) {
1532
+ const value = this.getNestedValue(extractedValue, restPath);
1533
+ return this.stringifyValue(value, match);
1534
+ } else {
1535
+ return this.stringifyValue(extractedValue, match);
1536
+ }
1537
+ });
1538
+ return resolved;
1539
+ }
1540
+ resolvePath(nodeId, path, previousOutputs) {
1541
+ let nodeOutput = previousOutputs.get(nodeId);
1542
+ if (nodeOutput === undefined) {
1543
+ const normalizedUnderscore = nodeId.replace(/-/g, "_");
1544
+ const normalizedHyphen = nodeId.replace(/_/g, "-");
1545
+ if (normalizedUnderscore !== nodeId) {
1546
+ nodeOutput = previousOutputs.get(normalizedUnderscore);
1547
+ }
1548
+ if (nodeOutput === undefined && normalizedHyphen !== nodeId) {
1549
+ nodeOutput = previousOutputs.get(normalizedHyphen);
1550
+ }
1551
+ }
1552
+ if (nodeOutput === undefined) {
1553
+ return;
1554
+ }
1555
+ if (path === undefined || path === "") {
1556
+ return nodeOutput;
1557
+ }
1558
+ return this.getNestedValue(nodeOutput, path);
1559
+ }
1560
+ getNestedValue(obj, path) {
1561
+ if (obj === null || obj === undefined) {
1562
+ return;
1563
+ }
1564
+ const segments = path.split(".");
1565
+ let current = obj;
1566
+ for (const segment of segments) {
1567
+ if (current === null || current === undefined) {
1568
+ return;
1569
+ }
1570
+ current = current[segment];
1571
+ }
1572
+ return current;
1573
+ }
1574
+ extractFromWrapper(value) {
1575
+ if (value === null || value === undefined) {
1576
+ return value;
1577
+ }
1578
+ if (typeof value !== "object") {
1579
+ return value;
1580
+ }
1581
+ let result;
1582
+ if ("output" in value) {
1583
+ result = value.output;
1584
+ } else if ("result" in value && !("output" in value)) {
1585
+ result = value.result;
1586
+ } else {
1587
+ return value;
1588
+ }
1589
+ if (typeof result === "string") {
1590
+ return result.trimEnd();
1591
+ }
1592
+ return result;
1593
+ }
1594
+ stringifyValue(value, fallback) {
1595
+ if (value === undefined || value === null) {
1596
+ return fallback;
1597
+ }
1598
+ let str;
1599
+ if (typeof value === "object") {
1600
+ str = JSON.stringify(value);
1601
+ } else {
1602
+ str = String(value);
1603
+ }
1604
+ return str.replace(/\\/g, "\\\\").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t").replace(/"/g, "\\\"").replace(/`/g, "\\`").replace(/\$/g, "\\$");
1605
+ }
1606
+ }
1607
+ var init_tool_node = () => {};
1608
+
1609
+ // src/env/workflow/nodes/skill-node.ts
1610
+ class SkillNode {
1611
+ definition;
1612
+ skillRegistry;
1613
+ type = "skill";
1614
+ id;
1615
+ constructor(definition, skillRegistry) {
1616
+ this.definition = definition;
1617
+ this.skillRegistry = skillRegistry;
1618
+ this.id = definition.id;
1619
+ }
1620
+ async execute(context2) {
1621
+ const startTime = Date.now();
1622
+ try {
1623
+ const skillName = this.definition.config?.skill;
1624
+ if (!skillName) {
1625
+ throw new Error("Skill name is required. Please specify config.skill in the node definition.");
1626
+ }
1627
+ const skill = this.skillRegistry.getSkill(skillName);
1628
+ if (!skill) {
1629
+ throw new Error(`Skill not found: ${skillName}`);
1630
+ }
1631
+ const input = this.definition.config?.input ?? {};
1632
+ const resolvedInput = this.resolveTemplateReferences(input, context2.previousOutputs, context2.input);
1633
+ const skillContext = {
1634
+ runId: context2.runId,
1635
+ workflowName: context2.workflowName,
1636
+ nodeId: context2.nodeId,
1637
+ debug: context2.debug
1638
+ };
1639
+ const output = await skill.invoke(resolvedInput, skillContext);
1640
+ return {
1641
+ output,
1642
+ error: undefined,
1643
+ durationMs: Date.now() - startTime
1644
+ };
1645
+ } catch (error) {
1646
+ return {
1647
+ output: undefined,
1648
+ error: error instanceof Error ? error : new Error(String(error)),
1649
+ durationMs: Date.now() - startTime
1650
+ };
1651
+ }
1652
+ }
1653
+ resolveTemplateReferences(input, previousOutputs, workflowInput) {
1654
+ if (typeof input === "string") {
1655
+ const pureTemplate = this.extractPureTemplate(input);
1656
+ if (pureTemplate) {
1657
+ return this.resolvePureTemplate(pureTemplate, previousOutputs, workflowInput);
1658
+ }
1659
+ return this.resolveStringTemplate(input, previousOutputs, workflowInput);
1660
+ }
1661
+ if (Array.isArray(input)) {
1662
+ return input.map((item) => this.resolveTemplateReferences(item, previousOutputs, workflowInput));
1663
+ }
1664
+ if (input !== null && typeof input === "object") {
1665
+ const resolved = {};
1666
+ for (const [key, value] of Object.entries(input)) {
1667
+ resolved[key] = this.resolveTemplateReferences(value, previousOutputs, workflowInput);
1668
+ }
1669
+ return resolved;
1670
+ }
1671
+ return input;
1672
+ }
1673
+ extractPureTemplate(str) {
1674
+ const trimmed = str.trim();
1675
+ if (trimmed.startsWith("{{") && trimmed.endsWith("}}") && trimmed.length > 4) {
1676
+ const content = trimmed.slice(2, -2).trim();
1677
+ if (!content.includes("{{") && !content.includes("}}")) {
1678
+ return content;
1679
+ }
1680
+ }
1681
+ return null;
1682
+ }
1683
+ resolvePureTemplate(templateContent, previousOutputs, workflowInput) {
1684
+ const trimmed = templateContent.trim();
1685
+ const originalTemplate = `{{${templateContent}}}`;
1686
+ if (trimmed.startsWith("input.")) {
1687
+ const value = this.getNestedValue(workflowInput, trimmed.slice(6));
1688
+ return value !== undefined ? value : originalTemplate;
1689
+ }
1690
+ if (trimmed.startsWith("nodes.")) {
1691
+ const path = trimmed.slice(6);
1692
+ const segments = path.split(".");
1693
+ const nodeId = segments[0];
1694
+ const restPath = segments.slice(1).join(".") || undefined;
1695
+ const value = this.resolvePath(nodeId, restPath, previousOutputs);
1696
+ return value !== undefined ? value : originalTemplate;
1697
+ }
1698
+ if (trimmed !== "input" && trimmed !== "nodes") {
1699
+ const segments = trimmed.split(".");
1700
+ const nodeId = segments[0];
1701
+ const restPath = segments.slice(1).join(".") || undefined;
1702
+ const value = this.resolvePath(nodeId, restPath, previousOutputs);
1703
+ return value !== undefined ? value : originalTemplate;
1704
+ }
1705
+ return originalTemplate;
1706
+ }
1707
+ resolveStringTemplate(template, previousOutputs, workflowInput) {
1708
+ let resolved = template;
1709
+ resolved = resolved.replace(/\{\{input\.([^}]+)\}\}/g, (match, path) => {
1710
+ const value = this.getNestedValue(workflowInput, path.trim());
1711
+ return this.stringifyValue(value, match);
1712
+ });
1713
+ resolved = resolved.replace(/\{\{([^:.{}][^}]*?)\}\}/g, (match, path) => {
1714
+ if (path.trim().startsWith("nodes.") || path.trim().startsWith("input.")) {
1715
+ return match;
1716
+ }
1717
+ const segments = path.trim().split(".");
1718
+ const nodeId = segments[0];
1719
+ const restPath = segments.slice(1).join(".") || undefined;
1720
+ const value = this.resolvePath(nodeId, restPath, previousOutputs);
1721
+ return this.stringifyValue(value, match);
1722
+ });
1723
+ resolved = resolved.replace(/\{\{nodes\.([^}]+)\}\}/g, (match, path) => {
1724
+ const segments = path.trim().split(".");
1725
+ const nodeId = segments[0];
1726
+ const restPath = segments.slice(1).join(".") || undefined;
1727
+ const value = this.resolvePath(nodeId, restPath, previousOutputs);
1728
+ return this.stringifyValue(value, match);
1729
+ });
1730
+ return resolved;
1731
+ }
1732
+ resolvePath(nodeId, path, previousOutputs) {
1733
+ let nodeOutput = previousOutputs.get(nodeId);
1734
+ if (nodeOutput === undefined) {
1735
+ const normalizedUnderscore = nodeId.replace(/-/g, "_");
1736
+ const normalizedHyphen = nodeId.replace(/_/g, "-");
1737
+ if (normalizedUnderscore !== nodeId) {
1738
+ nodeOutput = previousOutputs.get(normalizedUnderscore);
1739
+ }
1740
+ if (nodeOutput === undefined && normalizedHyphen !== nodeId) {
1741
+ nodeOutput = previousOutputs.get(normalizedHyphen);
1742
+ }
1743
+ }
1744
+ if (nodeOutput === undefined) {
1745
+ return;
1746
+ }
1747
+ let value = this.extractFromWrapper(nodeOutput);
1748
+ if (!path) {
1749
+ return value;
1750
+ }
1751
+ let segments = path.split(".");
1752
+ if (segments.length > 1 && (segments[0] === "output" || segments[0] === "result" || segments[0] === "metadata")) {
1753
+ segments = segments.slice(1);
1754
+ }
1755
+ let current = value;
1756
+ for (const segment of segments) {
1757
+ if (current === null || current === undefined) {
1758
+ return;
1759
+ }
1760
+ current = current[segment];
1761
+ }
1762
+ return current;
1763
+ }
1764
+ extractFromWrapper(value) {
1765
+ if (value === null || value === undefined) {
1766
+ return value;
1767
+ }
1768
+ if (typeof value !== "object") {
1769
+ return value;
1770
+ }
1771
+ if ("result" in value && "metadata" in value) {
1772
+ return value.result;
1773
+ }
1774
+ if ("output" in value) {
1775
+ return value.output;
1776
+ }
1777
+ return value;
1778
+ }
1779
+ getNestedValue(obj, path) {
1780
+ if (!obj) {
1781
+ return;
1782
+ }
1783
+ if ("input" in obj && path in obj["input"]) {
1784
+ return obj["input"][path];
1785
+ }
1786
+ return path.split(".").reduce((current, key) => {
1787
+ if (current && typeof current === "object") {
1788
+ return current[key];
1789
+ }
1790
+ return;
1791
+ }, obj);
1792
+ }
1793
+ stringifyValue(value, originalTemplate) {
1794
+ if (value === undefined) {
1795
+ return originalTemplate;
1796
+ }
1797
+ if (value === null) {
1798
+ return "null";
1799
+ }
1800
+ if (typeof value === "string") {
1801
+ return value;
1802
+ }
1803
+ return JSON.stringify(value);
1804
+ }
1805
+ }
1806
+ var init_skill_node = () => {};
1807
+
1808
+ // src/env/workflow/nodes/agent-node.ts
1809
+ var AgentNode;
1810
+ var init_agent_node = __esm(() => {
1811
+ init_workflow_hil();
1812
+ init_decorator();
1813
+ AgentNode = class AgentNode {
1814
+ definition;
1815
+ agentRunner;
1816
+ type = "agent";
1817
+ id;
1818
+ constructor(definition, agentRunner) {
1819
+ this.definition = definition;
1820
+ this.agentRunner = agentRunner;
1821
+ this.id = definition.id;
1822
+ }
1823
+ async execute(context2) {
1824
+ const startTime = Date.now();
1825
+ try {
1826
+ const config = this.definition.config || {};
1827
+ const agentType = config.agent_type || "general";
1828
+ const promptTemplate = config.prompt || "";
1829
+ const options = config.options || {};
1830
+ const resolvedPrompt = this.resolveTemplate(promptTemplate, context2);
1831
+ if (this.agentRunner.registerAgent && this.agentRunner.hasAgent) {
1832
+ if (!this.agentRunner.hasAgent(agentType)) {
1833
+ this.agentRunner.registerAgent(agentType, {
1834
+ type: agentType,
1835
+ systemPrompt: config.system_prompt || `You are a ${agentType} agent.`,
1836
+ model: options.model
1837
+ });
1838
+ }
1839
+ }
1840
+ const userResponse = context2.userResponse;
1841
+ let agentSessionId = context2.agentSessionId;
1842
+ if (!userResponse && context2.sessionComponent && !agentSessionId) {
1843
+ agentSessionId = await this.createAgentSubSession(context2);
1844
+ context2.agentSessionId = agentSessionId;
1845
+ }
1846
+ const agentConfig = {
1847
+ type: agentType,
1848
+ prompt: resolvedPrompt,
1849
+ options: {
1850
+ timeout: options.timeout,
1851
+ model: options.model,
1852
+ allowedTools: ["ask_user"]
1853
+ },
1854
+ workflowHistory: context2.workflowHistory,
1855
+ nodeId: this.definition.id,
1856
+ agentSessionId
1857
+ };
1858
+ const resumeOptions = userResponse ? { userResponse, agentSessionId } : undefined;
1859
+ const result = await this.agentRunner.run(agentConfig, resumeOptions);
1860
+ const duration = Date.now() - startTime;
1861
+ return {
1862
+ output: {
1863
+ result: result.output,
1864
+ metadata: result.metadata,
1865
+ workflowHistory: result.messages
1866
+ },
1867
+ error: undefined,
1868
+ duration
1869
+ };
1870
+ } catch (error) {
1871
+ if (error instanceof AskUserError) {
1872
+ const contextAgentSessionId = context2.agentSessionId;
1873
+ if (contextAgentSessionId && !error.agentSessionId) {
1874
+ throw new AskUserError(error.runId, error.sessionId, error.nodeId, error.nodeType, error.query, contextAgentSessionId, error.timestamp);
1875
+ }
1876
+ throw error;
1877
+ }
1878
+ const duration = Date.now() - startTime;
1879
+ const errorMessage = error instanceof Error ? error.message : String(error);
1880
+ return {
1881
+ output: undefined,
1882
+ error: errorMessage,
1883
+ duration
1884
+ };
1885
+ }
1886
+ }
1887
+ async createAgentSubSession(context2) {
1888
+ const sessionComponent = context2.sessionComponent;
1889
+ if (!sessionComponent) {
1890
+ return "";
1891
+ }
1892
+ const agentSessionId = `agent_${this.definition.id}_${Date.now()}`;
1893
+ await sessionComponent.create({
1894
+ id: agentSessionId,
1895
+ title: `Agent: ${this.definition.id}`,
1896
+ metadata: {
1897
+ type: "agent",
1898
+ parentSessionId: context2.sessionId,
1899
+ nodeId: this.definition.id,
1900
+ workflowName: context2.workflowName
1901
+ }
1902
+ });
1903
+ const workflowSession = await sessionComponent.get(context2.sessionId);
1904
+ if (workflowSession) {
1905
+ const metadata = workflowSession.metadata || {};
1906
+ const agentSessions = metadata.agentSessions || [];
1907
+ const existingIndex = agentSessions.findIndex((s) => s.nodeId === this.definition.id);
1908
+ if (existingIndex >= 0) {
1909
+ agentSessions[existingIndex] = {
1910
+ nodeId: this.definition.id,
1911
+ sessionId: agentSessionId,
1912
+ status: "active",
1913
+ createdAt: Date.now()
1914
+ };
1915
+ } else {
1916
+ agentSessions.push({
1917
+ nodeId: this.definition.id,
1918
+ sessionId: agentSessionId,
1919
+ status: "active",
1920
+ createdAt: Date.now()
1921
+ });
1922
+ }
1923
+ await sessionComponent.update(context2.sessionId, {
1924
+ metadata: {
1925
+ ...metadata,
1926
+ agentSessions
1927
+ }
1928
+ });
1929
+ }
1930
+ return agentSessionId;
1931
+ }
1932
+ resolveTemplate(template, context2) {
1933
+ if (!template) {
1934
+ return "";
1935
+ }
1936
+ let resolved = template;
1937
+ resolved = resolved.replace(/\{\{input\.([^}]+)\}\}/g, (match, path) => {
1938
+ const value = this.getNestedValue(context2.input, path);
1939
+ return this.stringifyValue(value, match);
1940
+ });
1941
+ resolved = resolved.replace(/\{\{nodes\.([^}]+)\}\}/g, (match, path) => {
1942
+ const segments = path.split(".");
1943
+ const nodeId = segments[0];
1944
+ let nodeOutput = context2.previousOutputs.get(nodeId);
1945
+ if (nodeOutput === undefined) {
1946
+ const normalizedUnderscore = nodeId.replace(/-/g, "_");
1947
+ const normalizedHyphen = nodeId.replace(/_/g, "-");
1948
+ if (normalizedUnderscore !== nodeId) {
1949
+ nodeOutput = context2.previousOutputs.get(normalizedUnderscore);
1950
+ }
1951
+ if (nodeOutput === undefined && normalizedHyphen !== nodeId) {
1952
+ nodeOutput = context2.previousOutputs.get(normalizedHyphen);
1953
+ }
1954
+ }
1955
+ if (nodeOutput === undefined) {
1956
+ return match;
1957
+ }
1958
+ nodeOutput = this.extractFromWrapper(nodeOutput);
1959
+ if (segments.length === 1) {
1960
+ return this.stringifyValue(nodeOutput, match);
1961
+ }
1962
+ let value = nodeOutput;
1963
+ let startIndex = 1;
1964
+ if (segments.length > 1 && (segments[1] === "output" || segments[1] === "result" || segments[1] === "metadata")) {
1965
+ startIndex = 2;
1966
+ }
1967
+ for (let i = startIndex;i < segments.length; i++) {
1968
+ if (value === null || value === undefined) {
1969
+ return match;
1970
+ }
1971
+ value = value[segments[i]];
1972
+ }
1973
+ return this.stringifyValue(value, match);
1974
+ });
1975
+ resolved = resolved.replace(/\{\{([^}]+)\}\}/g, (match, path) => {
1976
+ if (path.startsWith("input.") || path.startsWith("nodes.")) {
1977
+ return match;
1978
+ }
1979
+ const segments = path.split(".");
1980
+ const nodeId = segments[0];
1981
+ let nodeOutput = context2.previousOutputs.get(nodeId);
1982
+ if (nodeOutput === undefined) {
1983
+ const normalizedUnderscore = nodeId.replace(/-/g, "_");
1984
+ const normalizedHyphen = nodeId.replace(/_/g, "-");
1985
+ if (normalizedUnderscore !== nodeId) {
1986
+ nodeOutput = context2.previousOutputs.get(normalizedUnderscore);
1987
+ }
1988
+ if (nodeOutput === undefined && normalizedHyphen !== nodeId) {
1989
+ nodeOutput = context2.previousOutputs.get(normalizedHyphen);
1990
+ }
1991
+ }
1992
+ if (nodeOutput === undefined) {
1993
+ return match;
1994
+ }
1995
+ nodeOutput = this.extractFromWrapper(nodeOutput);
1996
+ if (segments.length === 1) {
1997
+ return this.stringifyValue(nodeOutput, match);
1998
+ }
1999
+ let value = nodeOutput;
2000
+ let startIndex = 1;
2001
+ if (segments.length > 1 && (segments[1] === "output" || segments[1] === "result" || segments[1] === "metadata")) {
2002
+ startIndex = 2;
2003
+ }
2004
+ for (let i = startIndex;i < segments.length; i++) {
2005
+ if (value === null || value === undefined) {
2006
+ return match;
2007
+ }
2008
+ value = value[segments[i]];
2009
+ }
2010
+ return this.stringifyValue(value, match);
2011
+ });
2012
+ return resolved;
2013
+ }
2014
+ stringifyValue(value, originalTemplate) {
2015
+ if (value === undefined) {
2016
+ return originalTemplate;
2017
+ }
2018
+ if (value === null) {
2019
+ return "null";
2020
+ }
2021
+ if (typeof value === "string") {
2022
+ return value;
2023
+ }
2024
+ return JSON.stringify(value);
2025
+ }
2026
+ extractFromWrapper(value) {
2027
+ if (value === null || value === undefined) {
2028
+ return value;
2029
+ }
2030
+ if (typeof value !== "object") {
2031
+ return value;
2032
+ }
2033
+ if ("result" in value && "metadata" in value) {
2034
+ return value.result;
2035
+ }
2036
+ if ("output" in value) {
2037
+ return value.output;
2038
+ }
2039
+ return value;
2040
+ }
2041
+ getNestedValue(obj, path) {
2042
+ if (!obj) {
2043
+ return;
2044
+ }
2045
+ if ("input" in obj && path in obj["input"]) {
2046
+ return obj["input"][path];
2047
+ }
2048
+ return path.split(".").reduce((current, key) => {
2049
+ if (current && typeof current === "object") {
2050
+ return current[key];
2051
+ }
2052
+ return;
2053
+ }, obj);
2054
+ }
2055
+ };
2056
+ __legacyDecorateClassTS([
2057
+ TracedAs("agent.node.execute", { recordParams: true, recordResult: true, log: true })
2058
+ ], AgentNode.prototype, "execute", null);
2059
+ __legacyDecorateClassTS([
2060
+ TracedAs("agent.node.createAgentSubSession", { recordParams: true, recordResult: true, log: true })
2061
+ ], AgentNode.prototype, "createAgentSubSession", null);
2062
+ });
2063
+
2064
+ // src/env/workflow/nodes/workflow-node.ts
2065
+ class WorkflowNode {
2066
+ workflowRunner;
2067
+ type = "workflow";
2068
+ id;
2069
+ config;
2070
+ constructor(definition, workflowRunner) {
2071
+ this.workflowRunner = workflowRunner;
2072
+ this.id = definition.id;
2073
+ this.config = definition.config ?? {};
2074
+ }
2075
+ async execute(context2) {
2076
+ const startTime = Date.now();
2077
+ try {
2078
+ const workflowName = this.config.workflow_name;
2079
+ if (!workflowName) {
2080
+ throw new Error("workflow_name is required in config. Please specify config.workflow_name in the node definition.");
2081
+ }
2082
+ const previousOutputs = context2.previousOutputs ?? this.convertToMap(context2.nodeOutputs ?? {});
2083
+ const resolvedInput = this.resolveInput(this.config.input ?? {}, previousOutputs);
2084
+ const result = await this.workflowRunner.run(workflowName, resolvedInput);
2085
+ const success = result.status === "completed";
2086
+ return {
2087
+ success,
2088
+ output: result.output,
2089
+ error: success ? undefined : result.error,
2090
+ duration: Date.now() - startTime
2091
+ };
2092
+ } catch (error) {
2093
+ return {
2094
+ success: false,
2095
+ output: undefined,
2096
+ error: error instanceof Error ? error : new Error(String(error)),
2097
+ duration: Date.now() - startTime
2098
+ };
2099
+ }
2100
+ }
2101
+ convertToMap(nodeOutputs) {
2102
+ const map = new Map;
2103
+ for (const [nodeId, result] of Object.entries(nodeOutputs)) {
2104
+ map.set(nodeId, result.output);
2105
+ }
2106
+ return map;
2107
+ }
2108
+ resolveInput(input, previousOutputs) {
2109
+ const resolved = {};
2110
+ for (const [key, value] of Object.entries(input)) {
2111
+ resolved[key] = this.resolveValue(value, previousOutputs);
2112
+ }
2113
+ return resolved;
2114
+ }
2115
+ resolveValue(value, previousOutputs) {
2116
+ if (typeof value === "string") {
2117
+ return this.resolveStringTemplate(value, previousOutputs);
2118
+ }
2119
+ if (Array.isArray(value)) {
2120
+ return value.map((item) => this.resolveValue(item, previousOutputs));
2121
+ }
2122
+ if (value !== null && typeof value === "object") {
2123
+ const resolved = {};
2124
+ for (const [k, v] of Object.entries(value)) {
2125
+ resolved[k] = this.resolveValue(v, previousOutputs);
2126
+ }
2127
+ return resolved;
2128
+ }
2129
+ return value;
2130
+ }
2131
+ resolveStringTemplate(template, previousOutputs) {
2132
+ const templatePattern = /\{\{([^}]+)\}\}/g;
2133
+ return template.replace(templatePattern, (match, path) => {
2134
+ const trimmedPath = path.trim();
2135
+ const value = this.resolvePath(trimmedPath, previousOutputs);
2136
+ if (value !== undefined) {
2137
+ return this.stringifyValue(value, match);
2138
+ }
2139
+ return match;
2140
+ });
2141
+ }
2142
+ resolvePath(path, previousOutputs) {
2143
+ const segments = path.split(".");
2144
+ if (segments.length === 0) {
2145
+ return;
2146
+ }
2147
+ const nodeId = segments[0];
2148
+ let nodeOutput = previousOutputs.get(nodeId);
2149
+ if (nodeOutput === undefined) {
2150
+ return;
2151
+ }
2152
+ nodeOutput = this.extractFromWrapper(nodeOutput);
2153
+ if (segments.length === 1) {
2154
+ return nodeOutput;
2155
+ }
2156
+ let current = nodeOutput;
2157
+ let startIndex = 1;
2158
+ if (segments.length > 1 && (segments[1] === "output" || segments[1] === "result" || segments[1] === "metadata")) {
2159
+ startIndex = 2;
2160
+ }
2161
+ for (let i = startIndex;i < segments.length; i++) {
2162
+ if (current === null || current === undefined) {
2163
+ return;
2164
+ }
2165
+ current = current[segments[i]];
2166
+ }
2167
+ return current;
2168
+ }
2169
+ extractFromWrapper(value) {
2170
+ if (value === null || value === undefined) {
2171
+ return value;
2172
+ }
2173
+ if (typeof value !== "object") {
2174
+ return value;
2175
+ }
2176
+ if ("result" in value && "metadata" in value) {
2177
+ return value.result;
2178
+ }
2179
+ if ("output" in value) {
2180
+ return value.output;
2181
+ }
2182
+ return value;
2183
+ }
2184
+ stringifyValue(value, originalTemplate) {
2185
+ if (value === undefined) {
2186
+ return originalTemplate;
2187
+ }
2188
+ if (value === null) {
2189
+ return "null";
2190
+ }
2191
+ if (typeof value === "string") {
2192
+ return value;
2193
+ }
2194
+ return JSON.stringify(value);
2195
+ }
2196
+ }
2197
+ var init_workflow_node = () => {};
2198
+
2199
+ // src/env/workflow/nodes/ask-user-node.ts
2200
+ class AskUserNode {
2201
+ type = "ask_user";
2202
+ id;
2203
+ config;
2204
+ constructor(definition) {
2205
+ this.id = definition.id;
2206
+ this.config = definition.config || {};
2207
+ }
2208
+ async execute(context2) {
2209
+ const query = this.config.query || "确认继续吗?";
2210
+ const options = this.config.options;
2211
+ const fullQuery = options ? `${query} (选项: ${options.join(", ")})` : query;
2212
+ await context2.eventBus.publish(createNodeInterruptEvent(context2.runId, this.id, this.type, fullQuery));
2213
+ throw new AskUserError(context2.runId, context2.sessionId, this.id, this.type, query);
2214
+ }
2215
+ validateConfig(_config) {
2216
+ return true;
2217
+ }
2218
+ }
2219
+ var init_ask_user_node = __esm(() => {
2220
+ init_workflow_hil();
2221
+ });
2222
+
2223
+ // src/env/workflow/engine/node-registry.ts
2224
+ class NodeRegistry {
2225
+ factories = new Map;
2226
+ toolRegistry;
2227
+ skillRegistry;
2228
+ agentRunner;
2229
+ workflowRunner;
2230
+ agentComponentAdapter;
2231
+ sessionComponent;
2232
+ constructor(options) {
2233
+ const {
2234
+ toolRegistry,
2235
+ skillRegistry,
2236
+ agentComponent,
2237
+ agentRunner,
2238
+ workflowRunner,
2239
+ sessionComponent
2240
+ } = options ?? {};
2241
+ this.toolRegistry = toolRegistry;
2242
+ this.skillRegistry = skillRegistry;
2243
+ this.workflowRunner = workflowRunner;
2244
+ this.sessionComponent = sessionComponent;
2245
+ if (agentRunner) {
2246
+ this.agentRunner = agentRunner;
2247
+ if (agentRunner.setSessionComponent && sessionComponent) {
2248
+ agentRunner.setSessionComponent(sessionComponent);
2249
+ }
2250
+ } else if (agentComponent) {
2251
+ this.agentComponentAdapter = new AgentComponentAdapter(agentComponent, {}, sessionComponent);
2252
+ this.agentRunner = this.agentComponentAdapter;
2253
+ }
2254
+ this.registerBuiltInTypes();
2255
+ }
2256
+ getAgentAdapter() {
2257
+ return this.agentComponentAdapter;
2258
+ }
2259
+ getAgentRunner() {
2260
+ return this.agentRunner;
2261
+ }
2262
+ getSessionComponent() {
2263
+ return this.sessionComponent;
2264
+ }
2265
+ registerBuiltInTypes() {
2266
+ this.factories.set("tool", (definition) => {
2267
+ if (!this.toolRegistry) {
2268
+ throw new Error("ToolRegistry is required for tool nodes");
2269
+ }
2270
+ return new ToolNode(definition, this.toolRegistry);
2271
+ });
2272
+ this.factories.set("skill", (definition) => {
2273
+ if (!this.skillRegistry) {
2274
+ throw new Error("SkillRegistry is required for skill nodes");
2275
+ }
2276
+ return new SkillNode(definition, this.skillRegistry);
2277
+ });
2278
+ this.factories.set("agent", (definition) => {
2279
+ if (!this.agentRunner) {
2280
+ throw new Error("AgentRunner is required for agent nodes");
2281
+ }
2282
+ return new AgentNode(definition, this.agentRunner);
2283
+ });
2284
+ this.factories.set("workflow", (definition) => {
2285
+ if (!this.workflowRunner) {
2286
+ throw new Error("WorkflowRunner is required for workflow nodes");
2287
+ }
2288
+ return new WorkflowNode(definition, this.workflowRunner);
2289
+ });
2290
+ this.factories.set("ask_user", (definition) => {
2291
+ return new AskUserNode(definition);
2292
+ });
2293
+ }
2294
+ register(type, factory) {
2295
+ this.factories.set(type, factory);
2296
+ }
2297
+ has(type) {
2298
+ return this.factories.has(type);
2299
+ }
2300
+ list() {
2301
+ return Array.from(this.factories.keys());
2302
+ }
2303
+ createNode(definition, context2) {
2304
+ const factory = this.factories.get(definition.type);
2305
+ if (!factory) {
2306
+ const availableTypes = this.list().join(", ");
2307
+ throw new Error(`Unknown node type: ${definition.type}. Available types: ${availableTypes}`);
2308
+ }
2309
+ return factory(definition, context2);
2310
+ }
2311
+ }
2312
+ var init_node_registry = __esm(() => {
2313
+ init_tool_node();
2314
+ init_skill_node();
2315
+ init_agent_node();
2316
+ init_agent_component_adapter();
2317
+ init_workflow_node();
2318
+ init_ask_user_node();
2319
+ });
2320
+
2321
+ // src/env/workflow/engine/engine.ts
2322
+ import { EventEmitter } from "events";
2323
+ var logger, WorkflowEngine;
2324
+ var init_engine = __esm(() => {
2325
+ init_event();
2326
+ init_workflow_hil();
2327
+ init_dag_manager();
2328
+ init_event_bus();
2329
+ init_scheduler();
2330
+ init_executor();
2331
+ init_node_registry();
2332
+ init_logger();
2333
+ init_decorator();
2334
+ logger = createLogger("workflow:engine");
2335
+ WorkflowEngine = class WorkflowEngine extends EventEmitter {
2336
+ activeSessions = new Map;
2337
+ sessionIdCounter = 0;
2338
+ sessionComponent;
2339
+ nodeRegistry;
2340
+ workflowRepository;
2341
+ constructor(nodeRegistry, sessionComponent, workflowRepository) {
2342
+ super();
2343
+ this.nodeRegistry = nodeRegistry;
2344
+ this.sessionComponent = sessionComponent;
2345
+ this.workflowRepository = workflowRepository;
2346
+ }
2347
+ static async create(options) {
2348
+ const agentComponent = options.env?.getComponent("agent");
2349
+ const sessionComponent = options.sessionComponent;
2350
+ const nodeRegistry = new NodeRegistry({
2351
+ toolRegistry: options.toolRegistry,
2352
+ skillRegistry: options.skillRegistry,
2353
+ agentComponent,
2354
+ workflowRunner: options.workflowRunner,
2355
+ sessionComponent
2356
+ });
2357
+ return new WorkflowEngine(nodeRegistry, sessionComponent, options.workflowRepository);
2358
+ }
2359
+ generateRunId() {
2360
+ const random = Math.random().toString(36).substring(2, 8);
2361
+ return `run_${Date.now()}_${++this.sessionIdCounter}_${random}`;
2362
+ }
2363
+ getRunIdFromSessionId(sessionId) {
2364
+ return sessionId.replace(/^workflow_/, "");
2365
+ }
2366
+ getSessionId(runId) {
2367
+ return `workflow_${runId}`;
2368
+ }
2369
+ async createSession(workflow2, options) {
2370
+ const definition = "definition" in workflow2 ? workflow2.definition : workflow2;
2371
+ const workflowId = "id" in workflow2 ? workflow2.id : `inline_${definition.name}`;
2372
+ const workflowName = definition.name;
2373
+ const runId = this.generateRunId();
2374
+ const sessionId = this.getSessionId(runId);
2375
+ const metadata = {
2376
+ type: "workflow",
2377
+ workflowId,
2378
+ workflowName,
2379
+ workflowVersion: definition.version,
2380
+ status: "running",
2381
+ input: options?.input,
2382
+ agentSessions: []
2383
+ };
2384
+ if (this.sessionComponent) {
2385
+ await this.sessionComponent.create({
2386
+ id: sessionId,
2387
+ title: `Workflow: ${workflowName} (${runId})`,
2388
+ metadata
2389
+ });
2390
+ }
2391
+ logger.info(`[WorkflowEngine] Created session: ${sessionId}`);
2392
+ return sessionId;
2393
+ }
2394
+ async run(sessionId, options) {
2395
+ let session = this.sessionComponent ? await this.sessionComponent.get(sessionId) : null;
2396
+ let workflowDef = null;
2397
+ let workflowId = "";
2398
+ let workflowName = "";
2399
+ if (session) {
2400
+ const metadata2 = session.metadata;
2401
+ if (metadata2.type === "workflow" && metadata2.workflowId) {
2402
+ workflowDef = this.findDefinitionForWorkflow(metadata2.workflowId);
2403
+ workflowId = metadata2.workflowId;
2404
+ workflowName = metadata2.workflowName;
2405
+ }
2406
+ if (!workflowDef && metadata2.workflowName) {
2407
+ workflowDef = this.findDefinitionForWorkflow(metadata2.workflowName);
2408
+ workflowId = metadata2.workflowName;
2409
+ workflowName = metadata2.workflowName;
2410
+ }
2411
+ } else {
2412
+ if (!options?.workflowId) {
2413
+ throw new Error("workflowId required for new session");
2414
+ }
2415
+ workflowDef = this.findDefinitionForWorkflow(options.workflowId);
2416
+ if (!workflowDef) {
2417
+ throw new Error(`Workflow not found: ${options.workflowId}`);
2418
+ }
2419
+ workflowId = options.workflowId;
2420
+ workflowName = workflowDef.name;
2421
+ if (this.sessionComponent) {
2422
+ const sessionMetadata = {
2423
+ type: "workflow",
2424
+ workflowId,
2425
+ workflowName,
2426
+ workflowVersion: workflowDef.version,
2427
+ status: "running"
2428
+ };
2429
+ await this.sessionComponent.create({
2430
+ id: sessionId,
2431
+ title: `Workflow: ${workflowName}`,
2432
+ metadata: sessionMetadata
2433
+ });
2434
+ session = await this.sessionComponent.get(sessionId);
2435
+ }
2436
+ }
2437
+ if (!session || !workflowDef) {
2438
+ throw new Error(`Cannot start workflow: session or workflow not found`);
2439
+ }
2440
+ const metadata = session.metadata;
2441
+ if (metadata.status === "completed") {
2442
+ return { runId: this.getRunIdFromSessionId(sessionId), status: "completed" };
2443
+ }
2444
+ if (metadata.status === "failed") {
2445
+ return { runId: this.getRunIdFromSessionId(sessionId), status: "failed" };
2446
+ }
2447
+ const messages = this.sessionComponent ? await this.sessionComponent.getMessages(sessionId) : [];
2448
+ const { inferNextNode } = await import("./chunk-25x2pdtp.js");
2449
+ const entry = workflowDef.entry;
2450
+ const entryNode = Array.isArray(entry) ? entry[0] : entry;
2451
+ const resumePoint = inferNextNode(messages, {
2452
+ entryNode: entryNode !== "__default_entry__" ? entryNode : undefined,
2453
+ edges: undefined
2454
+ });
2455
+ const sessionState = await this.initializeSessionState(sessionId, workflowDef, workflowId, workflowName, options);
2456
+ this.activeSessions.set(sessionId, sessionState);
2457
+ return this.runWithResume(sessionId, resumePoint, options);
2458
+ }
2459
+ async initializeSessionState(sessionId, definition, workflowId, workflowName, options) {
2460
+ const dagManager = new DAGManager(definition);
2461
+ const validation = dagManager.validate();
2462
+ if (!validation.valid) {
2463
+ throw new Error(`Invalid workflow: ${validation.errors.join(", ")}`);
2464
+ }
2465
+ const parallelLimit = options?.parallelLimit ?? definition.config?.parallel_limit ?? null;
2466
+ const scheduler = new Scheduler(dagManager, { parallelLimit });
2467
+ const eventBus = new EventBus;
2468
+ const executorOptions = {
2469
+ globalTimeout: options?.timeout ?? definition.config?.timeout ?? null,
2470
+ globalRetry: definition.config?.retry ?? null,
2471
+ debug: options?.debug ?? definition.config?.debug ?? false
2472
+ };
2473
+ const executor = new Executor(this.nodeRegistry, eventBus, executorOptions, this.sessionComponent);
2474
+ const config = {
2475
+ parallelLimit,
2476
+ timeout: options?.timeout ?? definition.config?.timeout ?? null,
2477
+ debug: options?.debug ?? definition.config?.debug ?? false
2478
+ };
2479
+ const abortController = new AbortController;
2480
+ let resolveCompleted;
2481
+ let rejectCompleted;
2482
+ const completedPromise = new Promise((resolve, reject) => {
2483
+ resolveCompleted = resolve;
2484
+ rejectCompleted = reject;
2485
+ });
2486
+ const sessionState = {
2487
+ sessionId,
2488
+ workflowId,
2489
+ workflowName,
2490
+ status: "running",
2491
+ startedAt: new Date,
2492
+ eventBus,
2493
+ dagManager,
2494
+ scheduler,
2495
+ executor,
2496
+ nodeRegistry: this.nodeRegistry,
2497
+ nodeOutputs: new Map,
2498
+ config,
2499
+ abortController,
2500
+ completedPromise,
2501
+ resolveCompleted,
2502
+ rejectCompleted,
2503
+ workflowHistory: [],
2504
+ agentSessions: new Map
2505
+ };
2506
+ this.setupEventHandlers(sessionState);
2507
+ return sessionState;
2508
+ }
2509
+ async runWithResume(sessionId, resumePoint, options) {
2510
+ const sessionState = this.activeSessions.get(sessionId);
2511
+ if (!sessionState) {
2512
+ throw new Error(`Session not found: ${sessionId}`);
2513
+ }
2514
+ const runId = this.getRunIdFromSessionId(sessionId);
2515
+ await sessionState.eventBus.publish(createWorkflowEvent("workflow.started", runId, {
2516
+ workflow_name: sessionState.workflowName,
2517
+ input: options?.input
2518
+ }));
2519
+ let pendingNodeId;
2520
+ let agentSessionId;
2521
+ switch (resumePoint.type) {
2522
+ case "entry_node":
2523
+ case "next_nodes":
2524
+ pendingNodeId = undefined;
2525
+ break;
2526
+ case "resume_node":
2527
+ case "ask_user":
2528
+ pendingNodeId = resumePoint.nodeId;
2529
+ agentSessionId = resumePoint.agentSessionId;
2530
+ break;
2531
+ }
2532
+ const userResponse = typeof options?.input === "string" ? options.input : undefined;
2533
+ this.scheduleAndExecute(sessionState, {
2534
+ input: options?.input,
2535
+ pendingNodeId,
2536
+ agentSessionId,
2537
+ userResponse
2538
+ }).catch((error) => {
2539
+ logger.error(`Workflow ${sessionId} scheduling error:`, error);
2540
+ this.failWorkflow(sessionState, error);
2541
+ });
2542
+ if (options?.sync !== false) {
2543
+ return this.waitForCompletion(sessionId, options?.timeout);
2544
+ }
2545
+ return { runId, status: "running" };
2546
+ }
2547
+ async runWorkflow(workflow2, options) {
2548
+ const definition = "definition" in workflow2 ? workflow2.definition : workflow2;
2549
+ const workflowId = "id" in workflow2 ? workflow2.id : `inline_${definition.name}`;
2550
+ const workflowName = definition.name;
2551
+ const sessionId = await this.createSession(workflow2, options);
2552
+ const sessionState = await this.initializeSessionState(sessionId, definition, workflowId, workflowName, options);
2553
+ this.activeSessions.set(sessionId, sessionState);
2554
+ return this.runWithResume(sessionId, { type: "entry_node" }, options);
2555
+ }
2556
+ async pause(sessionId) {
2557
+ const sessionState = this.activeSessions.get(sessionId);
2558
+ if (!sessionState) {
2559
+ throw new Error(`Session not found: ${sessionId}`);
2560
+ }
2561
+ if (sessionState.status !== "running") {
2562
+ throw new Error(`Session ${sessionId} is not running (current: ${sessionState.status})`);
2563
+ }
2564
+ sessionState.status = "paused";
2565
+ sessionState.abortController.abort();
2566
+ sessionState.executor.cancelAll();
2567
+ if (this.sessionComponent) {
2568
+ const metadata = await this.getSessionMetadata(sessionId);
2569
+ await this.sessionComponent.update(sessionId, {
2570
+ metadata: { ...metadata, status: "paused" }
2571
+ });
2572
+ }
2573
+ await sessionState.eventBus.publish(createWorkflowEvent("workflow.paused", this.getRunIdFromSessionId(sessionId), {}));
2574
+ logger.info(`[WorkflowEngine] Workflow paused: ${sessionId}`);
2575
+ }
2576
+ async resume(sessionId, options) {
2577
+ const sessionState = this.activeSessions.get(sessionId);
2578
+ if (!sessionState) {
2579
+ logger.info(`[WorkflowEngine] Session not in memory, attempting to restore from DB: ${sessionId}`);
2580
+ return this.resumeFromDatabase(sessionId, options);
2581
+ }
2582
+ if (options?.response) {
2583
+ await this.writeNodeResume(sessionId, options.response);
2584
+ }
2585
+ if (sessionState.status === "running") {
2586
+ return { runId: this.getRunIdFromSessionId(sessionId), status: "running" };
2587
+ }
2588
+ if (sessionState.status !== "paused") {
2589
+ throw new Error(`Session ${sessionId} is not paused (current: ${sessionState.status})`);
2590
+ }
2591
+ sessionState.status = "running";
2592
+ sessionState.abortController = new AbortController;
2593
+ if (this.sessionComponent) {
2594
+ const metadata = await this.getSessionMetadata(sessionId);
2595
+ await this.sessionComponent.update(sessionId, {
2596
+ metadata: { ...metadata, status: "running" }
2597
+ });
2598
+ }
2599
+ await sessionState.eventBus.publish(createWorkflowEvent("workflow.resumed", this.getRunIdFromSessionId(sessionId), {
2600
+ userResponse: options?.response
2601
+ }));
2602
+ const runtimeState = await this.restoreRuntimeState(sessionId);
2603
+ this.scheduleAndExecute(sessionState, {
2604
+ pendingNodeId: runtimeState.pendingNodeId || undefined,
2605
+ agentSessionId: runtimeState.agentSessionId,
2606
+ userResponse: options?.response,
2607
+ restoredOutputs: runtimeState.nodeOutputs
2608
+ });
2609
+ return {
2610
+ runId: this.getRunIdFromSessionId(sessionId),
2611
+ status: "running"
2612
+ };
2613
+ }
2614
+ async resumeFromDatabase(sessionId, options) {
2615
+ const session = await this.sessionComponent?.get(sessionId);
2616
+ if (!session) {
2617
+ throw new Error(`Session not found: ${sessionId}`);
2618
+ }
2619
+ const metadata = session.metadata;
2620
+ if (metadata.type !== "workflow") {
2621
+ throw new Error(`Session is not a workflow session: ${sessionId}`);
2622
+ }
2623
+ if (metadata.status !== "paused") {
2624
+ throw new Error(`Workflow is not paused: ${sessionId}, status: ${metadata.status}`);
2625
+ }
2626
+ const runtimeState = await this.restoreRuntimeState(sessionId);
2627
+ if (!runtimeState.pendingNodeId) {
2628
+ throw new Error(`No pending node found in session: ${sessionId}`);
2629
+ }
2630
+ if (options?.response) {
2631
+ await this.writeNodeResume(sessionId, options.response);
2632
+ }
2633
+ if (this.sessionComponent) {
2634
+ await this.sessionComponent.update(sessionId, {
2635
+ metadata: { ...metadata, status: "running" }
2636
+ });
2637
+ }
2638
+ logger.info(`[WorkflowEngine] Resumed from database: ${sessionId}, pendingNode: ${runtimeState.pendingNodeId}`);
2639
+ throw new Error(`Cannot resume from database without workflow definition. Session ${sessionId} is paused at node "${runtimeState.pendingNodeId}". Please ensure the workflow is registered before resuming.`);
2640
+ }
2641
+ async restoreRuntimeState(sessionId) {
2642
+ const messages = this.sessionComponent ? await this.sessionComponent.getMessages(sessionId) : [];
2643
+ const nodeOutputs = new Map;
2644
+ let lastCallNodeId = null;
2645
+ let lastInterruptMessage = null;
2646
+ let agentSessionId;
2647
+ for (const msg of messages) {
2648
+ const msgMetadata = msg.metadata;
2649
+ if (msgMetadata?.type === "workflow.node.call") {
2650
+ lastCallNodeId = msgMetadata.workflowNodeId;
2651
+ } else if (msgMetadata?.type === "workflow.node.result") {
2652
+ if (lastCallNodeId) {
2653
+ try {
2654
+ nodeOutputs.set(lastCallNodeId, JSON.parse(msg.content));
2655
+ } catch {
2656
+ nodeOutputs.set(lastCallNodeId, msg.content);
2657
+ }
2658
+ }
2659
+ lastCallNodeId = null;
2660
+ } else if (msgMetadata?.type === "workflow.node.interrupt") {
2661
+ lastInterruptMessage = msg;
2662
+ lastCallNodeId = msgMetadata.workflowNodeId;
2663
+ agentSessionId = msgMetadata.agentSessionId;
2664
+ }
2665
+ }
2666
+ return {
2667
+ nodeOutputs,
2668
+ pendingNodeId: lastCallNodeId,
2669
+ waitingForUser: !!lastInterruptMessage,
2670
+ agentSessionId,
2671
+ lastInterruptMessage
2672
+ };
2673
+ }
2674
+ async writeNodeResume(sessionId, response) {
2675
+ if (this.sessionComponent) {
2676
+ await this.sessionComponent.addMessage(sessionId, {
2677
+ role: "workflow.node.resume",
2678
+ content: response,
2679
+ metadata: {
2680
+ type: "workflow.node.resume",
2681
+ response,
2682
+ timestamp: Date.now()
2683
+ }
2684
+ });
2685
+ }
2686
+ }
2687
+ async stop(sessionId, reason) {
2688
+ const sessionState = this.activeSessions.get(sessionId);
2689
+ if (!sessionState) {
2690
+ if (this.sessionComponent) {
2691
+ await this.sessionComponent.update(sessionId, {
2692
+ metadata: { status: "stopped" }
2693
+ });
2694
+ }
2695
+ return;
2696
+ }
2697
+ sessionState.status = "stopped";
2698
+ sessionState.abortController.abort();
2699
+ sessionState.executor.cancelAll();
2700
+ if (this.sessionComponent) {
2701
+ const metadata = await this.getSessionMetadata(sessionId);
2702
+ await this.sessionComponent.update(sessionId, {
2703
+ metadata: { ...metadata, status: "stopped" }
2704
+ });
2705
+ }
2706
+ await sessionState.eventBus.publish(createWorkflowEvent("workflow.stopped", this.getRunIdFromSessionId(sessionId), {
2707
+ reason: reason ?? "User requested stop"
2708
+ }));
2709
+ this.cleanupSession(sessionState);
2710
+ }
2711
+ getSessionStatus(sessionId) {
2712
+ const sessionState = this.activeSessions.get(sessionId);
2713
+ return sessionState?.status ?? null;
2714
+ }
2715
+ isSessionActive(sessionId) {
2716
+ return this.activeSessions.has(sessionId);
2717
+ }
2718
+ setupEventHandlers(sessionState) {
2719
+ const { sessionId, eventBus, scheduler } = sessionState;
2720
+ const runId = this.getRunIdFromSessionId(sessionId);
2721
+ eventBus.on("node.completed", async (event2) => {
2722
+ if (event2.type !== "node.completed")
2723
+ return;
2724
+ sessionState.nodeOutputs.set(event2.node_id, event2.output);
2725
+ scheduler.markCompleted(event2.node_id);
2726
+ if (event2.output && typeof event2.output === "object" && "workflowHistory" in event2.output) {
2727
+ const messages = event2.output.workflowHistory;
2728
+ if (Array.isArray(messages)) {
2729
+ sessionState.workflowHistory.push(...messages);
2730
+ }
2731
+ }
2732
+ this.checkAndFinalize(sessionState);
2733
+ });
2734
+ eventBus.on("node.failed", async (event2) => {
2735
+ if (event2.type !== "node.failed")
2736
+ return;
2737
+ scheduler.markFailed(event2.node_id);
2738
+ await this.failWorkflow(sessionState, new Error(event2.error.message));
2739
+ });
2740
+ eventBus.on("node.interrupt", async (event2) => {
2741
+ if (event2.type !== "node.interrupt")
2742
+ return;
2743
+ logger.info(`Workflow paused at node "${event2.node_id}" - ask_user pending`);
2744
+ sessionState.status = "paused";
2745
+ sessionState.abortController.abort();
2746
+ if (this.sessionComponent) {
2747
+ const metadata = await this.getSessionMetadata(sessionId);
2748
+ await this.sessionComponent.update(sessionId, {
2749
+ metadata: { ...metadata, status: "paused" }
2750
+ });
2751
+ }
2752
+ await eventBus.publish(createWorkflowEvent("workflow.paused", runId, {
2753
+ pendingNodeId: event2.node_id,
2754
+ query: event2.query
2755
+ }));
2756
+ await this.writeNodeInterrupt(sessionId, event2.node_id, event2.node_type, event2.query, event2.agent_session_id);
2757
+ sessionState.resolveCompleted({
2758
+ runId,
2759
+ status: "paused",
2760
+ pendingNodeId: event2.node_id,
2761
+ query: event2.query,
2762
+ agentSessionId: event2.agent_session_id
2763
+ });
2764
+ });
2765
+ }
2766
+ async writeNodeInterrupt(sessionId, nodeId, nodeType, query, agentSessionId) {
2767
+ if (this.sessionComponent) {
2768
+ await this.sessionComponent.addMessage(sessionId, {
2769
+ role: "workflow.node.interrupt",
2770
+ content: query,
2771
+ metadata: {
2772
+ type: "workflow.node.interrupt",
2773
+ workflowNodeId: nodeId,
2774
+ workflowNodeType: nodeType,
2775
+ query,
2776
+ agentSessionId,
2777
+ timestamp: Date.now()
2778
+ }
2779
+ });
2780
+ }
2781
+ }
2782
+ async scheduleAndExecute(sessionState, options) {
2783
+ const { scheduler, executor, eventBus, abortController, nodeOutputs } = sessionState;
2784
+ const { input: globalInput, pendingNodeId, agentSessionId, userResponse, restoredOutputs } = options || {};
2785
+ if (restoredOutputs) {
2786
+ for (const [nodeId, output] of restoredOutputs) {
2787
+ nodeOutputs.set(nodeId, output);
2788
+ }
2789
+ }
2790
+ const scheduleAvailableNodes = async () => {
2791
+ const state = scheduler.getState();
2792
+ const completedNodes = new Set(state.completed);
2793
+ const readyNodes = scheduler.getReadyNodes(completedNodes);
2794
+ const canStart = scheduler.canStartMore();
2795
+ if (readyNodes.length === 0 || !canStart) {
2796
+ return false;
2797
+ }
2798
+ let scheduled = 0;
2799
+ for (const nodeId of readyNodes) {
2800
+ if (!scheduler.canStartMore())
2801
+ break;
2802
+ if (scheduled >= (sessionState.config.parallelLimit ?? Infinity))
2803
+ break;
2804
+ await this.startNode(sessionState, nodeId, globalInput);
2805
+ scheduled++;
2806
+ }
2807
+ return true;
2808
+ };
2809
+ if (pendingNodeId) {
2810
+ await this.resumeNode(sessionState, pendingNodeId, {
2811
+ agentSessionId,
2812
+ userResponse
2813
+ });
2814
+ } else {
2815
+ await scheduleAvailableNodes();
2816
+ }
2817
+ while (sessionState.status === "running" && !abortController.signal.aborted) {
2818
+ const state = scheduler.getState();
2819
+ if (state.pending.length === 0 && state.running.length === 0) {
2820
+ break;
2821
+ }
2822
+ try {
2823
+ await this.waitForNextNodeEvent(sessionState, abortController.signal);
2824
+ } catch {
2825
+ break;
2826
+ }
2827
+ await scheduleAvailableNodes();
2828
+ }
2829
+ }
2830
+ waitForNextNodeEvent(sessionState, signal) {
2831
+ return new Promise((resolve) => {
2832
+ const timeoutId = setTimeout(() => {
2833
+ cleanup();
2834
+ resolve();
2835
+ }, 100);
2836
+ const cleanup = () => {
2837
+ clearTimeout(timeoutId);
2838
+ sessionState.eventBus.off("node.completed", onCompleted);
2839
+ sessionState.eventBus.off("node.failed", onFailed);
2840
+ };
2841
+ const onCompleted = (event2) => {
2842
+ if (event2.type === "node.completed") {
2843
+ cleanup();
2844
+ resolve();
2845
+ }
2846
+ };
2847
+ const onFailed = (event2) => {
2848
+ if (event2.type === "node.failed") {
2849
+ cleanup();
2850
+ resolve();
2851
+ }
2852
+ };
2853
+ sessionState.eventBus.on("node.completed", onCompleted);
2854
+ sessionState.eventBus.on("node.failed", onFailed);
2855
+ if (signal.aborted) {
2856
+ cleanup();
2857
+ resolve();
2858
+ }
2859
+ });
2860
+ }
2861
+ async startNode(sessionState, nodeId, input) {
2862
+ const { scheduler, executor, eventBus, dagManager } = sessionState;
2863
+ const sessionId = sessionState.sessionId;
2864
+ const runId = this.getRunIdFromSessionId(sessionId);
2865
+ scheduler.markStarted(nodeId);
2866
+ await eventBus.publish(createWorkflowEvent("node.scheduled", runId, {
2867
+ node_id: nodeId
2868
+ }));
2869
+ const nodeDef = dagManager.getNode(nodeId);
2870
+ if (!nodeDef) {
2871
+ scheduler.markFailed(nodeId);
2872
+ return;
2873
+ }
2874
+ await this.writeNodeCall(sessionId, nodeId, nodeDef.type, input);
2875
+ const context2 = this.createExecutionContext(sessionState, nodeId, input);
2876
+ executor.executeNode(nodeDef, context2).catch(async (error) => {
2877
+ if (error instanceof AskUserError) {
2878
+ await eventBus.publish(createNodeInterruptEvent(runId, nodeId, nodeDef.type, error.query, error.agentSessionId));
2879
+ return;
2880
+ }
2881
+ scheduler.markFailed(nodeId);
2882
+ });
2883
+ }
2884
+ async writeNodeCall(sessionId, nodeId, nodeType, input) {
2885
+ if (this.sessionComponent) {
2886
+ await this.sessionComponent.addMessage(sessionId, {
2887
+ role: "workflow.node.call",
2888
+ content: JSON.stringify({ input }),
2889
+ metadata: {
2890
+ type: "workflow.node.call",
2891
+ workflowNodeId: nodeId,
2892
+ workflowNodeType: nodeType,
2893
+ timestamp: Date.now()
2894
+ }
2895
+ });
2896
+ }
2897
+ }
2898
+ async resumeNode(sessionState, nodeId, options) {
2899
+ const { scheduler, executor, eventBus, dagManager } = sessionState;
2900
+ const sessionId = sessionState.sessionId;
2901
+ const runId = this.getRunIdFromSessionId(sessionId);
2902
+ scheduler.markStarted(nodeId);
2903
+ await eventBus.publish(createWorkflowEvent("node.started", runId, {
2904
+ node_id: nodeId,
2905
+ agentSessionId: options?.agentSessionId,
2906
+ userResponse: options?.userResponse
2907
+ }));
2908
+ const nodeDef = dagManager.getNode(nodeId);
2909
+ if (!nodeDef) {
2910
+ scheduler.markFailed(nodeId);
2911
+ return;
2912
+ }
2913
+ const context2 = this.createExecutionContext(sessionState, nodeId, undefined);
2914
+ if (options?.agentSessionId || options?.userResponse) {
2915
+ context2.agentSessionId = options.agentSessionId;
2916
+ context2.userResponse = options.userResponse;
2917
+ }
2918
+ executor.executeNode(nodeDef, context2).catch((error) => {
2919
+ if (error instanceof AskUserError) {
2920
+ const event2 = createNodeInterruptEvent(runId, nodeId, nodeDef.type, error.query, error.agentSessionId);
2921
+ eventBus.publish(event2);
2922
+ return;
2923
+ }
2924
+ scheduler.markFailed(nodeId);
2925
+ });
2926
+ }
2927
+ createExecutionContext(sessionState, nodeId, globalInput) {
2928
+ const nodeDef = sessionState.dagManager.getNode(nodeId);
2929
+ const runId = this.getRunIdFromSessionId(sessionState.sessionId);
2930
+ const deps = nodeDef.depends_on || [];
2931
+ const input = {};
2932
+ for (const depId of deps) {
2933
+ const depOutput = sessionState.nodeOutputs.get(depId);
2934
+ if (depOutput !== undefined) {
2935
+ input[depId] = depOutput;
2936
+ }
2937
+ }
2938
+ const analysis = sessionState.dagManager.analyze();
2939
+ if (analysis.entryNodes.includes(nodeId) && globalInput) {
2940
+ Object.assign(input, globalInput);
2941
+ }
2942
+ const askUser = (query) => {
2943
+ throw new AskUserError(runId, sessionState.sessionId, nodeId, nodeDef.type, query);
2944
+ };
2945
+ return {
2946
+ runId,
2947
+ sessionId: sessionState.sessionId,
2948
+ workflowName: sessionState.workflowName,
2949
+ nodeId,
2950
+ input,
2951
+ previousOutputs: sessionState.nodeOutputs,
2952
+ config: nodeDef.config ?? {},
2953
+ debug: sessionState.config.debug,
2954
+ eventBus: sessionState.eventBus,
2955
+ nodeOutputs: sessionState.nodeOutputs,
2956
+ workflowHistory: sessionState.workflowHistory,
2957
+ sessionComponent: this.sessionComponent,
2958
+ askUser
2959
+ };
2960
+ }
2961
+ checkAndFinalize(sessionState) {
2962
+ const state = sessionState.scheduler.getState();
2963
+ if (state.pending.length === 0 && state.running.length === 0 && state.ready.length === 0) {
2964
+ if (state.failed.length > 0) {
2965
+ this.failWorkflow(sessionState, new Error(`Nodes failed: ${state.failed.join(", ")}`));
2966
+ } else {
2967
+ this.completeWorkflow(sessionState);
2968
+ }
2969
+ }
2970
+ }
2971
+ async completeWorkflow(sessionState) {
2972
+ const durationMs = Date.now() - sessionState.startedAt.getTime();
2973
+ const sessionId = sessionState.sessionId;
2974
+ const runId = this.getRunIdFromSessionId(sessionId);
2975
+ const output = {};
2976
+ for (const [nodeId, nodeOutput] of sessionState.nodeOutputs) {
2977
+ output[nodeId] = nodeOutput;
2978
+ }
2979
+ if (this.sessionComponent) {
2980
+ const metadata = await this.getSessionMetadata(sessionId);
2981
+ await this.sessionComponent.update(sessionId, {
2982
+ metadata: { ...metadata, status: "completed" }
2983
+ });
2984
+ }
2985
+ await sessionState.eventBus.publish(createWorkflowEvent("workflow.completed", runId, {
2986
+ result: output,
2987
+ duration_ms: durationMs
2988
+ }), true);
2989
+ sessionState.resolveCompleted({
2990
+ runId,
2991
+ status: "completed",
2992
+ output,
2993
+ durationMs
2994
+ });
2995
+ this.cleanupSession(sessionState);
2996
+ }
2997
+ async failWorkflow(sessionState, error) {
2998
+ const durationMs = Date.now() - sessionState.startedAt.getTime();
2999
+ const sessionId = sessionState.sessionId;
3000
+ const runId = this.getRunIdFromSessionId(sessionId);
3001
+ sessionState.executor.cancelAll();
3002
+ if (this.sessionComponent) {
3003
+ const metadata = await this.getSessionMetadata(sessionId);
3004
+ await this.sessionComponent.update(sessionId, {
3005
+ metadata: { ...metadata, status: "failed" }
3006
+ });
3007
+ }
3008
+ await sessionState.eventBus.publish(createWorkflowEvent("workflow.failed", runId, {
3009
+ error: { message: error.message, stack: error.stack },
3010
+ failed_at: new Date().toISOString()
3011
+ }), true);
3012
+ sessionState.resolveCompleted({
3013
+ runId,
3014
+ status: "failed",
3015
+ error: error.message,
3016
+ durationMs
3017
+ });
3018
+ this.cleanupSession(sessionState);
3019
+ }
3020
+ cleanupSession(sessionState) {
3021
+ sessionState.eventBus.clear();
3022
+ this.activeSessions.delete(sessionState.sessionId);
3023
+ }
3024
+ async waitForCompletion(sessionId, timeout) {
3025
+ const sessionState = this.activeSessions.get(sessionId);
3026
+ if (!sessionState) {
3027
+ throw new Error(`Session not found: ${sessionId}`);
3028
+ }
3029
+ const timeoutMs = timeout ?? 300000;
3030
+ const timeoutPromise = new Promise((_, reject) => {
3031
+ setTimeout(() => {
3032
+ reject(new Error(`Workflow execution timeout: ${timeoutMs}ms`));
3033
+ }, timeoutMs);
3034
+ });
3035
+ return Promise.race([
3036
+ sessionState.completedPromise,
3037
+ timeoutPromise
3038
+ ]);
3039
+ }
3040
+ async getSessionMetadata(sessionId) {
3041
+ if (!this.sessionComponent) {
3042
+ return { type: "workflow", workflowId: "", workflowName: "", status: "running" };
3043
+ }
3044
+ const session = await this.sessionComponent.get(sessionId);
3045
+ return session?.metadata || { type: "workflow", workflowId: "", workflowName: "", status: "running" };
3046
+ }
3047
+ findDefinitionForWorkflow(workflowIdOrName) {
3048
+ if (!this.workflowRepository) {
3049
+ return null;
3050
+ }
3051
+ let workflow2 = this.workflowRepository.getById(workflowIdOrName);
3052
+ if (workflow2)
3053
+ return workflow2.definition;
3054
+ workflow2 = this.workflowRepository.getByName(workflowIdOrName);
3055
+ if (workflow2)
3056
+ return workflow2.definition;
3057
+ return null;
3058
+ }
3059
+ };
3060
+ __legacyDecorateClassTS([
3061
+ TracedAs("workflow.engine.createSession", { recordParams: true, recordResult: true, log: true })
3062
+ ], WorkflowEngine.prototype, "createSession", null);
3063
+ __legacyDecorateClassTS([
3064
+ TracedAs("workflow.engine.run", { recordParams: true, recordResult: true, log: true })
3065
+ ], WorkflowEngine.prototype, "run", null);
3066
+ __legacyDecorateClassTS([
3067
+ TracedAs("workflow.engine.runWorkflow", { recordParams: true, recordResult: true, log: true })
3068
+ ], WorkflowEngine.prototype, "runWorkflow", null);
3069
+ __legacyDecorateClassTS([
3070
+ TracedAs("workflow.engine.pause", { recordParams: true, recordResult: true, log: true })
3071
+ ], WorkflowEngine.prototype, "pause", null);
3072
+ __legacyDecorateClassTS([
3073
+ TracedAs("workflow.engine.resume", { recordParams: true, recordResult: true, log: true })
3074
+ ], WorkflowEngine.prototype, "resume", null);
3075
+ __legacyDecorateClassTS([
3076
+ TracedAs("workflow.engine.resumeFromDatabase", { recordParams: true, recordResult: true, log: true })
3077
+ ], WorkflowEngine.prototype, "resumeFromDatabase", null);
3078
+ __legacyDecorateClassTS([
3079
+ TracedAs("workflow.engine.restoreRuntimeState", { recordParams: true, recordResult: true, log: true })
3080
+ ], WorkflowEngine.prototype, "restoreRuntimeState", null);
3081
+ __legacyDecorateClassTS([
3082
+ TracedAs("workflow.engine.writeNodeResume", { recordParams: true, recordResult: true, log: true })
3083
+ ], WorkflowEngine.prototype, "writeNodeResume", null);
3084
+ __legacyDecorateClassTS([
3085
+ TracedAs("workflow.engine.stop", { recordParams: true, recordResult: true, log: true })
3086
+ ], WorkflowEngine.prototype, "stop", null);
3087
+ __legacyDecorateClassTS([
3088
+ TracedAs("workflow.engine.writeNodeInterrupt", { recordParams: true, recordResult: true, log: true }),
3089
+ TracedAs("workflow.engine.writeNodeInterrupt", { recordParams: true, recordResult: true, log: true })
3090
+ ], WorkflowEngine.prototype, "writeNodeInterrupt", null);
3091
+ __legacyDecorateClassTS([
3092
+ TracedAs("workflow.engine.scheduleAndExecute", { recordParams: true, recordResult: true, log: true }),
3093
+ TracedAs("workflow.engine.scheduleAndExecute", { recordParams: true, recordResult: true, log: true })
3094
+ ], WorkflowEngine.prototype, "scheduleAndExecute", null);
3095
+ __legacyDecorateClassTS([
3096
+ TracedAs("workflow.engine.waitForNextNodeEvent", { recordParams: true, recordResult: true, log: true })
3097
+ ], WorkflowEngine.prototype, "waitForNextNodeEvent", null);
3098
+ __legacyDecorateClassTS([
3099
+ TracedAs("workflow.engine.startNode", { recordParams: true, recordResult: true, log: true }),
3100
+ TracedAs("workflow.engine.startNode", { recordParams: true, recordResult: true, log: true })
3101
+ ], WorkflowEngine.prototype, "startNode", null);
3102
+ __legacyDecorateClassTS([
3103
+ TracedAs("workflow.engine.writeNodeCall", { recordParams: true, recordResult: true, log: true }),
3104
+ TracedAs("workflow.engine.writeNodeCall", { recordParams: true, recordResult: true, log: true })
3105
+ ], WorkflowEngine.prototype, "writeNodeCall", null);
3106
+ __legacyDecorateClassTS([
3107
+ TracedAs("workflow.engine.resumeNode", { recordParams: true, recordResult: true, log: true }),
3108
+ TracedAs("workflow.engine.resumeNode", { recordParams: true, recordResult: true, log: true })
3109
+ ], WorkflowEngine.prototype, "resumeNode", null);
3110
+ __legacyDecorateClassTS([
3111
+ TracedAs("workflow.engine.checkAndFinalize", { recordParams: true, recordResult: true, log: true })
3112
+ ], WorkflowEngine.prototype, "checkAndFinalize", null);
3113
+ __legacyDecorateClassTS([
3114
+ TracedAs("workflow.engine.completeWorkflow", { recordParams: true, recordResult: true, log: true })
3115
+ ], WorkflowEngine.prototype, "completeWorkflow", null);
3116
+ __legacyDecorateClassTS([
3117
+ TracedAs("workflow.engine.failWorkflow", { recordParams: true, recordResult: true, log: true })
3118
+ ], WorkflowEngine.prototype, "failWorkflow", null);
3119
+ });
3120
+
3121
+ // src/env/workflow/engine/index.ts
3122
+ var exports_engine = {};
3123
+ __export(exports_engine, {
3124
+ WorkflowEngine: () => WorkflowEngine,
3125
+ Scheduler: () => Scheduler,
3126
+ NodeRegistry: () => NodeRegistry,
3127
+ Executor: () => Executor,
3128
+ EventBus: () => EventBus,
3129
+ DAGManager: () => DAGManager
3130
+ });
3131
+ var init_engine2 = __esm(() => {
3132
+ init_event_bus();
3133
+ init_dag_manager();
3134
+ init_scheduler();
3135
+ init_executor();
3136
+ init_engine();
3137
+ init_node_registry();
3138
+ });
3139
+
3140
+ export { Traced, TracedAs, TracedLightweight, wrapFunction, init_decorator, EventBus, DAGManager, Scheduler, Executor, NodeRegistry, WorkflowEngine, exports_engine, init_engine2 as init_engine };