tasq/node_modules/agentic-flow/dist/mcp/fastmcp/tools/hooks/post-command.js

91 lines
3.8 KiB
JavaScript

/**
* Post-Command Hook - Learn from command outcomes
* Records command results and learns from errors
*/
import { z } from 'zod';
import { loadIntelligence, saveIntelligence, simpleEmbed } from './shared.js';
const LEARNING_RATE = 0.1;
export const hookPostCommandTool = {
name: 'hook_post_command',
description: 'Post-command learning: record outcome and learn from errors',
parameters: z.object({
command: z.string().describe('Command that was executed'),
exitCode: z.number().describe('Command exit code'),
stderr: z.string().optional().describe('Standard error output'),
stdout: z.string().optional().describe('Standard output (truncated)')
}),
execute: async ({ command, exitCode, stderr, stdout }, { onProgress }) => {
const startTime = Date.now();
const intel = loadIntelligence();
const success = exitCode === 0;
const cmdBase = command.split(' ')[0];
const state = `command:${cmdBase}`;
// 1. Update command patterns
if (!intel.patterns[state]) {
intel.patterns[state] = {};
}
const action = success ? 'success' : 'failure';
const currentValue = intel.patterns[state][action] || 0;
const reward = success ? 1.0 : -0.5;
intel.patterns[state][action] = currentValue + LEARNING_RATE * (reward - currentValue);
// 2. Learn from failures
let errorPattern = null;
if (!success && stderr) {
// Extract error type from stderr
const errorMatch = stderr.match(/^(\w+Error|\w+Exception|error\[\w+\]|ENOENT|EACCES|EPERM)/im);
const errorType = errorMatch ? errorMatch[1] : 'CommandError';
// Check for existing pattern
const existing = intel.errorPatterns.find(p => p.errorType === errorType && p.context.includes(cmdBase));
if (existing) {
// Update existing pattern
existing.agentSuccess['command'] = (existing.agentSuccess['command'] || 0) + 1;
}
else {
// Create new error pattern
errorPattern = {
errorType,
context: `${cmdBase} command: ${stderr.slice(0, 100)}`,
resolution: '', // Will be filled when resolved
agentSuccess: { 'command': 1 }
};
intel.errorPatterns.push(errorPattern);
}
// Keep last 50 error patterns
if (intel.errorPatterns.length > 50) {
intel.errorPatterns = intel.errorPatterns.slice(-50);
}
}
// 3. Store successful command as memory if useful output
if (success && stdout && stdout.length > 10) {
const memoryContent = `Command "${cmdBase}" succeeded: ${stdout.slice(0, 100)}`;
intel.memories.push({
content: memoryContent,
type: 'command',
created: new Date().toISOString(),
embedding: simpleEmbed(memoryContent)
});
// Keep last 200 memories
if (intel.memories.length > 200) {
intel.memories = intel.memories.slice(-200);
}
}
// 4. Update metrics
intel.metrics.totalRoutes++;
if (success) {
intel.metrics.successfulRoutes++;
}
// 5. Save intelligence
saveIntelligence(intel);
const latency = Date.now() - startTime;
return {
success: true,
learned: true,
commandSuccess: success,
errorType: errorPattern?.errorType || null,
patternValue: intel.patterns[state][action],
latencyMs: latency,
timestamp: new Date().toISOString()
};
}
};
//# sourceMappingURL=post-command.js.map