@nuraly/lumenui 0.2.2 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/cdn.js +1 -0
  2. package/dist/nuralyui.bundle.js +2467 -1857
  3. package/dist/nuralyui.bundle.js.gz +0 -0
  4. package/dist/src/components/canvas/bundle.js +569 -204
  5. package/dist/src/components/canvas/bundle.js.gz +0 -0
  6. package/dist/src/components/canvas/canvas.constants.d.ts +1 -1
  7. package/dist/src/components/canvas/canvas.constants.js +1 -1
  8. package/dist/src/components/canvas/workflow-canvas.component.d.ts +7 -0
  9. package/dist/src/components/canvas/workflow-canvas.component.js +46 -2
  10. package/dist/src/components/canvas/workflow-canvas.types.d.ts +8 -1
  11. package/dist/src/components/canvas/workflow-canvas.types.js +157 -0
  12. package/dist/src/components/chat-panel/bundle.js +216 -0
  13. package/dist/src/components/chat-panel/bundle.js.gz +0 -0
  14. package/dist/src/components/chat-panel/chat-panel.component.d.ts +85 -0
  15. package/dist/src/components/chat-panel/chat-panel.component.js +510 -0
  16. package/dist/src/components/chat-panel/chat-panel.style.d.ts +2 -0
  17. package/dist/src/components/chat-panel/chat-panel.style.js +127 -0
  18. package/dist/src/components/chat-panel/chat-panel.types.d.ts +54 -0
  19. package/dist/src/components/chat-panel/chat-panel.types.js +2 -0
  20. package/dist/src/components/chat-panel/index.d.ts +3 -0
  21. package/dist/src/components/chat-panel/index.js +2 -0
  22. package/dist/src/components/chatbot/bundle.js +1 -1
  23. package/dist/src/components/chatbot/bundle.js.gz +0 -0
  24. package/dist/src/components/chatbot/providers/workflow-socket-provider.js +1 -1
  25. package/dist/src/components/presence/bundle.js +69 -42
  26. package/dist/src/components/presence/bundle.js.gz +0 -0
  27. package/dist/src/components/presence/presence-chat.component.d.ts +2 -0
  28. package/dist/src/components/presence/presence-chat.component.js +12 -2
  29. package/dist/src/components/presence/presence.component.d.ts +30 -6
  30. package/dist/src/components/presence/presence.component.js +277 -30
  31. package/dist/src/components/presence/presence.types.d.ts +2 -0
  32. package/dist/src/components/toast/bundle.js +11 -9
  33. package/dist/src/components/toast/bundle.js.gz +0 -0
  34. package/dist/src/components/toast/toast.component.d.ts +8 -0
  35. package/dist/src/components/toast/toast.component.js +17 -7
  36. package/dist/src/components/video/bundle.js +13 -12
  37. package/dist/src/components/video/bundle.js.gz +0 -0
  38. package/dist/src/components/video/video.component.d.ts +15 -1
  39. package/dist/src/components/video/video.component.js +131 -3
  40. package/package.json +5 -10
  41. package/packages/common/dist/VERSIONS.md +1 -1
@@ -24,7 +24,7 @@ export declare const TABLE_MIN_HEIGHT = 120;
24
24
  export declare const VIEWPORT_ADD_NODE_OFFSET_X = 400;
25
25
  export declare const VIEWPORT_ADD_NODE_OFFSET_Y = 200;
26
26
  export declare const TRIGGER_POLL_INTERVAL_MS = 10000;
27
- export declare const PERSISTENT_TRIGGER_TYPE_NAMES: readonly ["TELEGRAM_BOT", "SLACK_SOCKET", "DISCORD_BOT", "WHATSAPP_WEBHOOK", "CUSTOM_WEBSOCKET", "RABBITMQ_TRIGGER", "CALENDLY_TRIGGER", "KAFKA_TRIGGER"];
27
+ export declare const PERSISTENT_TRIGGER_TYPE_NAMES: readonly ["TELEGRAM_BOT", "SLACK_SOCKET", "DISCORD_BOT", "WHATSAPP_WEBHOOK", "CUSTOM_WEBSOCKET", "RABBITMQ_TRIGGER", "CALENDLY_TRIGGER", "KAFKA_TRIGGER", "CRON"];
28
28
  export declare const FILL_COLOR_PRESETS: readonly ["#fef08a", "#bbf7d0", "#bfdbfe", "#fecaca", "#e9d5ff", "#fed7aa", "#ffffff", "#f3f4f6"];
