UNPKG

claude-flow-multilang

Version:

Revolutionary multilingual AI orchestration framework with cultural awareness and DDD architecture

349 lines (296 loc) 10.6 kB
import { spawn } from 'child_process'; import { Logger } from '../../core/logger.js'; import type { PreTaskOptions, PostTaskOptions, PreEditOptions, PostEditOptions, PreCommandOptions, PostCommandOptions, SessionStartOptions, SessionEndOptions, SessionRestoreOptions, PreSearchOptions, NotificationOptions, HookCommandOptions, PerformanceOptions, MemorySyncOptions, TelemetryOptions, } from './hook-types.js'; const logger = new Logger( { level: 'info', format: 'text', destination: 'console', }, { prefix: 'Hook' }, ); // Helper function to build command arguments function buildArgs(hookType: string, options: Record<string, any>): string[] { const args = [hookType]; Object.entries(options).forEach(([key, value]) => { if (value !== undefined && value !== null) { const flagName = key.replace(/([A-Z])/g, '-$1').toLowerCase(); if (typeof value === 'boolean') { if (value) { args.push(`--${flagName}`); } else { args.push(`--no-${flagName}`); } } else { args.push(`--${flagName}`, String(value)); } } }); return args; } // Hook subcommand handlers const hookHandlers: Record<string, (args: string[]) => Promise<void>> = { 'pre-task': async (args: string[]) => { const options = parseArgs<PreTaskOptions>(args); await executeHook('pre-task', options); }, 'post-task': async (args: string[]) => { const options = parseArgs<PostTaskOptions>(args); if (!options.taskId) { throw new Error('--task-id is required for post-task hook'); } await executeHook('post-task', options); }, 'pre-edit': async (args: string[]) => { const options = parseArgs<PreEditOptions>(args); if (!options.file) { throw new Error('--file is required for pre-edit hook'); } await executeHook('pre-edit', options); }, 'post-edit': async (args: string[]) => { const options = parseArgs<PostEditOptions>(args); if (!options.file) { throw new Error('--file is required for post-edit hook'); } await executeHook('post-edit', options); }, 'pre-command': async (args: string[]) => { const options = parseArgs<PreCommandOptions>(args); if (!options.command) { throw new Error('--command is required for pre-command hook'); } await executeHook('pre-command', options); }, 'post-command': async (args: string[]) => { const options = parseArgs<PostCommandOptions>(args); if (!options.command) { throw new Error('--command is required for post-command hook'); } await executeHook('post-command', options); }, 'session-start': async (args: string[]) => { const options = parseArgs<SessionStartOptions>(args); await executeHook('session-start', options); }, 'session-end': async (args: string[]) => { const options = parseArgs<SessionEndOptions>(args); await executeHook('session-end', options); }, 'session-restore': async (args: string[]) => { const options = parseArgs<SessionRestoreOptions>(args); if (!options.sessionId) { throw new Error('--session-id is required for session-restore hook'); } await executeHook('session-restore', options); }, 'pre-search': async (args: string[]) => { const options = parseArgs<PreSearchOptions>(args); if (!options.query) { throw new Error('--query is required for pre-search hook'); } await executeHook('pre-search', options); }, notification: async (args: string[]) => { const options = parseArgs<NotificationOptions>(args); if (!options.message) { throw new Error('--message is required for notification hook'); } await executeHook('notification', options); }, performance: async (args: string[]) => { const options = parseArgs<PerformanceOptions>(args); await executeHook('performance', options); }, 'memory-sync': async (args: string[]) => { const options = parseArgs<MemorySyncOptions>(args); await executeHook('memory-sync', options); }, telemetry: async (args: string[]) => { const options = parseArgs<TelemetryOptions>(args); if (!options.event) { throw new Error('--event is required for telemetry hook'); } await executeHook('telemetry', options); }, }; // Parse command line arguments function parseArgs<T extends Record<string, any>>(args: string[]): T { const options: Record<string, any> = {}; for (let i = 0; i < args.length; i++) { const arg = args[i]; if (arg.startsWith('--')) { const key = arg.slice(2).replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()); const nextArg = args[i + 1]; if (!nextArg || nextArg.startsWith('--')) { // Boolean flag options[key] = !arg.startsWith('--no-'); } else { // Value flag options[key] = nextArg; i++; // Skip next arg } } } return options as T; } // Execute hook with ruv-swarm async function executeHook(hookType: string, options: Record<string, any>): Promise<void> { const args = buildArgs(hookType, options); logger.debug(`Executing hook: ruv-swarm hook ${args.join(' ')}`); const child = spawn('npx', ['ruv-swarm', 'hook', ...args], { stdio: 'inherit', shell: true, }); await new Promise<void>((resolve, reject) => { child.on('exit', (code) => { if (code === 0) { resolve(); } else { reject(new Error(`Hook ${hookType} failed with exit code ${code}`)); } }); child.on('error', (error) => { logger.error(`Failed to execute hook ${hookType}:`, error); reject(error); }); }); } // Main hook command handler export const hookCommand = { name: 'hook', description: 'Execute ruv-swarm hooks for agent coordination', action: async ({ args }: HookCommandOptions): Promise<void> => { try { if (args.length === 0) { showHookHelp(); return; } const subcommand = args[0]; const handler = hookHandlers[subcommand]; if (!handler) { logger.error(`Unknown hook subcommand: ${subcommand}`); showHookHelp(); throw new Error(`Unknown hook subcommand: ${subcommand}`); } await handler(args.slice(1)); } catch (error) { logger.error('Hook command error:', error); throw error; } }, }; // Show help for hook commands function showHookHelp(): void { console.log(` Claude Flow Hook Commands ======================== Available hooks: pre-task - Run before starting a task --description <desc> Task description --auto-spawn-agents Auto-spawn agents (default: true) --complexity <level> Task complexity: low|medium|high --estimated-minutes <n> Estimated duration --requires-research Task requires research --requires-testing Task requires testing post-task - Run after completing a task --task-id <id> Task ID (required) --analyze-performance Analyze performance metrics --generate-report Generate completion report pre-edit - Run before editing a file --file <path> File path (required) --operation <op> Operation type: read|write|edit|delete --validate Validate file before edit post-edit - Run after editing a file --file <path> File path (required) --memory-key <key> Store in memory with key --format Auto-format code --analyze Analyze changes pre-command - Run before executing a command --command <cmd> Command to execute (required) --validate Validate command safety --sandbox Run in sandbox mode post-command - Run after executing a command --command <cmd> Command executed (required) --exit-code <code> Command exit code --duration <ms> Execution duration session-start - Run at session start --session-id <id> Session identifier --load-previous Load previous session data --auto-restore Auto-restore context session-end - Run at session end --session-id <id> Session identifier --export-metrics Export performance metrics --generate-summary Generate session summary --save-to <path> Save session data to path session-restore - Restore a previous session --session-id <id> Session ID to restore (required) --load-memory Load memory state --load-agents Load agent configuration --load-tasks Load task list pre-search - Run before searching --query <text> Search query (required) --cache-results Cache search results --max-results <n> Maximum results to return notification - Send a notification --message <text> Notification message (required) --level <level> Message level: info|warning|error --telemetry Include in telemetry --persist Persist notification performance - Track performance metrics --operation <name> Operation name --duration <ms> Operation duration --metrics <json> Performance metrics as JSON memory-sync - Synchronize memory state --namespace <name> Memory namespace --direction <dir> Sync direction: push|pull|sync --target <location> Target location for sync telemetry - Send telemetry data --event <name> Event name (required) --data <json> Event data as JSON --tags <list> Comma-separated tags Common options: --verbose Show detailed output --metadata <json> Additional metadata as JSON Examples: claude hook pre-task --description "Build REST API" --complexity high claude hook post-edit --file src/index.js --memory-key "api/implementation" claude hook session-end --export-metrics --generate-summary claude hook performance --operation "api-build" --duration 1234 claude hook memory-sync --namespace "project" --direction push claude hook telemetry --event "task-completed" --data '{"taskId":"123"}' `); } // Export hook subcommands for better CLI integration export const hookSubcommands = [ 'pre-task', 'post-task', 'pre-edit', 'post-edit', 'pre-command', 'post-command', 'session-start', 'session-end', 'session-restore', 'pre-search', 'notification', 'performance', 'memory-sync', 'telemetry', ];