@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/esm/index.js CHANGED
@@ -1,79 +1,78 @@
1
1
  // ../interface/dist/esm/index.js
2
+ import z2 from "zod";
2
3
  import z from "zod";
3
4
  import z3 from "zod";
4
- import z2 from "zod";
5
5
  import z4 from "zod";
6
6
  import z5 from "zod";
7
7
  import z6 from "zod";
8
8
  import z7 from "zod";
9
+ var WorkflowIOZodSchema = z.record(z.string(), z.any());
10
+ var WorkflowSnapshotZodSchema = z.object({
11
+ id: z.string(),
12
+ nodeID: z.string(),
13
+ inputs: WorkflowIOZodSchema,
14
+ outputs: WorkflowIOZodSchema.optional(),
15
+ data: WorkflowIOZodSchema,
16
+ branch: z.string().optional()
17
+ });
18
+ var WorkflowStatusZodShape = {
19
+ status: z.string(),
20
+ terminated: z.boolean(),
21
+ startTime: z.number(),
22
+ endTime: z.number().optional(),
23
+ timeCost: z.number()
24
+ };
25
+ var WorkflowStatusZodSchema = z.object(WorkflowStatusZodShape);
26
+ var WorkflowNodeReportZodSchema = z.object({
27
+ id: z.string(),
28
+ ...WorkflowStatusZodShape,
29
+ snapshots: z.array(WorkflowSnapshotZodSchema)
30
+ });
31
+ var WorkflowReportsZodSchema = z.record(z.string(), WorkflowNodeReportZodSchema);
32
+ var WorkflowMessageZodSchema = z.object({
33
+ id: z.string(),
34
+ type: z.enum(["log", "info", "debug", "error", "warning"]),
35
+ message: z.string(),
36
+ nodeID: z.string().optional(),
37
+ timestamp: z.number()
38
+ });
39
+ var WorkflowMessagesZodSchema = z.record(
40
+ z.enum(["log", "info", "debug", "error", "warning"]),
41
+ z.array(WorkflowMessageZodSchema)
42
+ );
43
+ var WorkflowZodSchema = {
44
+ Inputs: WorkflowIOZodSchema,
45
+ Outputs: WorkflowIOZodSchema,
46
+ Status: WorkflowStatusZodSchema,
47
+ Snapshot: WorkflowSnapshotZodSchema,
48
+ Reports: WorkflowReportsZodSchema,
49
+ Messages: WorkflowMessagesZodSchema
50
+ };
9
51
  var FlowGramAPIName = /* @__PURE__ */ ((FlowGramAPIName2) => {
10
52
  FlowGramAPIName2["ServerInfo"] = "ServerInfo";
11
53
  FlowGramAPIName2["TaskRun"] = "TaskRun";
12
54
  FlowGramAPIName2["TaskReport"] = "TaskReport";
13
55
  FlowGramAPIName2["TaskResult"] = "TaskResult";
14
56
  FlowGramAPIName2["TaskCancel"] = "TaskCancel";
15
- FlowGramAPIName2["Validation"] = "Validation";
57
+ FlowGramAPIName2["TaskValidate"] = "TaskValidate";
16
58
  return FlowGramAPIName2;
17
59
  })(FlowGramAPIName || {});