29
29
  export declare const BORDER_COLOR_PRESETS: readonly ["#8b5cf6", "#3b82f6", "#ef4444", "#22c55e", "#f59e0b", "#6b7280", "#1a1a1a", "#e5e7eb"];
30
30
  export declare const TEXT_COLOR_PRESETS: readonly ["#1a1a1a", "#374151", "#713f12", "#1e3a5f", "#7f1d1d", "#4c1d95", "#ffffff"];
@@ -30,7 +30,7 @@ export const VIEWPORT_ADD_NODE_OFFSET_Y = 200;
30
30
  // ==================== Trigger Polling ====================
31
31
  export const TRIGGER_POLL_INTERVAL_MS = 10000;
32
32
  export const PERSISTENT_TRIGGER_TYPE_NAMES = [
33
- 'TELEGRAM_BOT', 'SLACK_SOCKET', 'DISCORD_BOT', 'WHATSAPP_WEBHOOK', 'CUSTOM_WEBSOCKET', 'RABBITMQ_TRIGGER', 'CALENDLY_TRIGGER', 'KAFKA_TRIGGER',
33
+ 'TELEGRAM_BOT', 'SLACK_SOCKET', 'DISCORD_BOT', 'WHATSAPP_WEBHOOK', 'CUSTOM_WEBSOCKET', 'RABBITMQ_TRIGGER', 'CALENDLY_TRIGGER', 'KAFKA_TRIGGER', 'CRON',
34
34
  ];
35
35
  // ==================== Color Presets ====================
36
36
  export const FILL_COLOR_PRESETS = [
@@ -90,6 +90,13 @@ export declare class WorkflowCanvasElement extends BaseCanvasElement {
90
90
  createAndActivateTrigger(nodeType: string, config: NodeConfiguration): Promise<string | undefined>;
91
91
  toggleDevMode(triggerId: string, enable: boolean): Promise<void>;
92
92
  private handleNodePreview;
93
+ /**
94
+ * Open (idempotent) the workflow socket and wire execution listeners so that
95
+ * START-node clicks produce live node status updates without requiring a
96
+ * CHAT_START preview to be open. No-op unless the host set
97
+ * `listenToExecutionEvents=true` and a workflow is loaded.
98
+ */
99
+ private ensureExecutionSocket;
93
100
  private initializeChatPreview;
94
101
  private connectChatPreviewSocket;
95
102
  private setupExecutionSocketListeners;
@@ -128,6 +128,11 @@ let WorkflowCanvasElement = class WorkflowCanvasElement extends BaseCanvasElemen
128
128
  if (changedProperties.has('workflow')) {
129
129
  this.startTriggerPollingIfNeeded();
130
130
  }
131
+ // When the host flips listenToExecutionEvents on (or the workflow id changes),
132
+ // open the socket so START node clicks produce live status updates.
133
+ if (changedProperties.has('workflow') || changedProperties.has('listenToExecutionEvents')) {
134
+ this.ensureExecutionSocket();
135
+ }
131
136
  }
132
137
  // ==================== Nodes with Statuses ====================
133
138
  getNodesForRendering() {
@@ -178,7 +183,7 @@ let WorkflowCanvasElement = class WorkflowCanvasElement extends BaseCanvasElemen
178
183
  return;
179
184
  const triggers = yield triggersRes.json();
180
185
  const persistentTypes = new Set([
181
- 'TELEGRAM_BOT', 'SLACK_SOCKET', 'DISCORD_BOT', 'WHATSAPP_WEBHOOK', 'CUSTOM_WEBSOCKET',
186
+ 'TELEGRAM_BOT', 'SLACK_SOCKET', 'DISCORD_BOT', 'WHATSAPP_WEBHOOK', 'CUSTOM_WEBSOCKET', 'RABBITMQ_TRIGGER', 'CRON',
182
187
  ]);
183
188
  const persistentTriggers = triggers.filter(t => persistentTypes.has(t.type));
184
189
  const statusPromises = persistentTriggers.map((trigger) => __awaiter(this, void 0, void 0, function* () {
@@ -303,6 +308,37 @@ let WorkflowCanvasElement = class WorkflowCanvasElement extends BaseCanvasElemen
303
308
  if (node.type === WorkflowNodeType.CHAT_START && ((_a = this.workflow) === null || _a === void 0 ? void 0 : _a.id)) {
304
309
  yield this.initializeChatPreview(this.workflow.id, node.configuration);
305
310
  }
311
+ else {
312
+ // Chat preview cleanup tore down the shared socket — re-open it so
313
+ // START-node execution events still reach the canvas.
314
+ yield this.ensureExecutionSocket();
315
+ }
316
+ }
317
+ });
318
+ }
319
+ /**
320
+ * Open (idempotent) the workflow socket and wire execution listeners so that
321
+ * START-node clicks produce live node status updates without requiring a
322
+ * CHAT_START preview to be open. No-op unless the host set
323
+ * `listenToExecutionEvents=true` and a workflow is loaded.
324
+ */
325
+ ensureExecutionSocket() {
326
+ return __awaiter(this, void 0, void 0, function* () {
327
+ var _a;
328
+ if (this.chatPreviewProvider ||
329
+ !this.listenToExecutionEvents ||
330
+ !((_a = this.workflow) === null || _a === void 0 ? void 0 : _a.id)) {
331
+ return;
332
+ }
333
+ try {
334
+ this.chatPreviewProvider = new WorkflowSocketProvider();
335
+ yield this.connectChatPreviewSocket(this.workflow.id);
336
+ this.setupExecutionSocketListeners();
337
+ console.log('[Canvas] Execution socket initialized for workflow:', this.workflow.id);
338
+ }
339
+ catch (error) {
340
+ console.error('[Canvas] Failed to initialize execution socket:', error);
341
+ this.chatPreviewProvider = null;
306
342
  }
307
343
  });
308
344
  }
@@ -494,7 +530,7 @@ let WorkflowCanvasElement = class WorkflowCanvasElement extends BaseCanvasElemen
494
530
  }
