@minded-ai/mindedjs 3.0.5 → 3.0.6-beta.1

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/cli/index.js CHANGED
@@ -39,6 +39,7 @@ const path = __importStar(require("path"));
39
39
  const logger_1 = require("../utils/logger");
40
40
  const child_process_1 = require("child_process");
41
41
  const localOperatorSetup_1 = require("./localOperatorSetup");
42
+ const validateFlow_1 = require("./validateFlow");
42
43
  const ENV_FILE = '.env';
43
44
  function getEnvFilePath() {
44
45
  return path.join(process.cwd(), ENV_FILE);
@@ -195,9 +196,13 @@ async function main() {
195
196
  process.exit(1);
196
197
  }
197
198
  }
199
+ else if (command === 'validate') {
200
+ // Command to validate a flow YAML file
201
+ (0, validateFlow_1.runValidateCommand)();
202
+ }
198
203
  else {
199
204
  logger_1.logger.error({
200
- msg: 'Unknown command. Available commands: token, setup-local-operator, check-local-operator, generate-lambda-ts-handler',
205
+ msg: 'Unknown command. Available commands: token, setup-local-operator, check-local-operator, generate-lambda-ts-handler, validate',
201
206
  });
202
207
  process.exit(1);
203
208
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ interface ValidationResult {
2
+ success: boolean;
3
+ flowName?: string;
4
+ stats?: {
5
+ nodes: number;
6
+ edges: number;
7
+ nodeTypes: string[];
8
+ edgeTypes: string[];
9
+ };
10
+ errors?: string[];
11
+ warnings?: string[];
12
+ message: string;
13
+ }
14
+ /**
15
+ * Validates a cron expression format using cron-parser.
16
+ * Cron format: minute hour day month day-of-week (5 fields)
17
+ */
18
+ export declare function validateCronExpression(cronExpression: string): {
19
+ valid: boolean;
20
+ error?: string;
21
+ };
22
+ /**
23
+ * Validates an IANA timezone identifier.
24
+ * Uses Intl.DateTimeFormat to check if the timezone is valid.
25
+ */
26
+ export declare function validateTimezone(timezone: string): {
27
+ valid: boolean;
28
+ error?: string;
29
+ };
30
+ /**
31
+ * Validates a schedule trigger node configuration.
32
+ * Returns an array of error messages (empty if valid).
33
+ */
34
+ export declare function validateScheduleTrigger(node: any, nodeIndex: string): {
35
+ errors: string[];
36
+ warnings: string[];
37
+ };
38
+ /**
39
+ * Validates a MindedJS YAML flow file.
40
+ */
41
+ export declare function validateFlow(flowPath: string): ValidationResult;
42
+ /**
43
+ * CLI command handler for validate
44
+ */
45
+ export declare function runValidateCommand(): void;
46
+ export {};
47
+ //# sourceMappingURL=validateFlow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validateFlow.d.ts","sourceRoot":"","sources":["../../src/cli/validateFlow.ts"],"names":[],"mappings":"AAKA,UAAU,gBAAgB;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,EAAE,CAAC;QACpB,SAAS,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;IACF,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,cAAc,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAcjG;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAiBrF;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,GAAG,EACT,SAAS,EAAE,MAAM,GAChB;IAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CA2B1C;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAwQ/D;AAiCD;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAoGzC"}
@@ -0,0 +1,454 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.validateCronExpression = validateCronExpression;
37
+ exports.validateTimezone = validateTimezone;
38
+ exports.validateScheduleTrigger = validateScheduleTrigger;
39
+ exports.validateFlow = validateFlow;
40
+ exports.runValidateCommand = runValidateCommand;
41
+ const fs = __importStar(require("fs"));
42
+ const path = __importStar(require("path"));
43
+ const yaml = __importStar(require("js-yaml"));
44
+ const cron_parser_1 = require("cron-parser");
45
+ /**
46
+ * Validates a cron expression format using cron-parser.
47
+ * Cron format: minute hour day month day-of-week (5 fields)
48
+ */
49
+ function validateCronExpression(cronExpression) {
50
+ if (typeof cronExpression !== 'string' || cronExpression.trim() === '') {
51
+ return { valid: false, error: 'Cron expression must be a non-empty string' };
52
+ }
53
+ try {
54
+ cron_parser_1.CronExpressionParser.parse(cronExpression.trim());
55
+ return { valid: true };
56
+ }
57
+ catch (error) {
58
+ return {
59
+ valid: false,
60
+ error: error instanceof Error ? error.message : 'Invalid cron expression format',
61
+ };
62
+ }
63
+ }
64
+ /**
65
+ * Validates an IANA timezone identifier.
66
+ * Uses Intl.DateTimeFormat to check if the timezone is valid.
67
+ */
68
+ function validateTimezone(timezone) {
69
+ if (typeof timezone !== 'string' || timezone.trim() === '') {
70
+ return { valid: false, error: 'Timezone must be a non-empty string' };
71
+ }
72
+ try {
73
+ // Try to create a date formatter with the timezone
74
+ const formatter = new Intl.DateTimeFormat('en-US', { timeZone: timezone });
75
+ // Test if the timezone is valid by trying to format a date
76
+ formatter.format(new Date());
77
+ return { valid: true };
78
+ }
79
+ catch (_a) {
80
+ return {
81
+ valid: false,
82
+ error: `Invalid IANA timezone identifier: "${timezone}"`,
83
+ };
84
+ }
85
+ }
86
+ /**
87
+ * Validates a schedule trigger node configuration.
88
+ * Returns an array of error messages (empty if valid).
89
+ */
90
+ function validateScheduleTrigger(node, nodeIndex) {
91
+ const errors = [];
92
+ const warnings = [];
93
+ if (!node.cronExpression) {
94
+ errors.push(`${nodeIndex} "${node.name}": schedule trigger missing required field "cronExpression"`);
95
+ }
96
+ else if (typeof node.cronExpression !== 'string') {
97
+ errors.push(`${nodeIndex} "${node.name}": schedule trigger "cronExpression" must be a string`);
98
+ }
99
+ else {
100
+ const cronValidation = validateCronExpression(node.cronExpression);
101
+ if (!cronValidation.valid) {
102
+ errors.push(`${nodeIndex} "${node.name}": invalid cron expression - ${cronValidation.error}`);
103
+ }
104
+ }
105
+ if (node.timezone !== undefined) {
106
+ if (typeof node.timezone !== 'string') {
107
+ errors.push(`${nodeIndex} "${node.name}": schedule trigger "timezone" must be a string`);
108
+ }
109
+ else {
110
+ const timezoneValidation = validateTimezone(node.timezone);
111
+ if (!timezoneValidation.valid) {
112
+ errors.push(`${nodeIndex} "${node.name}": ${timezoneValidation.error}`);
113
+ }
114
+ }
115
+ }
116
+ return { errors, warnings };
117
+ }
118
+ /**
119
+ * Validates a MindedJS YAML flow file.
120
+ */
121
+ function validateFlow(flowPath) {
122
+ // Resolve the path
123
+ const resolvedPath = path.isAbsolute(flowPath) ? flowPath : path.join(process.cwd(), flowPath);
124
+ // Read the file
125
+ let flowContent;
126
+ try {
127
+ flowContent = fs.readFileSync(resolvedPath, 'utf-8');
128
+ }
129
+ catch (error) {
130
+ return {
131
+ success: false,
132
+ message: `Failed to read file: ${error instanceof Error ? error.message : String(error)}`,
133
+ };
134
+ }
135
+ // Parse YAML
136
+ let flow;
137
+ try {
138
+ flow = yaml.load(flowContent);
139
+ }
140
+ catch (error) {
141
+ return {
142
+ success: false,
143
+ message: `Invalid YAML syntax: ${error instanceof Error ? error.message : String(error)}`,
144
+ };
145
+ }
146
+ // Validate flow structure
147
+ const errors = [];
148
+ const warnings = [];
149
+ // Check for required top-level fields
150
+ if (!flow.name) {
151
+ errors.push('Flow is missing required field: "name"');
152
+ }
153
+ if (!flow.nodes || !Array.isArray(flow.nodes)) {
154
+ errors.push('Flow is missing required field: "nodes" (must be an array)');
155
+ }
156
+ if (!flow.edges || !Array.isArray(flow.edges)) {
157
+ errors.push('Flow is missing required field: "edges" (must be an array)');
158
+ }
159
+ // If basic structure is invalid, return early
160
+ if (errors.length > 0) {
161
+ return {
162
+ success: false,
163
+ errors,
164
+ warnings,
165
+ message: `Flow validation failed with ${errors.length} error(s)`,
166
+ };
167
+ }
168
+ // Create a set of node names for validation
169
+ const nodeNames = new Set();
170
+ const nodesByName = new Map();
171
+ // Validate nodes
172
+ for (let i = 0; i < flow.nodes.length; i++) {
173
+ const node = flow.nodes[i];
174
+ const nodeIndex = `Node ${i + 1}`;
175
+ // Check for required name field
176
+ if (!node.name) {
177
+ errors.push(`${nodeIndex}: Missing required field "name"`);
178
+ continue;
179
+ }
180
+ // Check for duplicate node names
181
+ if (nodeNames.has(node.name)) {
182
+ errors.push(`${nodeIndex} "${node.name}": Duplicate node name`);
183
+ }
184
+ nodeNames.add(node.name);
185
+ nodesByName.set(node.name, node);
186
+ // Check for required type field
187
+ if (!node.type) {
188
+ errors.push(`${nodeIndex} "${node.name}": Missing required field "type"`);
189
+ continue;
190
+ }
191
+ // Validate node based on type
192
+ switch (node.type) {
193
+ case 'trigger':
194
+ if (!node.triggerType) {
195
+ errors.push(`${nodeIndex} "${node.name}": trigger node missing required field "triggerType"`);
196
+ }
197
+ else if (!['manual', 'app', 'webhook', 'schedule'].includes(node.triggerType)) {
198
+ errors.push(`${nodeIndex} "${node.name}": invalid triggerType "${node.triggerType}". Must be one of: manual, app, webhook, schedule`);
199
+ }
200
+ if (node.triggerType === 'app' && !node.appTriggerId) {
201
+ errors.push(`${nodeIndex} "${node.name}": app trigger missing required field "appTriggerId"`);
202
+ }
203
+ if (node.triggerType === 'schedule') {
204
+ const scheduleValidation = validateScheduleTrigger(node, nodeIndex);
205
+ errors.push(...scheduleValidation.errors);
206
+ warnings.push(...scheduleValidation.warnings);
207
+ }
208
+ break;
209
+ case 'promptNode':
210
+ if (!node.prompt) {
211
+ errors.push(`${nodeIndex} "${node.name}": promptNode missing required field "prompt"`);
212
+ }
213
+ if (!node.displayName || node.displayName.trim() === '') {
214
+ errors.push(`${nodeIndex} "${node.name}": promptNode missing required non-empty field "displayName"`);
215
+ }
216
+ if (node.llmConfig) {
217
+ if (!node.llmConfig.name) {
218
+ errors.push(`${nodeIndex} "${node.name}": llmConfig missing required field "name"`);
219
+ }
220
+ if (!node.llmConfig.properties) {
221
+ warnings.push(`${nodeIndex} "${node.name}": llmConfig missing "properties" field`);
222
+ }
223
+ }
224
+ break;
225
+ case 'thinking':
226
+ if (!node.prompt) {
227
+ errors.push(`${nodeIndex} "${node.name}": thinking node missing required field "prompt"`);
228
+ }
229
+ if (node.humanInTheLoop !== undefined) {
230
+ errors.push(`${nodeIndex} "${node.name}": thinking node does not support "humanInTheLoop" property (only prompt nodes support this)`);
231
+ }
232
+ if (node.canStayOnNode !== undefined) {
233
+ errors.push(`${nodeIndex} "${node.name}": thinking node does not support "canStayOnNode" property (only prompt nodes support this)`);
234
+ }
235
+ if (node.llmConfig) {
236
+ if (!node.llmConfig.name) {
237
+ errors.push(`${nodeIndex} "${node.name}": llmConfig missing required field "name"`);
238
+ }
239
+ if (!node.llmConfig.properties) {
240
+ warnings.push(`${nodeIndex} "${node.name}": llmConfig missing "properties" field`);
241
+ }
242
+ }
243
+ break;
244
+ case 'tool':
245
+ if (!node.toolName) {
246
+ errors.push(`${nodeIndex} "${node.name}": tool node missing required field "toolName"`);
247
+ }
248
+ break;
249
+ case 'junction':
250
+ // Junction only requires name and type, which we already checked
251
+ break;
252
+ case 'jumpToNode':
253
+ if (!node.targetNodeId) {
254
+ errors.push(`${nodeIndex} "${node.name}": jumpToNode missing required field "targetNodeId"`);
255
+ }
256
+ break;
257
+ case 'browserTask':
258
+ if (!node.prompt) {
259
+ errors.push(`${nodeIndex} "${node.name}": browserTask node missing required field "prompt"`);
260
+ }
261
+ break;
262
+ default:
263
+ warnings.push(`${nodeIndex} "${node.name}": unknown node type "${node.type}"`);
264
+ }
265
+ }
266
+ // Create a map to track which nodes have edges
267
+ const nodesWithEdges = new Set();
268
+ // Validate edges
269
+ for (let i = 0; i < flow.edges.length; i++) {
270
+ const edge = flow.edges[i];
271
+ const edgeIndex = `Edge ${i + 1}`;
272
+ // Check for required fields
273
+ if (!edge.source) {
274
+ errors.push(`${edgeIndex}: Missing required field "source"`);
275
+ continue;
276
+ }
277
+ if (!edge.target) {
278
+ errors.push(`${edgeIndex}: Missing required field "target"`);
279
+ continue;
280
+ }
281
+ if (!edge.type) {
282
+ errors.push(`${edgeIndex}: Missing required field "type"`);
283
+ continue;
284
+ }
285
+ // Track nodes that have edges
286
+ nodesWithEdges.add(edge.source);
287
+ nodesWithEdges.add(edge.target);
288
+ // Check if source and target nodes exist
289
+ if (!nodeNames.has(edge.source)) {
290
+ errors.push(`${edgeIndex}: source node "${edge.source}" does not exist`);
291
+ }
292
+ if (!nodeNames.has(edge.target)) {
293
+ errors.push(`${edgeIndex}: target node "${edge.target}" does not exist`);
294
+ }
295
+ // Validate edge based on type
296
+ switch (edge.type) {
297
+ case 'stepForward':
298
+ // stepForward only requires source, target, and type
299
+ break;
300
+ case 'promptCondition':
301
+ if (!edge.prompt) {
302
+ errors.push(`${edgeIndex}: promptCondition edge missing required field "prompt"`);
303
+ }
304
+ break;
305
+ case 'logicalCondition':
306
+ if (!edge.condition) {
307
+ errors.push(`${edgeIndex}: logicalCondition edge missing required field "condition"`);
308
+ }
309
+ break;
310
+ default:
311
+ warnings.push(`${edgeIndex}: unknown edge type "${edge.type}"`);
312
+ }
313
+ }
314
+ // Check for orphaned nodes (nodes without any edges)
315
+ // Note: Trigger nodes can be entry points without incoming edges
316
+ for (const nodeName of nodeNames) {
317
+ const node = nodesByName.get(nodeName);
318
+ if (!nodesWithEdges.has(nodeName) && node.type !== 'trigger') {
319
+ warnings.push(`Node "${nodeName}": orphaned node (not connected to any edges)`);
320
+ }
321
+ }
322
+ // Check for trigger nodes - at least one trigger should exist
323
+ const triggerNodes = flow.nodes.filter((n) => n.type === 'trigger');
324
+ if (triggerNodes.length === 0) {
325
+ warnings.push('Flow has no trigger nodes (entry points)');
326
+ }
327
+ const success = errors.length === 0;
328
+ return {
329
+ success,
330
+ flowName: flow.name,
331
+ stats: {
332
+ nodes: flow.nodes.length,
333
+ edges: flow.edges.length,
334
+ nodeTypes: [...new Set(flow.nodes.map((n) => n.type))],
335
+ edgeTypes: [...new Set(flow.edges.map((e) => e.type))],
336
+ },
337
+ errors: errors.length > 0 ? errors : undefined,
338
+ warnings: warnings.length > 0 ? warnings : undefined,
339
+ message: errors.length === 0
340
+ ? warnings.length === 0
341
+ ? 'Flow is valid with no issues'
342
+ : `Flow is valid but has ${warnings.length} warning(s)`
343
+ : `Flow validation failed with ${errors.length} error(s)`,
344
+ };
345
+ }
346
+ /**
347
+ * Finds all YAML files in a directory recursively.
348
+ */
349
+ function findYamlFiles(dir) {
350
+ const files = [];
351
+ if (!fs.existsSync(dir)) {
352
+ return files;
353
+ }
354
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
355
+ for (const entry of entries) {
356
+ const fullPath = path.join(dir, entry.name);
357
+ if (entry.isDirectory()) {
358
+ files.push(...findYamlFiles(fullPath));
359
+ }
360
+ else if (entry.isFile() && (entry.name.endsWith('.yaml') || entry.name.endsWith('.yml'))) {
361
+ files.push(fullPath);
362
+ }
363
+ }
364
+ return files;
365
+ }
366
+ /**
367
+ * CLI command handler for validate
368
+ */
369
+ function runValidateCommand() {
370
+ var _a, _b, _c, _d;
371
+ const mindedConfigPath = path.join(process.cwd(), 'minded.json');
372
+ // Check if minded.json exists
373
+ if (!fs.existsSync(mindedConfigPath)) {
374
+ console.error('Error: minded.json not found in the current directory');
375
+ console.error('Make sure you are running this command from a MindedJS agent project root');
376
+ process.exit(1);
377
+ }
378
+ // Read and parse minded.json
379
+ let mindedConfig;
380
+ try {
381
+ const configContent = fs.readFileSync(mindedConfigPath, 'utf8');
382
+ mindedConfig = JSON.parse(configContent);
383
+ }
384
+ catch (error) {
385
+ console.error(`Error: Failed to read or parse minded.json: ${error instanceof Error ? error.message : String(error)}`);
386
+ process.exit(1);
387
+ }
388
+ // Get flows folders
389
+ const flowsFolders = mindedConfig.flows;
390
+ if (!flowsFolders || flowsFolders.length === 0) {
391
+ console.error('Error: No flows folders configured in minded.json');
392
+ process.exit(1);
393
+ }
394
+ // Find all YAML files in flow folders
395
+ const flowFiles = [];
396
+ for (const folder of flowsFolders) {
397
+ const resolvedFolder = path.isAbsolute(folder) ? folder : path.join(process.cwd(), folder);
398
+ flowFiles.push(...findYamlFiles(resolvedFolder));
399
+ }
400
+ if (flowFiles.length === 0) {
401
+ console.error('Error: No flow YAML files found in configured flows folders');
402
+ process.exit(1);
403
+ }
404
+ console.log(`\nValidating ${flowFiles.length} flow(s)...\n`);
405
+ // Validate each flow
406
+ const results = [];
407
+ let totalErrors = 0;
408
+ let totalWarnings = 0;
409
+ for (const flowFile of flowFiles) {
410
+ const result = validateFlow(flowFile);
411
+ results.push({ path: flowFile, result });
412
+ totalErrors += (_b = (_a = result.errors) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
413
+ totalWarnings += (_d = (_c = result.warnings) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0;
414
+ }
415
+ // Print results for each flow
416
+ for (const { path: flowPath, result } of results) {
417
+ const relativePath = path.relative(process.cwd(), flowPath);
418
+ const statusIcon = result.success ? '✅' : '❌';
419
+ console.log(`${statusIcon} ${relativePath}`);
420
+ if (result.flowName) {
421
+ console.log(` Flow: ${result.flowName}`);
422
+ }
423
+ if (result.stats) {
424
+ console.log(` Stats: ${result.stats.nodes} nodes, ${result.stats.edges} edges`);
425
+ }
426
+ if (result.errors && result.errors.length > 0) {
427
+ console.log(' Errors:');
428
+ result.errors.forEach((error) => {
429
+ console.log(` ❌ ${error}`);
430
+ });
431
+ }
432
+ if (result.warnings && result.warnings.length > 0) {
433
+ console.log(' Warnings:');
434
+ result.warnings.forEach((warning) => {
435
+ console.log(` ⚠️ ${warning}`);
436
+ });
437
+ }
438
+ console.log('');
439
+ }
440
+ // Print summary
441
+ const allPassed = totalErrors === 0;
442
+ console.log('─'.repeat(50));
443
+ if (allPassed) {
444
+ console.log(`\n✅ All ${flowFiles.length} flow(s) validated successfully!`);
445
+ }
446
+ else {
447
+ console.log(`\n❌ Validation failed!`);
448
+ }
449
+ console.log(` Total: ${flowFiles.length} flow(s), ${totalErrors} error(s), ${totalWarnings} warning(s)\n`);
450
+ if (!allPassed) {
451
+ process.exit(1);
452
+ }
453
+ }
454
+ //# sourceMappingURL=validateFlow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validateFlow.js","sourceRoot":"","sources":["../../src/cli/validateFlow.ts"],"names":[],"mappings":"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"}
@@ -6,24 +6,6 @@ Minded AI agents automate complex workflows in customer environments while maint
6
6
 
7
7
  Minded is designed to provide maximum automation power while maintaining zero-trust security. You can automate mission-critical workflows with confidence, while Minded ensures every action is verified, logged, and restricted through multiple security layers.
8
8
 
9
- ## Quick Navigation
10
-
11
- - [System Overview](#️-system-overview)
12
- - [Security Layers](#️-security-layers)
13
- - [Network Isolation](#layer-1-network-isolation)
14
- - [Authentication & Authorization](#layer-2-authentication--authorization)
15
- - [RPA Security Controls](#layer-3-rpa-security-controls)
16
- - [Runtime Security](#layer-4-runtime-security)
17
- - [Monitoring & Audit](#layer-5-monitoring--audit)
18
- - [Credential Lifecycle Flow](#️-credential-lifecycle-flow)
19
- - [RPA Execution Flow](#️-rpa-execution-flow-with-security-controls)
20
- - [Agent Lifecycle Security](#️-agent-lifecycle-security)
21
- - [Tenant Isolation Architecture](#️-tenant-isolation-architecture)
22
- - [Infrastructure Security](#️-infrastructure-security)
23
- - [Agent Behavior Verification](#️-agent-behavior-verification--action-limits)
24
- - [Security FAQs](#security-faqs)
25
- - [See Also](#see-also)
26
-
27
9
  ---
28
10
 
29
11
  ## 🏗️ System Overview
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@minded-ai/mindedjs",
3
- "version": "3.0.5",
3
+ "version": "3.0.6-beta.1",
4
4
  "description": "MindedJS is a TypeScript library for building agents.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -57,6 +57,7 @@
57
57
  "@types/js-yaml": "^4.0.9",
58
58
  "axios": "^1.9.0",
59
59
  "chrome-remote-interface": "^0.33.3",
60
+ "cron-parser": "^5.4.0",
60
61
  "ejs": "^3.1.10",
61
62
  "flatted": "^3.3.3",
62
63
  "js-yaml": "^4.1.0",
@@ -72,4 +73,4 @@
72
73
  "peerDependencies": {
73
74
  "playwright": "^1.55.0"
74
75
  }
75
- }
76
+ }
package/src/cli/index.ts CHANGED
@@ -5,6 +5,7 @@ import * as path from 'path';
5
5
  import { logger } from '../utils/logger';
6
6
  import { execSync } from 'child_process';
7
7
  import { setupLocalOperator, isLocalOperatorSetup } from './localOperatorSetup';
8
+ import { runValidateCommand } from './validateFlow';
8
9
 
9
10
  const ENV_FILE = '.env';
10
11
 
@@ -174,9 +175,12 @@ async function main() {
174
175
  console.info('✗ Local operator is not set up. Run: npx minded setup-local-operator');
175
176
  process.exit(1);
176
177
  }
178
+ } else if (command === 'validate') {
179
+ // Command to validate a flow YAML file
180
+ runValidateCommand();
177
181
  } else {
178
182
  logger.error({
179
- msg: 'Unknown command. Available commands: token, setup-local-operator, check-local-operator, generate-lambda-ts-handler',
183
+ msg: 'Unknown command. Available commands: token, setup-local-operator, check-local-operator, generate-lambda-ts-handler, validate',
180
184
  });
181
185
  process.exit(1);
182
186
  }
@@ -0,0 +1,502 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import * as yaml from 'js-yaml';
4
+ import { CronExpressionParser } from 'cron-parser';
5
+
6
+ interface ValidationResult {
7
+ success: boolean;
8
+ flowName?: string;
9
+ stats?: {
10
+ nodes: number;
11
+ edges: number;
12
+ nodeTypes: string[];
13
+ edgeTypes: string[];
14
+ };
15
+ errors?: string[];
16
+ warnings?: string[];
17
+ message: string;
18
+ }
19
+
20
+ /**
21
+ * Validates a cron expression format using cron-parser.
22
+ * Cron format: minute hour day month day-of-week (5 fields)
23
+ */
24
+ export function validateCronExpression(cronExpression: string): { valid: boolean; error?: string } {
25
+ if (typeof cronExpression !== 'string' || cronExpression.trim() === '') {
26
+ return { valid: false, error: 'Cron expression must be a non-empty string' };
27
+ }
28
+
29
+ try {
30
+ CronExpressionParser.parse(cronExpression.trim());
31
+ return { valid: true };
32
+ } catch (error) {
33
+ return {
34
+ valid: false,
35
+ error: error instanceof Error ? error.message : 'Invalid cron expression format',
36
+ };
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Validates an IANA timezone identifier.
42
+ * Uses Intl.DateTimeFormat to check if the timezone is valid.
43
+ */
44
+ export function validateTimezone(timezone: string): { valid: boolean; error?: string } {
45
+ if (typeof timezone !== 'string' || timezone.trim() === '') {
46
+ return { valid: false, error: 'Timezone must be a non-empty string' };
47
+ }
48
+
49
+ try {
50
+ // Try to create a date formatter with the timezone
51
+ const formatter = new Intl.DateTimeFormat('en-US', { timeZone: timezone });
52
+ // Test if the timezone is valid by trying to format a date
53
+ formatter.format(new Date());
54
+ return { valid: true };
55
+ } catch {
56
+ return {
57
+ valid: false,
58
+ error: `Invalid IANA timezone identifier: "${timezone}"`,
59
+ };
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Validates a schedule trigger node configuration.
65
+ * Returns an array of error messages (empty if valid).
66
+ */
67
+ export function validateScheduleTrigger(
68
+ node: any,
69
+ nodeIndex: string
70
+ ): { errors: string[]; warnings: string[] } {
71
+ const errors: string[] = [];
72
+ const warnings: string[] = [];
73
+
74
+ if (!node.cronExpression) {
75
+ errors.push(`${nodeIndex} "${node.name}": schedule trigger missing required field "cronExpression"`);
76
+ } else if (typeof node.cronExpression !== 'string') {
77
+ errors.push(`${nodeIndex} "${node.name}": schedule trigger "cronExpression" must be a string`);
78
+ } else {
79
+ const cronValidation = validateCronExpression(node.cronExpression);
80
+ if (!cronValidation.valid) {
81
+ errors.push(`${nodeIndex} "${node.name}": invalid cron expression - ${cronValidation.error}`);
82
+ }
83
+ }
84
+
85
+ if (node.timezone !== undefined) {
86
+ if (typeof node.timezone !== 'string') {
87
+ errors.push(`${nodeIndex} "${node.name}": schedule trigger "timezone" must be a string`);
88
+ } else {
89
+ const timezoneValidation = validateTimezone(node.timezone);
90
+ if (!timezoneValidation.valid) {
91
+ errors.push(`${nodeIndex} "${node.name}": ${timezoneValidation.error}`);
92
+ }
93
+ }
94
+ }
95
+
96
+ return { errors, warnings };
97
+ }
98
+
99
+ /**
100
+ * Validates a MindedJS YAML flow file.
101
+ */
102
+ export function validateFlow(flowPath: string): ValidationResult {
103
+ // Resolve the path
104
+ const resolvedPath = path.isAbsolute(flowPath) ? flowPath : path.join(process.cwd(), flowPath);
105
+
106
+ // Read the file
107
+ let flowContent: string;
108
+ try {
109
+ flowContent = fs.readFileSync(resolvedPath, 'utf-8');
110
+ } catch (error) {
111
+ return {
112
+ success: false,
113
+ message: `Failed to read file: ${error instanceof Error ? error.message : String(error)}`,
114
+ };
115
+ }
116
+
117
+ // Parse YAML
118
+ let flow: any;
119
+ try {
120
+ flow = yaml.load(flowContent);
121
+ } catch (error) {
122
+ return {
123
+ success: false,
124
+ message: `Invalid YAML syntax: ${error instanceof Error ? error.message : String(error)}`,
125
+ };
126
+ }
127
+
128
+ // Validate flow structure
129
+ const errors: string[] = [];
130
+ const warnings: string[] = [];
131
+
132
+ // Check for required top-level fields
133
+ if (!flow.name) {
134
+ errors.push('Flow is missing required field: "name"');
135
+ }
136
+
137
+ if (!flow.nodes || !Array.isArray(flow.nodes)) {
138
+ errors.push('Flow is missing required field: "nodes" (must be an array)');
139
+ }
140
+
141
+ if (!flow.edges || !Array.isArray(flow.edges)) {
142
+ errors.push('Flow is missing required field: "edges" (must be an array)');
143
+ }
144
+
145
+ // If basic structure is invalid, return early
146
+ if (errors.length > 0) {
147
+ return {
148
+ success: false,
149
+ errors,
150
+ warnings,
151
+ message: `Flow validation failed with ${errors.length} error(s)`,
152
+ };
153
+ }
154
+
155
+ // Create a set of node names for validation
156
+ const nodeNames = new Set<string>();
157
+ const nodesByName = new Map<string, any>();
158
+
159
+ // Validate nodes
160
+ for (let i = 0; i < flow.nodes.length; i++) {
161
+ const node = flow.nodes[i];
162
+ const nodeIndex = `Node ${i + 1}`;
163
+
164
+ // Check for required name field
165
+ if (!node.name) {
166
+ errors.push(`${nodeIndex}: Missing required field "name"`);
167
+ continue;
168
+ }
169
+
170
+ // Check for duplicate node names
171
+ if (nodeNames.has(node.name)) {
172
+ errors.push(`${nodeIndex} "${node.name}": Duplicate node name`);
173
+ }
174
+ nodeNames.add(node.name);
175
+ nodesByName.set(node.name, node);
176
+
177
+ // Check for required type field
178
+ if (!node.type) {
179
+ errors.push(`${nodeIndex} "${node.name}": Missing required field "type"`);
180
+ continue;
181
+ }
182
+
183
+ // Validate node based on type
184
+ switch (node.type) {
185
+ case 'trigger':
186
+ if (!node.triggerType) {
187
+ errors.push(`${nodeIndex} "${node.name}": trigger node missing required field "triggerType"`);
188
+ } else if (!['manual', 'app', 'webhook', 'schedule'].includes(node.triggerType)) {
189
+ errors.push(
190
+ `${nodeIndex} "${node.name}": invalid triggerType "${node.triggerType}". Must be one of: manual, app, webhook, schedule`
191
+ );
192
+ }
193
+ if (node.triggerType === 'app' && !node.appTriggerId) {
194
+ errors.push(`${nodeIndex} "${node.name}": app trigger missing required field "appTriggerId"`);
195
+ }
196
+ if (node.triggerType === 'schedule') {
197
+ const scheduleValidation = validateScheduleTrigger(node, nodeIndex);
198
+ errors.push(...scheduleValidation.errors);
199
+ warnings.push(...scheduleValidation.warnings);
200
+ }
201
+ break;
202
+
203
+ case 'promptNode':
204
+ if (!node.prompt) {
205
+ errors.push(`${nodeIndex} "${node.name}": promptNode missing required field "prompt"`);
206
+ }
207
+ if (!node.displayName || node.displayName.trim() === '') {
208
+ errors.push(`${nodeIndex} "${node.name}": promptNode missing required non-empty field "displayName"`);
209
+ }
210
+ if (node.llmConfig) {
211
+ if (!node.llmConfig.name) {
212
+ errors.push(`${nodeIndex} "${node.name}": llmConfig missing required field "name"`);
213
+ }
214
+ if (!node.llmConfig.properties) {
215
+ warnings.push(`${nodeIndex} "${node.name}": llmConfig missing "properties" field`);
216
+ }
217
+ }
218
+ break;
219
+
220
+ case 'thinking':
221
+ if (!node.prompt) {
222
+ errors.push(`${nodeIndex} "${node.name}": thinking node missing required field "prompt"`);
223
+ }
224
+ if (node.humanInTheLoop !== undefined) {
225
+ errors.push(
226
+ `${nodeIndex} "${node.name}": thinking node does not support "humanInTheLoop" property (only prompt nodes support this)`
227
+ );
228
+ }
229
+ if (node.canStayOnNode !== undefined) {
230
+ errors.push(
231
+ `${nodeIndex} "${node.name}": thinking node does not support "canStayOnNode" property (only prompt nodes support this)`
232
+ );
233
+ }
234
+ if (node.llmConfig) {
235
+ if (!node.llmConfig.name) {
236
+ errors.push(`${nodeIndex} "${node.name}": llmConfig missing required field "name"`);
237
+ }
238
+ if (!node.llmConfig.properties) {
239
+ warnings.push(`${nodeIndex} "${node.name}": llmConfig missing "properties" field`);
240
+ }
241
+ }
242
+ break;
243
+
244
+ case 'tool':
245
+ if (!node.toolName) {
246
+ errors.push(`${nodeIndex} "${node.name}": tool node missing required field "toolName"`);
247
+ }
248
+ break;
249
+
250
+ case 'junction':
251
+ // Junction only requires name and type, which we already checked
252
+ break;
253
+
254
+ case 'jumpToNode':
255
+ if (!node.targetNodeId) {
256
+ errors.push(`${nodeIndex} "${node.name}": jumpToNode missing required field "targetNodeId"`);
257
+ }
258
+ break;
259
+
260
+ case 'browserTask':
261
+ if (!node.prompt) {
262
+ errors.push(`${nodeIndex} "${node.name}": browserTask node missing required field "prompt"`);
263
+ }
264
+ break;
265
+
266
+ default:
267
+ warnings.push(`${nodeIndex} "${node.name}": unknown node type "${node.type}"`);
268
+ }
269
+ }
270
+
271
+ // Create a map to track which nodes have edges
272
+ const nodesWithEdges = new Set<string>();
273
+
274
+ // Validate edges
275
+ for (let i = 0; i < flow.edges.length; i++) {
276
+ const edge = flow.edges[i];
277
+ const edgeIndex = `Edge ${i + 1}`;
278
+
279
+ // Check for required fields
280
+ if (!edge.source) {
281
+ errors.push(`${edgeIndex}: Missing required field "source"`);
282
+ continue;
283
+ }
284
+
285
+ if (!edge.target) {
286
+ errors.push(`${edgeIndex}: Missing required field "target"`);
287
+ continue;
288
+ }
289
+
290
+ if (!edge.type) {
291
+ errors.push(`${edgeIndex}: Missing required field "type"`);
292
+ continue;
293
+ }
294
+
295
+ // Track nodes that have edges
296
+ nodesWithEdges.add(edge.source);
297
+ nodesWithEdges.add(edge.target);
298
+
299
+ // Check if source and target nodes exist
300
+ if (!nodeNames.has(edge.source)) {
301
+ errors.push(`${edgeIndex}: source node "${edge.source}" does not exist`);
302
+ }
303
+
304
+ if (!nodeNames.has(edge.target)) {
305
+ errors.push(`${edgeIndex}: target node "${edge.target}" does not exist`);
306
+ }
307
+
308
+ // Validate edge based on type
309
+ switch (edge.type) {
310
+ case 'stepForward':
311
+ // stepForward only requires source, target, and type
312
+ break;
313
+
314
+ case 'promptCondition':
315
+ if (!edge.prompt) {
316
+ errors.push(`${edgeIndex}: promptCondition edge missing required field "prompt"`);
317
+ }
318
+ break;
319
+
320
+ case 'logicalCondition':
321
+ if (!edge.condition) {
322
+ errors.push(`${edgeIndex}: logicalCondition edge missing required field "condition"`);
323
+ }
324
+ break;
325
+
326
+ default:
327
+ warnings.push(`${edgeIndex}: unknown edge type "${edge.type}"`);
328
+ }
329
+ }
330
+
331
+ // Check for orphaned nodes (nodes without any edges)
332
+ // Note: Trigger nodes can be entry points without incoming edges
333
+ for (const nodeName of nodeNames) {
334
+ const node = nodesByName.get(nodeName);
335
+ if (!nodesWithEdges.has(nodeName) && node.type !== 'trigger') {
336
+ warnings.push(`Node "${nodeName}": orphaned node (not connected to any edges)`);
337
+ }
338
+ }
339
+
340
+ // Check for trigger nodes - at least one trigger should exist
341
+ const triggerNodes = flow.nodes.filter((n: any) => n.type === 'trigger');
342
+ if (triggerNodes.length === 0) {
343
+ warnings.push('Flow has no trigger nodes (entry points)');
344
+ }
345
+
346
+ const success = errors.length === 0;
347
+
348
+ return {
349
+ success,
350
+ flowName: flow.name,
351
+ stats: {
352
+ nodes: flow.nodes.length,
353
+ edges: flow.edges.length,
354
+ nodeTypes: [...new Set(flow.nodes.map((n: any) => n.type))] as string[],
355
+ edgeTypes: [...new Set(flow.edges.map((e: any) => e.type))] as string[],
356
+ },
357
+ errors: errors.length > 0 ? errors : undefined,
358
+ warnings: warnings.length > 0 ? warnings : undefined,
359
+ message:
360
+ errors.length === 0
361
+ ? warnings.length === 0
362
+ ? 'Flow is valid with no issues'
363
+ : `Flow is valid but has ${warnings.length} warning(s)`
364
+ : `Flow validation failed with ${errors.length} error(s)`,
365
+ };
366
+ }
367
+
368
+ interface MindedConfig {
369
+ flows?: string[];
370
+ tools?: string[];
371
+ playbooks?: string[];
372
+ agent?: string;
373
+ }
374
+
375
+ /**
376
+ * Finds all YAML files in a directory recursively.
377
+ */
378
+ function findYamlFiles(dir: string): string[] {
379
+ const files: string[] = [];
380
+
381
+ if (!fs.existsSync(dir)) {
382
+ return files;
383
+ }
384
+
385
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
386
+
387
+ for (const entry of entries) {
388
+ const fullPath = path.join(dir, entry.name);
389
+ if (entry.isDirectory()) {
390
+ files.push(...findYamlFiles(fullPath));
391
+ } else if (entry.isFile() && (entry.name.endsWith('.yaml') || entry.name.endsWith('.yml'))) {
392
+ files.push(fullPath);
393
+ }
394
+ }
395
+
396
+ return files;
397
+ }
398
+
399
+ /**
400
+ * CLI command handler for validate
401
+ */
402
+ export function runValidateCommand(): void {
403
+ const mindedConfigPath = path.join(process.cwd(), 'minded.json');
404
+
405
+ // Check if minded.json exists
406
+ if (!fs.existsSync(mindedConfigPath)) {
407
+ console.error('Error: minded.json not found in the current directory');
408
+ console.error('Make sure you are running this command from a MindedJS agent project root');
409
+ process.exit(1);
410
+ }
411
+
412
+ // Read and parse minded.json
413
+ let mindedConfig: MindedConfig;
414
+ try {
415
+ const configContent = fs.readFileSync(mindedConfigPath, 'utf8');
416
+ mindedConfig = JSON.parse(configContent);
417
+ } catch (error) {
418
+ console.error(`Error: Failed to read or parse minded.json: ${error instanceof Error ? error.message : String(error)}`);
419
+ process.exit(1);
420
+ }
421
+
422
+ // Get flows folders
423
+ const flowsFolders = mindedConfig.flows;
424
+ if (!flowsFolders || flowsFolders.length === 0) {
425
+ console.error('Error: No flows folders configured in minded.json');
426
+ process.exit(1);
427
+ }
428
+
429
+ // Find all YAML files in flow folders
430
+ const flowFiles: string[] = [];
431
+ for (const folder of flowsFolders) {
432
+ const resolvedFolder = path.isAbsolute(folder) ? folder : path.join(process.cwd(), folder);
433
+ flowFiles.push(...findYamlFiles(resolvedFolder));
434
+ }
435
+
436
+ if (flowFiles.length === 0) {
437
+ console.error('Error: No flow YAML files found in configured flows folders');
438
+ process.exit(1);
439
+ }
440
+
441
+ console.log(`\nValidating ${flowFiles.length} flow(s)...\n`);
442
+
443
+ // Validate each flow
444
+ const results: { path: string; result: ValidationResult }[] = [];
445
+ let totalErrors = 0;
446
+ let totalWarnings = 0;
447
+
448
+ for (const flowFile of flowFiles) {
449
+ const result = validateFlow(flowFile);
450
+ results.push({ path: flowFile, result });
451
+ totalErrors += result.errors?.length ?? 0;
452
+ totalWarnings += result.warnings?.length ?? 0;
453
+ }
454
+
455
+ // Print results for each flow
456
+ for (const { path: flowPath, result } of results) {
457
+ const relativePath = path.relative(process.cwd(), flowPath);
458
+ const statusIcon = result.success ? '✅' : '❌';
459
+
460
+ console.log(`${statusIcon} ${relativePath}`);
461
+
462
+ if (result.flowName) {
463
+ console.log(` Flow: ${result.flowName}`);
464
+ }
465
+
466
+ if (result.stats) {
467
+ console.log(` Stats: ${result.stats.nodes} nodes, ${result.stats.edges} edges`);
468
+ }
469
+
470
+ if (result.errors && result.errors.length > 0) {
471
+ console.log(' Errors:');
472
+ result.errors.forEach((error) => {
473
+ console.log(` ❌ ${error}`);
474
+ });
475
+ }
476
+
477
+ if (result.warnings && result.warnings.length > 0) {
478
+ console.log(' Warnings:');
479
+ result.warnings.forEach((warning) => {
480
+ console.log(` ⚠️ ${warning}`);
481
+ });
482
+ }
483
+
484
+ console.log('');
485
+ }
486
+
487
+ // Print summary
488
+ const allPassed = totalErrors === 0;
489
+ console.log('─'.repeat(50));
490
+
491
+ if (allPassed) {
492
+ console.log(`\n✅ All ${flowFiles.length} flow(s) validated successfully!`);
493
+ } else {
494
+ console.log(`\n❌ Validation failed!`);
495
+ }
496
+
497
+ console.log(` Total: ${flowFiles.length} flow(s), ${totalErrors} error(s), ${totalWarnings} warning(s)\n`);
498
+
499
+ if (!allPassed) {
500
+ process.exit(1);
501
+ }
502
+ }