@qualitas-id/mcp 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +262 -0
  3. package/dist/constants.d.ts +18 -0
  4. package/dist/constants.d.ts.map +1 -0
  5. package/dist/constants.js +18 -0
  6. package/dist/constants.js.map +1 -0
  7. package/dist/index.d.ts +10 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +82 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/schemas/common.d.ts +20 -0
  12. package/dist/schemas/common.d.ts.map +1 -0
  13. package/dist/schemas/common.js +10 -0
  14. package/dist/schemas/common.js.map +1 -0
  15. package/dist/schemas/flow.d.ts +358 -0
  16. package/dist/schemas/flow.d.ts.map +1 -0
  17. package/dist/schemas/flow.js +72 -0
  18. package/dist/schemas/flow.js.map +1 -0
  19. package/dist/schemas/project.d.ts +70 -0
  20. package/dist/schemas/project.d.ts.map +1 -0
  21. package/dist/schemas/project.js +26 -0
  22. package/dist/schemas/project.js.map +1 -0
  23. package/dist/schemas/run.d.ts +54 -0
  24. package/dist/schemas/run.d.ts.map +1 -0
  25. package/dist/schemas/run.js +20 -0
  26. package/dist/schemas/run.js.map +1 -0
  27. package/dist/schemas/variable.d.ts +91 -0
  28. package/dist/schemas/variable.d.ts.map +1 -0
  29. package/dist/schemas/variable.js +30 -0
  30. package/dist/schemas/variable.js.map +1 -0
  31. package/dist/services/api-client.d.ts +101 -0
  32. package/dist/services/api-client.d.ts.map +1 -0
  33. package/dist/services/api-client.js +184 -0
  34. package/dist/services/api-client.js.map +1 -0
  35. package/dist/services/flow-generator.d.ts +31 -0
  36. package/dist/services/flow-generator.d.ts.map +1 -0
  37. package/dist/services/flow-generator.js +638 -0
  38. package/dist/services/flow-generator.js.map +1 -0
  39. package/dist/shared-types.d.ts +579 -0
  40. package/dist/shared-types.d.ts.map +1 -0
  41. package/dist/shared-types.js +12 -0
  42. package/dist/shared-types.js.map +1 -0
  43. package/dist/tools/flows.d.ts +13 -0
  44. package/dist/tools/flows.d.ts.map +1 -0
  45. package/dist/tools/flows.js +458 -0
  46. package/dist/tools/flows.js.map +1 -0
  47. package/dist/tools/projects.d.ts +13 -0
  48. package/dist/tools/projects.d.ts.map +1 -0
  49. package/dist/tools/projects.js +381 -0
  50. package/dist/tools/projects.js.map +1 -0
  51. package/dist/tools/runs.d.ts +9 -0
  52. package/dist/tools/runs.d.ts.map +1 -0
  53. package/dist/tools/runs.js +342 -0
  54. package/dist/tools/runs.js.map +1 -0
  55. package/dist/tools/utils.d.ts +12 -0
  56. package/dist/tools/utils.d.ts.map +1 -0
  57. package/dist/tools/utils.js +144 -0
  58. package/dist/tools/utils.js.map +1 -0
  59. package/dist/tools/variables.d.ts +9 -0
  60. package/dist/tools/variables.d.ts.map +1 -0
  61. package/dist/tools/variables.js +316 -0
  62. package/dist/tools/variables.js.map +1 -0
  63. package/dist/types.d.ts +117 -0
  64. package/dist/types.d.ts.map +1 -0
  65. package/dist/types.js +8 -0
  66. package/dist/types.js.map +1 -0
  67. package/dist/utils/flow-layout.d.ts +34 -0
  68. package/dist/utils/flow-layout.d.ts.map +1 -0
  69. package/dist/utils/flow-layout.js +109 -0
  70. package/dist/utils/flow-layout.js.map +1 -0
  71. package/dist/utils/flow-validation.d.ts +74 -0
  72. package/dist/utils/flow-validation.d.ts.map +1 -0
  73. package/dist/utils/flow-validation.js +386 -0
  74. package/dist/utils/flow-validation.js.map +1 -0
  75. package/dist/utils/ocr.d.ts +25 -0
  76. package/dist/utils/ocr.d.ts.map +1 -0
  77. package/dist/utils/ocr.js +88 -0
  78. package/dist/utils/ocr.js.map +1 -0
  79. package/package.json +65 -0
  80. package/skills/qualitas.md +253 -0
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Flow Validation Utilities
3
+ *
4
+ * Validates flow structure, node inputs, and connections.
5
+ * Ported from front-end/src/features/flows/utils/flow-validation.ts
6
+ */
7
+ interface ValidationNode {
8
+ id: string;
9
+ type: string;
10
+ data: Record<string, unknown>;
11
+ position: {
12
+ x: number;
13
+ y: number;
14
+ };
15
+ }
16
+ interface ValidationEdge {
17
+ id: string;
18
+ source: string;
19
+ target: string;
20
+ sourceHandle?: string;
21
+ targetHandle?: string;
22
+ }
23
+ interface ValidationResult {
24
+ isValid: boolean;
25
+ error?: {
26
+ title: string;
27
+ description: string;
28
+ };
29
+ }
30
+ interface NodeInputValidationResult {
31
+ isValid: boolean;
32
+ errors: {
33
+ nodeId: string;
34
+ nodeName: string;
35
+ missingFields: string[];
36
+ }[];
37
+ }
38
+ /**
39
+ * Validate flow structure before saving/running.
40
+ *
41
+ * Rules:
42
+ * 1. Flow MUST start with a 'start' OR 'schedule' node
43
+ * 2. The immediate next node after root MUST be navigate/callFragment/apiCall/generateEmail/ifCondition/loop
44
+ */
45
+ export declare function validateFlowStructure(nodes: ValidationNode[], edges: ValidationEdge[]): ValidationResult;
46
+ /**
47
+ * Validate fragment structure.
48
+ *
49
+ * Rules:
50
+ * 1. Fragment must have at least one action node
51
+ * 2. Fragment CANNOT contain start, schedule, or callFragment nodes
52
+ */
53
+ export declare function validateFragmentStructure(nodes: ValidationNode[], edges: ValidationEdge[]): ValidationResult;
54
+ /**
55
+ * Validate structure based on flow type
56
+ */
57
+ export declare function validateStructure(nodes: ValidationNode[], edges: ValidationEdge[], flowType: "flow" | "fragment"): ValidationResult;
58
+ /**
59
+ * Validate that all nodes have their required inputs filled
60
+ */
61
+ export declare function validateNodeInputs(nodes: ValidationNode[]): NodeInputValidationResult;
62
+ /**
63
+ * Validate that all nodes are properly connected
64
+ */
65
+ export declare function validateNodeConnections(nodes: ValidationNode[], edges: ValidationEdge[], flowType?: "flow" | "fragment"): ValidationResult;
66
+ /**
67
+ * Run all validations on a flow
68
+ */
69
+ export declare function validateFlow(nodes: ValidationNode[], edges: ValidationEdge[], flowType?: "flow" | "fragment"): {
70
+ isValid: boolean;
71
+ errors: string[];
72
+ };
73
+ export {};
74
+ //# sourceMappingURL=flow-validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-validation.d.ts","sourceRoot":"","sources":["../../src/utils/flow-validation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,UAAU,cAAc;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,QAAQ,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACpC;AAED,UAAU,cAAc;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,gBAAgB;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAED,UAAU,yBAAyB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE;QACN,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,aAAa,EAAE,MAAM,EAAE,CAAC;KACzB,EAAE,CAAC;CACL;AAiGD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,cAAc,EAAE,EACvB,KAAK,EAAE,cAAc,EAAE,GACtB,gBAAgB,CA6DlB;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,cAAc,EAAE,EACvB,KAAK,EAAE,cAAc,EAAE,GACtB,gBAAgB,CA4BlB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,cAAc,EAAE,EACvB,KAAK,EAAE,cAAc,EAAE,EACvB,QAAQ,EAAE,MAAM,GAAG,UAAU,GAC5B,gBAAgB,CAKlB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,yBAAyB,CA4DrF;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,cAAc,EAAE,EACvB,KAAK,EAAE,cAAc,EAAE,EACvB,QAAQ,GAAE,MAAM,GAAG,UAAmB,GACrC,gBAAgB,CAuGlB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,cAAc,EAAE,EACvB,KAAK,EAAE,cAAc,EAAE,EACvB,QAAQ,GAAE,MAAM,GAAG,UAAmB,GACrC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CA2BxC"}
@@ -0,0 +1,386 @@
1
+ /**
2
+ * Flow Validation Utilities
3
+ *
4
+ * Validates flow structure, node inputs, and connections.
5
+ * Ported from front-end/src/features/flows/utils/flow-validation.ts
6
+ */
7
+ // ===========================================
8
+ // Constants
9
+ // ===========================================
10
+ const ROOT_NODE_TYPES = ["start", "schedule"];
11
+ const VALID_FIRST_STEP_TYPES = ["navigate", "callFragment", "apiCall", "generateEmail", "ifCondition", "loop"];
12
+ const FORBIDDEN_FRAGMENT_NODE_TYPES = ["start", "schedule", "callFragment"];
13
+ // Required fields by node type
14
+ const nodeRequiredFields = {
15
+ navigate: [{ key: "url", label: "URL" }],
16
+ click: [{ key: "selector", label: "CSS Selector" }],
17
+ dblclick: [{ key: "selector", label: "CSS Selector" }],
18
+ rightclick: [{ key: "selector", label: "CSS Selector" }],
19
+ hover: [{ key: "selector", label: "CSS Selector" }],
20
+ dragAndDrop: [
21
+ { key: "sourceSelector", label: "Source Selector" },
22
+ { key: "targetSelector", label: "Target Selector" },
23
+ ],
24
+ type: [
25
+ { key: "selector", label: "CSS Selector" },
26
+ { key: "text", label: "Text to Type" },
27
+ ],
28
+ fill: [
29
+ { key: "selector", label: "CSS Selector" },
30
+ { key: "text", label: "Value" },
31
+ ],
32
+ clear: [{ key: "selector", label: "CSS Selector" }],
33
+ press: [{ key: "key", label: "Key" }],
34
+ submit: [{ key: "selector", label: "Form Selector" }],
35
+ check: [{ key: "selector", label: "Checkbox Selector" }],
36
+ uncheck: [{ key: "selector", label: "Checkbox Selector" }],
37
+ select: [
38
+ { key: "selector", label: "Select Selector" },
39
+ { key: "value", label: "Option Value" },
40
+ ],
41
+ upload: [
42
+ { key: "selector", label: "File Input Selector" },
43
+ { key: "filePath", label: "File Path" },
44
+ ],
45
+ focus: [{ key: "selector", label: "CSS Selector" }],
46
+ blur: [{ key: "selector", label: "CSS Selector" }],
47
+ scrollIntoView: [{ key: "selector", label: "CSS Selector" }],
48
+ wait: [{ key: "duration", label: "Duration" }],
49
+ waitForElement: [{ key: "selector", label: "CSS Selector" }],
50
+ waitForResponse: [{ key: "urlPattern", label: "URL Pattern" }],
51
+ assertVisible: [{ key: "selector", label: "CSS Selector" }],
52
+ assertText: [
53
+ { key: "selector", label: "CSS Selector" },
54
+ { key: "expectedText", label: "Expected Text" },
55
+ ],
56
+ assertValue: [
57
+ { key: "selector", label: "CSS Selector" },
58
+ { key: "expectedValue", label: "Expected Value" },
59
+ ],
60
+ assertVariable: [
61
+ { key: "leftValue", label: "Left Value" },
62
+ { key: "rightValue", label: "Right Value" },
63
+ ],
64
+ assertTableCell: [
65
+ { key: "tableSelector", label: "Table Selector" },
66
+ { key: "findColumnName", label: "Find Row Column" },
67
+ { key: "findValue", label: "Find Row Value" },
68
+ { key: "assertColumnName", label: "Assert Column" },
69
+ { key: "expectedValue", label: "Expected Value" },
70
+ ],
71
+ assertCount: [
72
+ { key: "selector", label: "CSS Selector" },
73
+ { key: "expectedValue", label: "Expected Value" },
74
+ ],
75
+ assertUrl: [{ key: "expectedUrl", label: "Expected URL" }],
76
+ assertTitle: [{ key: "expectedTitle", label: "Expected Title" }],
77
+ schedule: [{ key: "cron", label: "Cron Expression" }],
78
+ callFragment: [{ key: "fragmentId", label: "Fragment" }],
79
+ generateEmail: [{ key: "emailName", label: "Alias Name" }],
80
+ readEmail: [
81
+ { key: "generatedFrom", label: "Generated Email Reference" },
82
+ { key: "outputKey", label: "Saved Result Name" },
83
+ ],
84
+ extractEmail: [
85
+ { key: "readSourceNodeId", label: "Read Email Source" },
86
+ { key: "variableName", label: "Save Match As" },
87
+ ],
88
+ extractFromElement: [
89
+ { key: "selector", label: "Selector" },
90
+ { key: "saveAs", label: "Save As" },
91
+ ],
92
+ ifCondition: [{ key: "saveResultAs", label: "Save Result As" }],
93
+ loop: [{ key: "loopVariableName", label: "Loop Variable Name" }],
94
+ };
95
+ // ===========================================
96
+ // Validation Functions
97
+ // ===========================================
98
+ /**
99
+ * Validate flow structure before saving/running.
100
+ *
101
+ * Rules:
102
+ * 1. Flow MUST start with a 'start' OR 'schedule' node
103
+ * 2. The immediate next node after root MUST be navigate/callFragment/apiCall/generateEmail/ifCondition/loop
104
+ */
105
+ export function validateFlowStructure(nodes, edges) {
106
+ // Rule 1: Check for root node
107
+ const rootNode = nodes.find((node) => ROOT_NODE_TYPES.includes(node.type));
108
+ if (!rootNode) {
109
+ return {
110
+ isValid: false,
111
+ error: {
112
+ title: "Invalid Flow Structure",
113
+ description: "Flow must start with a Start or Schedule node.",
114
+ },
115
+ };
116
+ }
117
+ // Check if there are nodes beyond root
118
+ if (nodes.length === 1) {
119
+ return {
120
+ isValid: false,
121
+ error: {
122
+ title: "Incomplete Flow",
123
+ description: "Flow must have at least one action after the Start node.",
124
+ },
125
+ };
126
+ }
127
+ // Rule 2: Check first step after root
128
+ const outgoingEdge = edges.find((edge) => edge.source === rootNode.id);
129
+ if (!outgoingEdge) {
130
+ return {
131
+ isValid: false,
132
+ error: {
133
+ title: "Disconnected Start Node",
134
+ description: "Start node must be connected to a Navigate node.",
135
+ },
136
+ };
137
+ }
138
+ const firstStepNode = nodes.find((node) => node.id === outgoingEdge.target);
139
+ if (!firstStepNode) {
140
+ return {
141
+ isValid: false,
142
+ error: {
143
+ title: "Invalid Connection",
144
+ description: "The connection from Start node leads to an invalid node.",
145
+ },
146
+ };
147
+ }
148
+ if (!VALID_FIRST_STEP_TYPES.includes(firstStepNode.type)) {
149
+ return {
150
+ isValid: false,
151
+ error: {
152
+ title: "Invalid Flow Structure",
153
+ description: `First step after Start must be Navigate, Call Fragment, API Call, Generate Email, If Condition, or Loop. Currently connected to: ${firstStepNode.type}`,
154
+ },
155
+ };
156
+ }
157
+ return { isValid: true };
158
+ }
159
+ /**
160
+ * Validate fragment structure.
161
+ *
162
+ * Rules:
163
+ * 1. Fragment must have at least one action node
164
+ * 2. Fragment CANNOT contain start, schedule, or callFragment nodes
165
+ */
166
+ export function validateFragmentStructure(nodes, edges) {
167
+ void edges;
168
+ if (nodes.length === 0) {
169
+ return {
170
+ isValid: false,
171
+ error: {
172
+ title: "Empty Fragment",
173
+ description: "Fragment must have at least one action node.",
174
+ },
175
+ };
176
+ }
177
+ const forbiddenNode = nodes.find((node) => FORBIDDEN_FRAGMENT_NODE_TYPES.includes(node.type));
178
+ if (forbiddenNode) {
179
+ return {
180
+ isValid: false,
181
+ error: {
182
+ title: "Invalid Fragment Structure",
183
+ description: `Fragments cannot contain ${forbiddenNode.type} nodes. Remove the ${forbiddenNode.type} node to continue.`,
184
+ },
185
+ };
186
+ }
187
+ return { isValid: true };
188
+ }
189
+ /**
190
+ * Validate structure based on flow type
191
+ */
192
+ export function validateStructure(nodes, edges, flowType) {
193
+ if (flowType === "fragment") {
194
+ return validateFragmentStructure(nodes, edges);
195
+ }
196
+ return validateFlowStructure(nodes, edges);
197
+ }
198
+ /**
199
+ * Validate that all nodes have their required inputs filled
200
+ */
201
+ export function validateNodeInputs(nodes) {
202
+ const errors = [];
203
+ for (const node of nodes) {
204
+ const requiredFields = nodeRequiredFields[node.type];
205
+ if (!requiredFields)
206
+ continue;
207
+ const data = node.data;
208
+ const missingFields = [];
209
+ for (const field of requiredFields) {
210
+ let value = data[field.key];
211
+ // For selector fields, check selectorEntries first
212
+ if (field.key === "selector") {
213
+ const entries = data.selectorEntries;
214
+ if (entries && Array.isArray(entries) && entries.length > 0) {
215
+ const hasValue = entries.some((e) => e.value && e.value.trim());
216
+ if (hasValue)
217
+ continue;
218
+ value = "";
219
+ }
220
+ else {
221
+ const importedSelectors = data.selectors;
222
+ if (importedSelectors && Array.isArray(importedSelectors) && importedSelectors.some((s) => typeof s === "string" && s.trim())) {
223
+ continue;
224
+ }
225
+ }
226
+ }
227
+ else {
228
+ const fallbackValue = typeof data.value === "string" ? data.value : "";
229
+ const fallbackText = typeof data.text === "string" ? data.text : "";
230
+ if ((field.key === "url" || field.key === "expectedUrl") && !value)
231
+ value = fallbackValue || fallbackText;
232
+ if ((field.key === "text" || field.key === "expectedText") && !value)
233
+ value = fallbackValue;
234
+ if ((field.key === "value" || field.key === "expectedValue") && !value)
235
+ value = fallbackText || fallbackValue;
236
+ if (field.key === "key" && !value)
237
+ value = fallbackValue;
238
+ }
239
+ // Check if field is missing, empty string, or just whitespace
240
+ if (value === undefined || value === null || value === "") {
241
+ missingFields.push(field.label);
242
+ }
243
+ else if (typeof value === "string" && value.trim() === "") {
244
+ missingFields.push(field.label);
245
+ }
246
+ else if (typeof value === "number" && (isNaN(value) || value <= 0)) {
247
+ if (field.key === "duration") {
248
+ missingFields.push(field.label);
249
+ }
250
+ }
251
+ }
252
+ if (missingFields.length > 0) {
253
+ errors.push({
254
+ nodeId: node.id,
255
+ nodeName: node.type,
256
+ missingFields,
257
+ });
258
+ }
259
+ }
260
+ return {
261
+ isValid: errors.length === 0,
262
+ errors,
263
+ };
264
+ }
265
+ /**
266
+ * Validate that all nodes are properly connected
267
+ */
268
+ export function validateNodeConnections(nodes, edges, flowType = "flow") {
269
+ const nodesWithIncoming = new Set(edges.map((e) => e.target));
270
+ const nodesWithOutgoing = new Set(edges.map((e) => e.source));
271
+ const disconnectedNodes = [];
272
+ const unreachableNodes = [];
273
+ let fragmentEntryCount = 0;
274
+ for (const node of nodes) {
275
+ const isRootNode = ROOT_NODE_TYPES.includes(node.type);
276
+ const hasIncoming = nodesWithIncoming.has(node.id);
277
+ const hasOutgoing = nodesWithOutgoing.has(node.id);
278
+ // Check ifCondition has then branch
279
+ if (node.type === "ifCondition") {
280
+ const outgoingEdges = edges.filter((edge) => edge.source === node.id);
281
+ const hasThenBranch = outgoingEdges.some((edge) => {
282
+ const handle = (edge.sourceHandle || "").trim().toLowerCase();
283
+ return handle === "then";
284
+ });
285
+ if (!hasThenBranch) {
286
+ return {
287
+ isValid: false,
288
+ error: {
289
+ title: "If Condition Incomplete",
290
+ description: "If Condition node must have a Then connection.",
291
+ },
292
+ };
293
+ }
294
+ }
295
+ // Check loop has loop branch
296
+ if (node.type === "loop") {
297
+ const outgoingEdges = edges.filter((edge) => edge.source === node.id);
298
+ const hasLoopBranch = outgoingEdges.some((edge) => {
299
+ const handle = (edge.sourceHandle || "").trim().toLowerCase();
300
+ return handle === "loop";
301
+ });
302
+ if (!hasLoopBranch) {
303
+ return {
304
+ isValid: false,
305
+ error: {
306
+ title: "Loop Incomplete",
307
+ description: "Loop node must have a Loop branch connection.",
308
+ },
309
+ };
310
+ }
311
+ }
312
+ if (isRootNode)
313
+ continue;
314
+ // Fragment entry navigate check
315
+ const isFragmentEntryNavigate = flowType === "fragment" &&
316
+ node.type === "navigate" &&
317
+ !hasIncoming;
318
+ if (isFragmentEntryNavigate) {
319
+ fragmentEntryCount += 1;
320
+ continue;
321
+ }
322
+ // Check disconnected nodes
323
+ if (!hasIncoming && !hasOutgoing) {
324
+ disconnectedNodes.push(node.type);
325
+ }
326
+ else if (!hasIncoming) {
327
+ unreachableNodes.push(node.type);
328
+ }
329
+ }
330
+ if (flowType === "fragment" && fragmentEntryCount > 1) {
331
+ return {
332
+ isValid: false,
333
+ error: {
334
+ title: "Invalid Fragment Entry",
335
+ description: "Fragments can only have one entry Navigate node without incoming connections.",
336
+ },
337
+ };
338
+ }
339
+ if (disconnectedNodes.length > 0) {
340
+ return {
341
+ isValid: false,
342
+ error: {
343
+ title: "Disconnected Nodes Found",
344
+ description: `The following nodes are not connected to the flow: ${disconnectedNodes.join(", ")}.`,
345
+ },
346
+ };
347
+ }
348
+ if (unreachableNodes.length > 0) {
349
+ return {
350
+ isValid: false,
351
+ error: {
352
+ title: "Unreachable Nodes Found",
353
+ description: `The following nodes will never execute: ${unreachableNodes.join(", ")}.`,
354
+ },
355
+ };
356
+ }
357
+ return { isValid: true };
358
+ }
359
+ /**
360
+ * Run all validations on a flow
361
+ */
362
+ export function validateFlow(nodes, edges, flowType = "flow") {
363
+ const errors = [];
364
+ // 1. Structure validation
365
+ const structureResult = validateStructure(nodes, edges, flowType);
366
+ if (!structureResult.isValid && structureResult.error) {
367
+ errors.push(`${structureResult.error.title}: ${structureResult.error.description}`);
368
+ }
369
+ // 2. Node input validation
370
+ const inputResult = validateNodeInputs(nodes);
371
+ if (!inputResult.isValid) {
372
+ for (const err of inputResult.errors) {
373
+ errors.push(`Node "${err.nodeName}" (${err.nodeId}): Missing ${err.missingFields.join(", ")}`);
374
+ }
375
+ }
376
+ // 3. Connection validation
377
+ const connectionResult = validateNodeConnections(nodes, edges, flowType);
378
+ if (!connectionResult.isValid && connectionResult.error) {
379
+ errors.push(`${connectionResult.error.title}: ${connectionResult.error.description}`);
380
+ }
381
+ return {
382
+ isValid: errors.length === 0,
383
+ errors,
384
+ };
385
+ }
386
+ //# sourceMappingURL=flow-validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-validation.js","sourceRoot":"","sources":["../../src/utils/flow-validation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * OCR Utility
3
+ *
4
+ * Extract text from images using Tesseract.js
5
+ * Used for reading error messages from test screenshots
6
+ */
7
+ export interface OcrResult {
8
+ text: string;
9
+ confidence: number;
10
+ error?: string;
11
+ }
12
+ /**
13
+ * Extract text from an image URL
14
+ */
15
+ export declare function extractTextFromImageUrl(imageUrl: string): Promise<OcrResult>;
16
+ /**
17
+ * Extract text from an image buffer
18
+ */
19
+ export declare function extractTextFromBuffer(imageBuffer: Buffer): Promise<OcrResult>;
20
+ /**
21
+ * Extract error message from screenshot text
22
+ * Looks for common error patterns
23
+ */
24
+ export declare function extractErrorMessage(ocrText: string): string | null;
25
+ //# sourceMappingURL=ocr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ocr.d.ts","sourceRoot":"","sources":["../../src/utils/ocr.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAiBlF;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAiBnF;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAuClE"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * OCR Utility
3
+ *
4
+ * Extract text from images using Tesseract.js
5
+ * Used for reading error messages from test screenshots
6
+ */
7
+ import Tesseract from "tesseract.js";
8
+ /**
9
+ * Extract text from an image URL
10
+ */
11
+ export async function extractTextFromImageUrl(imageUrl) {
12
+ try {
13
+ const result = await Tesseract.recognize(imageUrl, "eng", {
14
+ logger: () => { }, // Suppress progress logs
15
+ });
16
+ return {
17
+ text: result.data.text.trim(),
18
+ confidence: result.data.confidence,
19
+ };
20
+ }
21
+ catch (error) {
22
+ return {
23
+ text: "",
24
+ confidence: 0,
25
+ error: `OCR failed: ${error instanceof Error ? error.message : String(error)}`,
26
+ };
27
+ }
28
+ }
29
+ /**
30
+ * Extract text from an image buffer
31
+ */
32
+ export async function extractTextFromBuffer(imageBuffer) {
33
+ try {
34
+ const result = await Tesseract.recognize(imageBuffer, "eng", {
35
+ logger: () => { },
36
+ });
37
+ return {
38
+ text: result.data.text.trim(),
39
+ confidence: result.data.confidence,
40
+ };
41
+ }
42
+ catch (error) {
43
+ return {
44
+ text: "",
45
+ confidence: 0,
46
+ error: `OCR failed: ${error instanceof Error ? error.message : String(error)}`,
47
+ };
48
+ }
49
+ }
50
+ /**
51
+ * Extract error message from screenshot text
52
+ * Looks for common error patterns
53
+ */
54
+ export function extractErrorMessage(ocrText) {
55
+ const lines = ocrText.split("\n").map((line) => line.trim()).filter(Boolean);
56
+ // Common error patterns
57
+ const errorPatterns = [
58
+ /error[:\s]+(.+)/i,
59
+ /failed[:\s]+(.+)/i,
60
+ /exception[:\s]+(.+)/i,
61
+ /cannot[:\s]+(.+)/i,
62
+ /unable to[:\s]+(.+)/i,
63
+ /invalid[:\s]+(.+)/i,
64
+ /missing[:\s]+(.+)/i,
65
+ /required[:\s]+(.+)/i,
66
+ /not found[:\s]+(.+)/i,
67
+ /timeout[:\s]+(.+)/i,
68
+ /denied[:\s]+(.+)/i,
69
+ /rejected[:\s]+(.+)/i,
70
+ /warning[:\s]+(.+)/i,
71
+ ];
72
+ for (const line of lines) {
73
+ for (const pattern of errorPatterns) {
74
+ const match = line.match(pattern);
75
+ if (match) {
76
+ return match[0]; // Return the full matched line
77
+ }
78
+ }
79
+ }
80
+ // If no pattern matches, return first non-empty line that looks like an error
81
+ const suspiciousLines = lines.filter((line) => line.length > 10 &&
82
+ line.length < 500 &&
83
+ !line.match(/^[©®™]/) && // Skip copyright symbols
84
+ !line.match(/^\d+$/) // Skip pure numbers
85
+ );
86
+ return suspiciousLines[0] || null;
87
+ }
88
+ //# sourceMappingURL=ocr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ocr.js","sourceRoot":"","sources":["../../src/utils/ocr.ts"],"names":[],"mappings":"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"}