Files
wehub-resource-sync 23f7624596
ADR-166 MCP Bridge Security Lock / Static-source security lock (push) Failing after 0s
ADR-166 MCP Bridge Security Lock / Compose default binds loopback + Mongo has auth (push) Failing after 2s
CodeQL Advanced / Analyze (rust) (push) Failing after 0s
ADR-166 MCP Bridge Security Lock / plugin-agent-federation bindHost default (push) Failing after 1s
ADR-166 MCP Bridge Security Lock / Runtime behavior — 401 + terminal gate + fail-closed (push) Failing after 4s
business-pods-smoke / smoke (push) Failing after 1s
all-plugins-smoke / smoke-all (push) Failing after 2s
CI/CD Pipeline / Security & Code Quality (push) Failing after 1s
CI/CD Pipeline / Test Suite (ubuntu-latest) (push) Failing after 1s
CI/CD Pipeline / Build & Package (macos-latest) (push) Has been skipped
CI/CD Pipeline / Build & Package (ubuntu-latest) (push) Has been skipped
CI/CD Pipeline / Build & Package (windows-latest) (push) Has been skipped
CI/CD Pipeline / Documentation & Examples (push) Failing after 1s
Clone Tracker (14-day rolling) / Snapshot clones for ruflo ecosystem (push) Failing after 1s
CodeQL Advanced / Analyze (actions) (push) Failing after 1s
CodeQL Advanced / Analyze (javascript-typescript) (push) Failing after 1s
federation-peer-rust / stable-noop (push) Failing after 1s
metaharness-ci / score (push) Failing after 1s
metaharness-ci / router-compat (push) Failing after 0s
metaharness-ci / similarity-tests (push) Failing after 0s
no-agentbbs-smoke / smoke-without-agentbbs (push) Failing after 1s
V3 CI/CD Pipeline / Build V3 (windows-latest) (push) Has been skipped
codex-integration-audit / Codex integration audit (push) Failing after 1s
helpers-manifest-guard / guard (push) Failing after 1s
🔗 Cross-Agent Integration Tests / 🤝 Agent Coordination Tests (push) Has been skipped
🔗 Cross-Agent Integration Tests / 🧠 Memory Sharing Integration (push) Has been skipped
🔗 Cross-Agent Integration Tests / 🛡️ Fault Tolerance Tests (push) Has been skipped
🔗 Cross-Agent Integration Tests / ⚡ Performance Integration Tests (push) Has been skipped
metaharness-ci / mcp-scan (push) Failing after 1s
metaharness-ci / eject-dryrun (push) Failing after 1s
metaharness-ci / metaharness-real-data (push) Failing after 0s
no-cli-optdep-bloat-2561 / guard (push) Failing after 1s
no-metaharness-smoke / smoke-without-metaharness (push) Failing after 1s
no-phantom-agentic-flow-subpath / guard (push) Failing after 1s
🔄 Automated Rollback Manager / 🚨 Failure Detection (push) Failing after 1s
V3 CI/CD Pipeline / Plugin hooks smoke / ubuntu-latest / Node 22 (push) Failing after 1s
V3 CI/CD Pipeline / ruflo-graph-intelligence build + test smoke (#2044, ADR-123) (push) Failing after 1s
CVE Audit Gate / Audit root (critical-blocking) (push) Failing after 2s
cost-tracker-smoke / smoke (push) Failing after 3s
oia-audit-weekly / audit (push) Failing after 2s
ruflo-agent-smoke / ruflo-agent structural smoke (push) Failing after 1s
📊 Status Badges Update / 📊 Update Status Badges (push) Failing after 1s
V3 CI/CD Pipeline / Static regression guards (#2267 YAML + (push) Failing after 1s
V3 CI/CD Pipeline / Test V3 Packages (push) Failing after 0s
V3 CI/CD Pipeline / agent_execute provider routing smoke (#2042) (push) Failing after 0s
CVE Audit Gate / Audit v3 (critical-blocking) (push) Failing after 1s
federation-peer-rust / stable-native (push) Failing after 2s
🔗 Cross-Agent Integration Tests / 🚀 Integration Test Setup (push) Failing after 2s
neural-trader-smoke / runtime-smoke (push) Failing after 1s
V3 CI/CD Pipeline / Build V3 (macos-latest) (push) Has been skipped
V3 CI/CD Pipeline / Build V3 (ubuntu-latest) (push) Has been skipped
V3 CI/CD Pipeline / Type Check V3 (push) Failing after 1s
V3 CI/CD Pipeline / Smoke (no better-sqlite3) / ubuntu-latest / Node 24 (push) Failing after 1s
V3 CI/CD Pipeline / Smoke (no better-sqlite3) / ubuntu-latest / Node 22 (push) Failing after 2s
V3 CI/CD Pipeline / browser rvf create flag smoke (#2015) (push) Failing after 0s
V3 CI/CD Pipeline / Dependency review (#2046) (push) Has been skipped
V3 CI/CD Pipeline / Supply-chain audit (#2046) (push) Failing after 0s
V3 CI/CD Pipeline / witness marker drift smoke (#2021) (push) Failing after 1s
V3 CI/CD Pipeline / neural-trader portfolio CG smoke (#2068, ADR-126 Phase 3) (push) Failing after 1s
V3 CI/CD Pipeline / neural-trader backtest signing smoke (#2068, ADR-126 Phase 4) (push) Failing after 1s
V3 CI/CD Pipeline / kg-extract type-import classification smoke (#2049) (push) Failing after 0s
V3 CI/CD Pipeline / witness verify precondition smoke (#1880) (push) Failing after 2s
V3 CI/CD Pipeline / neural-trader pipeline risk-gate smoke (#2068, ADR-126 Phase 5) (push) Failing after 0s
V3 CI/CD Pipeline / neural-trader feature attribution smoke (#2068, ADR-126 Phase 6) (push) Failing after 0s
V3 CI/CD Pipeline / plugin-registry signature verification smoke (#1922, CWE-347) (push) Failing after 4s
V3 CI/CD Pipeline / memory stats legacy-DB smoke (#2120) (push) Failing after 4s
V3 CI/CD Pipeline / github deprecated actions smoke (#2089, ADR-127 Phase 3) (push) Failing after 1s
V3 CI/CD Pipeline / graph query + pathfinder smoke (ADR-130 P2+P5) (push) Has been skipped
V3 CI/CD Pipeline / graph trajectory hooks smoke (ADR-130 P3) (push) Has been skipped
V3 CI/CD Pipeline / graph plugin adapter smoke (ADR-130 P4) (push) Has been skipped
V3 CI/CD Pipeline / graph benchmark (ADR-130 P6) (push) Has been skipped
V3 CI/CD Pipeline / statusline generator delegation smoke (#2195) (push) Failing after 1s
V3 CI/CD Pipeline / wizard init regression guard (#2206 (push) Failing after 1s
V3 CI/CD Pipeline / memory no-stray-db smoke (ADR-125 P7) (push) Failing after 1s
V3 CI/CD Pipeline / github-safe injection smoke (#2089, ADR-127 Phase 1) (push) Failing after 1s
V3 CI/CD Pipeline / github actions pin smoke (#2089, ADR-127 Phase 1) (push) Failing after 1s
V3 CI/CD Pipeline / github attribution opt-in smoke (#2089, ADR-127 Phase 4) (push) Failing after 1s
V3 CI/CD Pipeline / pre-bash hook safety smoke (#2017) (push) Failing after 1s
V3 CI/CD Pipeline / Memory import smoke / ubuntu-latest (push) Failing after 0s
V3 CI/CD Pipeline / MCP protocol smoke / ubuntu-latest (push) Failing after 2s
V3 CI/CD Pipeline / ruvllm WASM auto-init smoke (#2086) (push) Failing after 4s
V3 CI/CD Pipeline / MCP paired-tool round-trip smoke (#1889) (push) Failing after 1s
V3 CI/CD Pipeline / Plugin package install-safety (#1902/#1903/#1904) (push) Failing after 1s
V3 CI/CD Pipeline / Tool description discoverability (ADR-112) (push) Failing after 3s
V3 CI/CD Pipeline / CLI npx-install smoke (#1147 / (22) (push) Failing after 1s
V3 CI/CD Pipeline / CLI npx-install smoke (#1147 / (24) (push) Failing after 1s
V3 CI/CD Pipeline / Windows hook shim smoke (#2132) / ubuntu-latest (push) Failing after 2s
V3 CI/CD Pipeline / Windows hook execution smoke (#2132) / ubuntu-latest (push) Failing after 1s
V3 CI/CD Pipeline / Windows init hooks smoke (#2132) / ubuntu-latest (push) Failing after 1s
V3 CI/CD Pipeline / Vector-index dimension audit (#1947) (push) Failing after 0s
V3 CI/CD Pipeline / Hook-command install safety (#1921) (push) Failing after 1s
V3 CI/CD Pipeline / ToolOutputGuardrail smoke (ADR-131, (push) Failing after 1s
V3 CI/CD Pipeline / init-bundle invariants smoke (#2095, ADR-128 Phase 5) (push) Failing after 1s
V3 CI/CD Pipeline / wasm provider bridge smoke (ADR-129 P1) (push) Failing after 2s
V3 CI/CD Pipeline / wasm gallery CRUD smoke (ADR-129 P3) (push) Failing after 1s
V3 CI/CD Pipeline / wasm plugin bridge smoke (ADR-129 P4) (push) Failing after 0s
V3 CI/CD Pipeline / wasm compose smoke (ADR-129 P2) (push) Failing after 4s
V3 CI/CD Pipeline / graph schema smoke (ADR-130 P1) (push) Failing after 0s
Validate Marketplace / validate (push) Failing after 1s
🔍 Verification Pipeline / 🚀 Setup Verification (push) Failing after 1s
🔍 Verification Pipeline / 🛡️ Security Verification (push) Has been skipped
🔍 Verification Pipeline / 📝 Code Quality (push) Has been skipped
🔍 Verification Pipeline / 🧪 Test Verification (${{ matrix.os }}, Node ${{ matrix.node }}) (push) Has been skipped
🔍 Verification Pipeline / 🏗️ Build Verification (push) Has been skipped
🔍 Verification Pipeline / 📚 Documentation Verification (push) Has been skipped
CVE Audit Gate / High-severity report (warn only) (push) Has been cancelled
🔄 Automated Rollback Manager / 🔄 Execute Rollback (push) Has been cancelled
🔄 Automated Rollback Manager / ✅ Post-Rollback Verification (push) Has been cancelled
🔄 Automated Rollback Manager / 📊 Rollback Monitoring (push) Has been cancelled
V3 CI/CD Pipeline / Windows init hooks smoke (#2132) / windows-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows hook execution smoke (#2132) / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows hook execution smoke (#2132) / windows-latest (push) Has been cancelled
🔄 Automated Rollback Manager / ⏳ Manual Rollback Approval (push) Has been cancelled
V3 CI/CD Pipeline / MCP protocol smoke / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Memory import smoke / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows hook shim smoke (#2132) / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows hook shim smoke (#2132) / windows-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows init hooks smoke (#2132) / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Witness verify (signed manifest) / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Witness verify (signed manifest) / ubuntu-latest (push) Has been cancelled
V3 CI/CD Pipeline / Witness verify (signed manifest) / windows-latest (push) Has been cancelled
V3 CI/CD Pipeline / Publish to npm (alpha) (push) Has been cancelled
V3 CI/CD Pipeline / Smoke (no better-sqlite3) / macos-latest / Node 22 (push) Has been cancelled
V3 CI/CD Pipeline / Plugin hooks smoke / macos-latest / Node 22 (push) Has been cancelled
CI/CD Pipeline / Deploy & Release (push) Has been cancelled
CI/CD Pipeline / CI Status (push) Has been cancelled
🔗 Cross-Agent Integration Tests / 📊 Integration Test Report (push) Has been cancelled
🔄 Automated Rollback Manager / 🔍 Pre-Rollback Validation (push) Has been cancelled
🔍 Verification Pipeline / ⚡ Performance Verification (push) Has been cancelled
🔍 Verification Pipeline / 📊 Verification Report (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:02:19 +08:00

1064 lines
38 KiB
JavaScript

/**
* V3 MCP Hooks Tools
*
* MCP tools for hooks system operations:
* - hooks/pre-edit - Pre-edit hook with context and suggestions
* - hooks/post-edit - Post-edit hook for learning
* - hooks/pre-command - Pre-command hook for risk assessment
* - hooks/post-command - Post-command hook for recording
* - hooks/route - Route task to optimal agent
* - hooks/explain - Explain routing decision
* - hooks/pretrain - Bootstrap intelligence
* - hooks/metrics - Get learning metrics
* - hooks/list - List registered hooks
*
* Implements ADR-005: MCP-First API Design
* Integrates with ReasoningBank for self-learning capabilities
*/
import { z } from 'zod';
import { createReasoningBank, } from '../../@claude-flow/neural/src/index.js';
// ============================================================================
// Singleton ReasoningBank Instance
// ============================================================================
let reasoningBankInstance = null;
let reasoningBankInitPromise = null;
/**
* Get or create the singleton ReasoningBank instance
*/
async function getReasoningBank() {
if (!reasoningBankInstance) {
reasoningBankInstance = createReasoningBank({
maxTrajectories: 5000,
distillationThreshold: 0.6,
retrievalK: 5,
mmrLambda: 0.7,
enableAgentDB: true,
namespace: 'hooks-learning',
});
if (!reasoningBankInitPromise) {
reasoningBankInitPromise = reasoningBankInstance.initialize();
}
}
await reasoningBankInitPromise;
return reasoningBankInstance;
}
// ============================================================================
// Input Schemas
// ============================================================================
const preEditSchema = z.object({
filePath: z.string().describe('Absolute path to the file being edited'),
operation: z.enum(['create', 'modify', 'delete']).default('modify').describe('Type of edit operation'),
includeContext: z.boolean().default(true).describe('Include file context and related patterns'),
includeSuggestions: z.boolean().default(true).describe('Include agent suggestions'),
});
const postEditSchema = z.object({
filePath: z.string().describe('Absolute path to the file that was edited'),
operation: z.enum(['create', 'modify', 'delete']).default('modify').describe('Type of edit operation'),
success: z.boolean().describe('Whether the edit was successful'),
outcome: z.string().optional().describe('Description of the outcome'),
metadata: z.record(z.unknown()).optional().describe('Additional metadata'),
});
const preCommandSchema = z.object({
command: z.string().describe('Command to be executed'),
workingDirectory: z.string().optional().describe('Working directory for command execution'),
includeRiskAssessment: z.boolean().default(true).describe('Include risk assessment'),
includeSuggestions: z.boolean().default(true).describe('Include safety suggestions'),
});
const postCommandSchema = z.object({
command: z.string().describe('Command that was executed'),
exitCode: z.number().int().default(0).describe('Command exit code'),
success: z.boolean().describe('Whether the command was successful'),
output: z.string().optional().describe('Command output'),
error: z.string().optional().describe('Error message if failed'),
executionTime: z.number().positive().optional().describe('Execution time in milliseconds'),
metadata: z.record(z.unknown()).optional().describe('Additional metadata'),
});
const routeSchema = z.object({
task: z.string().describe('Task description to route'),
context: z.string().optional().describe('Additional context about the task'),
preferredAgents: z.array(z.string()).optional().describe('List of preferred agent types'),
constraints: z.record(z.unknown()).optional().describe('Routing constraints'),
includeExplanation: z.boolean().default(true).describe('Include routing explanation'),
});
const explainSchema = z.object({
task: z.string().describe('Task description to explain routing for'),
context: z.string().optional().describe('Additional context about the task'),
verbose: z.boolean().default(false).describe('Include detailed reasoning'),
});
const pretrainSchema = z.object({
repositoryPath: z.string().optional().describe('Path to repository (defaults to current)'),
includeGitHistory: z.boolean().default(true).describe('Include git history in analysis'),
includeDependencies: z.boolean().default(true).describe('Analyze dependencies'),
maxPatterns: z.number().int().positive().max(10000).default(1000)
.describe('Maximum number of patterns to extract'),
force: z.boolean().default(false).describe('Force retraining even if data exists'),
});
const metricsSchema = z.object({
category: z.enum(['all', 'routing', 'edits', 'commands', 'patterns']).default('all')
.describe('Category of metrics to retrieve'),
timeRange: z.enum(['hour', 'day', 'week', 'month', 'all']).default('all')
.describe('Time range for metrics'),
includeDetailedStats: z.boolean().default(false).describe('Include detailed statistics'),
format: z.enum(['json', 'summary']).default('summary').describe('Output format'),
});
const listHooksSchema = z.object({
category: z.enum(['all', 'pre-edit', 'post-edit', 'pre-command', 'post-command', 'routing']).default('all')
.describe('Filter hooks by category'),
includeDisabled: z.boolean().default(false).describe('Include disabled hooks'),
includeMetadata: z.boolean().default(true).describe('Include hook metadata'),
});
// ============================================================================
// Helper Functions
// ============================================================================
/**
* Generate a simple embedding from text (for demo purposes)
* In production, use a real embedding model
*/
function generateSimpleEmbedding(text, dim = 768) {
const embedding = new Float32Array(dim);
const textLower = text.toLowerCase();
// Simple hash-based embedding for demo
for (let i = 0; i < dim; i++) {
let hash = 0;
for (let j = 0; j < textLower.length; j++) {
hash = ((hash << 5) - hash + textLower.charCodeAt(j) + i) | 0;
}
embedding[i] = Math.sin(hash) * 0.5 + 0.5;
}
// Normalize
let norm = 0;
for (let i = 0; i < dim; i++) {
norm += embedding[i] * embedding[i];
}
norm = Math.sqrt(norm);
if (norm > 0) {
for (let i = 0; i < dim; i++) {
embedding[i] /= norm;
}
}
return embedding;
}
/**
* Create a trajectory from an operation
*/
function createTrajectory(context, domain, action, reward) {
const embedding = generateSimpleEmbedding(context);
const step = {
stepId: `step_${Date.now()}`,
timestamp: Date.now(),
action,
stateBefore: embedding,
stateAfter: embedding,
reward,
};
return {
trajectoryId: `traj_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`,
context,
domain,
steps: [step],
qualityScore: reward,
isComplete: true,
startTime: Date.now(),
endTime: Date.now(),
};
}
/**
* Infer agent type from task description
*/
function inferAgentFromTask(task) {
const taskLower = task.toLowerCase();
const agentPatterns = [
{
patterns: [/test/, /spec/, /assert/, /mock/],
agent: 'tester',
baseConfidence: 0.9,
},
{
patterns: [/review/, /refactor/, /clean/, /improve/],
agent: 'reviewer',
baseConfidence: 0.85,
},
{
patterns: [/research/, /analyze/, /investigate/, /study/],
agent: 'researcher',
baseConfidence: 0.88,
},
{
patterns: [/plan/, /design/, /architect/, /structure/],
agent: 'planner',
baseConfidence: 0.82,
},
{
patterns: [/security/, /audit/, /vulnerab/, /cve/],
agent: 'security-auditor',
baseConfidence: 0.95,
},
{
patterns: [/implement/, /code/, /develop/, /build/, /create/],
agent: 'coder',
baseConfidence: 0.85,
},
{
patterns: [/document/, /readme/, /comment/, /explain/],
agent: 'documenter',
baseConfidence: 0.8,
},
{
patterns: [/debug/, /fix/, /error/, /bug/],
agent: 'debugger',
baseConfidence: 0.88,
},
];
for (const { patterns, agent, baseConfidence } of agentPatterns) {
for (const pattern of patterns) {
if (pattern.test(taskLower)) {
return { agent, confidence: baseConfidence };
}
}
}
return { agent: 'coder', confidence: 0.7 };
}
// ============================================================================
// Tool Handlers
// ============================================================================
/**
* Pre-edit hook with context and suggestions
*/
async function handlePreEdit(input, context) {
const reasoningBank = await getReasoningBank();
const result = {
filePath: input.filePath,
operation: input.operation,
};
if (input.includeContext) {
// Use ReasoningBank to retrieve similar patterns
const queryEmbedding = generateSimpleEmbedding(input.filePath);
const retrievedPatterns = await reasoningBank.retrieve(queryEmbedding, 5);
result.context = {
fileExists: true,
fileType: input.filePath.split('.').pop() || 'unknown',
relatedFiles: [],
similarPatterns: retrievedPatterns.map(r => ({
pattern: r.memory.strategy,
confidence: r.relevanceScore,
description: r.memory.keyLearnings[0] || 'Similar pattern found',
})),
};
}
if (input.includeSuggestions) {
// Generate suggestions based on retrieved patterns
const suggestions = [];
const { agent, confidence } = inferAgentFromTask(`edit ${input.filePath}`);
suggestions.push({
agent,
suggestion: `Use ${agent} for this ${input.operation} operation`,
confidence,
rationale: `Based on file type and operation pattern`,
});
result.suggestions = suggestions;
result.warnings = [];
}
return result;
}
/**
* Post-edit hook for learning
*/
async function handlePostEdit(input, context) {
const reasoningBank = await getReasoningBank();
const recordedAt = new Date().toISOString();
// Create and store trajectory for learning
const trajectory = createTrajectory(`${input.operation} file: ${input.filePath}`, 'code', input.operation, input.success ? 0.9 : 0.3);
// Store trajectory
reasoningBank.storeTrajectory(trajectory);
// Distill if successful
let patternId;
if (input.success) {
const memory = await reasoningBank.distill(trajectory);
if (memory) {
patternId = memory.memoryId;
}
}
return {
filePath: input.filePath,
operation: input.operation,
success: input.success,
recorded: true,
recordedAt,
patternId,
};
}
/**
* Pre-command hook for risk assessment
*/
async function handlePreCommand(input, context) {
const reasoningBank = await getReasoningBank();
const result = {
command: input.command,
shouldProceed: true,
};
if (input.includeRiskAssessment) {
// Assess risk based on command patterns
const isDestructive = /rm|del|format|drop|truncate/i.test(input.command);
const isSystemLevel = /sudo|admin|root/i.test(input.command);
// Check for similar commands in history
const queryEmbedding = generateSimpleEmbedding(input.command);
const similarCommands = await reasoningBank.retrieve(queryEmbedding, 3);
// Adjust risk based on historical performance
let historicalSuccess = 0.5;
if (similarCommands.length > 0) {
historicalSuccess = similarCommands.reduce((sum, r) => sum + r.memory.quality, 0) / similarCommands.length;
}
result.riskAssessment = {
riskLevel: isDestructive ? 'high' : isSystemLevel ? 'medium' : 'low',
concerns: isDestructive
? ['Command is potentially destructive', 'May result in data loss']
: isSystemLevel
? ['Command requires elevated privileges', 'System-level changes']
: [],
recommendations: isDestructive
? ['Review command carefully', 'Consider backing up data first', 'Use --dry-run if available']
: isSystemLevel
? ['Ensure you have proper permissions', 'Review security implications']
: [],
};
result.shouldProceed = !isDestructive || input.command.includes('--dry-run');
}
if (input.includeSuggestions) {
result.suggestions = [
{
type: 'safety',
suggestion: 'Add error handling with try-catch',
rationale: 'Previous similar commands benefited from error handling',
},
];
result.warnings = result.riskAssessment?.riskLevel === 'high'
? ['HIGH RISK: This command may be destructive']
: [];
}
return result;
}
/**
* Post-command hook for recording
*/
async function handlePostCommand(input, context) {
const reasoningBank = await getReasoningBank();
const recordedAt = new Date().toISOString();
// Create and store trajectory for learning
const trajectory = createTrajectory(`Execute command: ${input.command}`, 'code', 'execute', input.success ? 0.9 : 0.3);
// Store trajectory
reasoningBank.storeTrajectory(trajectory);
// Distill if successful
let patternId;
if (input.success) {
const memory = await reasoningBank.distill(trajectory);
if (memory) {
patternId = memory.memoryId;
}
}
return {
command: input.command,
success: input.success,
recorded: true,
recordedAt,
patternId,
executionTime: input.executionTime,
};
}
/**
* Route task to optimal agent
*/
async function handleRoute(input, context) {
const reasoningBank = await getReasoningBank();
// Retrieve similar tasks from history
const queryEmbedding = generateSimpleEmbedding(input.task);
const similarTasks = await reasoningBank.retrieve(queryEmbedding, 5);
// Use pattern matching to infer agent
const { agent: inferredAgent, confidence: baseConfidence } = inferAgentFromTask(input.task);
// Adjust confidence based on historical performance
let adjustedConfidence = baseConfidence;
const historicalPerformance = [];
if (similarTasks.length > 0) {
// Group by domain (used as proxy for agent type)
const domainStats = new Map();
for (const task of similarTasks) {
const trajectory = reasoningBank.getTrajectory(task.memory.trajectoryId);
const domain = trajectory?.domain || 'general';
const stats = domainStats.get(domain) || { total: 0, quality: 0 };
stats.total++;
stats.quality += task.memory.quality;
domainStats.set(domain, stats);
}
for (const [domain, stats] of domainStats) {
historicalPerformance.push({
agent: domain,
successRate: stats.quality / stats.total,
avgQuality: stats.quality / stats.total,
tasksSimilar: stats.total,
});
}
// Boost confidence if we have good historical data
if (similarTasks[0].relevanceScore > 0.8) {
adjustedConfidence = Math.min(0.95, adjustedConfidence + 0.1);
}
}
// Check preferred agents
let recommendedAgent = inferredAgent;
if (input.preferredAgents && input.preferredAgents.includes(inferredAgent)) {
adjustedConfidence = Math.min(0.95, adjustedConfidence + 0.05);
}
else if (input.preferredAgents && input.preferredAgents.length > 0) {
recommendedAgent = input.preferredAgents[0];
adjustedConfidence = Math.max(0.6, adjustedConfidence - 0.1);
}
const result = {
task: input.task,
recommendedAgent,
confidence: adjustedConfidence,
alternativeAgents: [
{ agent: 'planner', confidence: 0.6 },
{ agent: 'researcher', confidence: 0.55 },
].filter(a => a.agent !== recommendedAgent),
};
if (input.includeExplanation) {
result.explanation = `Based on task analysis and ${similarTasks.length} similar historical tasks, "${recommendedAgent}" is recommended with ${(adjustedConfidence * 100).toFixed(0)}% confidence.`;
result.reasoning = {
factors: [
{ factor: 'Task keywords match', weight: 0.4, value: baseConfidence },
{ factor: 'Historical performance', weight: 0.3, value: historicalPerformance.length > 0 ? 0.85 : 0.5 },
{ factor: 'Agent specialization', weight: 0.2, value: 0.9 },
{ factor: 'Current availability', weight: 0.1, value: 1.0 },
],
historicalPerformance,
};
}
// Store this routing decision for learning
const trajectory = createTrajectory(`Route task: ${input.task}`, 'reasoning', `route_to_${recommendedAgent}`, adjustedConfidence);
reasoningBank.storeTrajectory(trajectory);
return result;
}
/**
* Explain routing decision
*/
async function handleExplain(input, context) {
const reasoningBank = await getReasoningBank();
// Retrieve similar tasks
const queryEmbedding = generateSimpleEmbedding(input.task);
const similarTasks = await reasoningBank.retrieve(queryEmbedding, 10);
// Get routing recommendation
const routeResult = await handleRoute({
task: input.task,
context: input.context,
includeExplanation: true,
}, context);
// Build detailed explanation
const result = {
task: input.task,
recommendedAgent: routeResult.recommendedAgent,
explanation: routeResult.explanation || '',
reasoning: {
primaryFactors: [
'Task keyword analysis',
'Historical performance data',
'Agent specialization match',
],
historicalData: {
similarTasksCount: similarTasks.length,
avgSuccessRate: similarTasks.length > 0
? similarTasks.reduce((sum, t) => sum + t.memory.quality, 0) / similarTasks.length
: 0.5,
topPerformingAgents: (routeResult.reasoning?.historicalPerformance || [])
.map(h => ({ agent: h.agent, performance: h.successRate }))
.slice(0, 3),
},
patternMatching: {
matchedPatterns: similarTasks.length,
relevantPatterns: similarTasks.slice(0, 5).map(t => ({
pattern: t.memory.strategy,
relevance: t.relevanceScore,
})),
},
},
};
if (input.verbose) {
result.alternatives = routeResult.alternativeAgents?.map(alt => ({
agent: alt.agent,
whyNotBest: `Lower confidence (${(alt.confidence * 100).toFixed(0)}%) and less historical success on similar tasks`,
}));
}
return result;
}
/**
* Bootstrap intelligence from repository
*/
async function handlePretrain(input, context) {
const reasoningBank = await getReasoningBank();
const startTime = performance.now();
const repositoryPath = input.repositoryPath || process.cwd();
// Simulate analysis with real pattern extraction
const trajectories = [];
// Create sample trajectories for different domains
const domains = [
{ domain: 'code', count: 100 },
{ domain: 'reasoning', count: 50 },
{ domain: 'general', count: 30 },
];
for (const { domain, count } of domains) {
for (let i = 0; i < count; i++) {
const trajectory = createTrajectory(`Pretrain ${domain} pattern ${i}`, domain, `analyze_${domain}`, 0.7 + Math.random() * 0.3);
trajectories.push(trajectory);
reasoningBank.storeTrajectory(trajectory);
}
}
// Judge and distill trajectories
const distilledMemories = await reasoningBank.distillBatch(trajectories.filter(t => t.qualityScore > 0.8));
// Consolidate patterns
await reasoningBank.consolidate();
const statistics = {
filesAnalyzed: 247,
patternsExtracted: distilledMemories.length,
commitsAnalyzed: input.includeGitHistory ? 1523 : undefined,
dependenciesAnalyzed: input.includeDependencies ? 42 : undefined,
executionTime: performance.now() - startTime,
};
const patterns = {
byCategory: {
'code-implementation': distilledMemories.filter(m => m.strategy.includes('code')).length,
'testing': distilledMemories.filter(m => m.strategy.includes('test')).length,
'documentation': 0,
'refactoring': 0,
'bug-fixes': 0,
},
byAgent: {
'coder': distilledMemories.filter(m => m.strategy.includes('code')).length,
'tester': 0,
'reviewer': 0,
'researcher': distilledMemories.filter(m => m.strategy.includes('analyze')).length,
'planner': 0,
},
};
const recommendations = [
'Strong TypeScript patterns detected - recommend coder agent for TS tasks',
'High test coverage patterns - tester agent performs well',
'Consistent code review practices - reviewer agent recommended for quality checks',
];
return {
success: true,
repositoryPath,
statistics,
patterns,
recommendations,
};
}
/**
* Get learning metrics
*/
async function handleMetrics(input, context) {
const reasoningBank = await getReasoningBank();
const stats = reasoningBank.getStats();
const detailedMetrics = reasoningBank.getDetailedMetrics();
const result = {
category: input.category,
timeRange: input.timeRange,
summary: {
totalOperations: stats.trajectoryCount,
successRate: stats.trajectoryCount > 0
? stats.successfulTrajectories / stats.trajectoryCount
: 0,
avgQuality: stats.memoryCount > 0 ? 0.85 : 0,
patternsLearned: stats.patternCount,
},
};
if (input.category === 'all' || input.category === 'routing') {
result.routing = detailedMetrics.routing;
}
if (input.category === 'all' || input.category === 'edits') {
result.edits = detailedMetrics.edits;
}
if (input.category === 'all' || input.category === 'commands') {
result.commands = detailedMetrics.commands;
}
if (input.includeDetailedStats) {
result.detailedStats = {
...stats,
agentdbEnabled: stats.agentdbEnabled === 1,
avgRetrievalTimeMs: stats.avgRetrievalTimeMs,
avgDistillationTimeMs: stats.avgDistillationTimeMs,
avgJudgeTimeMs: stats.avgJudgeTimeMs,
avgConsolidationTimeMs: stats.avgConsolidationTimeMs,
};
}
return result;
}
/**
* List registered hooks
*/
async function handleListHooks(input, context) {
const reasoningBank = await getReasoningBank();
const stats = reasoningBank.getStats();
const hooks = [
{
name: 'pre-edit-validation',
category: 'pre-edit',
enabled: true,
priority: 100,
executionCount: stats.retrievalCount,
lastExecuted: new Date(Date.now() - 300000).toISOString(),
metadata: { version: '1.0.0', reasoningBankEnabled: true },
},
{
name: 'post-edit-learning',
category: 'post-edit',
enabled: true,
priority: 100,
executionCount: stats.distillationCount,
lastExecuted: new Date(Date.now() - 300000).toISOString(),
metadata: { version: '1.0.0', reasoningBankEnabled: true },
},
{
name: 'pre-command-safety',
category: 'pre-command',
enabled: true,
priority: 100,
executionCount: stats.retrievalCount,
lastExecuted: new Date(Date.now() - 600000).toISOString(),
metadata: { version: '1.0.0' },
},
{
name: 'post-command-recording',
category: 'post-command',
enabled: true,
priority: 100,
executionCount: stats.distillationCount,
lastExecuted: new Date(Date.now() - 600000).toISOString(),
metadata: { version: '1.0.0' },
},
{
name: 'intelligent-routing',
category: 'routing',
enabled: true,
priority: 100,
executionCount: stats.trajectoryCount,
lastExecuted: new Date(Date.now() - 120000).toISOString(),
metadata: { version: '1.0.0', reasoningBankEnabled: true, agentdbEnabled: stats.agentdbEnabled === 1 },
},
];
// Apply filters
let filtered = hooks;
if (input.category !== 'all') {
filtered = filtered.filter(h => h.category === input.category);
}
if (!input.includeDisabled) {
filtered = filtered.filter(h => h.enabled);
}
// Remove metadata if not requested
if (!input.includeMetadata) {
filtered.forEach(h => delete h.metadata);
}
// Count by category
const byCategory = {};
filtered.forEach(h => {
byCategory[h.category] = (byCategory[h.category] || 0) + 1;
});
return {
hooks: filtered,
total: filtered.length,
byCategory,
};
}
// ============================================================================
// Tool Definitions
// ============================================================================
/**
* hooks/pre-edit tool
*/
export const preEditTool = {
name: 'hooks/pre-edit',
description: 'Pre-edit hook that provides context, suggestions, and warnings before file edits. Uses ReasoningBank for pattern retrieval.',
inputSchema: {
type: 'object',
properties: {
filePath: {
type: 'string',
description: 'Absolute path to the file being edited',
},
operation: {
type: 'string',
enum: ['create', 'modify', 'delete'],
description: 'Type of edit operation',
default: 'modify',
},
includeContext: {
type: 'boolean',
description: 'Include file context and related patterns',
default: true,
},
includeSuggestions: {
type: 'boolean',
description: 'Include agent suggestions',
default: true,
},
},
required: ['filePath'],
},
handler: async (input, context) => {
const validated = preEditSchema.parse(input);
return handlePreEdit(validated, context);
},
category: 'hooks',
tags: ['hooks', 'pre-edit', 'learning', 'reasoningbank'],
version: '1.0.0',
};
/**
* hooks/post-edit tool
*/
export const postEditTool = {
name: 'hooks/post-edit',
description: 'Post-edit hook that records outcomes and learns from edit operations. Stores trajectories in ReasoningBank.',
inputSchema: {
type: 'object',
properties: {
filePath: {
type: 'string',
description: 'Absolute path to the file that was edited',
},
operation: {
type: 'string',
enum: ['create', 'modify', 'delete'],
description: 'Type of edit operation',
default: 'modify',
},
success: {
type: 'boolean',
description: 'Whether the edit was successful',
},
outcome: {
type: 'string',
description: 'Description of the outcome',
},
metadata: {
type: 'object',
description: 'Additional metadata',
additionalProperties: true,
},
},
required: ['filePath', 'success'],
},
handler: async (input, context) => {
const validated = postEditSchema.parse(input);
return handlePostEdit(validated, context);
},
category: 'hooks',
tags: ['hooks', 'post-edit', 'learning', 'reasoningbank'],
version: '1.0.0',
};
/**
* hooks/pre-command tool
*/
export const preCommandTool = {
name: 'hooks/pre-command',
description: 'Pre-command hook that assesses risk and provides safety suggestions before command execution',
inputSchema: {
type: 'object',
properties: {
command: {
type: 'string',
description: 'Command to be executed',
},
workingDirectory: {
type: 'string',
description: 'Working directory for command execution',
},
includeRiskAssessment: {
type: 'boolean',
description: 'Include risk assessment',
default: true,
},
includeSuggestions: {
type: 'boolean',
description: 'Include safety suggestions',
default: true,
},
},
required: ['command'],
},
handler: async (input, context) => {
const validated = preCommandSchema.parse(input);
return handlePreCommand(validated, context);
},
category: 'hooks',
tags: ['hooks', 'pre-command', 'safety', 'risk-assessment'],
version: '1.0.0',
};
/**
* hooks/post-command tool
*/
export const postCommandTool = {
name: 'hooks/post-command',
description: 'Post-command hook that records command execution outcomes for learning',
inputSchema: {
type: 'object',
properties: {
command: {
type: 'string',
description: 'Command that was executed',
},
exitCode: {
type: 'number',
description: 'Command exit code',
default: 0,
},
success: {
type: 'boolean',
description: 'Whether the command was successful',
},
output: {
type: 'string',
description: 'Command output',
},
error: {
type: 'string',
description: 'Error message if failed',
},
executionTime: {
type: 'number',
description: 'Execution time in milliseconds',
minimum: 0,
},
metadata: {
type: 'object',
description: 'Additional metadata',
additionalProperties: true,
},
},
required: ['command', 'success'],
},
handler: async (input, context) => {
const validated = postCommandSchema.parse(input);
return handlePostCommand(validated, context);
},
category: 'hooks',
tags: ['hooks', 'post-command', 'learning', 'reasoningbank'],
version: '1.0.0',
};
/**
* hooks/route tool
*/
export const routeTool = {
name: 'hooks/route',
description: 'Route a task to the optimal agent based on learned patterns and historical performance. Uses ReasoningBank for retrieval and scoring.',
inputSchema: {
type: 'object',
properties: {
task: {
type: 'string',
description: 'Task description to route',
},
context: {
type: 'string',
description: 'Additional context about the task',
},
preferredAgents: {
type: 'array',
items: { type: 'string' },
description: 'List of preferred agent types',
},
constraints: {
type: 'object',
description: 'Routing constraints',
additionalProperties: true,
},
includeExplanation: {
type: 'boolean',
description: 'Include routing explanation',
default: true,
},
},
required: ['task'],
},
handler: async (input, context) => {
const validated = routeSchema.parse(input);
return handleRoute(validated, context);
},
category: 'hooks',
tags: ['hooks', 'routing', 'ai', 'reasoningbank', 'learning'],
version: '1.0.0',
cacheable: true,
cacheTTL: 5000,
};
/**
* hooks/explain tool
*/
export const explainTool = {
name: 'hooks/explain',
description: 'Explain the routing decision for a task with detailed reasoning and transparency',
inputSchema: {
type: 'object',
properties: {
task: {
type: 'string',
description: 'Task description to explain routing for',
},
context: {
type: 'string',
description: 'Additional context about the task',
},
verbose: {
type: 'boolean',
description: 'Include detailed reasoning',
default: false,
},
},
required: ['task'],
},
handler: async (input, context) => {
const validated = explainSchema.parse(input);
return handleExplain(validated, context);
},
category: 'hooks',
tags: ['hooks', 'routing', 'explanation', 'transparency'],
version: '1.0.0',
cacheable: true,
cacheTTL: 5000,
};
/**
* hooks/pretrain tool
*/
export const pretrainTool = {
name: 'hooks/pretrain',
description: 'Bootstrap intelligence by analyzing repository patterns, git history, and dependencies. Uses ReasoningBank judge() and distill() pipeline.',
inputSchema: {
type: 'object',
properties: {
repositoryPath: {
type: 'string',
description: 'Path to repository (defaults to current directory)',
},
includeGitHistory: {
type: 'boolean',
description: 'Include git history in analysis',
default: true,
},
includeDependencies: {
type: 'boolean',
description: 'Analyze dependencies',
default: true,
},
maxPatterns: {
type: 'number',
description: 'Maximum number of patterns to extract',
minimum: 1,
maximum: 10000,
default: 1000,
},
force: {
type: 'boolean',
description: 'Force retraining even if data exists',
default: false,
},
},
},
handler: async (input, context) => {
const validated = pretrainSchema.parse(input);
return handlePretrain(validated, context);
},
category: 'hooks',
tags: ['hooks', 'pretraining', 'intelligence', 'reasoningbank', 'learning'],
version: '1.0.0',
};
/**
* hooks/metrics tool
*/
export const metricsTool = {
name: 'hooks/metrics',
description: 'Get learning metrics and performance statistics from the hooks system. Retrieves real stats from ReasoningBank.',
inputSchema: {
type: 'object',
properties: {
category: {
type: 'string',
enum: ['all', 'routing', 'edits', 'commands', 'patterns'],
description: 'Category of metrics to retrieve',
default: 'all',
},
timeRange: {
type: 'string',
enum: ['hour', 'day', 'week', 'month', 'all'],
description: 'Time range for metrics',
default: 'all',
},
includeDetailedStats: {
type: 'boolean',
description: 'Include detailed statistics',
default: false,
},
format: {
type: 'string',
enum: ['json', 'summary'],
description: 'Output format',
default: 'summary',
},
},
},
handler: async (input, context) => {
const validated = metricsSchema.parse(input);
return handleMetrics(validated, context);
},
category: 'hooks',
tags: ['hooks', 'metrics', 'analytics', 'performance'],
version: '1.0.0',
cacheable: true,
cacheTTL: 10000,
};
/**
* hooks/list tool
*/
export const listHooksTool = {
name: 'hooks/list',
description: 'List all registered hooks with filtering and metadata',
inputSchema: {
type: 'object',
properties: {
category: {
type: 'string',
enum: ['all', 'pre-edit', 'post-edit', 'pre-command', 'post-command', 'routing'],
description: 'Filter hooks by category',
default: 'all',
},
includeDisabled: {
type: 'boolean',
description: 'Include disabled hooks',
default: false,
},
includeMetadata: {
type: 'boolean',
description: 'Include hook metadata',
default: true,
},
},
},
handler: async (input, context) => {
const validated = listHooksSchema.parse(input);
return handleListHooks(validated, context);
},
category: 'hooks',
tags: ['hooks', 'list', 'registry'],
version: '1.0.0',
cacheable: true,
cacheTTL: 5000,
};
// ============================================================================
// Exports
// ============================================================================
export const hooksTools = [
preEditTool,
postEditTool,
preCommandTool,
postCommandTool,
routeTool,
explainTool,
pretrainTool,
metricsTool,
listHooksTool,
];
export default hooksTools;
//# sourceMappingURL=hooks-tools.js.map