Files
wifi-densepose/.claude/helpers/hook-handler.cjs
Claude 6c931b826f feat(claude-flow): Init claude-flow v3, pretrain on repo, update CLAUDE.md
- Run npx @claude-flow/cli@latest init --force: 115 files created
  (agents, commands, helpers, skills, settings, MCP config)
- Initialize memory.db (147 KB): 84 files analyzed, 30 patterns
  extracted, 46 trajectories evaluated via 4-step RETRIEVE/JUDGE/DISTILL/CONSOLIDATE
- Run pretraining with MoE model: hyperbolic Poincaré embeddings,
  3 contradictions resolved, all-MiniLM-L6-v2 ONNX embedding index
- Include .claude/memory.db and .claude-flow/metrics/learning.json in
  repo for team sharing (semantic search available to all contributors)
- Update CLAUDE.md: add wifi-densepose project context, key crates,
  ruvector integration map, correct build/test commands for this repo,
  ADR cross-reference (ADR-014 through ADR-017)

https://claude.ai/code/session_01BSBAQJ34SLkiJy4A8SoiL4
2026-02-28 16:06:55 +00:00

233 lines
7.8 KiB
JavaScript

#!/usr/bin/env node
/**
* Claude Flow Hook Handler (Cross-Platform)
* Dispatches hook events to the appropriate helper modules.
*
* Usage: node hook-handler.cjs <command> [args...]
*
* Commands:
* route - Route a task to optimal agent (reads PROMPT from env/stdin)
* pre-bash - Validate command safety before execution
* post-edit - Record edit outcome for learning
* session-restore - Restore previous session state
* session-end - End session and persist state
*/
const path = require('path');
const fs = require('fs');
const helpersDir = __dirname;
// Safe require with stdout suppression - the helper modules have CLI
// sections that run unconditionally on require(), so we mute console
// during the require to prevent noisy output.
function safeRequire(modulePath) {
try {
if (fs.existsSync(modulePath)) {
const origLog = console.log;
const origError = console.error;
console.log = () => {};
console.error = () => {};
try {
const mod = require(modulePath);
return mod;
} finally {
console.log = origLog;
console.error = origError;
}
}
} catch (e) {
// silently fail
}
return null;
}
const router = safeRequire(path.join(helpersDir, 'router.js'));
const session = safeRequire(path.join(helpersDir, 'session.js'));
const memory = safeRequire(path.join(helpersDir, 'memory.js'));
const intelligence = safeRequire(path.join(helpersDir, 'intelligence.cjs'));
// Get the command from argv
const [,, command, ...args] = process.argv;
// Get prompt from environment variable (set by Claude Code hooks)
const prompt = process.env.PROMPT || process.env.TOOL_INPUT_command || args.join(' ') || '';
const handlers = {
'route': () => {
// Inject ranked intelligence context before routing
if (intelligence && intelligence.getContext) {
try {
const ctx = intelligence.getContext(prompt);
if (ctx) console.log(ctx);
} catch (e) { /* non-fatal */ }
}
if (router && router.routeTask) {
const result = router.routeTask(prompt);
// Format output for Claude Code hook consumption
const output = [
`[INFO] Routing task: ${prompt.substring(0, 80) || '(no prompt)'}`,
'',
'Routing Method',
' - Method: keyword',
' - Backend: keyword matching',
` - Latency: ${(Math.random() * 0.5 + 0.1).toFixed(3)}ms`,
' - Matched Pattern: keyword-fallback',
'',
'Semantic Matches:',
' bugfix-task: 15.0%',
' devops-task: 14.0%',
' testing-task: 13.0%',
'',
'+------------------- Primary Recommendation -------------------+',
`| Agent: ${result.agent.padEnd(53)}|`,
`| Confidence: ${(result.confidence * 100).toFixed(1)}%${' '.repeat(44)}|`,
`| Reason: ${result.reason.substring(0, 53).padEnd(53)}|`,
'+--------------------------------------------------------------+',
'',
'Alternative Agents',
'+------------+------------+-------------------------------------+',
'| Agent Type | Confidence | Reason |',
'+------------+------------+-------------------------------------+',
'| researcher | 60.0% | Alternative agent for researcher... |',
'| tester | 50.0% | Alternative agent for tester cap... |',
'+------------+------------+-------------------------------------+',
'',
'Estimated Metrics',
' - Success Probability: 70.0%',
' - Estimated Duration: 10-30 min',
' - Complexity: LOW',
];
console.log(output.join('\n'));
} else {
console.log('[INFO] Router not available, using default routing');
}
},
'pre-bash': () => {
// Basic command safety check
const cmd = prompt.toLowerCase();
const dangerous = ['rm -rf /', 'format c:', 'del /s /q c:\\', ':(){:|:&};:'];
for (const d of dangerous) {
if (cmd.includes(d)) {
console.error(`[BLOCKED] Dangerous command detected: ${d}`);
process.exit(1);
}
}
console.log('[OK] Command validated');
},
'post-edit': () => {
// Record edit for session metrics
if (session && session.metric) {
try { session.metric('edits'); } catch (e) { /* no active session */ }
}
// Record edit for intelligence consolidation
if (intelligence && intelligence.recordEdit) {
try {
const file = process.env.TOOL_INPUT_file_path || args[0] || '';
intelligence.recordEdit(file);
} catch (e) { /* non-fatal */ }
}
console.log('[OK] Edit recorded');
},
'session-restore': () => {
if (session) {
// Try restore first, fall back to start
const existing = session.restore && session.restore();
if (!existing) {
session.start && session.start();
}
} else {
// Minimal session restore output
const sessionId = `session-${Date.now()}`;
console.log(`[INFO] Restoring session: %SESSION_ID%`);
console.log('');
console.log(`[OK] Session restored from %SESSION_ID%`);
console.log(`New session ID: ${sessionId}`);
console.log('');
console.log('Restored State');
console.log('+----------------+-------+');
console.log('| Item | Count |');
console.log('+----------------+-------+');
console.log('| Tasks | 0 |');
console.log('| Agents | 0 |');
console.log('| Memory Entries | 0 |');
console.log('+----------------+-------+');
}
// Initialize intelligence graph after session restore
if (intelligence && intelligence.init) {
try {
const result = intelligence.init();
if (result && result.nodes > 0) {
console.log(`[INTELLIGENCE] Loaded ${result.nodes} patterns, ${result.edges} edges`);
}
} catch (e) { /* non-fatal */ }
}
},
'session-end': () => {
// Consolidate intelligence before ending session
if (intelligence && intelligence.consolidate) {
try {
const result = intelligence.consolidate();
if (result && result.entries > 0) {
console.log(`[INTELLIGENCE] Consolidated: ${result.entries} entries, ${result.edges} edges${result.newEntries > 0 ? `, ${result.newEntries} new` : ''}, PageRank recomputed`);
}
} catch (e) { /* non-fatal */ }
}
if (session && session.end) {
session.end();
} else {
console.log('[OK] Session ended');
}
},
'pre-task': () => {
if (session && session.metric) {
try { session.metric('tasks'); } catch (e) { /* no active session */ }
}
// Route the task if router is available
if (router && router.routeTask && prompt) {
const result = router.routeTask(prompt);
console.log(`[INFO] Task routed to: ${result.agent} (confidence: ${result.confidence})`);
} else {
console.log('[OK] Task started');
}
},
'post-task': () => {
// Implicit success feedback for intelligence
if (intelligence && intelligence.feedback) {
try {
intelligence.feedback(true);
} catch (e) { /* non-fatal */ }
}
console.log('[OK] Task completed');
},
'stats': () => {
if (intelligence && intelligence.stats) {
intelligence.stats(args.includes('--json'));
} else {
console.log('[WARN] Intelligence module not available. Run session-restore first.');
}
},
};
// Execute the handler
if (command && handlers[command]) {
try {
handlers[command]();
} catch (e) {
// Hooks should never crash Claude Code - fail silently
console.log(`[WARN] Hook ${command} encountered an error: ${e.message}`);
}
} else if (command) {
// Unknown command - pass through without error
console.log(`[OK] Hook: ${command}`);
} else {
console.log('Usage: hook-handler.cjs <route|pre-bash|post-edit|session-restore|session-end|pre-task|post-task|stats>');
}