495
531
  closePreviewPanel() {
496
532
  this.previewNodeId = null;
497
- this.cleanupChatPreview();
533
+ this.cleanupChatPreview().then(() => this.ensureExecutionSocket());
498
534
  this.resetHttpPreview();
499
535
  }
500
536
  handleNodeTrigger(e) {
@@ -519,6 +555,11 @@ let WorkflowCanvasElement = class WorkflowCanvasElement extends BaseCanvasElemen
519
555
  return;
520
556
  }
521
557
  console.log('[Canvas] Node trigger clicked:', node.name, node.type);
558
+ // START nodes dispatch workflow-run so the host page can execute the workflow
559
+ if (node.type === WorkflowNodeType.START) {
560
+ this.dispatchEvent(new CustomEvent('workflow-run', { bubbles: true, composed: true }));
561
+ return;
562
+ }
522
563
  this.dispatchEvent(new CustomEvent('workflow-trigger', {
523
564
  detail: { node },
524
565
  bubbles: true,
@@ -1006,6 +1047,9 @@ let WorkflowCanvasElement = class WorkflowCanvasElement extends BaseCanvasElemen
1006
1047
  }
1007
1048
  },
1008
1049
  onRetryNode: this.currentExecutionId ? (nodeId) => { void this.handleRetryNode(nodeId); } : undefined,
1050
+ onRunWorkflow: () => {
1051
+ this.dispatchEvent(new CustomEvent('workflow-run', { bubbles: true, composed: true }));
1052
+ },
1009
1053
  },
1010
1054
  workflowId: (_b = this.workflow) === null || _b === void 0 ? void 0 : _b.id,
1011
1055
  workflow: this.workflow,
