@flowgram.ai/runtime-js 0.2.22 → 0.2.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -34,6 +34,7 @@ __export(src_exports, {
34
34
  TaskReportAPI: () => TaskReportAPI,
35
35
  TaskResultAPI: () => TaskResultAPI,
36
36
  TaskRunAPI: () => TaskRunAPI,
37
+ TaskValidateAPI: () => TaskValidateAPI,
37
38
  WorkflowRuntimeAPIs: () => WorkflowRuntimeAPIs
38
39
  });
39
40
  module.exports = __toCommonJS(src_exports);
@@ -46,86 +47,85 @@ var import_zod4 = __toESM(require("zod"));
46
47
  var import_zod5 = __toESM(require("zod"));
47
48
  var import_zod6 = __toESM(require("zod"));
48
49
  var import_zod7 = __toESM(require("zod"));
50
+ var WorkflowIOZodSchema = import_zod2.default.record(import_zod2.default.string(), import_zod2.default.any());
51
+ var WorkflowSnapshotZodSchema = import_zod2.default.object({
52
+ id: import_zod2.default.string(),
53
+ nodeID: import_zod2.default.string(),
54
+ inputs: WorkflowIOZodSchema,
55
+ outputs: WorkflowIOZodSchema.optional(),
56
+ data: WorkflowIOZodSchema,
57
+ branch: import_zod2.default.string().optional()
58
+ });
59
+ var WorkflowStatusZodShape = {
60
+ status: import_zod2.default.string(),
61
+ terminated: import_zod2.default.boolean(),
62
+ startTime: import_zod2.default.number(),
63
+ endTime: import_zod2.default.number().optional(),
64
+ timeCost: import_zod2.default.number()
65
+ };
66
+ var WorkflowStatusZodSchema = import_zod2.default.object(WorkflowStatusZodShape);
67
+ var WorkflowNodeReportZodSchema = import_zod2.default.object({
68
+ id: import_zod2.default.string(),
69
+ ...WorkflowStatusZodShape,
70
+ snapshots: import_zod2.default.array(WorkflowSnapshotZodSchema)
71
+ });
72
+ var WorkflowReportsZodSchema = import_zod2.default.record(import_zod2.default.string(), WorkflowNodeReportZodSchema);
73
+ var WorkflowMessageZodSchema = import_zod2.default.object({
74
+ id: import_zod2.default.string(),
75
+ type: import_zod2.default.enum(["log", "info", "debug", "error", "warning"]),
76
+ message: import_zod2.default.string(),
77
+ nodeID: import_zod2.default.string().optional(),
78
+ timestamp: import_zod2.default.number()
79
+ });
80
+ var WorkflowMessagesZodSchema = import_zod2.default.record(
81
+ import_zod2.default.enum(["log", "info", "debug", "error", "warning"]),
82
+ import_zod2.default.array(WorkflowMessageZodSchema)
83
+ );
84
+ var WorkflowZodSchema = {
85
+ Inputs: WorkflowIOZodSchema,
86
+ Outputs: WorkflowIOZodSchema,
87
+ Status: WorkflowStatusZodSchema,
88
+ Snapshot: WorkflowSnapshotZodSchema,
89
+ Reports: WorkflowReportsZodSchema,
90
+ Messages: WorkflowMessagesZodSchema
91
+ };
49
92
  var FlowGramAPIName = /* @__PURE__ */ ((FlowGramAPIName2) => {
50
93
  FlowGramAPIName2["ServerInfo"] = "ServerInfo";
51
94
  FlowGramAPIName2["TaskRun"] = "TaskRun";
52
95
  FlowGramAPIName2["TaskReport"] = "TaskReport";
53
96
  FlowGramAPIName2["TaskResult"] = "TaskResult";
54
97
  FlowGramAPIName2["TaskCancel"] = "TaskCancel";
55
- FlowGramAPIName2["Validation"] = "Validation";
98
+ FlowGramAPIName2["TaskValidate"] = "TaskValidate";
56
99
  return FlowGramAPIName2;
57
100
  })(FlowGramAPIName || {});
58
- var ValidationDefine = {
59
- name: "Validation",
101
+ var TaskValidateDefine = {
102
+ name: "TaskValidate",
60
103
  method: "POST",
61
- path: "/validation",
62
- module: "Validation",
104
+ path: "/task/validate",
105
+ module: "Task",
63
106
  schema: {
64
107
  input: import_zod.default.object({
65
- schema: import_zod.default.string()
108
+ schema: import_zod.default.string(),
109
+ inputs: WorkflowZodSchema.Inputs
66
110
  }),
67
111
  output: import_zod.default.object({
68
112
  valid: import_zod.default.boolean(),
69
- nodeErrors: import_zod.default.array(
70
- import_zod.default.object({
71
- message: import_zod.default.string(),
72
- nodeID: import_zod.default.string()
73
- })
74
- ),
75
- edgeErrors: import_zod.default.array(
76
- import_zod.default.object({
77
- message: import_zod.default.string(),
78
- edge: import_zod.default.object({
79
- sourceNodeID: import_zod.default.string(),
80
- targetNodeID: import_zod.default.string(),
81
- sourcePortID: import_zod.default.string().optional(),
82
- targetPortID: import_zod.default.string().optional()
83
- })
84
- })
85
- )
113
+ errors: import_zod.default.array(import_zod.default.string()).optional()
86
114
  })
87
115
  }
88
116
  };
89
- var WorkflowIOZodSchema = import_zod3.default.record(import_zod3.default.string(), import_zod3.default.any());
90
- var WorkflowSnapshotZodSchema = import_zod3.default.object({
91
- id: import_zod3.default.string(),
92
- nodeID: import_zod3.default.string(),
93
- inputs: WorkflowIOZodSchema,
94
- outputs: WorkflowIOZodSchema.optional(),
95
- data: WorkflowIOZodSchema,
96
- branch: import_zod3.default.string().optional()
97
- });
98
- var WorkflowStatusZodShape = {
99
- status: import_zod3.default.string(),
100
- terminated: import_zod3.default.boolean(),
101
- startTime: import_zod3.default.number(),
102
- endTime: import_zod3.default.number().optional(),
103
- timeCost: import_zod3.default.number()
104
- };
105
- var WorkflowStatusZodSchema = import_zod3.default.object(WorkflowStatusZodShape);
106
- var WorkflowZodSchema = {
107
- Inputs: WorkflowIOZodSchema,
108
- Outputs: WorkflowIOZodSchema,
109
- Status: WorkflowStatusZodSchema,
110
- Snapshot: WorkflowSnapshotZodSchema,
111
- NodeReport: import_zod3.default.object({
112
- id: import_zod3.default.string(),
113
- ...WorkflowStatusZodShape,
114
- snapshots: import_zod3.default.array(WorkflowSnapshotZodSchema)
115
- })
116
- };
117
117
  var TaskRunDefine = {
118
118
  name: "TaskRun",
119
119
  method: "POST",
120
120
  path: "/task/run",
121
121
  module: "Task",
122
122
  schema: {
123
- input: import_zod2.default.object({
124
- schema: import_zod2.default.string(),
123
+ input: import_zod3.default.object({
124
+ schema: import_zod3.default.string(),
125
125
  inputs: WorkflowZodSchema.Inputs
126
126
  }),
127
- output: import_zod2.default.object({
128
- taskID: import_zod2.default.string()
127
+ output: import_zod3.default.object({
128
+ taskID: import_zod3.default.string()
129
129
  })
130
130
  }
131
131
  };
@@ -155,7 +155,8 @@ var TaskReportDefine = {
155
155
  inputs: WorkflowZodSchema.Inputs,
156
156
  outputs: WorkflowZodSchema.Outputs,
157
157
  workflowStatus: WorkflowZodSchema.Status,
158
- reports: import_zod5.default.record(import_zod5.default.string(), WorkflowZodSchema.NodeReport)
158
+ reports: WorkflowZodSchema.Reports,
159
+ messages: WorkflowZodSchema.Messages
159
160
  })
160
161
  }
161
162
  };
@@ -210,9 +211,9 @@ var FlowGramAPIs = {
210
211
  /* TaskCancel */
211
212
  ]: TaskCancelDefine,
212
213
  [
213
- "Validation"
214
- /* Validation */
215
- ]: ValidationDefine
214
+ "TaskValidate"
215
+ /* TaskValidate */
216
+ ]: TaskValidateDefine
216
217
  };
217
218
  var FlowGramAPINames = Object.keys(FlowGramAPIs);
