jay-code
Version:
Streamlined AI CLI orchestration engine with mathematical rigor and enterprise-grade reliability
288 lines (251 loc) • 7.86 kB
text/typescript
/**
* Example Configuration Validator
* Validates all example configuration files for correctness
*/
import { walk } from "https://deno.land/std@0.220.0/fs/mod.ts";
interface ValidationResult {
file: string;
valid: boolean;
errors: string[];
}
interface ConfigSchema {
[key: string]: {
type: string;
required?: boolean;
properties?: ConfigSchema;
};
}
const JAY_CODE_CONFIG_SCHEMA: ConfigSchema = {
orchestrator: {
type: 'object',
required: true,
properties: {
maxConcurrentAgents: { type: 'number' },
taskQueueSize: { type: 'number' },
healthCheckInterval: { type: 'number' },
shutdownTimeout: { type: 'number' },
},
},
terminal: {
type: 'object',
properties: {
type: { type: 'string' },
poolSize: { type: 'number' },
recycleAfter: { type: 'number' },
healthCheckInterval: { type: 'number' },
commandTimeout: { type: 'number' },
},
},
memory: {
type: 'object',
properties: {
backend: { type: 'string' },
cacheSizeMB: { type: 'number' },
syncInterval: { type: 'number' },
conflictResolution: { type: 'string' },
retentionDays: { type: 'number' },
},
},
coordination: {
type: 'object',
properties: {
maxRetries: { type: 'number' },
retryDelay: { type: 'number' },
deadlockDetection: { type: 'boolean' },
resourceTimeout: { type: 'number' },
messageTimeout: { type: 'number' },
},
},
mcp: {
type: 'object',
properties: {
transport: { type: 'string' },
port: { type: 'number' },
tlsEnabled: { type: 'boolean' },
},
},
logging: {
type: 'object',
properties: {
level: { type: 'string' },
format: { type: 'string' },
destination: { type: 'string' },
},
},
};
const WORKFLOW_SCHEMA: ConfigSchema = {
name: { type: 'string', required: true },
description: { type: 'string' },
tasks: {
type: 'array',
required: true,
properties: {
id: { type: 'string', required: true },
type: { type: 'string', required: true },
description: { type: 'string', required: true },
dependencies: { type: 'array' },
assignTo: { type: 'string' },
priority: { type: 'string' },
timeout: { type: 'number' },
},
},
};
function validateType(value: any, expectedType: string): boolean {
switch (expectedType) {
case 'string':
return typeof value === 'string';
case 'number':
return typeof value === 'number';
case 'boolean':
return typeof value === 'boolean';
case 'array':
return Array.isArray(value);
case 'object':
return typeof value === 'object' && value !== null && !Array.isArray(value);
default:
return false;
}
}
function validateObject(obj: any, schema: ConfigSchema, path = ''): string[] {
const errors: string[] = [];
// Check required fields
for (const [key, spec] of Object.entries(schema)) {
if (spec.required && !(key in obj)) {
errors.push(`${path}${key} is required but missing`);
continue;
}
if (key in obj) {
const value = obj[key];
const currentPath = path ? `${path}${key}.` : `${key}.`;
if (!validateType(value, spec.type)) {
errors.push(`${path}${key} should be of type ${spec.type}, got ${typeof value}`);
continue;
}
// Validate nested objects
if (spec.type === 'object' && spec.properties) {
errors.push(...validateObject(value, spec.properties, currentPath));
}
// Validate array items
if (spec.type === 'array' && spec.properties && Array.isArray(value)) {
value.forEach((item, index) => {
if (typeof item === 'object') {
errors.push(...validateObject(item, spec.properties!, `${currentPath}[${index}].`));
}
});
}
}
}
return errors;
}
function validateClaudeFlowConfig(config: any): string[] {
return validateObject(config, JAY_CODE_CONFIG_SCHEMA);
}
function validateWorkflow(workflow: any): string[] {
const errors = validateObject(workflow, WORKFLOW_SCHEMA);
// Additional workflow-specific validations
if (workflow.tasks && Array.isArray(workflow.tasks)) {
const taskIds = new Set<string>();
for (const [index, task] of workflow.tasks.entries()) {
// Check for duplicate task IDs
if (taskIds.has(task.id)) {
errors.push(`Duplicate task ID "${task.id}" found at index ${index}`);
} else {
taskIds.add(task.id);
}
// Validate dependencies reference existing tasks
if (task.dependencies && Array.isArray(task.dependencies)) {
for (const dep of task.dependencies) {
if (!taskIds.has(dep) && !workflow.tasks.slice(0, index).some((t: any) => t.id === dep)) {
errors.push(`Task "${task.id}" depends on non-existent task "${dep}"`);
}
}
}
// Validate priority values
if (task.priority && !['low', 'medium', 'high', 'critical'].includes(task.priority)) {
errors.push(`Task "${task.id}" has invalid priority "${task.priority}"`);
}
// Validate timeout is positive
if (task.timeout && task.timeout <= 0) {
errors.push(`Task "${task.id}" has invalid timeout ${task.timeout}`);
}
}
}
return errors;
}
async function validateFile(filePath: string): Promise<ValidationResult> {
const result: ValidationResult = {
file: filePath,
valid: false,
errors: [],
};
try {
const content = await Deno.readTextFile(filePath);
const config = JSON.parse(content);
// Determine validation type based on file name/content
if (filePath.includes('workflow') || config.tasks) {
result.errors = validateWorkflow(config);
} else if (filePath.includes('config') || config.orchestrator) {
result.errors = validateClaudeFlowConfig(config);
} else {
result.errors.push('Unknown configuration file type');
}
result.valid = result.errors.length === 0;
} catch (error) {
if (error instanceof SyntaxError) {
result.errors.push(`Invalid JSON: ${error.message}`);
} else {
result.errors.push(`Failed to read file: ${error.message}`);
}
}
return result;
}
async function main(): Promise<void> {
console.log('Validating example configurations...\n');
const results: ValidationResult[] = [];
// Find all JSON files in examples directory
for await (const entry of walk('./examples', { exts: ['.json'] })) {
if (entry.isFile) {
const result = await validateFile(entry.path);
results.push(result);
}
}
// Also check any config files in the root
const rootConfigFiles = ['jay-code.config.json', 'config.json'];
for (const filename of rootConfigFiles) {
try {
await Deno.stat(filename);
const result = await validateFile(filename);
results.push(result);
} catch {
// File doesn't exist, skip
}
}
if (results.length === 0) {
console.log('No configuration files found to validate.');
return;
}
// Report results
let hasErrors = false;
for (const result of results) {
if (result.valid) {
console.log(`✅ ${result.file}: Valid`);
} else {
console.log(`❌ ${result.file}: Invalid`);
for (const error of result.errors) {
console.log(` - ${error}`);
}
hasErrors = true;
}
}
console.log(`\nValidated ${results.length} configuration files.`);
if (hasErrors) {
console.error('❌ Some configuration files have errors!');
Deno.exit(1);
} else {
console.log('✅ All configuration files are valid!');
}
}
if (import.meta.main) {
await main();
}