@@ -15,12 +15,18 @@ export declare enum WorkflowNodeType {
15
15
  HTTP_END = "HTTP_END",
16
16
  CHAT_START = "CHAT_START",
17
17
  CHAT_OUTPUT = "CHAT_OUTPUT",
18
+ SOCIAL_POST = "SOCIAL_POST",
18
19
  FUNCTION = "FUNCTION",
19
20
  HTTP = "HTTP",
20
21
  CONDITION = "CONDITION",
22
+ SWITCH = "SWITCH",
21
23
  DELAY = "DELAY",
22
24
  PARALLEL = "PARALLEL",
25
+ MERGE = "MERGE",
23
26
  LOOP = "LOOP",
27
+ BREAK = "BREAK",
28
+ WAIT = "WAIT",
29
+ TRY_CATCH = "TRY_CATCH",
24
30
  TRANSFORM = "TRANSFORM",
25
31
  SUB_WORKFLOW = "SUB_WORKFLOW",
26
32
  EMAIL = "EMAIL",
@@ -76,7 +82,8 @@ export declare enum WorkflowNodeType {
76
82
  CALENDLY_TRIGGER = "CALENDLY_TRIGGER",
77
83
  UI_TABLE = "UI_TABLE",
78
84
  NOTE = "NOTE",
79
- FRAME = "FRAME"
85
+ FRAME = "FRAME",
86
+ CRON = "CRON"
80
87
  }
81
88
  /**
82
89
  * Node types for agent-based workflows
@@ -17,12 +17,18 @@ export var WorkflowNodeType;
17
17
  WorkflowNodeType["HTTP_END"] = "HTTP_END";
18
18
  WorkflowNodeType["CHAT_START"] = "CHAT_START";
19
19
  WorkflowNodeType["CHAT_OUTPUT"] = "CHAT_OUTPUT";
20
+ WorkflowNodeType["SOCIAL_POST"] = "SOCIAL_POST";
20
21
  WorkflowNodeType["FUNCTION"] = "FUNCTION";
21
22
  WorkflowNodeType["HTTP"] = "HTTP";
22
23
  WorkflowNodeType["CONDITION"] = "CONDITION";
24
+ WorkflowNodeType["SWITCH"] = "SWITCH";
23
25
  WorkflowNodeType["DELAY"] = "DELAY";
24
26
  WorkflowNodeType["PARALLEL"] = "PARALLEL";
27
+ WorkflowNodeType["MERGE"] = "MERGE";
25
28
  WorkflowNodeType["LOOP"] = "LOOP";
29
+ WorkflowNodeType["BREAK"] = "BREAK";
30
+ WorkflowNodeType["WAIT"] = "WAIT";
31
+ WorkflowNodeType["TRY_CATCH"] = "TRY_CATCH";
26
32
  WorkflowNodeType["TRANSFORM"] = "TRANSFORM";
27
33
  WorkflowNodeType["SUB_WORKFLOW"] = "SUB_WORKFLOW";
28
34
  WorkflowNodeType["EMAIL"] = "EMAIL";
@@ -104,6 +110,8 @@ export var WorkflowNodeType;
104
110
  // Annotation nodes
105
111
  WorkflowNodeType["NOTE"] = "NOTE";
106
112
  WorkflowNodeType["FRAME"] = "FRAME";
113
+ // Cron/scheduled trigger
114
+ WorkflowNodeType["CRON"] = "CRON";
107
115
  })(WorkflowNodeType || (WorkflowNodeType = {}));
108
116
  /**
109
117
  * Node types for agent-based workflows
@@ -231,12 +239,18 @@ export const NODE_COLORS = {
231
239
  [WorkflowNodeType.HTTP_END]: '#dc2626',
232
240
  [WorkflowNodeType.CHAT_START]: '#0ea5e9',
233
241
  [WorkflowNodeType.CHAT_OUTPUT]: '#06b6d4',
242
+ [WorkflowNodeType.SOCIAL_POST]: '#7c3aed',
234
243
  [WorkflowNodeType.FUNCTION]: '#3b82f6',
235
244
  [WorkflowNodeType.HTTP]: '#8b5cf6',
236
245
  [WorkflowNodeType.CONDITION]: '#f59e0b',
246
+ [WorkflowNodeType.SWITCH]: '#eab308',
237
247
  [WorkflowNodeType.DELAY]: '#6b7280',
238
248
  [WorkflowNodeType.PARALLEL]: '#06b6d4',
249
+ [WorkflowNodeType.MERGE]: '#0891b2',
239
250
  [WorkflowNodeType.LOOP]: '#ec4899',
251
+ [WorkflowNodeType.BREAK]: '#991b1b',
252
+ [WorkflowNodeType.WAIT]: '#a78bfa',
253
+ [WorkflowNodeType.TRY_CATCH]: '#f43f5e',
240
254
  [WorkflowNodeType.TRANSFORM]: '#14b8a6',
241
255
  [WorkflowNodeType.SUB_WORKFLOW]: '#6366f1',
242
256
  [WorkflowNodeType.EMAIL]: '#f97316',
@@ -318,6 +332,8 @@ export const NODE_COLORS = {
318
332
  // Annotation nodes
319
333
  [WorkflowNodeType.NOTE]: '#fef08a',
320
334
  [WorkflowNodeType.FRAME]: '#6366f1',
335
+ // Cron/scheduled trigger
336
+ [WorkflowNodeType.CRON]: '#d97706',
321
337
  // Agent nodes
322
338
  [AgentNodeType.AGENT]: '#10b981',
323
339
  [AgentNodeType.TOOL]: '#0ea5e9',
@@ -369,12 +385,18 @@ export const NODE_ICONS = {
369
385
  [WorkflowNodeType.HTTP_END]: 'upload',
370
386
  [WorkflowNodeType.CHAT_START]: 'message-circle',
371
387
  [WorkflowNodeType.CHAT_OUTPUT]: 'message-square',
388
+ [WorkflowNodeType.SOCIAL_POST]: 'send',
372
389
  [WorkflowNodeType.FUNCTION]: 'code',
373
390
  [WorkflowNodeType.HTTP]: 'globe',
374
391
  [WorkflowNodeType.CONDITION]: 'git-branch',
392
+ [WorkflowNodeType.SWITCH]: 'git-fork',
375
393
  [WorkflowNodeType.DELAY]: 'clock',
376
394
  [WorkflowNodeType.PARALLEL]: 'git-merge',
395
+ [WorkflowNodeType.MERGE]: 'merge',
377
396
  [WorkflowNodeType.LOOP]: 'repeat',
397
+ [WorkflowNodeType.BREAK]: 'circle-stop',
398
+ [WorkflowNodeType.WAIT]: 'hourglass',
399
+ [WorkflowNodeType.TRY_CATCH]: 'shield-alert',
378
400
  [WorkflowNodeType.TRANSFORM]: 'shuffle',
379
401
  [WorkflowNodeType.SUB_WORKFLOW]: 'layers',
380
402
  [WorkflowNodeType.EMAIL]: 'mail',
@@ -456,6 +478,8 @@ export const NODE_ICONS = {
456
478
  // Annotation nodes
457
479
  [WorkflowNodeType.NOTE]: 'sticky-note',
458
480
  [WorkflowNodeType.FRAME]: 'square',
481
+ // Cron/scheduled trigger
482
+ [WorkflowNodeType.CRON]: 'timer',
459
483
  // Agent nodes
460
484
  [AgentNodeType.AGENT]: 'cpu',
461
485
  [AgentNodeType.TOOL]: 'tool',
@@ -612,6 +636,24 @@ export const NODE_TEMPLATES = [
612
636
  outputs: [{ id: 'out', type: PortType.OUTPUT, label: 'Output' }],
613
637
  },
614
638
  },
639
+ {
640
+ type: WorkflowNodeType.SOCIAL_POST,
641
+ name: 'Social Post',
642
+ description: 'Post to social feed on behalf of an agent',
643
+ icon: NODE_ICONS[WorkflowNodeType.SOCIAL_POST],
644
+ color: NODE_COLORS[WorkflowNodeType.SOCIAL_POST],
645
+ category: 'action',
646
+ defaultConfig: {
647
+ agentId: '',
648
+ content: '${variables.response}',
649
+ mediaUrl: '',
650
+ mediaType: '',
651
+ },
652
+ defaultPorts: {
653
+ inputs: [{ id: 'in', type: PortType.INPUT, label: 'Input' }],
654
+ outputs: [{ id: 'out', type: PortType.OUTPUT, label: 'Output' }],
655
+ },
656
+ },
615
657
  {
616
658
  type: WorkflowNodeType.LLM,
617
659
  name: 'LLM',
@@ -772,6 +814,92 @@ export const NODE_TEMPLATES = [
772
814
  ],
773
815
  },
774
816
  },
817
+ {
818
+ type: WorkflowNodeType.SWITCH,
819
+ name: 'Switch',
820
+ description: 'Route to a branch based on a value',
821
+ icon: NODE_ICONS[WorkflowNodeType.SWITCH],
822
+ color: NODE_COLORS[WorkflowNodeType.SWITCH],
823
+ category: 'control',
824
+ defaultConfig: {
825
+ expression: '',
826
+ language: 'javascript',
827
+ cases: [
828
+ { value: 'case1', label: 'Case 1' },
829
+ { value: 'case2', label: 'Case 2' },
830
+ ],
831
+ includeDefault: true,
832
+ },
833
+ defaultPorts: {
834
+ inputs: [{ id: 'in', type: PortType.INPUT, label: 'Input' }],
835
+ outputs: [
836
+ { id: 'case1', type: PortType.OUTPUT, label: 'Case 1' },
837
+ { id: 'case2', type: PortType.OUTPUT, label: 'Case 2' },
838
+ { id: 'default', type: PortType.CONDITIONAL_DEFAULT, label: 'Default' },
839
+ ],
840
+ },
841
+ },
842
+ {
843
+ type: WorkflowNodeType.MERGE,
844
+ name: 'Merge',
845
+ description: 'Join multiple branches into one',
846
+ icon: NODE_ICONS[WorkflowNodeType.MERGE],
847
+ color: NODE_COLORS[WorkflowNodeType.MERGE],
848
+ category: 'control',
849
+ defaultConfig: { mode: 'waitAll' },
850
+ defaultPorts: {
851
+ inputs: [
852
+ { id: 'in1', type: PortType.INPUT, label: 'Input 1', multiple: true },
853
+ { id: 'in2', type: PortType.INPUT, label: 'Input 2', multiple: true },
854
+ ],
855
+ outputs: [{ id: 'out', type: PortType.OUTPUT, label: 'Output' }],
856
+ },
857
+ },
858
+ {
859
+ type: WorkflowNodeType.WAIT,
860
+ name: 'Wait',
861
+ description: 'Pause until a signal or event is received',
862
+ icon: NODE_ICONS[WorkflowNodeType.WAIT],
863
+ color: NODE_COLORS[WorkflowNodeType.WAIT],
864
+ category: 'control',
865
+ defaultConfig: { signalName: '', timeout: 300000 },
866
+ defaultPorts: {
867
+ inputs: [{ id: 'in', type: PortType.INPUT, label: 'Input' }],
868
+ outputs: [
869
+ { id: 'out', type: PortType.OUTPUT, label: 'Signal' },
870
+ { id: 'timeout', type: PortType.OUTPUT, label: 'Timeout' },
871
+ ],
872
+ },
873
+ },
874
+ {
875
+ type: WorkflowNodeType.TRY_CATCH,
876
+ name: 'Try / Catch',
877
+ description: 'Catch errors from the connected branch',
878
+ icon: NODE_ICONS[WorkflowNodeType.TRY_CATCH],
879
+ color: NODE_COLORS[WorkflowNodeType.TRY_CATCH],
880
+ category: 'control',
881
+ defaultConfig: { catchTypes: ['*'], errorVariable: 'error' },
882
+ defaultPorts: {
883
+ inputs: [{ id: 'in', type: PortType.INPUT, label: 'Input' }],
884
+ outputs: [
885
+ { id: 'try', type: PortType.OUTPUT, label: 'Try' },
886
+ { id: 'catch', type: PortType.ERROR, label: 'Catch' },
887
+ ],
888
+ },
889
+ },
890
+ {
891
+ type: WorkflowNodeType.BREAK,
892
+ name: 'Break',
893
+ description: 'Exit the enclosing loop',
894
+ icon: NODE_ICONS[WorkflowNodeType.BREAK],
895
+ color: NODE_COLORS[WorkflowNodeType.BREAK],
896
+ category: 'control',
897
+ defaultConfig: {},
898
+ defaultPorts: {
899
+ inputs: [{ id: 'in', type: PortType.INPUT, label: 'Input' }],
900
+ outputs: [],
901
+ },
902
+ },
775
903
  {
776
904
  type: WorkflowNodeType.TRANSFORM,
777
905
  name: 'Transform',
@@ -1748,6 +1876,26 @@ export const NODE_TEMPLATES = [
1748
1876
  ],
1749
1877
  },
1750
1878
  },
1879
+ // Cron/scheduled trigger
1880
+ {
1881
+ type: WorkflowNodeType.CRON,
1882
+ name: 'Cron Trigger',
1883
+ description: 'Triggers workflow on a scheduled cron expression',
1884
+ icon: NODE_ICONS[WorkflowNodeType.CRON],
1885
+ color: NODE_COLORS[WorkflowNodeType.CRON],
1886
+ category: 'trigger',
1887
+ defaultConfig: {
1888
+ cronExpression: '0 * * * *',
1889
+ timezone: 'UTC',
1890
+ },
1891
+ defaultPorts: {
1892
+ inputs: [],
1893
+ outputs: [
1894
+ { id: 'out', type: PortType.OUTPUT, label: 'Tick' },
1895
+ { id: 'error', type: PortType.ERROR, label: 'Error' },
1896
+ ],
1897
+ },
1898
+ },
1751
1899
  // MCP integration
1752
1900
  {
1753
1901
  type: WorkflowNodeType.MCP,
@@ -2509,6 +2657,7 @@ export const NODE_CATEGORIES = [
2509
2657
  WorkflowNodeType.START,
2510
2658
  WorkflowNodeType.HTTP_START,
2511
2659
  WorkflowNodeType.CHAT_START,
2660
+ WorkflowNodeType.CRON,
2512
2661
  WorkflowNodeType.TELEGRAM_BOT,
2513
2662
  WorkflowNodeType.SLACK_SOCKET,
2514
2663
  WorkflowNodeType.DISCORD_BOT,
@@ -2527,9 +2676,14 @@ export const NODE_CATEGORIES = [
2527
2676
  WorkflowNodeType.END,
2528
2677
  WorkflowNodeType.HTTP_END,
2529
2678
  WorkflowNodeType.CONDITION,
2679
+ WorkflowNodeType.SWITCH,
2530
2680
  WorkflowNodeType.DELAY,
2681
+ WorkflowNodeType.WAIT,
2531
2682
  WorkflowNodeType.PARALLEL,
2683
+ WorkflowNodeType.MERGE,
2532
2684
  WorkflowNodeType.LOOP,
2685
+ WorkflowNodeType.BREAK,
2686
+ WorkflowNodeType.TRY_CATCH,
2533
2687
  ],
2534
2688
  canvasType: CanvasType.WORKFLOW,
2535
2689
  },
@@ -2543,6 +2697,7 @@ export const NODE_CATEGORIES = [
2543
2697
  WorkflowNodeType.INFORMATION_EXTRACTOR,
2544
2698
  WorkflowNodeType.OCR,
2545
2699
  WorkflowNodeType.CHAT_OUTPUT,
2700
+ WorkflowNodeType.SOCIAL_POST,
2546
2701
  WorkflowNodeType.SUB_WORKFLOW,
2547
2702
  WorkflowNodeType.EMAIL,
2548
2703
  WorkflowNodeType.EMAIL_READER,
@@ -2939,8 +3094,10 @@ export const PERSISTENT_TRIGGER_TYPES = new Set([
2939
3094
  WorkflowNodeType.DISCORD_BOT,
2940
3095
  WorkflowNodeType.WHATSAPP_WEBHOOK,
2941
3096
  WorkflowNodeType.CUSTOM_WEBSOCKET,
3097
+ WorkflowNodeType.RABBITMQ_TRIGGER,
2942
3098
  WorkflowNodeType.CALENDLY_TRIGGER,
2943
3099
  WorkflowNodeType.KAFKA_TRIGGER,
3100
+ WorkflowNodeType.CRON,
2944
3101
  ]);
2945
3102
  export function isPersistentTriggerNode(type) {
2946
3103
  return PERSISTENT_TRIGGER_TYPES.has(type);