218
219
  var WorkflowPortType = /* @__PURE__ */ ((WorkflowPortType2) => {
@@ -240,8 +241,27 @@ var FlowGramNode = /* @__PURE__ */ ((FlowGramNode22) => {
240
241
  FlowGramNode22["Loop"] = "loop";
241
242
  FlowGramNode22["Comment"] = "comment";
242
243
  FlowGramNode22["Group"] = "group";
244
+ FlowGramNode22["BlockStart"] = "block-start";
245
+ FlowGramNode22["BlockEnd"] = "block-end";
243
246
  return FlowGramNode22;
244
247
  })(FlowGramNode || {});
248
+ var ConditionOperation = /* @__PURE__ */ ((ConditionOperation2) => {
249
+ ConditionOperation2["EQ"] = "eq";
250
+ ConditionOperation2["NEQ"] = "neq";
251
+ ConditionOperation2["GT"] = "gt";
252
+ ConditionOperation2["GTE"] = "gte";
253
+ ConditionOperation2["LT"] = "lt";
254
+ ConditionOperation2["LTE"] = "lte";
255
+ ConditionOperation2["IN"] = "in";
256
+ ConditionOperation2["NIN"] = "nin";
257
+ ConditionOperation2["CONTAINS"] = "contains";
258
+ ConditionOperation2["NOT_CONTAINS"] = "not_contains";
259
+ ConditionOperation2["IS_EMPTY"] = "is_empty";
260
+ ConditionOperation2["IS_NOT_EMPTY"] = "is_not_empty";
261
+ ConditionOperation2["IS_TRUE"] = "is_true";
262
+ ConditionOperation2["IS_FALSE"] = "is_false";
263
+ return ConditionOperation2;
264
+ })(ConditionOperation || {});
245
265
  var IEngine = Symbol.for("Engine");
246
266
  var IExecutor = Symbol.for("Executor");
247
267
  var WorkflowStatus = /* @__PURE__ */ ((WorkflowStatus2) => {
@@ -253,6 +273,14 @@ var WorkflowStatus = /* @__PURE__ */ ((WorkflowStatus2) => {
253
273
  return WorkflowStatus2;
254
274
  })(WorkflowStatus || {});
255
275
  var IValidation = Symbol.for("Validation");
276
+ var WorkflowMessageType = /* @__PURE__ */ ((WorkflowMessageType2) => {
277
+ WorkflowMessageType2["Log"] = "log";
278
+ WorkflowMessageType2["Info"] = "info";
279
+ WorkflowMessageType2["Debug"] = "debug";
280
+ WorkflowMessageType2["Error"] = "error";
281
+ WorkflowMessageType2["Warn"] = "warning";
282
+ return WorkflowMessageType2;
283
+ })(WorkflowMessageType || {});
256
284
 
257
285
  // src/nodes/start/index.ts
258
286
  var StartExecutor = class {
@@ -268,26 +296,329 @@ var StartExecutor = class {
268
296
 
269
297
  // src/nodes/loop/index.ts
270
298
  var import_lodash_es = require("lodash-es");
299
+
300
+ // src/infrastructure/utils/uuid.ts
301
+ var import_uuid = require("uuid");
302
+ var uuid = import_uuid.v4;
303
+
304
+ // src/infrastructure/utils/runtime-type.ts
305
+ var WorkflowRuntimeType;
306
+ ((WorkflowRuntimeType2) => {
307
+ WorkflowRuntimeType2.getWorkflowType = (value) => {
308
+ if (value === null || value === void 0) {
309
+ return WorkflowVariableType.Null;
310
+ }
311
+ if (typeof value === "string") {
312
+ return WorkflowVariableType.String;
313
+ }
314
+ if (typeof value === "boolean") {
315
+ return WorkflowVariableType.Boolean;
316
+ }
317
+ if (typeof value === "number") {
318
+ if (Number.isInteger(value)) {
319
+ return WorkflowVariableType.Integer;
320
+ }
321
+ return WorkflowVariableType.Number;
322
+ }
323
+ if (Array.isArray(value)) {
324
+ return WorkflowVariableType.Array;
325
+ }
326
+ if (typeof value === "object") {
327
+ return WorkflowVariableType.Object;
328
+ }
329
+ return null;
330
+ };
331
+ WorkflowRuntimeType2.isMatchWorkflowType = (value, type) => {
332
+ const workflowType = (0, WorkflowRuntimeType2.getWorkflowType)(value);
333
+ if (!workflowType) {
334
+ return false;
335
+ }
336
+ return workflowType === type;
337
+ };
338
+ WorkflowRuntimeType2.isTypeEqual = (leftType, rightType) => {
339
+ if (leftType === WorkflowVariableType.Number && rightType === WorkflowVariableType.Integer || leftType === WorkflowVariableType.Integer && rightType === WorkflowVariableType.Number) {
340
+ return true;
341
+ }
342
+ return leftType === rightType;
343
+ };
344
+ WorkflowRuntimeType2.getArrayItemsType = (types) => {
345
+ const expectedType = types[0];
346
+ types.forEach((type) => {
347
+ if (type !== expectedType) {
348
+ throw new Error(`array items type must be same, expect ${expectedType}, but got ${type}`);
349
+ }
350
+ });
351
+ return expectedType;
352
+ };
353
+ })(WorkflowRuntimeType || (WorkflowRuntimeType = {}));
354
+
355
+ // src/infrastructure/utils/traverse-nodes.ts
356
+ function traverseNodes(startNode, getConnectedNodes) {
357
+ const visited = /* @__PURE__ */ new Set();
358
+ const result = [];
359
+ const traverse = (node) => {
360
+ for (const connectedNode of getConnectedNodes(node)) {
361
+ if (!visited.has(connectedNode.id)) {
362
+ visited.add(connectedNode.id);
363
+ result.push(connectedNode);
364
+ traverse(connectedNode);
365
+ }
366
+ }
367
+ };
368
+ traverse(startNode);
369
+ return result;
370
+ }
371
+
372
+ // src/infrastructure/utils/compare-node-groups.ts
373
+ function compareNodeGroups(groupA, groupB) {
374
+ const flatA = groupA.flat();
375
+ const setA = /* @__PURE__ */ new Map();
376
+ flatA.forEach((node) => {
377
+ setA.set(node.id, node);
378
+ });
379
+ const flatB = groupB.flat();
380
+ const setB = /* @__PURE__ */ new Map();
381
+ flatB.forEach((node) => {
382
+ setB.set(node.id, node);
383
+ });
384
+ const common = [];
385
+ const uniqueToA = [];
386
+ const uniqueToB = [];
387
+ setA.forEach((node, id) => {
388
+ if (setB.has(id)) {
389
+ common.push(node);
390
+ } else {
391
+ uniqueToA.push(node);
392
+ }
393
+ });
394
+ setB.forEach((node, id) => {
395
+ if (!setA.has(id)) {
396
+ uniqueToB.push(node);
397
+ }
398
+ });
399
+ return {
400
+ common,
401
+ uniqueToA,
402
+ uniqueToB
403
+ };
404
+ }
405
+
406
+ // src/infrastructure/utils/json-schema-validator.ts
407
+ var ROOT_PATH = "root";
408
+ var isRootPath = (path) => path === ROOT_PATH;
409
+ var validateValue = (value, schema, path) => {
410
+ if (schema.$ref) {
411
+ return { result: true };
412
+ }
413
+ if (schema.enum && schema.enum.length > 0) {
414
+ if (!schema.enum.includes(value)) {
415
+ return {
416
+ result: false,
417
+ errorMessage: `Value at ${path} must be one of: ${schema.enum.join(
418
+ ", "
419
+ )}, but got: ${JSON.stringify(value)}`
420
+ };
421
+ }
422
+ }
423
+ switch (schema.type) {
424
+ case "boolean":
425
+ return validateBoolean(value, path);
426
+ case "string":
427
+ return validateString(value, path);
428
+ case "integer":
429
+ return validateInteger(value, path);
430
+ case "number":
431
+ return validateNumber(value, path);
432
+ case "object":
433
+ return validateObject(value, schema, path);
434
+ case "array":
435
+ return validateArray(value, schema, path);
436
+ case "map":
437
+ return validateMap(value, schema, path);
438
+ default:
439
+ return {
440
+ result: false,
441
+ errorMessage: `Unknown type "${schema.type}" at ${path}`
442
+ };
443
+ }
444
+ };
445
+ var validateBoolean = (value, path) => {
446
+ if (typeof value !== "boolean") {
447
+ return {
448
+ result: false,
449
+ errorMessage: `Expected boolean at ${path}, but got: ${typeof value}`
450
+ };
451
+ }
452
+ return { result: true };
453
+ };
454
+ var validateString = (value, path) => {
455
+ if (typeof value !== "string") {
456
+ return {
457
+ result: false,
458
+ errorMessage: `Expected string at ${path}, but got: ${typeof value}`
459
+ };
460
+ }
461
+ return { result: true };
462
+ };
463
+ var validateInteger = (value, path) => {
464
+ if (!Number.isInteger(value)) {
465
+ return {
466
+ result: false,
467
+ errorMessage: `Expected integer at ${path}, but got: ${JSON.stringify(value)}`
468
+ };
469
+ }
470
+ return { result: true };
471
+ };
472
+ var validateNumber = (value, path) => {
473
+ if (typeof value !== "number" || isNaN(value)) {
474
+ return {
475
+ result: false,
476
+ errorMessage: `Expected number at ${path}, but got: ${JSON.stringify(value)}`
477
+ };
478
+ }
479
+ return { result: true };
480
+ };
481
+ var validateObject = (value, schema, path) => {
482
+ if (value === null || value === void 0) {
483
+ return {
484
+ result: false,
485
+ errorMessage: `Expected object at ${path}, but got: ${value}`
486
+ };
487
+ }
488
+ if (typeof value !== "object" || Array.isArray(value)) {
489
+ return {
490
+ result: false,
491
+ errorMessage: `Expected object at ${path}, but got: ${Array.isArray(value) ? "array" : typeof value}`
492
+ };
493
+ }
494
+ const objectValue = value;
495
+ if (schema.required && schema.required.length > 0) {
496
+ for (const requiredProperty of schema.required) {
497
+ if (!(requiredProperty in objectValue)) {
498
+ return {
499
+ result: false,
500
+ errorMessage: `Missing required property "${requiredProperty}" at ${path}`
501
+ };
502
+ }
503
+ }
504
+ }
505
+ if (schema.properties) {
506
+ for (const [propertyName, propertySchema] of Object.entries(schema.properties)) {
507
+ const isRequired = propertySchema.isPropertyRequired === true;
508
+ if (isRequired && !(propertyName in objectValue)) {
509
+ return {
510
+ result: false,
511
+ errorMessage: `Missing required property "${propertyName}" at ${path}`
512
+ };
513
+ }
514
+ }
515
+ }
516
+ if (schema.properties) {
517
+ for (const [propertyName, propertySchema] of Object.entries(schema.properties)) {
518
+ if (propertyName in objectValue) {
519
+ const propertyPath = isRootPath(path) ? propertyName : `${path}.${propertyName}`;
520
+ const propertyResult = validateValue(
521
+ objectValue[propertyName],
522
+ propertySchema,
523
+ propertyPath
524
+ );
525
+ if (!propertyResult.result) {
526
+ return propertyResult;
527
+ }
528
+ }
529
+ }
530
+ }
531
+ if (schema.additionalProperties) {
532
+ const definedProperties = new Set(Object.keys(schema.properties || {}));
533
+ for (const [propertyName, propertyValue] of Object.entries(objectValue)) {
534
+ if (!definedProperties.has(propertyName)) {
535
+ const propertyPath = isRootPath(path) ? propertyName : `${path}.${propertyName}`;
536
+ const propertyResult = validateValue(
537
+ propertyValue,
538
+ schema.additionalProperties,
539
+ propertyPath
540
+ );
541
+ if (!propertyResult.result) {
542
+ return propertyResult;
543
+ }
544
+ }
545
+ }
546
+ }
547
+ return { result: true };
548
+ };
549
+ var validateArray = (value, schema, path) => {
550
+ if (!Array.isArray(value)) {
551
+ return {
552
+ result: false,
553
+ errorMessage: `Expected array at ${path}, but got: ${typeof value}`
554
+ };
555
+ }
556
+ if (schema.items) {
557
+ for (const [index, item] of value.entries()) {
558
+ const itemPath = `${path}[${index}]`;
559
+ const itemResult = validateValue(item, schema.items, itemPath);
560
+ if (!itemResult.result) {
561
+ return itemResult;
562
+ }
563
+ }
564
+ }
565
+ return { result: true };
566
+ };
567
+ var validateMap = (value, schema, path) => {
568
+ if (value === null || value === void 0) {
569
+ return {
570
+ result: false,
571
+ errorMessage: `Expected map at ${path}, but got: ${value}`
572
+ };
573
+ }
574
+ if (typeof value !== "object" || Array.isArray(value)) {
575
+ return {
576
+ result: false,
577
+ errorMessage: `Expected map at ${path}, but got: ${Array.isArray(value) ? "array" : typeof value}`
578
+ };
579
+ }
580
+ const mapValue = value;
581
+ if (schema.additionalProperties) {
582
+ for (const [key, mapItemValue] of Object.entries(mapValue)) {
583
+ const keyPath = isRootPath(path) ? key : `${path}.${key}`;
584
+ const keyResult = validateValue(mapItemValue, schema.additionalProperties, keyPath);
585
+ if (!keyResult.result) {
586
+ return keyResult;
587
+ }
588
+ }
589
+ }
590
+ return { result: true };
591
+ };
592
+ var JSONSchemaValidator = (params) => {
593
+ const { schema, value } = params;
594
+ try {
595
+ const validationResult = validateValue(value, schema, ROOT_PATH);
596
+ return validationResult;
597
+ } catch (error) {
598
+ return {
599
+ result: false,
600
+ errorMessage: `Validation error: ${error instanceof Error ? error.message : String(error)}`
601
+ };
602
+ }
603
+ };
604
+
605
+ // src/nodes/loop/index.ts
271
606
  var LoopExecutor = class {
272
607
  constructor() {
273
608
  this.type = FlowGramNode.Loop;
274
609
  }
275
610
  async execute(context) {
276
611
  const loopNodeID = context.node.id;
277
- const loopArrayResult = context.runtime.state.parseRef(context.node.data.batchFor);
278
- this.checkLoopArray(loopArrayResult);
279
- const loopArray = loopArrayResult.value;
280
- const itemsType = loopArrayResult.itemsType;
281
612
  const engine = context.container.get(IEngine);
613
+ const { value: loopArray, itemsType } = this.getLoopArrayVariable(context);
282
614
  const subNodes = context.node.children;
283
- const startSubNodes = subNodes.filter((node) => node.prev.length === 0);
284
- if (loopArray.length === 0 || startSubNodes.length === 0) {
285
- return {
286
- outputs: {}
287
- };
615
+ const blockStartNode = subNodes.find((node) => node.type === FlowGramNode.BlockStart);
616
+ if (!blockStartNode) {
617
+ throw new Error("block start node not found");
288
618
  }
289
- for (let i = 0; i < loopArray.length; i++) {
290
- const loopItem = loopArray[i];
619
+ const blockOutputs = [];
620
+ for (let index = 0; index < loopArray.length; index++) {
621
+ const loopItem = loopArray[index];
291
622
  const subContext = context.runtime.sub();
292
623
  subContext.variableStore.setVariable({
293
624
  nodeID: `${loopNodeID}_locals`,
@@ -295,33 +626,99 @@ var LoopExecutor = class {
295
626
  type: itemsType,
296
627
  value: loopItem
297
628
  });
298
- await Promise.all(
299
- startSubNodes.map(
300
- (node) => engine.executeNode({
301
- context: subContext,
302
- node
303
- })
304
- )
305
- );
629
+ subContext.variableStore.setVariable({
630
+ nodeID: `${loopNodeID}_locals`,
631
+ key: "index",
632
+ type: WorkflowVariableType.Number,
633
+ value: index
634
+ });
635
+ await engine.executeNode({
636
+ context: subContext,
637
+ node: blockStartNode
638
+ });
639
+ const blockOutput = this.getBlockOutput(context, subContext);
640
+ blockOutputs.push(blockOutput);
306
641
  }
642
+ this.setLoopNodeOutputs(context, blockOutputs);
643
+ const outputs = this.combineBlockOutputs(context, blockOutputs);
307
644
  return {
308
- outputs: {}
645
+ outputs
309
646
  };
310
647
  }
311
- checkLoopArray(loopArrayResult) {
312
- const loopArray = loopArrayResult?.value;
648
+ getLoopArrayVariable(executionContext) {
649
+ const loopNodeData = executionContext.node.data;
650
+ const LoopArrayVariable = executionContext.runtime.state.parseRef(
651
+ loopNodeData.loopFor
652
+ );
653
+ this.checkLoopArray(LoopArrayVariable);
654
+ return LoopArrayVariable;
655
+ }
656
+ checkLoopArray(LoopArrayVariable) {
657
+ const loopArray = LoopArrayVariable?.value;
313
658
  if (!loopArray || (0, import_lodash_es.isNil)(loopArray) || !Array.isArray(loopArray)) {
314
- throw new Error("batchFor is required");
659
+ throw new Error("loopFor is required");
315
660
  }
316
- const loopArrayType = loopArrayResult.type;
661
+ const loopArrayType = LoopArrayVariable.type;
317
662
  if (loopArrayType !== WorkflowVariableType.Array) {
318
- throw new Error("batchFor must be an array");
663
+ throw new Error("loopFor must be an array");
319
664
  }
320
- const loopArrayItemType = loopArrayResult.itemsType;
665
+ const loopArrayItemType = LoopArrayVariable.itemsType;
321
666
  if ((0, import_lodash_es.isNil)(loopArrayItemType)) {
322
- throw new Error("batchFor items must be array items");
667
+ throw new Error("loopFor items must be array items");
323
668
  }
324
669
  }
670
+ getBlockOutput(executionContext, subContext) {
671
+ const loopOutputsDeclare = this.getLoopOutputsDeclare(executionContext);
672
+ const blockOutput = Object.entries(loopOutputsDeclare).reduce(
673
+ (acc, [outputName, outputRef]) => {
674
+ const outputVariable = subContext.state.parseRef(outputRef);
675
+ if (!outputVariable) {
676
+ return acc;
677
+ }
678
+ return {
679
+ ...acc,
680
+ [outputName]: outputVariable
681
+ };
682
+ },
683
+ {}
684
+ );
685
+ return blockOutput;
686
+ }
687
+ setLoopNodeOutputs(executionContext, blockOutputs) {
688
+ const loopNode = executionContext.node;
689
+ const loopOutputsDeclare = this.getLoopOutputsDeclare(executionContext);
690
+ const loopOutputNames = Object.keys(loopOutputsDeclare);
691
+ loopOutputNames.forEach((outputName) => {
692
+ const outputVariables = blockOutputs.map((blockOutput) => blockOutput[outputName]);
693
+ const outputTypes = outputVariables.map((fieldVariable) => fieldVariable.type);
694
+ const itemsType = WorkflowRuntimeType.getArrayItemsType(outputTypes);
695
+ const value = outputVariables.map((fieldVariable) => fieldVariable.value);
696
+ executionContext.runtime.variableStore.setVariable({
697
+ nodeID: loopNode.id,
698
+ key: outputName,
699
+ type: WorkflowVariableType.Array,
700
+ itemsType,
701
+ value
702
+ });
703
+ });
704
+ }
705
+ combineBlockOutputs(executionContext, blockOutputs) {
706
+ const loopOutputsDeclare = this.getLoopOutputsDeclare(executionContext);
707
+ const loopOutputNames = Object.keys(loopOutputsDeclare);
708
+ const loopOutput = loopOutputNames.reduce(
709
+ (outputs, outputName) => ({
710
+ ...outputs,
711
+ [outputName]: blockOutputs.map((blockOutput) => blockOutput[outputName].value)
712
+ }),
713
+ {}
714
+ );
715
+ return loopOutput;
716
+ }
717
+ getLoopOutputsDeclare(executionContext) {
718
+ const loopNodeData = executionContext.node.data;
719
+ const loopOutputsDeclare = loopNodeData.loopOutputs ?? {};
720
+ return loopOutputsDeclare;
721
+ }
325
722
  };
326
723
 
327
724
  // src/nodes/llm/index.ts
@@ -384,67 +781,89 @@ var EndExecutor = class {
384
781
  }
385
782
  };
386
783
 
784
+ // src/nodes/empty/index.ts
785
+ var BlockStartExecutor = class {
786
+ constructor() {
787
+ this.type = FlowGramNode.BlockStart;
788
+ }
789
+ async execute(context) {
790
+ return {
791
+ outputs: {}
792
+ };
793
+ }
794
+ };
795
+ var BlockEndExecutor = class {
796
+ constructor() {
797
+ this.type = FlowGramNode.BlockEnd;
798
+ }
799
+ async execute(context) {
800
+ return {
801
+ outputs: {}
802
+ };
803
+ }
804
+ };
805
+
387
806
  // src/nodes/condition/index.ts
388
807
  var import_lodash_es9 = require("lodash-es");
389
808
 
390
809
  // src/nodes/condition/rules.ts
391
810
  var conditionRules = {
392
811
  [WorkflowVariableType.String]: {
393
- ["eq" /* EQ */]: WorkflowVariableType.String,
394
- ["neq" /* NEQ */]: WorkflowVariableType.String,
395
- ["contains" /* CONTAINS */]: WorkflowVariableType.String,
396
- ["not_contains" /* NOT_CONTAINS */]: WorkflowVariableType.String,
397
- ["in" /* IN */]: WorkflowVariableType.Array,
398
- ["nin" /* NIN */]: WorkflowVariableType.Array,
399
- ["is_empty" /* IS_EMPTY */]: WorkflowVariableType.String,
400
- ["is_not_empty" /* IS_NOT_EMPTY */]: WorkflowVariableType.String
812
+ [ConditionOperation.EQ]: WorkflowVariableType.String,
813
+ [ConditionOperation.NEQ]: WorkflowVariableType.String,
814
+ [ConditionOperation.CONTAINS]: WorkflowVariableType.String,
815
+ [ConditionOperation.NOT_CONTAINS]: WorkflowVariableType.String,
816
+ [ConditionOperation.IN]: WorkflowVariableType.Array,
817
+ [ConditionOperation.NIN]: WorkflowVariableType.Array,
818
+ [ConditionOperation.IS_EMPTY]: WorkflowVariableType.String,
819
+ [ConditionOperation.IS_NOT_EMPTY]: WorkflowVariableType.String
401
820
  },
402
821
  [WorkflowVariableType.Number]: {
403
- ["eq" /* EQ */]: WorkflowVariableType.Number,
404
- ["neq" /* NEQ */]: WorkflowVariableType.Number,
405
- ["gt" /* GT */]: WorkflowVariableType.Number,
406
- ["gte" /* GTE */]: WorkflowVariableType.Number,
407
- ["lt" /* LT */]: WorkflowVariableType.Number,
408
- ["lte" /* LTE */]: WorkflowVariableType.Number,
409
- ["in" /* IN */]: WorkflowVariableType.Array,
410
- ["nin" /* NIN */]: WorkflowVariableType.Array,
411
- ["is_empty" /* IS_EMPTY */]: WorkflowVariableType.Null,
412
- ["is_not_empty" /* IS_NOT_EMPTY */]: WorkflowVariableType.Null
822
+ [ConditionOperation.EQ]: WorkflowVariableType.Number,
823
+ [ConditionOperation.NEQ]: WorkflowVariableType.Number,
824
+ [ConditionOperation.GT]: WorkflowVariableType.Number,
825
+ [ConditionOperation.GTE]: WorkflowVariableType.Number,
826
+ [ConditionOperation.LT]: WorkflowVariableType.Number,
827
+ [ConditionOperation.LTE]: WorkflowVariableType.Number,
828
+ [ConditionOperation.IN]: WorkflowVariableType.Array,
829
+ [ConditionOperation.NIN]: WorkflowVariableType.Array,
830
+ [ConditionOperation.IS_EMPTY]: WorkflowVariableType.Null,
831
+ [ConditionOperation.IS_NOT_EMPTY]: WorkflowVariableType.Null
413
832
  },
414
833
  [WorkflowVariableType.Integer]: {
415
- ["eq" /* EQ */]: WorkflowVariableType.Integer,
416
- ["neq" /* NEQ */]: WorkflowVariableType.Integer,
417
- ["gt" /* GT */]: WorkflowVariableType.Integer,
418
- ["gte" /* GTE */]: WorkflowVariableType.Integer,
419
- ["lt" /* LT */]: WorkflowVariableType.Integer,
420
- ["lte" /* LTE */]: WorkflowVariableType.Integer,
421
- ["in" /* IN */]: WorkflowVariableType.Array,
422
- ["nin" /* NIN */]: WorkflowVariableType.Array,
423
- ["is_empty" /* IS_EMPTY */]: WorkflowVariableType.Null,
424
- ["is_not_empty" /* IS_NOT_EMPTY */]: WorkflowVariableType.Null
834
+ [ConditionOperation.EQ]: WorkflowVariableType.Integer,
835
+ [ConditionOperation.NEQ]: WorkflowVariableType.Integer,
836
+ [ConditionOperation.GT]: WorkflowVariableType.Integer,
837
+ [ConditionOperation.GTE]: WorkflowVariableType.Integer,
838
+ [ConditionOperation.LT]: WorkflowVariableType.Integer,
839
+ [ConditionOperation.LTE]: WorkflowVariableType.Integer,
840
+ [ConditionOperation.IN]: WorkflowVariableType.Array,
841
+ [ConditionOperation.NIN]: WorkflowVariableType.Array,
842
+ [ConditionOperation.IS_EMPTY]: WorkflowVariableType.Null,
843
+ [ConditionOperation.IS_NOT_EMPTY]: WorkflowVariableType.Null
425
844
  },
426
845
  [WorkflowVariableType.Boolean]: {
427
- ["eq" /* EQ */]: WorkflowVariableType.Boolean,
428
- ["neq" /* NEQ */]: WorkflowVariableType.Boolean,
429
- ["is_true" /* IS_TRUE */]: WorkflowVariableType.Null,
430
- ["is_false" /* IS_FALSE */]: WorkflowVariableType.Null,
431
- ["in" /* IN */]: WorkflowVariableType.Array,
432
- ["nin" /* NIN */]: WorkflowVariableType.Array,
433
- ["is_empty" /* IS_EMPTY */]: WorkflowVariableType.Null,
434
- ["is_not_empty" /* IS_NOT_EMPTY */]: WorkflowVariableType.Null
846
+ [ConditionOperation.EQ]: WorkflowVariableType.Boolean,
847
+ [ConditionOperation.NEQ]: WorkflowVariableType.Boolean,
848
+ [ConditionOperation.IS_TRUE]: WorkflowVariableType.Null,
849
+ [ConditionOperation.IS_FALSE]: WorkflowVariableType.Null,
850
+ [ConditionOperation.IN]: WorkflowVariableType.Array,
851
+ [ConditionOperation.NIN]: WorkflowVariableType.Array,
852
+ [ConditionOperation.IS_EMPTY]: WorkflowVariableType.Null,
853
+ [ConditionOperation.IS_NOT_EMPTY]: WorkflowVariableType.Null
435
854
  },
436
855
  [WorkflowVariableType.Object]: {
437
- ["is_empty" /* IS_EMPTY */]: WorkflowVariableType.Null,
438
- ["is_not_empty" /* IS_NOT_EMPTY */]: WorkflowVariableType.Null
856
+ [ConditionOperation.IS_EMPTY]: WorkflowVariableType.Null,
857
+ [ConditionOperation.IS_NOT_EMPTY]: WorkflowVariableType.Null
439
858
  },
440
859
  [WorkflowVariableType.Array]: {
441
- ["is_empty" /* IS_EMPTY */]: WorkflowVariableType.Null,
442
- ["is_not_empty" /* IS_NOT_EMPTY */]: WorkflowVariableType.Null
860
+ [ConditionOperation.IS_EMPTY]: WorkflowVariableType.Null,
861
+ [ConditionOperation.IS_NOT_EMPTY]: WorkflowVariableType.Null
443
862
  },
444
863
  [WorkflowVariableType.Null]: {
445
- ["eq" /* EQ */]: WorkflowVariableType.Null,
446
- ["is_empty" /* IS_EMPTY */]: WorkflowVariableType.Null,
447
- ["is_not_empty" /* IS_NOT_EMPTY */]: WorkflowVariableType.Null
864
+ [ConditionOperation.EQ]: WorkflowVariableType.Null,
865
+ [ConditionOperation.IS_EMPTY]: WorkflowVariableType.Null,
866
+ [ConditionOperation.IS_NOT_EMPTY]: WorkflowVariableType.Null
448
867
  }
449
868
  };
450
869
 
@@ -453,34 +872,34 @@ var import_lodash_es3 = require("lodash-es");
453
872
  var conditionStringHandler = (condition) => {
454
873
  const { operator } = condition;
455
874
  const leftValue = condition.leftValue;
456
- if (operator === "eq" /* EQ */) {
875
+ if (operator === ConditionOperation.EQ) {
457
876
  const rightValue = condition.rightValue;
458
877
  return leftValue === rightValue;
459
878
  }
460
- if (operator === "neq" /* NEQ */) {
879
+ if (operator === ConditionOperation.NEQ) {
461
880
  const rightValue = condition.rightValue;
462
881
  return leftValue !== rightValue;
463
882
  }
464
- if (operator === "contains" /* CONTAINS */) {
883
+ if (operator === ConditionOperation.CONTAINS) {
465
884
  const rightValue = condition.rightValue;
466
885
  return leftValue.includes(rightValue);
467
886
  }
468
- if (operator === "not_contains" /* NOT_CONTAINS */) {
887
+ if (operator === ConditionOperation.NOT_CONTAINS) {
469
888
  const rightValue = condition.rightValue;
470
889
  return !leftValue.includes(rightValue);
471
890
  }
472
- if (operator === "in" /* IN */) {
891
+ if (operator === ConditionOperation.IN) {
473
892
  const rightValue = condition.rightValue;
474
893
  return rightValue.includes(leftValue);
475
894
  }
476
- if (operator === "nin" /* NIN */) {
895
+ if (operator === ConditionOperation.NIN) {
477
896
  const rightValue = condition.rightValue;
478
897
  return !rightValue.includes(leftValue);
479
898
  }
480
- if (operator === "is_empty" /* IS_EMPTY */) {
899
+ if (operator === ConditionOperation.IS_EMPTY) {
481
900
  return (0, import_lodash_es3.isNil)(leftValue);
482
901
  }
483
- if (operator === "is_not_empty" /* IS_NOT_EMPTY */) {
902
+ if (operator === ConditionOperation.IS_NOT_EMPTY) {
484
903
  return !(0, import_lodash_es3.isNil)(leftValue);
485
904
  }
486
905
  return false;
@@ -491,10 +910,10 @@ var import_lodash_es4 = require("lodash-es");
491
910
  var conditionObjectHandler = (condition) => {
492
911
  const { operator } = condition;
493
912
  const leftValue = condition.leftValue;
494
- if (operator === "is_empty" /* IS_EMPTY */) {
913
+ if (operator === ConditionOperation.IS_EMPTY) {
495
914
  return (0, import_lodash_es4.isNil)(leftValue);
496
915
  }
497
- if (operator === "is_not_empty" /* IS_NOT_EMPTY */) {
916
+ if (operator === ConditionOperation.IS_NOT_EMPTY) {
498
917
  return !(0, import_lodash_es4.isNil)(leftValue);
499
918
  }
500
919
  return false;
@@ -505,42 +924,42 @@ var import_lodash_es5 = require("lodash-es");
505
924
  var conditionNumberHandler = (condition) => {
506
925
  const { operator } = condition;
507
926
  const leftValue = condition.leftValue;
508
- if (operator === "eq" /* EQ */) {
927
+ if (operator === ConditionOperation.EQ) {
509
928
  const rightValue = condition.rightValue;
510
929
  return leftValue === rightValue;
511
930
  }
512
- if (operator === "neq" /* NEQ */) {
931
+ if (operator === ConditionOperation.NEQ) {
513
932
  const rightValue = condition.rightValue;
514
933
  return leftValue !== rightValue;
515
934
  }
516
- if (operator === "gt" /* GT */) {
935
+ if (operator === ConditionOperation.GT) {
517
936
  const rightValue = condition.rightValue;
518
937
  return leftValue > rightValue;
519
938
  }
520
- if (operator === "gte" /* GTE */) {
939
+ if (operator === ConditionOperation.GTE) {
521
940
  const rightValue = condition.rightValue;
522
941
  return leftValue >= rightValue;
523
942
  }
524
- if (operator === "lt" /* LT */) {
943
+ if (operator === ConditionOperation.LT) {
525
944
  const rightValue = condition.rightValue;
526
945
  return leftValue < rightValue;
527
946
  }
528
- if (operator === "lte" /* LTE */) {
947
+ if (operator === ConditionOperation.LTE) {
529
948
  const rightValue = condition.rightValue;
530
949
  return leftValue <= rightValue;
531
950
  }
532
- if (operator === "in" /* IN */) {
951
+ if (operator === ConditionOperation.IN) {
533
952
  const rightValue = condition.rightValue;
534
953
  return rightValue.includes(leftValue);
535
954
  }
536
- if (operator === "nin" /* NIN */) {
955
+ if (operator === ConditionOperation.NIN) {
537
956
  const rightValue = condition.rightValue;
538
957
  return !rightValue.includes(leftValue);
539
958
  }
540
- if (operator === "is_empty" /* IS_EMPTY */) {
959
+ if (operator === ConditionOperation.IS_EMPTY) {
541
960
  return (0, import_lodash_es5.isNil)(leftValue);
542
961
  }
543
- if (operator === "is_not_empty" /* IS_NOT_EMPTY */) {
962
+ if (operator === ConditionOperation.IS_NOT_EMPTY) {
544
963
  return !(0, import_lodash_es5.isNil)(leftValue);
545
964
  }
546
965
  return false;
@@ -551,13 +970,13 @@ var import_lodash_es6 = require("lodash-es");
551
970
  var conditionNullHandler = (condition) => {
552
971
  const { operator } = condition;
553
972
  const leftValue = condition.leftValue;
554
- if (operator === "eq" /* EQ */) {
973
+ if (operator === ConditionOperation.EQ) {
555
974
  return (0, import_lodash_es6.isNil)(leftValue) && (0, import_lodash_es6.isNil)(condition.rightValue);
556
975
  }
557
- if (operator === "is_empty" /* IS_EMPTY */) {
976
+ if (operator === ConditionOperation.IS_EMPTY) {
558
977
  return (0, import_lodash_es6.isNil)(leftValue);
559
978
  }
560
- if (operator === "is_not_empty" /* IS_NOT_EMPTY */) {
979
+ if (operator === ConditionOperation.IS_NOT_EMPTY) {
561
980
  return !(0, import_lodash_es6.isNil)(leftValue);
562
981
  }
563
982
  return false;
@@ -568,32 +987,32 @@ var import_lodash_es7 = require("lodash-es");
568
987
  var conditionBooleanHandler = (condition) => {
569
988
  const { operator } = condition;
570
989
  const leftValue = condition.leftValue;
571
- if (operator === "eq" /* EQ */) {
990
+ if (operator === ConditionOperation.EQ) {
572
991
  const rightValue = condition.rightValue;
573
992
  return leftValue === rightValue;
574
993
  }
575
- if (operator === "neq" /* NEQ */) {
994
+ if (operator === ConditionOperation.NEQ) {
576
995
  const rightValue = condition.rightValue;
577
996
  return leftValue !== rightValue;
578
997
  }
579
- if (operator === "is_true" /* IS_TRUE */) {
998
+ if (operator === ConditionOperation.IS_TRUE) {
580
999
  return leftValue === true;
581
1000
  }
582
- if (operator === "is_false" /* IS_FALSE */) {
1001
+ if (operator === ConditionOperation.IS_FALSE) {
583
1002
  return leftValue === false;
584
1003
  }
585
- if (operator === "in" /* IN */) {
1004
+ if (operator === ConditionOperation.IN) {
586
1005
  const rightValue = condition.rightValue;
587
1006
  return rightValue.includes(leftValue);
588
1007
  }
589
- if (operator === "nin" /* NIN */) {
1008
+ if (operator === ConditionOperation.NIN) {
590
1009
  const rightValue = condition.rightValue;
591
1010
  return !rightValue.includes(leftValue);
592
1011
  }
593
- if (operator === "is_empty" /* IS_EMPTY */) {
1012
+ if (operator === ConditionOperation.IS_EMPTY) {
594
1013
  return (0, import_lodash_es7.isNil)(leftValue);
595
1014
  }
596
- if (operator === "is_not_empty" /* IS_NOT_EMPTY */) {
1015
+ if (operator === ConditionOperation.IS_NOT_EMPTY) {
597
1016
  return !(0, import_lodash_es7.isNil)(leftValue);
598
1017
  }
599
1018
  return false;
@@ -604,10 +1023,10 @@ var import_lodash_es8 = require("lodash-es");
604
1023
  var conditionArrayHandler = (condition) => {
605
1024
  const { operator } = condition;
606
1025
  const leftValue = condition.leftValue;
607
- if (operator === "is_empty" /* IS_EMPTY */) {
1026
+ if (operator === ConditionOperation.IS_EMPTY) {
608
1027
  return (0, import_lodash_es8.isNil)(leftValue);
609
1028
  }
610
- if (operator === "is_not_empty" /* IS_NOT_EMPTY */) {
1029
+ if (operator === ConditionOperation.IS_NOT_EMPTY) {
611
1030
  return !(0, import_lodash_es8.isNil)(leftValue);
612
1031
  }
613
1032
  return false;
@@ -639,9 +1058,7 @@ var ConditionExecutor = class {
639
1058
  const parsedConditions = conditions.map((item) => this.parseCondition(item, context)).filter((item) => this.checkCondition(item));
640
1059
  const activatedCondition = parsedConditions.find((item) => this.handleCondition(item));
641
1060
  if (!activatedCondition) {
642
- return {
643
- outputs: {}
644
- };
1061
+ throw new Error("no condition is activated");
645
1062
  }
646
1063
  return {
647
1064
  outputs: {},
@@ -696,16 +1113,55 @@ var WorkflowRuntimeNodeExecutors = [
696
1113
  EndExecutor,
697
1114
  LLMExecutor,
698
1115
  ConditionExecutor,
699
- LoopExecutor
1116
+ LoopExecutor,
1117
+ BlockStartExecutor,
1118
+ BlockEndExecutor
700
1119
  ];
701
1120
 
702
1121
  // src/domain/validation/index.ts
703
1122
  var WorkflowRuntimeValidation = class {
704
- validate(schema) {
1123
+ invoke(params) {
1124
+ const { schema, inputs } = params;
1125
+ const schemaValidationResult = this.schema(schema);
1126
+ if (!schemaValidationResult.valid) {
1127
+ return schemaValidationResult;
1128
+ }
1129
+ const inputsValidationResult = this.inputs(this.getWorkflowInputsDeclare(schema), inputs);
1130
+ if (!inputsValidationResult.valid) {
1131
+ return inputsValidationResult;
1132
+ }
1133
+ return {
1134
+ valid: true
1135
+ };
1136
+ }
1137
+ schema(schema) {
1138
+ return {
1139
+ valid: true
1140
+ };
1141
+ }
1142
+ inputs(inputsSchema, inputs) {
1143
+ const { result, errorMessage } = JSONSchemaValidator({
1144
+ schema: inputsSchema,
1145
+ value: inputs
1146
+ });
1147
+ if (!result) {
1148
+ const error = `JSON Schema validation failed: ${errorMessage}`;
1149
+ return {
1150
+ valid: false,
1151
+ errors: [error]
1152
+ };
1153
+ }
705
1154
  return {
706
1155
  valid: true
707
1156
  };
708
1157
  }
1158
+ getWorkflowInputsDeclare(schema) {
1159
+ const startNode = schema.nodes.find((node) => node.type === FlowGramNode.Start);
1160
+ if (!startNode) {
1161
+ throw new Error("Workflow schema must have a start node");
1162
+ }
1163
+ return startNode.data.outputs;
1164
+ }
709
1165
  };
710
1166
 
711
1167
  // src/domain/executor/index.ts
@@ -730,52 +1186,6 @@ var WorkflowRuntimeExecutor = class {
730
1186
  }
731
1187
  };
732
1188
 
733
- // src/infrastructure/utils/uuid.ts
734
- var import_uuid = require("uuid");
735
- var uuid = import_uuid.v4;
736
-
737
- // src/infrastructure/utils/runtime-type.ts
738
- var WorkflowRuntimeType;
739
- ((WorkflowRuntimeType2) => {
740
- WorkflowRuntimeType2.getWorkflowType = (value) => {
741
- if (value === null || value === void 0) {
742
- return WorkflowVariableType.Null;
743
- }
744
- if (typeof value === "string") {
745
- return WorkflowVariableType.String;
746
- }
747
- if (typeof value === "boolean") {
748
- return WorkflowVariableType.Boolean;
749
- }
750
- if (typeof value === "number") {
751
- if (Number.isInteger(value)) {
752
- return WorkflowVariableType.Integer;
753
- }
754
- return WorkflowVariableType.Number;
755
- }
756
- if (Array.isArray(value)) {
757
- return WorkflowVariableType.Array;
758
- }
759
- if (typeof value === "object") {
760
- return WorkflowVariableType.Object;
761
- }
762
- return null;
763
- };
764
- WorkflowRuntimeType2.isMatchWorkflowType = (value, type) => {
765
- const workflowType = (0, WorkflowRuntimeType2.getWorkflowType)(value);
766
- if (!workflowType) {
767
- return false;
768
- }
769
- return workflowType === type;
770
- };
771
- WorkflowRuntimeType2.isTypeEqual = (leftType, rightType) => {
772
- if (leftType === WorkflowVariableType.Number && rightType === WorkflowVariableType.Integer || leftType === WorkflowVariableType.Integer && rightType === WorkflowVariableType.Number) {
773
- return true;
774
- }
775
- return leftType === rightType;
776
- };
777
- })(WorkflowRuntimeType || (WorkflowRuntimeType = {}));
778
-
779
1189
  // src/domain/task/index.ts
780
1190
  var WorkflowRuntimeTask = class _WorkflowRuntimeTask {
781
1191
  constructor(params) {
@@ -795,6 +1205,85 @@ var WorkflowRuntimeTask = class _WorkflowRuntimeTask {
795
1205
  }
796
1206
  };
797
1207
 
1208
+ // src/domain/message/message-value-object/index.ts
1209
+ var WorkflowRuntimeMessage;
1210
+ ((WorkflowRuntimeMessage2) => {
1211
+ WorkflowRuntimeMessage2.create = (params) => {
1212
+ const message = {
1213
+ id: uuid(),
1214
+ ...params
1215
+ };
1216
+ if (!params.timestamp) {
1217
+ message.timestamp = Date.now();
1218
+ }
1219
+ return message;
1220
+ };
1221
+ })(WorkflowRuntimeMessage || (WorkflowRuntimeMessage = {}));
1222
+
1223
+ // src/domain/message/message-center/index.ts
1224
+ var WorkflowRuntimeMessageCenter = class {
1225
+ init() {
1226
+ this.messages = {
1227
+ [WorkflowMessageType.Log]: [],
1228
+ [WorkflowMessageType.Info]: [],
1229
+ [WorkflowMessageType.Debug]: [],
1230
+ [WorkflowMessageType.Error]: [],
1231
+ [WorkflowMessageType.Warn]: []
1232
+ };
1233
+ }
1234
+ dispose() {
1235
+ }
1236
+ log(data) {
1237
+ const message = WorkflowRuntimeMessage.create({
1238
+ type: WorkflowMessageType.Log,
1239
+ ...data
1240
+ });
1241
+ this.messages[WorkflowMessageType.Log].push(message);
1242
+ return message;
1243
+ }
1244
+ info(data) {
1245
+ const message = WorkflowRuntimeMessage.create({
1246
+ type: WorkflowMessageType.Info,
1247
+ ...data
1248
+ });
1249
+ this.messages[WorkflowMessageType.Info].push(message);
1250
+ return message;
1251
+ }
1252
+ debug(data) {
1253
+ const message = WorkflowRuntimeMessage.create({
1254
+ type: WorkflowMessageType.Debug,
1255
+ ...data
1256
+ });
1257
+ this.messages[WorkflowMessageType.Debug].push(message);
1258
+ return message;
1259
+ }
1260
+ error(data) {
1261
+ const message = WorkflowRuntimeMessage.create({
1262
+ type: WorkflowMessageType.Error,
1263
+ ...data
1264
+ });
1265
+ this.messages[WorkflowMessageType.Error].push(message);
1266
+ return message;
1267
+ }
1268
+ warn(data) {
1269
+ const message = WorkflowRuntimeMessage.create({
1270
+ type: WorkflowMessageType.Warn,
1271
+ ...data
1272
+ });
1273
+ this.messages[WorkflowMessageType.Warn].push(message);
1274
+ return message;
1275
+ }
1276
+ export() {
1277
+ return {
1278
+ [WorkflowMessageType.Log]: this.messages[WorkflowMessageType.Log].slice(),
1279
+ [WorkflowMessageType.Info]: this.messages[WorkflowMessageType.Info].slice(),
1280
+ [WorkflowMessageType.Debug]: this.messages[WorkflowMessageType.Debug].slice(),
1281
+ [WorkflowMessageType.Error]: this.messages[WorkflowMessageType.Error].slice(),
1282
+ [WorkflowMessageType.Warn]: this.messages[WorkflowMessageType.Warn].slice()
1283
+ };
1284
+ }
1285
+ };
1286
+
798
1287
  // src/domain/variable/variable-store/index.ts
799
1288
  var import_lodash_es10 = require("lodash-es");
800
1289
 
@@ -1144,7 +1633,7 @@ var WorkflowRuntimeSnapshot = class _WorkflowRuntimeSnapshot {
1144
1633
  this.id = uuid();
1145
1634
  this.data = data;
1146
1635
  }
1147
- addData(data) {
1636
+ update(data) {
1148
1637
  Object.assign(this.data, data);
1149
1638
  }
1150
1639
  validate() {
@@ -1205,10 +1694,11 @@ var WorkflowRuntimeReport;
1205
1694
 
1206
1695
  // src/domain/report/reporter/index.ts
1207
1696
  var WorkflowRuntimeReporter = class {
1208
- constructor(ioCenter, snapshotCenter, statusCenter) {
1697
+ constructor(ioCenter, snapshotCenter, statusCenter, messageCenter) {
1209
1698
  this.ioCenter = ioCenter;
1210
1699
  this.snapshotCenter = snapshotCenter;
1211
1700
  this.statusCenter = statusCenter;
1701
+ this.messageCenter = messageCenter;
1212
1702
  }
1213
1703
  init() {
1214
1704
  }
@@ -1219,7 +1709,8 @@ var WorkflowRuntimeReporter = class {
1219
1709
  inputs: this.ioCenter.inputs,
1220
1710
  outputs: this.ioCenter.outputs,
1221
1711
  workflowStatus: this.statusCenter.workflow.export(),
1222
- reports: this.nodeReports()
1712
+ reports: this.nodeReports(),
1713
+ messages: this.messageCenter.export()
1223
1714
  });
1224
1715
  return report;
1225
1716
  }
@@ -1357,6 +1848,12 @@ var WorkflowRuntimeNode = class {
1357
1848
  get next() {
1358
1849
  return this._next;
1359
1850
  }
1851
+ get successors() {
1852
+ return traverseNodes(this, (node) => node.next);
1853
+ }
1854
+ get predecessors() {
1855
+ return traverseNodes(this, (node) => node.prev);
1856
+ }
1360
1857
  get isBranch() {
1361
1858
  return this.ports.outputs.length > 1;
1362
1859
  }
@@ -1594,6 +2091,7 @@ var WorkflowRuntimeContext = class _WorkflowRuntimeContext {
1594
2091
  this.ioCenter = data.ioCenter;
1595
2092
  this.snapshotCenter = data.snapshotCenter;
1596
2093
  this.statusCenter = data.statusCenter;
2094
+ this.messageCenter = data.messageCenter;
1597
2095
  this.reporter = data.reporter;
1598
2096
  }
1599
2097
  init(params) {
@@ -1604,6 +2102,7 @@ var WorkflowRuntimeContext = class _WorkflowRuntimeContext {
1604
2102
  this.ioCenter.init(inputs);
1605
2103
  this.snapshotCenter.init();
1606
2104
  this.statusCenter.init();
2105
+ this.messageCenter.init();
1607
2106
  this.reporter.init();
1608
2107
  }
1609
2108
  dispose() {
@@ -1617,6 +2116,7 @@ var WorkflowRuntimeContext = class _WorkflowRuntimeContext {
1617
2116
  this.ioCenter.dispose();
1618
2117
  this.snapshotCenter.dispose();
1619
2118
  this.statusCenter.dispose();
2119
+ this.messageCenter.dispose();
1620
2120
  this.reporter.dispose();
1621
2121
  }
1622
2122
  sub() {
@@ -1628,6 +2128,7 @@ var WorkflowRuntimeContext = class _WorkflowRuntimeContext {
1628
2128
  ioCenter: this.ioCenter,
1629
2129
  snapshotCenter: this.snapshotCenter,
1630
2130
  statusCenter: this.statusCenter,
2131
+ messageCenter: this.messageCenter,
1631
2132
  reporter: this.reporter,
1632
2133
  variableStore,
1633
2134
  state
@@ -1645,7 +2146,13 @@ var WorkflowRuntimeContext = class _WorkflowRuntimeContext {
1645
2146
  const ioCenter = new WorkflowRuntimeIOCenter();
1646
2147
  const snapshotCenter = new WorkflowRuntimeSnapshotCenter();
1647
2148
  const statusCenter = new WorkflowRuntimeStatusCenter();
1648
- const reporter = new WorkflowRuntimeReporter(ioCenter, snapshotCenter, statusCenter);
2149
+ const messageCenter = new WorkflowRuntimeMessageCenter();
2150
+ const reporter = new WorkflowRuntimeReporter(
2151
+ ioCenter,
2152
+ snapshotCenter,
2153
+ statusCenter,
2154
+ messageCenter
2155
+ );
1649
2156
  return new _WorkflowRuntimeContext({
1650
2157
  document,
1651
2158
  variableStore,
@@ -1653,6 +2160,7 @@ var WorkflowRuntimeContext = class _WorkflowRuntimeContext {
1653
2160
  ioCenter,
1654
2161
  snapshotCenter,
1655
2162
  statusCenter,
2163
+ messageCenter,
1656
2164
  reporter
1657
2165
  });
1658
2166
  }
@@ -1661,11 +2169,19 @@ var WorkflowRuntimeContext = class _WorkflowRuntimeContext {
1661
2169
  // src/domain/engine/index.ts
1662
2170
  var WorkflowRuntimeEngine = class {
1663
2171
  constructor(service) {
2172
+ this.validation = service.Validation;
1664
2173
  this.executor = service.Executor;
1665
2174
  }
1666
2175
  invoke(params) {
1667
2176
  const context = WorkflowRuntimeContext.create();
1668
2177
  context.init(params);
2178
+ const valid = this.validate(params, context);
2179
+ if (!valid) {
2180
+ return WorkflowRuntimeTask.create({
2181
+ processing: Promise.resolve({}),
2182
+ context
2183
+ });
2184
+ }
1669
2185
  const processing = this.process(context);
1670
2186
  processing.then(() => {
1671
2187
  context.dispose();
@@ -1681,11 +2197,14 @@ var WorkflowRuntimeEngine = class {
1681
2197
  return;
1682
2198
  }
1683
2199
  context.statusCenter.nodeStatus(node.id).process();
2200
+ const snapshot = context.snapshotCenter.create({
2201
+ nodeID: node.id,
2202
+ data: node.data
2203
+ });
2204
+ let nextNodes = [];
1684
2205
  try {
1685
2206
  const inputs = context.state.getNodeInputs(node);
1686
- const snapshot = context.snapshotCenter.create({
1687
- nodeID: node.id,
1688
- data: node.data,
2207
+ snapshot.update({
1689
2208
  inputs
1690
2209
  });
1691
2210
  const result = await this.executor.execute({
@@ -1698,17 +2217,23 @@ var WorkflowRuntimeEngine = class {
1698
2217
  return;
1699
2218
  }
1700
2219
  const { outputs, branch } = result;
1701
- snapshot.addData({ outputs, branch });
2220
+ snapshot.update({ outputs, branch });
1702
2221
  context.state.setNodeOutputs({ node, outputs });
1703
2222
  context.state.addExecutedNode(node);
1704
2223
  context.statusCenter.nodeStatus(node.id).success();
1705
- const nextNodes = this.getNextNodes({ node, branch, context });
1706
- await this.executeNext({ node, nextNodes, context });
2224
+ nextNodes = this.getNextNodes({ node, branch, context });
1707
2225
  } catch (e) {
2226
+ const errorMessage = e instanceof Error ? e.message : "An unknown error occurred";
2227
+ snapshot.update({ error: errorMessage });
2228
+ context.messageCenter.error({
2229
+ nodeID: node.id,
2230
+ message: errorMessage
2231
+ });
1708
2232
  context.statusCenter.nodeStatus(node.id).fail();
1709
2233
  console.error(e);
1710
- return;
2234
+ throw e;
1711
2235
  }
2236
+ await this.executeNext({ node, nextNodes, context });
1712
2237
  }
1713
2238
  async process(context) {
1714
2239
  const startNode = context.document.start;
@@ -1720,8 +2245,21 @@ var WorkflowRuntimeEngine = class {
1720
2245
  return outputs;
1721
2246
  } catch (e) {
1722
2247
  context.statusCenter.workflow.fail();
1723
- throw e;
2248
+ return {};
2249
+ }
2250
+ }
2251
+ validate(params, context) {
2252
+ const { valid, errors } = this.validation.invoke(params);
2253
+ if (valid) {
2254
+ return true;
1724
2255
  }
2256
+ errors?.forEach((message) => {
2257
+ context.messageCenter.error({
2258
+ message
2259
+ });
2260
+ });
2261
+ context.statusCenter.workflow.fail();
2262
+ return false;
1725
2263
  }
1726
2264
  canExecuteNode(params) {
1727
2265
  const { node, context } = params;
@@ -1744,8 +2282,11 @@ var WorkflowRuntimeEngine = class {
1744
2282
  const nextNodeIDs = new Set(targetPort.edges.map((edge) => edge.to.id));
1745
2283
  const nextNodes = allNextNodes.filter((nextNode) => nextNodeIDs.has(nextNode.id));
1746
2284
  const skipNodes = allNextNodes.filter((nextNode) => !nextNodeIDs.has(nextNode.id));
1747
- skipNodes.forEach((skipNode) => {
1748
- context.state.addExecutedNode(skipNode);
2285
+ const nextGroups = nextNodes.map((nextNode) => [nextNode, ...nextNode.successors]);
2286
+ const skipGroups = skipNodes.map((skipNode) => [skipNode, ...skipNode.successors]);
2287
+ const { uniqueToB: skippedNodes } = compareNodeGroups(nextGroups, skipGroups);
2288
+ skippedNodes.forEach((node2) => {
2289
+ context.state.addExecutedNode(node2);
1749
2290
  });
1750
2291
  return nextNodes;
1751
2292
  }
@@ -1788,6 +2329,7 @@ var WorkflowRuntimeContainer = class _WorkflowRuntimeContainer {
1788
2329
  const Validation = new WorkflowRuntimeValidation();
1789
2330
  const Executor = new WorkflowRuntimeExecutor(WorkflowRuntimeNodeExecutors);
1790
2331
  const Engine = new WorkflowRuntimeEngine({
2332
+ Validation,
1791
2333
  Executor
1792
2334
  });
1793
2335
  return {
@@ -1844,6 +2386,12 @@ var WorkflowApplication = class _WorkflowApplication {
1844
2386
  }
1845
2387
  return task.context.ioCenter.outputs;
1846
2388
  }
2389
+ validate(params) {
2390
+ const validation = this.container.get(IValidation);
2391
+ const result = validation.invoke(params);
2392
+ console.log("> POST TaskValidate - valid: ", result.valid);
2393
+ return result;
2394
+ }
1847
2395
  static get instance() {
1848
2396
  if (this._instance) {
1849
2397
  return this._instance;
@@ -1853,6 +2401,19 @@ var WorkflowApplication = class _WorkflowApplication {
1853
2401
  }
1854
2402
  };
1855
2403
 
2404
+ // src/api/task-validate.ts
2405
+ var TaskValidateAPI = async (input) => {
2406
+ const app = WorkflowApplication.instance;
2407
+ const { schema: stringSchema, inputs } = input;
2408
+ const schema = JSON.parse(stringSchema);
2409
+ const result = app.validate({
2410
+ schema,
2411
+ inputs
2412
+ });
2413
+ const output = result;
2414
+ return output;
2415
+ };
2416
+
1856
2417
  // src/api/task-run.ts
1857
2418
  var TaskRunAPI = async (input) => {
1858
2419
  const app = WorkflowApplication.instance;
@@ -1903,16 +2464,14 @@ var TaskCancelAPI = async (input) => {
1903
2464
 
1904
2465
  // src/api/index.ts
1905
2466
  var WorkflowRuntimeAPIs = {
2467
+ [FlowGramAPIName.ServerInfo]: () => {
2468
+ },
2469
+ // TODO
1906
2470
  [FlowGramAPIName.TaskRun]: TaskRunAPI,
1907
2471
  [FlowGramAPIName.TaskReport]: TaskReportAPI,
1908
2472
  [FlowGramAPIName.TaskResult]: TaskResultAPI,
1909
2473
  [FlowGramAPIName.TaskCancel]: TaskCancelAPI,
1910
- [FlowGramAPIName.ServerInfo]: () => {
1911
- },
1912
- // TODO
1913
- [FlowGramAPIName.Validation]: () => {
1914
- }
1915
- // TODO
2474
+ [FlowGramAPIName.TaskValidate]: TaskValidateAPI
1916
2475
  };
1917
2476
  // Annotate the CommonJS export names for ESM import in node:
1918
2477
  0 && (module.exports = {
@@ -1920,6 +2479,7 @@ var WorkflowRuntimeAPIs = {
1920
2479
  TaskReportAPI,
1921
2480
  TaskResultAPI,
1922
2481
  TaskRunAPI,
2482
+ TaskValidateAPI,
1923
2483
  WorkflowRuntimeAPIs
1924
2484
  });
1925
2485
  //# sourceMappingURL=index.js.map