18
- var ValidationDefine = {
19
- name: "Validation",
60
+ var TaskValidateDefine = {
61
+ name: "TaskValidate",
20
62
  method: "POST",
21
- path: "/validation",
22
- module: "Validation",
63
+ path: "/task/validate",
64
+ module: "Task",
23
65
  schema: {
24
- input: z.object({
25
- schema: z.string()
66
+ input: z2.object({
67
+ schema: z2.string(),
68
+ inputs: WorkflowZodSchema.Inputs
26
69
  }),
27
- output: z.object({
28
- valid: z.boolean(),
29
- nodeErrors: z.array(
30
- z.object({
31
- message: z.string(),
32
- nodeID: z.string()
33
- })
34
- ),
35
- edgeErrors: z.array(
36
- z.object({
37
- message: z.string(),
38
- edge: z.object({
39
- sourceNodeID: z.string(),
40
- targetNodeID: z.string(),
41
- sourcePortID: z.string().optional(),
42
- targetPortID: z.string().optional()
43
- })
44
- })
45
- )
70
+ output: z2.object({
71
+ valid: z2.boolean(),
72
+ errors: z2.array(z2.string()).optional()
46
73
  })
47
74
  }
48
75
  };
49
- var WorkflowIOZodSchema = z2.record(z2.string(), z2.any());
50
- var WorkflowSnapshotZodSchema = z2.object({
51
- id: z2.string(),
52
- nodeID: z2.string(),
53
- inputs: WorkflowIOZodSchema,
54
- outputs: WorkflowIOZodSchema.optional(),
55
- data: WorkflowIOZodSchema,
56
- branch: z2.string().optional()
57
- });
58
- var WorkflowStatusZodShape = {
59
- status: z2.string(),
60
- terminated: z2.boolean(),
61
- startTime: z2.number(),
62
- endTime: z2.number().optional(),
63
- timeCost: z2.number()
64
- };
65
- var WorkflowStatusZodSchema = z2.object(WorkflowStatusZodShape);
66
- var WorkflowZodSchema = {
67
- Inputs: WorkflowIOZodSchema,
68
- Outputs: WorkflowIOZodSchema,
69
- Status: WorkflowStatusZodSchema,
70
- Snapshot: WorkflowSnapshotZodSchema,
71
- NodeReport: z2.object({
72
- id: z2.string(),
73
- ...WorkflowStatusZodShape,
74
- snapshots: z2.array(WorkflowSnapshotZodSchema)
75
- })
76
- };
77
76
  var TaskRunDefine = {
78
77
  name: "TaskRun",
79
78
  method: "POST",
@@ -115,7 +114,8 @@ var TaskReportDefine = {
115
114
  inputs: WorkflowZodSchema.Inputs,
116
115
  outputs: WorkflowZodSchema.Outputs,
117
116
  workflowStatus: WorkflowZodSchema.Status,
118
- reports: z5.record(z5.string(), WorkflowZodSchema.NodeReport)
117
+ reports: WorkflowZodSchema.Reports,
118
+ messages: WorkflowZodSchema.Messages
119
119
  })
120
120
  }
121
121
  };
@@ -170,9 +170,9 @@ var FlowGramAPIs = {
170
170
  /* TaskCancel */
171
171
  ]: TaskCancelDefine,
172
172
  [
173
- "Validation"
174
- /* Validation */
175
- ]: ValidationDefine
173
+ "TaskValidate"
174
+ /* TaskValidate */
175
+ ]: TaskValidateDefine
176
176
  };
177
177
  var FlowGramAPINames = Object.keys(FlowGramAPIs);
178
178
  var WorkflowPortType = /* @__PURE__ */ ((WorkflowPortType2) => {
@@ -200,8 +200,27 @@ var FlowGramNode = /* @__PURE__ */ ((FlowGramNode22) => {
200
200
  FlowGramNode22["Loop"] = "loop";
201
201
  FlowGramNode22["Comment"] = "comment";
202
202
  FlowGramNode22["Group"] = "group";
203
+ FlowGramNode22["BlockStart"] = "block-start";
204
+ FlowGramNode22["BlockEnd"] = "block-end";
203
205
  return FlowGramNode22;
204
206
  })(FlowGramNode || {});
207
+ var ConditionOperation = /* @__PURE__ */ ((ConditionOperation2) => {
208
+ ConditionOperation2["EQ"] = "eq";
209
+ ConditionOperation2["NEQ"] = "neq";
210
+ ConditionOperation2["GT"] = "gt";
211
+ ConditionOperation2["GTE"] = "gte";
212
+ ConditionOperation2["LT"] = "lt";
213
+ ConditionOperation2["LTE"] = "lte";
214
+ ConditionOperation2["IN"] = "in";
215
+ ConditionOperation2["NIN"] = "nin";
216
+ ConditionOperation2["CONTAINS"] = "contains";
217
+ ConditionOperation2["NOT_CONTAINS"] = "not_contains";
218
+ ConditionOperation2["IS_EMPTY"] = "is_empty";
219
+ ConditionOperation2["IS_NOT_EMPTY"] = "is_not_empty";
220
+ ConditionOperation2["IS_TRUE"] = "is_true";
221
+ ConditionOperation2["IS_FALSE"] = "is_false";
222
+ return ConditionOperation2;
223
+ })(ConditionOperation || {});
205
224
  var IEngine = Symbol.for("Engine");
206
225
  var IExecutor = Symbol.for("Executor");
207
226
  var WorkflowStatus = /* @__PURE__ */ ((WorkflowStatus2) => {
@@ -213,6 +232,14 @@ var WorkflowStatus = /* @__PURE__ */ ((WorkflowStatus2) => {
213
232
  return WorkflowStatus2;
214
233
  })(WorkflowStatus || {});
215
234
  var IValidation = Symbol.for("Validation");
235
+ var WorkflowMessageType = /* @__PURE__ */ ((WorkflowMessageType2) => {
236
+ WorkflowMessageType2["Log"] = "log";
237
+ WorkflowMessageType2["Info"] = "info";
238
+ WorkflowMessageType2["Debug"] = "debug";
239
+ WorkflowMessageType2["Error"] = "error";
240
+ WorkflowMessageType2["Warn"] = "warning";
241
+ return WorkflowMessageType2;
242
+ })(WorkflowMessageType || {});
216
243
 
217
244
  // src/nodes/start/index.ts
218
245
  var StartExecutor = class {
@@ -228,26 +255,329 @@ var StartExecutor = class {
228
255
 
229
256
  // src/nodes/loop/index.ts
230
257
  import { isNil } from "lodash-es";
258
+
259
+ // src/infrastructure/utils/uuid.ts
260
+ import { v4 } from "uuid";
261
+ var uuid = v4;
262
+
263
+ // src/infrastructure/utils/runtime-type.ts
264
+ var WorkflowRuntimeType;
265
+ ((WorkflowRuntimeType2) => {
266
+ WorkflowRuntimeType2.getWorkflowType = (value) => {
267
+ if (value === null || value === void 0) {
268
+ return WorkflowVariableType.Null;
269
+ }
270
+ if (typeof value === "string") {
271
+ return WorkflowVariableType.String;
272
+ }
273
+ if (typeof value === "boolean") {
274
+ return WorkflowVariableType.Boolean;
275
+ }
276
+ if (typeof value === "number") {
277
+ if (Number.isInteger(value)) {
278
+ return WorkflowVariableType.Integer;
279
+ }
280
+ return WorkflowVariableType.Number;
281
+ }
282
+ if (Array.isArray(value)) {
283
+ return WorkflowVariableType.Array;
284
+ }
285
+ if (typeof value === "object") {
286
+ return WorkflowVariableType.Object;
287
+ }
288
+ return null;
289
+ };
290
+ WorkflowRuntimeType2.isMatchWorkflowType = (value, type) => {
291
+ const workflowType = (0, WorkflowRuntimeType2.getWorkflowType)(value);
292
+ if (!workflowType) {
293
+ return false;
294
+ }
295
+ return workflowType === type;
296
+ };
297
+ WorkflowRuntimeType2.isTypeEqual = (leftType, rightType) => {
298
+ if (leftType === WorkflowVariableType.Number && rightType === WorkflowVariableType.Integer || leftType === WorkflowVariableType.Integer && rightType === WorkflowVariableType.Number) {
299
+ return true;
300
+ }
301
+ return leftType === rightType;
302
+ };
303
+ WorkflowRuntimeType2.getArrayItemsType = (types) => {
304
+ const expectedType = types[0];
305
+ types.forEach((type) => {
306
+ if (type !== expectedType) {
307
+ throw new Error(`array items type must be same, expect ${expectedType}, but got ${type}`);
308
+ }
309
+ });
310
+ return expectedType;
311
+ };
312
+ })(WorkflowRuntimeType || (WorkflowRuntimeType = {}));
313
+
314
+ // src/infrastructure/utils/traverse-nodes.ts
315
+ function traverseNodes(startNode, getConnectedNodes) {
316
+ const visited = /* @__PURE__ */ new Set();
317
+ const result = [];
318
+ const traverse = (node) => {
319
+ for (const connectedNode of getConnectedNodes(node)) {
320
+ if (!visited.has(connectedNode.id)) {
321
+ visited.add(connectedNode.id);
322
+ result.push(connectedNode);
323
+ traverse(connectedNode);
324
+ }
325
+ }
326
+ };
327
+ traverse(startNode);
328
+ return result;
329
+ }
330
+
331
+ // src/infrastructure/utils/compare-node-groups.ts
332
+ function compareNodeGroups(groupA, groupB) {
333
+ const flatA = groupA.flat();
334
+ const setA = /* @__PURE__ */ new Map();
335
+ flatA.forEach((node) => {
336
+ setA.set(node.id, node);
337
+ });
338
+ const flatB = groupB.flat();
339
+ const setB = /* @__PURE__ */ new Map();
340
+ flatB.forEach((node) => {
341
+ setB.set(node.id, node);
342
+ });
343
+ const common = [];
344
+ const uniqueToA = [];
345
+ const uniqueToB = [];
346
+ setA.forEach((node, id) => {
347
+ if (setB.has(id)) {
348
+ common.push(node);
349
+ } else {
350
+ uniqueToA.push(node);
351
+ }
352
+ });
353
+ setB.forEach((node, id) => {
354
+ if (!setA.has(id)) {
355
+ uniqueToB.push(node);
356
+ }
357
+ });
358
+ return {
359
+ common,
360
+ uniqueToA,
361
+ uniqueToB
362
+ };
363
+ }
364
+
365
+ // src/infrastructure/utils/json-schema-validator.ts
366
+ var ROOT_PATH = "root";
367
+ var isRootPath = (path) => path === ROOT_PATH;
368
+ var validateValue = (value, schema, path) => {
369
+ if (schema.$ref) {
370
+ return { result: true };
371
+ }
372
+ if (schema.enum && schema.enum.length > 0) {
373
+ if (!schema.enum.includes(value)) {
374
+ return {
375
+ result: false,
376
+ errorMessage: `Value at ${path} must be one of: ${schema.enum.join(
377
+ ", "
378
+ )}, but got: ${JSON.stringify(value)}`
379
+ };
380
+ }
381
+ }
382
+ switch (schema.type) {
383
+ case "boolean":
384
+ return validateBoolean(value, path);
385
+ case "string":
386
+ return validateString(value, path);
387
+ case "integer":
388
+ return validateInteger(value, path);
389
+ case "number":
390
+ return validateNumber(value, path);
391
+ case "object":
392
+ return validateObject(value, schema, path);
393
+ case "array":
394
+ return validateArray(value, schema, path);
395
+ case "map":
396
+ return validateMap(value, schema, path);
397
+ default:
398
+ return {
399
+ result: false,
400
+ errorMessage: `Unknown type "${schema.type}" at ${path}`
401
+ };
402
+ }
403
+ };
404
+ var validateBoolean = (value, path) => {
405
+ if (typeof value !== "boolean") {
406
+ return {
407
+ result: false,
408
+ errorMessage: `Expected boolean at ${path}, but got: ${typeof value}`
409
+ };
410
+ }
411
+ return { result: true };
412
+ };
413
+ var validateString = (value, path) => {
414
+ if (typeof value !== "string") {
415
+ return {
416
+ result: false,
417
+ errorMessage: `Expected string at ${path}, but got: ${typeof value}`
418
+ };
419
+ }
420
+ return { result: true };
421
+ };
422
+ var validateInteger = (value, path) => {
423
+ if (!Number.isInteger(value)) {
424
+ return {
425
+ result: false,
426
+ errorMessage: `Expected integer at ${path}, but got: ${JSON.stringify(value)}`
427
+ };
428
+ }
429
+ return { result: true };
430
+ };
431
+ var validateNumber = (value, path) => {
432
+ if (typeof value !== "number" || isNaN(value)) {
433
+ return {
434
+ result: false,
435
+ errorMessage: `Expected number at ${path}, but got: ${JSON.stringify(value)}`
436
+ };
437
+ }
438
+ return { result: true };
439
+ };
440
+ var validateObject = (value, schema, path) => {
441
+ if (value === null || value === void 0) {
442
+ return {
443
+ result: false,
444
+ errorMessage: `Expected object at ${path}, but got: ${value}`
445
+ };
446
+ }
447
+ if (typeof value !== "object" || Array.isArray(value)) {
448
+ return {
449
+ result: false,
450
+ errorMessage: `Expected object at ${path}, but got: ${Array.isArray(value) ? "array" : typeof value}`
451
+ };
452
+ }
453
+ const objectValue = value;
454
+ if (schema.required && schema.required.length > 0) {
455
+ for (const requiredProperty of schema.required) {
456
+ if (!(requiredProperty in objectValue)) {
457
+ return {
458
+ result: false,
459
+ errorMessage: `Missing required property "${requiredProperty}" at ${path}`
460
+ };
461
+ }
462
+ }
463
+ }
464
+ if (schema.properties) {
465
+ for (const [propertyName, propertySchema] of Object.entries(schema.properties)) {
466
+ const isRequired = propertySchema.isPropertyRequired === true;
467
+ if (isRequired && !(propertyName in objectValue)) {
468
+ return {
469
+ result: false,
470
+ errorMessage: `Missing required property "${propertyName}" at ${path}`
471
+ };
472
+ }
473
+ }
474
+ }
475
+ if (schema.properties) {
476
+ for (const [propertyName, propertySchema] of Object.entries(schema.properties)) {
477
+ if (propertyName in objectValue) {
478
+ const propertyPath = isRootPath(path) ? propertyName : `${path}.${propertyName}`;
479
+ const propertyResult = validateValue(
480
+ objectValue[propertyName],
481
+ propertySchema,
482
+ propertyPath
483
+ );
484
+ if (!propertyResult.result) {
485
+ return propertyResult;
486
+ }
487
+ }
488
+ }
489
+ }
490
+ if (schema.additionalProperties) {
491
+ const definedProperties = new Set(Object.keys(schema.properties || {}));
492
+ for (const [propertyName, propertyValue] of Object.entries(objectValue)) {
493
+ if (!definedProperties.has(propertyName)) {
494
+ const propertyPath = isRootPath(path) ? propertyName : `${path}.${propertyName}`;
495
+ const propertyResult = validateValue(
496
+ propertyValue,
497
+ schema.additionalProperties,
498
+ propertyPath
499
+ );
500
+ if (!propertyResult.result) {
501
+ return propertyResult;
502
+ }
503
+ }
504
+ }
505
+ }
506
+ return { result: true };
507
+ };
508
+ var validateArray = (value, schema, path) => {
509
+ if (!Array.isArray(value)) {
510
+ return {
511
+ result: false,
512
+ errorMessage: `Expected array at ${path}, but got: ${typeof value}`
513
+ };
514
+ }
515
+ if (schema.items) {
516
+ for (const [index, item] of value.entries()) {
517
+ const itemPath = `${path}[${index}]`;
518
+ const itemResult = validateValue(item, schema.items, itemPath);
519
+ if (!itemResult.result) {
520
+ return itemResult;
521
+ }
522
+ }
523
+ }
524
+ return { result: true };
525
+ };
526
+ var validateMap = (value, schema, path) => {
527
+ if (value === null || value === void 0) {
528
+ return {
529
+ result: false,
530
+ errorMessage: `Expected map at ${path}, but got: ${value}`
531
+ };
532
+ }
533
+ if (typeof value !== "object" || Array.isArray(value)) {
534
+ return {
535
+ result: false,
536
+ errorMessage: `Expected map at ${path}, but got: ${Array.isArray(value) ? "array" : typeof value}`
537
+ };
538
+ }
539
+ const mapValue = value;
540
+ if (schema.additionalProperties) {
541
+ for (const [key, mapItemValue] of Object.entries(mapValue)) {
542
+ const keyPath = isRootPath(path) ? key : `${path}.${key}`;
543
+ const keyResult = validateValue(mapItemValue, schema.additionalProperties, keyPath);
544
+ if (!keyResult.result) {
545
+ return keyResult;
546
+ }
547
+ }
548
+ }
549
+ return { result: true };
550
+ };
551
+ var JSONSchemaValidator = (params) => {
552
+ const { schema, value } = params;
553
+ try {
554
+ const validationResult = validateValue(value, schema, ROOT_PATH);
555
+ return validationResult;
556
+ } catch (error) {
557
+ return {
558
+ result: false,
559
+ errorMessage: `Validation error: ${error instanceof Error ? error.message : String(error)}`
560
+ };
561
+ }
562
+ };
563
+
564
+ // src/nodes/loop/index.ts
231
565
  var LoopExecutor = class {
232
566
  constructor() {
233
567
  this.type = FlowGramNode.Loop;
234
568
  }
235
569
  async execute(context) {
236
570
  const loopNodeID = context.node.id;
237
- const loopArrayResult = context.runtime.state.parseRef(context.node.data.batchFor);
238
- this.checkLoopArray(loopArrayResult);
239
- const loopArray = loopArrayResult.value;
240
- const itemsType = loopArrayResult.itemsType;
241
571
  const engine = context.container.get(IEngine);
572
+ const { value: loopArray, itemsType } = this.getLoopArrayVariable(context);
242
573
  const subNodes = context.node.children;
243
- const startSubNodes = subNodes.filter((node) => node.prev.length === 0);
244
- if (loopArray.length === 0 || startSubNodes.length === 0) {
245
- return {
246
- outputs: {}
247
- };
574
+ const blockStartNode = subNodes.find((node) => node.type === FlowGramNode.BlockStart);
575
+ if (!blockStartNode) {
576
+ throw new Error("block start node not found");
248
577
  }
249
- for (let i = 0; i < loopArray.length; i++) {
250
- const loopItem = loopArray[i];
578
+ const blockOutputs = [];
579
+ for (let index = 0; index < loopArray.length; index++) {
580
+ const loopItem = loopArray[index];
251
581
  const subContext = context.runtime.sub();
252
582
  subContext.variableStore.setVariable({
253
583
  nodeID: `${loopNodeID}_locals`,
@@ -255,33 +585,99 @@ var LoopExecutor = class {
255
585
  type: itemsType,
256
586
  value: loopItem
257
587
  });
258
- await Promise.all(
259
- startSubNodes.map(
260
- (node) => engine.executeNode({
261
- context: subContext,
262
- node
263
- })
264
- )
265
- );
588
+ subContext.variableStore.setVariable({
589
+ nodeID: `${loopNodeID}_locals`,
590
+ key: "index",
591
+ type: WorkflowVariableType.Number,
592
+ value: index
593
+ });
594
+ await engine.executeNode({
595
+ context: subContext,
596
+ node: blockStartNode
597
+ });
598
+ const blockOutput = this.getBlockOutput(context, subContext);
599
+ blockOutputs.push(blockOutput);
266
600
  }
601
+ this.setLoopNodeOutputs(context, blockOutputs);
602
+ const outputs = this.combineBlockOutputs(context, blockOutputs);
267
603
  return {
268
- outputs: {}
604
+ outputs
269
605
  };
270
606
  }
271
- checkLoopArray(loopArrayResult) {
272
- const loopArray = loopArrayResult?.value;
607
+ getLoopArrayVariable(executionContext) {
608
+ const loopNodeData = executionContext.node.data;
609
+ const LoopArrayVariable = executionContext.runtime.state.parseRef(
610
+ loopNodeData.loopFor
611
+ );
612
+ this.checkLoopArray(LoopArrayVariable);
613
+ return LoopArrayVariable;
614
+ }
615
+ checkLoopArray(LoopArrayVariable) {
616
+ const loopArray = LoopArrayVariable?.value;
273
617
  if (!loopArray || isNil(loopArray) || !Array.isArray(loopArray)) {
274
- throw new Error("batchFor is required");
618
+ throw new Error("loopFor is required");
275
619
  }
276
- const loopArrayType = loopArrayResult.type;
620
+ const loopArrayType = LoopArrayVariable.type;
277
621
  if (loopArrayType !== WorkflowVariableType.Array) {
278
- throw new Error("batchFor must be an array");
622
+ throw new Error("loopFor must be an array");
279
623
  }
280
- const loopArrayItemType = loopArrayResult.itemsType;
624
+ const loopArrayItemType = LoopArrayVariable.itemsType;
281
625
  if (isNil(loopArrayItemType)) {
282
- throw new Error("batchFor items must be array items");
626
+ throw new Error("loopFor items must be array items");
283
627
  }
284
628
  }
629
+ getBlockOutput(executionContext, subContext) {
630
+ const loopOutputsDeclare = this.getLoopOutputsDeclare(executionContext);
631
+ const blockOutput = Object.entries(loopOutputsDeclare).reduce(
632
+ (acc, [outputName, outputRef]) => {
633
+ const outputVariable = subContext.state.parseRef(outputRef);
634
+ if (!outputVariable) {
635
+ return acc;
636
+ }
637
+ return {
638
+ ...acc,
639
+ [outputName]: outputVariable
640
+ };
641
+ },
642
+ {}
643
+ );
644
+ return blockOutput;
645
+ }
646
+ setLoopNodeOutputs(executionContext, blockOutputs) {
647
+ const loopNode = executionContext.node;
648
+ const loopOutputsDeclare = this.getLoopOutputsDeclare(executionContext);
649
+ const loopOutputNames = Object.keys(loopOutputsDeclare);
650
+ loopOutputNames.forEach((outputName) => {
651
+ const outputVariables = blockOutputs.map((blockOutput) => blockOutput[outputName]);
652
+ const outputTypes = outputVariables.map((fieldVariable) => fieldVariable.type);
653
+ const itemsType = WorkflowRuntimeType.getArrayItemsType(outputTypes);
654
+ const value = outputVariables.map((fieldVariable) => fieldVariable.value);
655
+ executionContext.runtime.variableStore.setVariable({
656
+ nodeID: loopNode.id,
657
+ key: outputName,
658
+ type: WorkflowVariableType.Array,
659
+ itemsType,
660
+ value
661
+ });
662
+ });
663
+ }
664
+ combineBlockOutputs(executionContext, blockOutputs) {
665
+ const loopOutputsDeclare = this.getLoopOutputsDeclare(executionContext);
666
+ const loopOutputNames = Object.keys(loopOutputsDeclare);
667
+ const loopOutput = loopOutputNames.reduce(
668
+ (outputs, outputName) => ({
669
+ ...outputs,
670
+ [outputName]: blockOutputs.map((blockOutput) => blockOutput[outputName].value)
671
+ }),
672
+ {}
673
+ );
674
+ return loopOutput;
675
+ }
676
+ getLoopOutputsDeclare(executionContext) {
677
+ const loopNodeData = executionContext.node.data;
678
+ const loopOutputsDeclare = loopNodeData.loopOutputs ?? {};
679
+ return loopOutputsDeclare;
680
+ }
285
681
  };
286
682
 
287
683
  // src/nodes/llm/index.ts
@@ -344,67 +740,89 @@ var EndExecutor = class {
344
740
  }
345
741
  };
346
742
 
743
+ // src/nodes/empty/index.ts
744
+ var BlockStartExecutor = class {
745
+ constructor() {
746
+ this.type = FlowGramNode.BlockStart;
747
+ }
748
+ async execute(context) {
749
+ return {
750
+ outputs: {}
751
+ };
752
+ }
753
+ };
754
+ var BlockEndExecutor = class {
755
+ constructor() {
756
+ this.type = FlowGramNode.BlockEnd;
757
+ }
758
+ async execute(context) {
759
+ return {
760
+ outputs: {}
761
+ };
762
+ }
763
+ };
764
+
347
765
  // src/nodes/condition/index.ts
348
766
  import { isNil as isNil9 } from "lodash-es";
349
767
 
350
768
  // src/nodes/condition/rules.ts
351
769
  var conditionRules = {
352
770
  [WorkflowVariableType.String]: {
353
- ["eq" /* EQ */]: WorkflowVariableType.String,
354
- ["neq" /* NEQ */]: WorkflowVariableType.String,
355
- ["contains" /* CONTAINS */]: WorkflowVariableType.String,
356
- ["not_contains" /* NOT_CONTAINS */]: WorkflowVariableType.String,
357
- ["in" /* IN */]: WorkflowVariableType.Array,
358
- ["nin" /* NIN */]: WorkflowVariableType.Array,
359
- ["is_empty" /* IS_EMPTY */]: WorkflowVariableType.String,
360
- ["is_not_empty" /* IS_NOT_EMPTY */]: WorkflowVariableType.String
771
+ [ConditionOperation.EQ]: WorkflowVariableType.String,
772
+ [ConditionOperation.NEQ]: WorkflowVariableType.String,
773
+ [ConditionOperation.CONTAINS]: WorkflowVariableType.String,
774
+ [ConditionOperation.NOT_CONTAINS]: WorkflowVariableType.String,
775
+ [ConditionOperation.IN]: WorkflowVariableType.Array,
776
+ [ConditionOperation.NIN]: WorkflowVariableType.Array,
777
+ [ConditionOperation.IS_EMPTY]: WorkflowVariableType.String,
778
+ [ConditionOperation.IS_NOT_EMPTY]: WorkflowVariableType.String
361
779
  },
362
780
  [WorkflowVariableType.Number]: {
363
- ["eq" /* EQ */]: WorkflowVariableType.Number,
364
- ["neq" /* NEQ */]: WorkflowVariableType.Number,
365
- ["gt" /* GT */]: WorkflowVariableType.Number,
366
- ["gte" /* GTE */]: WorkflowVariableType.Number,
367
- ["lt" /* LT */]: WorkflowVariableType.Number,
368
- ["lte" /* LTE */]: WorkflowVariableType.Number,
369
- ["in" /* IN */]: WorkflowVariableType.Array,
370
- ["nin" /* NIN */]: WorkflowVariableType.Array,
371
- ["is_empty" /* IS_EMPTY */]: WorkflowVariableType.Null,
372
- ["is_not_empty" /* IS_NOT_EMPTY */]: WorkflowVariableType.Null
781
+ [ConditionOperation.EQ]: WorkflowVariableType.Number,
782
+ [ConditionOperation.NEQ]: WorkflowVariableType.Number,
783
+ [ConditionOperation.GT]: WorkflowVariableType.Number,
784
+ [ConditionOperation.GTE]: WorkflowVariableType.Number,
785
+ [ConditionOperation.LT]: WorkflowVariableType.Number,
786
+ [ConditionOperation.LTE]: WorkflowVariableType.Number,
787
+ [ConditionOperation.IN]: WorkflowVariableType.Array,
788
+ [ConditionOperation.NIN]: WorkflowVariableType.Array,
789
+ [ConditionOperation.IS_EMPTY]: WorkflowVariableType.Null,
790
+ [ConditionOperation.IS_NOT_EMPTY]: WorkflowVariableType.Null
373
791
  },
374
792
  [WorkflowVariableType.Integer]: {
375
- ["eq" /* EQ */]: WorkflowVariableType.Integer,
376
- ["neq" /* NEQ */]: WorkflowVariableType.Integer,
377
- ["gt" /* GT */]: WorkflowVariableType.Integer,
378
- ["gte" /* GTE */]: WorkflowVariableType.Integer,
379
- ["lt" /* LT */]: WorkflowVariableType.Integer,
380
- ["lte" /* LTE */]: WorkflowVariableType.Integer,
381
- ["in" /* IN */]: WorkflowVariableType.Array,
382
- ["nin" /* NIN */]: WorkflowVariableType.Array,
383
- ["is_empty" /* IS_EMPTY */]: WorkflowVariableType.Null,
384
- ["is_not_empty" /* IS_NOT_EMPTY */]: WorkflowVariableType.Null
793
+ [ConditionOperation.EQ]: WorkflowVariableType.Integer,
794
+ [ConditionOperation.NEQ]: WorkflowVariableType.Integer,
795
+ [ConditionOperation.GT]: WorkflowVariableType.Integer,
796
+ [ConditionOperation.GTE]: WorkflowVariableType.Integer,
797
+ [ConditionOperation.LT]: WorkflowVariableType.Integer,
798
+ [ConditionOperation.LTE]: WorkflowVariableType.Integer,
799
+ [ConditionOperation.IN]: WorkflowVariableType.Array,
800
+ [ConditionOperation.NIN]: WorkflowVariableType.Array,
801
+ [ConditionOperation.IS_EMPTY]: WorkflowVariableType.Null,
802
+ [ConditionOperation.IS_NOT_EMPTY]: WorkflowVariableType.Null
385
803
  },
386
804
  [WorkflowVariableType.Boolean]: {
387
- ["eq" /* EQ */]: WorkflowVariableType.Boolean,
388
- ["neq" /* NEQ */]: WorkflowVariableType.Boolean,
389
- ["is_true" /* IS_TRUE */]: WorkflowVariableType.Null,
390
- ["is_false" /* IS_FALSE */]: WorkflowVariableType.Null,
391
- ["in" /* IN */]: WorkflowVariableType.Array,
392
- ["nin" /* NIN */]: WorkflowVariableType.Array,
393
- ["is_empty" /* IS_EMPTY */]: WorkflowVariableType.Null,
394
- ["is_not_empty" /* IS_NOT_EMPTY */]: WorkflowVariableType.Null
805
+ [ConditionOperation.EQ]: WorkflowVariableType.Boolean,
806
+ [ConditionOperation.NEQ]: WorkflowVariableType.Boolean,
807
+ [ConditionOperation.IS_TRUE]: WorkflowVariableType.Null,
808
+ [ConditionOperation.IS_FALSE]: WorkflowVariableType.Null,
809
+ [ConditionOperation.IN]: WorkflowVariableType.Array,
810
+ [ConditionOperation.NIN]: WorkflowVariableType.Array,
811
+ [ConditionOperation.IS_EMPTY]: WorkflowVariableType.Null,
812
+ [ConditionOperation.IS_NOT_EMPTY]: WorkflowVariableType.Null
395
813
  },
396
814
  [WorkflowVariableType.Object]: {
397
- ["is_empty" /* IS_EMPTY */]: WorkflowVariableType.Null,
398
- ["is_not_empty" /* IS_NOT_EMPTY */]: WorkflowVariableType.Null
815
+ [ConditionOperation.IS_EMPTY]: WorkflowVariableType.Null,
816
+ [ConditionOperation.IS_NOT_EMPTY]: WorkflowVariableType.Null
399
817
  },
400
818
  [WorkflowVariableType.Array]: {
401
- ["is_empty" /* IS_EMPTY */]: WorkflowVariableType.Null,
402
- ["is_not_empty" /* IS_NOT_EMPTY */]: WorkflowVariableType.Null
819
+ [ConditionOperation.IS_EMPTY]: WorkflowVariableType.Null,
820
+ [ConditionOperation.IS_NOT_EMPTY]: WorkflowVariableType.Null
403
821
  },
404
822
  [WorkflowVariableType.Null]: {
405
- ["eq" /* EQ */]: WorkflowVariableType.Null,
406
- ["is_empty" /* IS_EMPTY */]: WorkflowVariableType.Null,
407
- ["is_not_empty" /* IS_NOT_EMPTY */]: WorkflowVariableType.Null
823
+ [ConditionOperation.EQ]: WorkflowVariableType.Null,
824
+ [ConditionOperation.IS_EMPTY]: WorkflowVariableType.Null,
825
+ [ConditionOperation.IS_NOT_EMPTY]: WorkflowVariableType.Null
408
826
  }
409
827
  };
410
828
 
@@ -413,34 +831,34 @@ import { isNil as isNil3 } from "lodash-es";
413
831
  var conditionStringHandler = (condition) => {
414
832
  const { operator } = condition;
415
833
  const leftValue = condition.leftValue;
416
- if (operator === "eq" /* EQ */) {
834
+ if (operator === ConditionOperation.EQ) {
417
835
  const rightValue = condition.rightValue;
418
836
  return leftValue === rightValue;
419
837
  }
420
- if (operator === "neq" /* NEQ */) {
838
+ if (operator === ConditionOperation.NEQ) {
421
839
  const rightValue = condition.rightValue;
422
840
  return leftValue !== rightValue;
423
841
  }
424
- if (operator === "contains" /* CONTAINS */) {
842
+ if (operator === ConditionOperation.CONTAINS) {
425
843
  const rightValue = condition.rightValue;
426
844
  return leftValue.includes(rightValue);
427
845
  }
428
- if (operator === "not_contains" /* NOT_CONTAINS */) {
846
+ if (operator === ConditionOperation.NOT_CONTAINS) {
429
847
  const rightValue = condition.rightValue;
430
848
  return !leftValue.includes(rightValue);
431
849
  }
432
- if (operator === "in" /* IN */) {
850
+ if (operator === ConditionOperation.IN) {
433
851
  const rightValue = condition.rightValue;
434
852
  return rightValue.includes(leftValue);
435
853
  }
436
- if (operator === "nin" /* NIN */) {
854
+ if (operator === ConditionOperation.NIN) {
437
855
  const rightValue = condition.rightValue;
438
856
  return !rightValue.includes(leftValue);
439
857
  }
440
- if (operator === "is_empty" /* IS_EMPTY */) {
858
+ if (operator === ConditionOperation.IS_EMPTY) {
441
859
  return isNil3(leftValue);
442
860
  }
443
- if (operator === "is_not_empty" /* IS_NOT_EMPTY */) {
861
+ if (operator === ConditionOperation.IS_NOT_EMPTY) {
444
862
  return !isNil3(leftValue);
445
863
  }
446
864
  return false;
@@ -451,10 +869,10 @@ import { isNil as isNil4 } from "lodash-es";
451
869
  var conditionObjectHandler = (condition) => {
452
870
  const { operator } = condition;
453
871
  const leftValue = condition.leftValue;
454
- if (operator === "is_empty" /* IS_EMPTY */) {
872
+ if (operator === ConditionOperation.IS_EMPTY) {
455
873
  return isNil4(leftValue);
456
874
  }
457
- if (operator === "is_not_empty" /* IS_NOT_EMPTY */) {
875
+ if (operator === ConditionOperation.IS_NOT_EMPTY) {
458
876
  return !isNil4(leftValue);
459
877
  }
460
878
  return false;
@@ -465,42 +883,42 @@ import { isNil as isNil5 } from "lodash-es";
465
883
  var conditionNumberHandler = (condition) => {
466
884
  const { operator } = condition;
467
885
  const leftValue = condition.leftValue;
468
- if (operator === "eq" /* EQ */) {
886
+ if (operator === ConditionOperation.EQ) {
469
887
  const rightValue = condition.rightValue;
470
888
  return leftValue === rightValue;
471
889
  }
472
- if (operator === "neq" /* NEQ */) {
890
+ if (operator === ConditionOperation.NEQ) {
473
891
  const rightValue = condition.rightValue;
474
892
  return leftValue !== rightValue;
475
893
  }
476
- if (operator === "gt" /* GT */) {
894
+ if (operator === ConditionOperation.GT) {
477
895
  const rightValue = condition.rightValue;
478
896
  return leftValue > rightValue;
479
897
  }
480
- if (operator === "gte" /* GTE */) {
898
+ if (operator === ConditionOperation.GTE) {
481
899
  const rightValue = condition.rightValue;
482
900
  return leftValue >= rightValue;
483
901
  }
484
- if (operator === "lt" /* LT */) {
902
+ if (operator === ConditionOperation.LT) {
485
903
  const rightValue = condition.rightValue;
486
904
  return leftValue < rightValue;
487
905
  }
488
- if (operator === "lte" /* LTE */) {
906
+ if (operator === ConditionOperation.LTE) {
489
907
  const rightValue = condition.rightValue;
490
908
  return leftValue <= rightValue;
491
909
  }
492
- if (operator === "in" /* IN */) {
910
+ if (operator === ConditionOperation.IN) {
493
911
  const rightValue = condition.rightValue;
494
912
  return rightValue.includes(leftValue);
495
913
  }
496
- if (operator === "nin" /* NIN */) {
914
+ if (operator === ConditionOperation.NIN) {
497
915
  const rightValue = condition.rightValue;
498
916
  return !rightValue.includes(leftValue);
499
917
  }
500
- if (operator === "is_empty" /* IS_EMPTY */) {
918
+ if (operator === ConditionOperation.IS_EMPTY) {
501
919
  return isNil5(leftValue);
502
920
  }
503
- if (operator === "is_not_empty" /* IS_NOT_EMPTY */) {
921
+ if (operator === ConditionOperation.IS_NOT_EMPTY) {
504
922
  return !isNil5(leftValue);
505
923
  }
506
924
  return false;
@@ -511,13 +929,13 @@ import { isNil as isNil6 } from "lodash-es";
511
929
  var conditionNullHandler = (condition) => {
512
930
  const { operator } = condition;
513
931
  const leftValue = condition.leftValue;
514
- if (operator === "eq" /* EQ */) {
932
+ if (operator === ConditionOperation.EQ) {
515
933
  return isNil6(leftValue) && isNil6(condition.rightValue);
516
934
  }
517
- if (operator === "is_empty" /* IS_EMPTY */) {
935
+ if (operator === ConditionOperation.IS_EMPTY) {
518
936
  return isNil6(leftValue);
519
937
  }
520
- if (operator === "is_not_empty" /* IS_NOT_EMPTY */) {
938
+ if (operator === ConditionOperation.IS_NOT_EMPTY) {
521
939
  return !isNil6(leftValue);
522
940
  }
523
941
  return false;
@@ -528,32 +946,32 @@ import { isNil as isNil7 } from "lodash-es";
528
946
  var conditionBooleanHandler = (condition) => {
529
947
  const { operator } = condition;
530
948
  const leftValue = condition.leftValue;
531
- if (operator === "eq" /* EQ */) {
949
+ if (operator === ConditionOperation.EQ) {
532
950
  const rightValue = condition.rightValue;
533
951
  return leftValue === rightValue;
534
952
  }
535
- if (operator === "neq" /* NEQ */) {
953
+ if (operator === ConditionOperation.NEQ) {
536
954
  const rightValue = condition.rightValue;
537
955
  return leftValue !== rightValue;
538
956
  }
539
- if (operator === "is_true" /* IS_TRUE */) {
957
+ if (operator === ConditionOperation.IS_TRUE) {
540
958
  return leftValue === true;
541
959
  }
542
- if (operator === "is_false" /* IS_FALSE */) {
960
+ if (operator === ConditionOperation.IS_FALSE) {
543
961
  return leftValue === false;
544
962
  }
545
- if (operator === "in" /* IN */) {
963
+ if (operator === ConditionOperation.IN) {
546
964
  const rightValue = condition.rightValue;
547
965
  return rightValue.includes(leftValue);
548
966
  }
549
- if (operator === "nin" /* NIN */) {
967
+ if (operator === ConditionOperation.NIN) {
550
968
  const rightValue = condition.rightValue;
551
969
  return !rightValue.includes(leftValue);
552
970
  }
553
- if (operator === "is_empty" /* IS_EMPTY */) {
971
+ if (operator === ConditionOperation.IS_EMPTY) {
554
972
  return isNil7(leftValue);
555
973
  }
556
- if (operator === "is_not_empty" /* IS_NOT_EMPTY */) {
974
+ if (operator === ConditionOperation.IS_NOT_EMPTY) {
557
975
  return !isNil7(leftValue);
558
976
  }
559
977
  return false;
@@ -564,10 +982,10 @@ import { isNil as isNil8 } from "lodash-es";
564
982
  var conditionArrayHandler = (condition) => {
565
983
  const { operator } = condition;
566
984
  const leftValue = condition.leftValue;
567
- if (operator === "is_empty" /* IS_EMPTY */) {
985
+ if (operator === ConditionOperation.IS_EMPTY) {
568
986
  return isNil8(leftValue);
569
987
  }
570
- if (operator === "is_not_empty" /* IS_NOT_EMPTY */) {
988
+ if (operator === ConditionOperation.IS_NOT_EMPTY) {
571
989
  return !isNil8(leftValue);
572
990
  }
573
991
  return false;
@@ -599,9 +1017,7 @@ var ConditionExecutor = class {
599
1017
  const parsedConditions = conditions.map((item) => this.parseCondition(item, context)).filter((item) => this.checkCondition(item));
600
1018
  const activatedCondition = parsedConditions.find((item) => this.handleCondition(item));
601
1019
  if (!activatedCondition) {
602
- return {
603
- outputs: {}
604
- };
1020
+ throw new Error("no condition is activated");
605
1021
  }
606
1022
  return {
607
1023
  outputs: {},
@@ -656,16 +1072,55 @@ var WorkflowRuntimeNodeExecutors = [
656
1072
  EndExecutor,
657
1073
  LLMExecutor,
658
1074
  ConditionExecutor,
659
- LoopExecutor
1075
+ LoopExecutor,
1076
+ BlockStartExecutor,
1077
+ BlockEndExecutor
660
1078
  ];
661
1079
 
662
1080
  // src/domain/validation/index.ts
663
1081
  var WorkflowRuntimeValidation = class {
664
- validate(schema) {
1082
+ invoke(params) {
1083
+ const { schema, inputs } = params;
1084
+ const schemaValidationResult = this.schema(schema);
1085
+ if (!schemaValidationResult.valid) {
1086
+ return schemaValidationResult;
1087
+ }
1088
+ const inputsValidationResult = this.inputs(this.getWorkflowInputsDeclare(schema), inputs);
1089
+ if (!inputsValidationResult.valid) {
1090
+ return inputsValidationResult;
1091
+ }
1092
+ return {
1093
+ valid: true
1094
+ };
1095
+ }
1096
+ schema(schema) {
665
1097
  return {
666
1098
  valid: true
667
1099
  };
668
1100
  }
1101
+ inputs(inputsSchema, inputs) {
1102
+ const { result, errorMessage } = JSONSchemaValidator({
1103
+ schema: inputsSchema,
1104
+ value: inputs
1105
+ });
1106
+ if (!result) {
1107
+ const error = `JSON Schema validation failed: ${errorMessage}`;
1108
+ return {
1109
+ valid: false,
1110
+ errors: [error]
1111
+ };
1112
+ }
1113
+ return {
1114
+ valid: true
1115
+ };
1116
+ }
1117
+ getWorkflowInputsDeclare(schema) {
1118
+ const startNode = schema.nodes.find((node) => node.type === FlowGramNode.Start);
1119
+ if (!startNode) {
1120
+ throw new Error("Workflow schema must have a start node");
1121
+ }
1122
+ return startNode.data.outputs;
1123
+ }
669
1124
  };
670
1125
 
671
1126
  // src/domain/executor/index.ts
@@ -690,52 +1145,6 @@ var WorkflowRuntimeExecutor = class {
690
1145
  }
691
1146
  };
692
1147
 
693
- // src/infrastructure/utils/uuid.ts
694
- import { v4 } from "uuid";
695
- var uuid = v4;
696
-
697
- // src/infrastructure/utils/runtime-type.ts
698
- var WorkflowRuntimeType;
699
- ((WorkflowRuntimeType2) => {
700
- WorkflowRuntimeType2.getWorkflowType = (value) => {
701
- if (value === null || value === void 0) {
702
- return WorkflowVariableType.Null;
703
- }
704
- if (typeof value === "string") {
705
- return WorkflowVariableType.String;
706
- }
707
- if (typeof value === "boolean") {
708
- return WorkflowVariableType.Boolean;
709
- }
710
- if (typeof value === "number") {
711
- if (Number.isInteger(value)) {
712
- return WorkflowVariableType.Integer;
713
- }
714
- return WorkflowVariableType.Number;
715
- }
716
- if (Array.isArray(value)) {
717
- return WorkflowVariableType.Array;
718
- }
719
- if (typeof value === "object") {
720
- return WorkflowVariableType.Object;
721
- }
722
- return null;
723
- };
724
- WorkflowRuntimeType2.isMatchWorkflowType = (value, type) => {
725
- const workflowType = (0, WorkflowRuntimeType2.getWorkflowType)(value);
726
- if (!workflowType) {
727
- return false;
728
- }
729
- return workflowType === type;
730
- };
731
- WorkflowRuntimeType2.isTypeEqual = (leftType, rightType) => {
732
- if (leftType === WorkflowVariableType.Number && rightType === WorkflowVariableType.Integer || leftType === WorkflowVariableType.Integer && rightType === WorkflowVariableType.Number) {
733
- return true;
734
- }
735
- return leftType === rightType;
736
- };
737
- })(WorkflowRuntimeType || (WorkflowRuntimeType = {}));
738
-
739
1148
  // src/domain/task/index.ts
740
1149
  var WorkflowRuntimeTask = class _WorkflowRuntimeTask {
741
1150
  constructor(params) {
@@ -755,6 +1164,85 @@ var WorkflowRuntimeTask = class _WorkflowRuntimeTask {
755
1164
  }
756
1165
  };
757
1166
 
1167
+ // src/domain/message/message-value-object/index.ts
1168
+ var WorkflowRuntimeMessage;
1169
+ ((WorkflowRuntimeMessage2) => {
1170
+ WorkflowRuntimeMessage2.create = (params) => {
1171
+ const message = {
1172
+ id: uuid(),
1173
+ ...params
1174
+ };
1175
+ if (!params.timestamp) {
1176
+ message.timestamp = Date.now();
1177
+ }
1178
+ return message;
1179
+ };
1180
+ })(WorkflowRuntimeMessage || (WorkflowRuntimeMessage = {}));
1181
+
1182
+ // src/domain/message/message-center/index.ts
1183
+ var WorkflowRuntimeMessageCenter = class {
1184
+ init() {
1185
+ this.messages = {
1186
+ [WorkflowMessageType.Log]: [],
1187
+ [WorkflowMessageType.Info]: [],
1188
+ [WorkflowMessageType.Debug]: [],
1189
+ [WorkflowMessageType.Error]: [],
1190
+ [WorkflowMessageType.Warn]: []
1191
+ };
1192
+ }
1193
+ dispose() {
1194
+ }
1195
+ log(data) {
1196
+ const message = WorkflowRuntimeMessage.create({
1197
+ type: WorkflowMessageType.Log,
1198
+ ...data
1199
+ });
1200
+ this.messages[WorkflowMessageType.Log].push(message);
1201
+ return message;
1202
+ }
1203
+ info(data) {
1204
+ const message = WorkflowRuntimeMessage.create({
1205
+ type: WorkflowMessageType.Info,
1206
+ ...data
1207
+ });
1208
+ this.messages[WorkflowMessageType.Info].push(message);
1209
+ return message;
1210
+ }
1211
+ debug(data) {
1212
+ const message = WorkflowRuntimeMessage.create({
1213
+ type: WorkflowMessageType.Debug,
1214
+ ...data
1215
+ });
1216
+ this.messages[WorkflowMessageType.Debug].push(message);
1217
+ return message;
1218
+ }
1219
+ error(data) {
1220
+ const message = WorkflowRuntimeMessage.create({
1221
+ type: WorkflowMessageType.Error,
1222
+ ...data
1223
+ });
1224
+ this.messages[WorkflowMessageType.Error].push(message);
1225
+ return message;
1226
+ }
1227
+ warn(data) {
1228
+ const message = WorkflowRuntimeMessage.create({
1229
+ type: WorkflowMessageType.Warn,
1230
+ ...data
1231
+ });
1232
+ this.messages[WorkflowMessageType.Warn].push(message);
1233
+ return message;
1234
+ }
1235
+ export() {
1236
+ return {
1237
+ [WorkflowMessageType.Log]: this.messages[WorkflowMessageType.Log].slice(),
1238
+ [WorkflowMessageType.Info]: this.messages[WorkflowMessageType.Info].slice(),
1239
+ [WorkflowMessageType.Debug]: this.messages[WorkflowMessageType.Debug].slice(),
1240
+ [WorkflowMessageType.Error]: this.messages[WorkflowMessageType.Error].slice(),
1241
+ [WorkflowMessageType.Warn]: this.messages[WorkflowMessageType.Warn].slice()
1242
+ };
1243
+ }
1244
+ };
1245
+
758
1246
  // src/domain/variable/variable-store/index.ts
759
1247
  import { get, set } from "lodash-es";
760
1248
 
@@ -1104,7 +1592,7 @@ var WorkflowRuntimeSnapshot = class _WorkflowRuntimeSnapshot {
1104
1592
  this.id = uuid();
1105
1593
  this.data = data;
1106
1594
  }
1107
- addData(data) {
1595
+ update(data) {
1108
1596
  Object.assign(this.data, data);
1109
1597
  }
1110
1598
  validate() {
@@ -1165,10 +1653,11 @@ var WorkflowRuntimeReport;
1165
1653
 
1166
1654
  // src/domain/report/reporter/index.ts
1167
1655
  var WorkflowRuntimeReporter = class {
1168
- constructor(ioCenter, snapshotCenter, statusCenter) {
1656
+ constructor(ioCenter, snapshotCenter, statusCenter, messageCenter) {
1169
1657
  this.ioCenter = ioCenter;
1170
1658
  this.snapshotCenter = snapshotCenter;
1171
1659
  this.statusCenter = statusCenter;
1660
+ this.messageCenter = messageCenter;
1172
1661
  }
1173
1662
  init() {
1174
1663
  }
@@ -1179,7 +1668,8 @@ var WorkflowRuntimeReporter = class {
1179
1668
  inputs: this.ioCenter.inputs,
1180
1669
  outputs: this.ioCenter.outputs,
1181
1670
  workflowStatus: this.statusCenter.workflow.export(),
1182
- reports: this.nodeReports()
1671
+ reports: this.nodeReports(),
1672
+ messages: this.messageCenter.export()
1183
1673
  });
1184
1674
  return report;
1185
1675
  }
@@ -1317,6 +1807,12 @@ var WorkflowRuntimeNode = class {
1317
1807
  get next() {
1318
1808
  return this._next;
1319
1809
  }
1810
+ get successors() {
1811
+ return traverseNodes(this, (node) => node.next);
1812
+ }
1813
+ get predecessors() {
1814
+ return traverseNodes(this, (node) => node.prev);
1815
+ }
1320
1816
  get isBranch() {
1321
1817
  return this.ports.outputs.length > 1;
1322
1818
  }
@@ -1554,6 +2050,7 @@ var WorkflowRuntimeContext = class _WorkflowRuntimeContext {
1554
2050
  this.ioCenter = data.ioCenter;
1555
2051
  this.snapshotCenter = data.snapshotCenter;
1556
2052
  this.statusCenter = data.statusCenter;
2053
+ this.messageCenter = data.messageCenter;
1557
2054
  this.reporter = data.reporter;
1558
2055
  }
1559
2056
  init(params) {
@@ -1564,6 +2061,7 @@ var WorkflowRuntimeContext = class _WorkflowRuntimeContext {
1564
2061
  this.ioCenter.init(inputs);
1565
2062
  this.snapshotCenter.init();
1566
2063
  this.statusCenter.init();
2064
+ this.messageCenter.init();
1567
2065
  this.reporter.init();
1568
2066
  }
1569
2067
  dispose() {
@@ -1577,6 +2075,7 @@ var WorkflowRuntimeContext = class _WorkflowRuntimeContext {
1577
2075
  this.ioCenter.dispose();
1578
2076
  this.snapshotCenter.dispose();
1579
2077
  this.statusCenter.dispose();
2078
+ this.messageCenter.dispose();
1580
2079
  this.reporter.dispose();
1581
2080
  }
1582
2081
  sub() {
@@ -1588,6 +2087,7 @@ var WorkflowRuntimeContext = class _WorkflowRuntimeContext {
1588
2087
  ioCenter: this.ioCenter,
1589
2088
  snapshotCenter: this.snapshotCenter,
1590
2089
  statusCenter: this.statusCenter,
2090
+ messageCenter: this.messageCenter,
1591
2091
  reporter: this.reporter,
1592
2092
  variableStore,
1593
2093
  state
@@ -1605,7 +2105,13 @@ var WorkflowRuntimeContext = class _WorkflowRuntimeContext {
1605
2105
  const ioCenter = new WorkflowRuntimeIOCenter();
1606
2106
  const snapshotCenter = new WorkflowRuntimeSnapshotCenter();
1607
2107
  const statusCenter = new WorkflowRuntimeStatusCenter();
1608
- const reporter = new WorkflowRuntimeReporter(ioCenter, snapshotCenter, statusCenter);
2108
+ const messageCenter = new WorkflowRuntimeMessageCenter();
2109
+ const reporter = new WorkflowRuntimeReporter(
2110
+ ioCenter,
2111
+ snapshotCenter,
2112
+ statusCenter,
2113
+ messageCenter
2114
+ );
1609
2115
  return new _WorkflowRuntimeContext({
1610
2116
  document,
1611
2117
  variableStore,
@@ -1613,6 +2119,7 @@ var WorkflowRuntimeContext = class _WorkflowRuntimeContext {
1613
2119
  ioCenter,
1614
2120
  snapshotCenter,
1615
2121
  statusCenter,
2122
+ messageCenter,
1616
2123
  reporter
1617
2124
  });
1618
2125
  }
@@ -1621,11 +2128,19 @@ var WorkflowRuntimeContext = class _WorkflowRuntimeContext {
1621
2128
  // src/domain/engine/index.ts
1622
2129
  var WorkflowRuntimeEngine = class {
1623
2130
  constructor(service) {
2131
+ this.validation = service.Validation;
1624
2132
  this.executor = service.Executor;
1625
2133
  }
1626
2134
  invoke(params) {
1627
2135
  const context = WorkflowRuntimeContext.create();
1628
2136
  context.init(params);
2137
+ const valid = this.validate(params, context);
2138
+ if (!valid) {
2139
+ return WorkflowRuntimeTask.create({
2140
+ processing: Promise.resolve({}),
2141
+ context
2142
+ });
2143
+ }
1629
2144
  const processing = this.process(context);
1630
2145
  processing.then(() => {
1631
2146
  context.dispose();
@@ -1641,11 +2156,14 @@ var WorkflowRuntimeEngine = class {
1641
2156
  return;
1642
2157
  }
1643
2158
  context.statusCenter.nodeStatus(node.id).process();
2159
+ const snapshot = context.snapshotCenter.create({
2160
+ nodeID: node.id,
2161
+ data: node.data
2162
+ });
2163
+ let nextNodes = [];
1644
2164
  try {
1645
2165
  const inputs = context.state.getNodeInputs(node);
1646
- const snapshot = context.snapshotCenter.create({
1647
- nodeID: node.id,
1648
- data: node.data,
2166
+ snapshot.update({
1649
2167
  inputs
1650
2168
  });
1651
2169
  const result = await this.executor.execute({
@@ -1658,17 +2176,23 @@ var WorkflowRuntimeEngine = class {
1658
2176
  return;
1659
2177
  }
1660
2178
  const { outputs, branch } = result;
1661
- snapshot.addData({ outputs, branch });
2179
+ snapshot.update({ outputs, branch });
1662
2180
  context.state.setNodeOutputs({ node, outputs });
1663
2181
  context.state.addExecutedNode(node);
1664
2182
  context.statusCenter.nodeStatus(node.id).success();
1665
- const nextNodes = this.getNextNodes({ node, branch, context });
1666
- await this.executeNext({ node, nextNodes, context });
2183
+ nextNodes = this.getNextNodes({ node, branch, context });
1667
2184
  } catch (e) {
2185
+ const errorMessage = e instanceof Error ? e.message : "An unknown error occurred";
2186
+ snapshot.update({ error: errorMessage });
2187
+ context.messageCenter.error({
2188
+ nodeID: node.id,
2189
+ message: errorMessage
2190
+ });
1668
2191
  context.statusCenter.nodeStatus(node.id).fail();
1669
2192
  console.error(e);
1670
- return;
2193
+ throw e;
1671
2194
  }
2195
+ await this.executeNext({ node, nextNodes, context });
1672
2196
  }
1673
2197
  async process(context) {
1674
2198
  const startNode = context.document.start;
@@ -1680,8 +2204,21 @@ var WorkflowRuntimeEngine = class {
1680
2204
  return outputs;
1681
2205
  } catch (e) {
1682
2206
  context.statusCenter.workflow.fail();
1683
- throw e;
2207
+ return {};
2208
+ }
2209
+ }
2210
+ validate(params, context) {
2211
+ const { valid, errors } = this.validation.invoke(params);
2212
+ if (valid) {
2213
+ return true;
1684
2214
  }
2215
+ errors?.forEach((message) => {
2216
+ context.messageCenter.error({
2217
+ message
2218
+ });
2219
+ });
2220
+ context.statusCenter.workflow.fail();
2221
+ return false;
1685
2222
  }
1686
2223
  canExecuteNode(params) {
1687
2224
  const { node, context } = params;
@@ -1704,8 +2241,11 @@ var WorkflowRuntimeEngine = class {
1704
2241
  const nextNodeIDs = new Set(targetPort.edges.map((edge) => edge.to.id));
1705
2242
  const nextNodes = allNextNodes.filter((nextNode) => nextNodeIDs.has(nextNode.id));
1706
2243
  const skipNodes = allNextNodes.filter((nextNode) => !nextNodeIDs.has(nextNode.id));
1707
- skipNodes.forEach((skipNode) => {
1708
- context.state.addExecutedNode(skipNode);
2244
+ const nextGroups = nextNodes.map((nextNode) => [nextNode, ...nextNode.successors]);
2245
+ const skipGroups = skipNodes.map((skipNode) => [skipNode, ...skipNode.successors]);
2246
+ const { uniqueToB: skippedNodes } = compareNodeGroups(nextGroups, skipGroups);
2247
+ skippedNodes.forEach((node2) => {
2248
+ context.state.addExecutedNode(node2);
1709
2249
  });
1710
2250
  return nextNodes;
1711
2251
  }
@@ -1748,6 +2288,7 @@ var WorkflowRuntimeContainer = class _WorkflowRuntimeContainer {
1748
2288
  const Validation = new WorkflowRuntimeValidation();
1749
2289
  const Executor = new WorkflowRuntimeExecutor(WorkflowRuntimeNodeExecutors);
1750
2290
  const Engine = new WorkflowRuntimeEngine({
2291
+ Validation,
1751
2292
  Executor
1752
2293
  });
1753
2294
  return {
@@ -1804,6 +2345,12 @@ var WorkflowApplication = class _WorkflowApplication {
1804
2345
  }
1805
2346
  return task.context.ioCenter.outputs;
1806
2347
  }
2348
+ validate(params) {
2349
+ const validation = this.container.get(IValidation);
2350
+ const result = validation.invoke(params);
2351
+ console.log("> POST TaskValidate - valid: ", result.valid);
2352
+ return result;
2353
+ }
1807
2354
  static get instance() {
1808
2355
  if (this._instance) {
1809
2356
  return this._instance;
@@ -1813,6 +2360,19 @@ var WorkflowApplication = class _WorkflowApplication {
1813
2360
  }
1814
2361
  };
1815
2362
 
2363
+ // src/api/task-validate.ts
2364
+ var TaskValidateAPI = async (input) => {
2365
+ const app = WorkflowApplication.instance;
2366
+ const { schema: stringSchema, inputs } = input;
2367
+ const schema = JSON.parse(stringSchema);
2368
+ const result = app.validate({
2369
+ schema,
2370
+ inputs
2371
+ });
2372
+ const output = result;
2373
+ return output;
2374
+ };
2375
+
1816
2376
  // src/api/task-run.ts
1817
2377
  var TaskRunAPI = async (input) => {
1818
2378
  const app = WorkflowApplication.instance;
@@ -1863,22 +2423,21 @@ var TaskCancelAPI = async (input) => {
1863
2423
 
1864
2424
  // src/api/index.ts
1865
2425
  var WorkflowRuntimeAPIs = {
2426
+ [FlowGramAPIName.ServerInfo]: () => {
2427
+ },
2428
+ // TODO
1866
2429
  [FlowGramAPIName.TaskRun]: TaskRunAPI,
1867
2430
  [FlowGramAPIName.TaskReport]: TaskReportAPI,
1868
2431
  [FlowGramAPIName.TaskResult]: TaskResultAPI,
1869
2432
  [FlowGramAPIName.TaskCancel]: TaskCancelAPI,
1870
- [FlowGramAPIName.ServerInfo]: () => {
1871
- },
1872
- // TODO
1873
- [FlowGramAPIName.Validation]: () => {
1874
- }
1875
- // TODO
2433
+ [FlowGramAPIName.TaskValidate]: TaskValidateAPI
1876
2434
  };
1877
2435
  export {
1878
2436
  TaskCancelAPI,
1879
2437
  TaskReportAPI,
1880
2438
  TaskResultAPI,
1881
2439
  TaskRunAPI,
2440
+ TaskValidateAPI,
1882
2441
  WorkflowRuntimeAPIs
1883
2442
  };
1884
2443
  //# sourceMappingURL=index.js.map