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

658 lines
21 KiB
TypeScript

/**
* ReasoningBank Integration Plugin
*
* Stores successful reasoning trajectories and retrieves them for similar problems.
* Uses @ruvector/wasm for vector storage with HNSW indexing (<1ms search).
*
* Features:
* - Store reasoning chains with embeddings
* - Retrieve similar past reasoning for new problems
* - Learn from successful/failed outcomes
* - Verdict judgment for quality scoring
* - Memory distillation for pattern extraction
*
* @example
* ```typescript
* import { reasoningBankPlugin } from '@claude-flow/plugins/examples/ruvector-plugins';
* await getDefaultRegistry().register(reasoningBankPlugin);
* ```
*/
import {
PluginBuilder,
MCPToolBuilder,
HookBuilder,
HookEvent,
HookPriority,
Security,
} from '../../src/index.js';
// Import shared vector utilities (consolidated from all plugins)
import {
IVectorDB,
createVectorDB,
generateHashEmbedding,
} from './shared/vector-utils.js';
// ============================================================================
// Types
// ============================================================================
export interface ReasoningTrajectory {
id: string;
problem: string;
problemEmbedding?: Float32Array;
steps: ReasoningStep[];
outcome: 'success' | 'failure' | 'partial';
score: number;
metadata: {
taskType: string;
duration: number;
tokensUsed: number;
model?: string;
timestamp: Date;
};
}
export interface ReasoningStep {
thought: string;
action: string;
observation: string;
confidence: number;
}
export interface RetrievalResult {
trajectory: ReasoningTrajectory;
similarity: number;
applicability: number;
}
export interface VerdictJudgment {
trajectoryId: string;
verdict: 'accept' | 'reject' | 'revise';
score: number;
feedback: string;
improvements?: string[];
}
// ============================================================================
// ReasoningBank Core
// ============================================================================
export class ReasoningBank {
private vectorDb: IVectorDB | null = null;
private trajectories = new Map<string, ReasoningTrajectory>();
private dimensions: number;
private nextId = 1;
private initPromise: Promise<void> | null = null;
constructor(dimensions: number = 1536) {
this.dimensions = dimensions;
}
/**
* Initialize the vector database.
*/
async initialize(): Promise<void> {
if (this.vectorDb) return;
if (this.initPromise) return this.initPromise;
this.initPromise = (async () => {
this.vectorDb = await createVectorDB(this.dimensions);
})();
return this.initPromise;
}
private async ensureInitialized(): Promise<IVectorDB> {
await this.initialize();
return this.vectorDb!;
}
/**
* Store a reasoning trajectory.
*/
async store(trajectory: Omit<ReasoningTrajectory, 'id'>): Promise<string> {
const db = await this.ensureInitialized();
const id = `reasoning-${this.nextId++}`;
// Validate inputs
const safeProblem = Security.validateString(trajectory.problem, { maxLength: 10000 });
// Generate embedding from problem + steps
const embedding = trajectory.problemEmbedding ?? this.generateEmbedding(safeProblem);
const fullTrajectory: ReasoningTrajectory = {
...trajectory,
id,
problem: safeProblem,
problemEmbedding: embedding,
};
// Store in vector DB with HNSW indexing
db.insert(embedding, id, {
problem: safeProblem,
outcome: trajectory.outcome,
score: trajectory.score,
taskType: trajectory.metadata.taskType,
stepsCount: trajectory.steps.length,
timestamp: trajectory.metadata.timestamp.toISOString(),
});
// Store full trajectory
this.trajectories.set(id, fullTrajectory);
return id;
}
/**
* Retrieve similar reasoning trajectories (<1ms with HNSW).
*/
async retrieve(
problem: string,
options?: {
k?: number;
minScore?: number;
taskType?: string;
outcomeFilter?: 'success' | 'failure' | 'partial';
}
): Promise<RetrievalResult[]> {
const db = await this.ensureInitialized();
const k = options?.k ?? 5;
const minScore = options?.minScore ?? 0.5;
const safeProblem = Security.validateString(problem, { maxLength: 10000 });
const queryEmbedding = this.generateEmbedding(safeProblem);
// HNSW search - sub-millisecond for 10K+ vectors
const searchResults = db.search(queryEmbedding, k * 2);
const results: RetrievalResult[] = [];
for (const result of searchResults) {
if (result.score < minScore) continue;
const trajectory = this.trajectories.get(result.id);
if (!trajectory) continue;
// Apply filters
if (options?.taskType && trajectory.metadata.taskType !== options.taskType) continue;
if (options?.outcomeFilter && trajectory.outcome !== options.outcomeFilter) continue;
// Calculate applicability based on task type match and recency
const applicability = this.calculateApplicability(trajectory, safeProblem, options?.taskType);
results.push({
trajectory,
similarity: result.score,
applicability,
});
if (results.length >= k) break;
}
return results.sort((a, b) => (b.similarity * b.applicability) - (a.similarity * a.applicability));
}
/**
* Judge a trajectory and update its score.
*/
async judge(judgment: VerdictJudgment): Promise<void> {
const trajectory = this.trajectories.get(judgment.trajectoryId);
if (!trajectory) {
throw new Error(`Trajectory ${judgment.trajectoryId} not found`);
}
const db = await this.ensureInitialized();
// Update score based on verdict
const scoreAdjustment = {
accept: 0.1,
reject: -0.2,
revise: -0.05,
}[judgment.verdict];
trajectory.score = Math.max(0, Math.min(1, trajectory.score + scoreAdjustment));
// If rejected with low score, remove from index
if (judgment.verdict === 'reject' && trajectory.score < 0.2) {
db.delete(trajectory.id);
this.trajectories.delete(trajectory.id);
}
}
/**
* Distill patterns from successful trajectories.
*/
async distill(taskType?: string): Promise<{
patterns: string[];
commonSteps: string[];
avgSteps: number;
successRate: number;
}> {
const trajectories = Array.from(this.trajectories.values())
.filter(t => (!taskType || t.metadata.taskType === taskType) && t.score > 0.6);
if (trajectories.length === 0) {
return { patterns: [], commonSteps: [], avgSteps: 0, successRate: 0 };
}
const actionCounts = new Map<string, number>();
let totalSteps = 0;
let successCount = 0;
for (const t of trajectories) {
totalSteps += t.steps.length;
if (t.outcome === 'success') successCount++;
for (const step of t.steps) {
const count = actionCounts.get(step.action) ?? 0;
actionCounts.set(step.action, count + 1);
}
}
const commonSteps = Array.from(actionCounts.entries())
.sort((a, b) => b[1] - a[1])
.slice(0, 10)
.map(([action]) => action);
const patterns = this.extractPatterns(trajectories);
return {
patterns,
commonSteps,
avgSteps: totalSteps / trajectories.length,
successRate: successCount / trajectories.length,
};
}
/**
* Get statistics about stored trajectories.
*/
getStats(): {
total: number;
byOutcome: Record<string, number>;
byTaskType: Record<string, number>;
avgScore: number;
} {
const trajectories = Array.from(this.trajectories.values());
const byOutcome: Record<string, number> = { success: 0, failure: 0, partial: 0 };
const byTaskType: Record<string, number> = {};
let totalScore = 0;
for (const t of trajectories) {
byOutcome[t.outcome]++;
byTaskType[t.metadata.taskType] = (byTaskType[t.metadata.taskType] ?? 0) + 1;
totalScore += t.score;
}
return {
total: trajectories.length,
byOutcome,
byTaskType,
avgScore: trajectories.length > 0 ? totalScore / trajectories.length : 0,
};
}
// =========================================================================
// Private Helpers
// =========================================================================
/**
* External embedding provider (optional - set via setEmbeddingProvider)
* When set, uses @claude-flow/embeddings for high-quality embeddings
*/
private embeddingProvider: ((text: string) => Promise<Float32Array>) | null = null;
/**
* Set external embedding provider from @claude-flow/embeddings
*
* @example
* ```typescript
* import { createEmbeddingService } from '@claude-flow/embeddings';
* const embeddings = createEmbeddingService({ provider: 'transformers' });
* await embeddings.initialize();
* bank.setEmbeddingProvider(async (text) => {
* const result = await embeddings.embed(text);
* return result.embedding;
* });
* ```
*/
setEmbeddingProvider(provider: (text: string) => Promise<Float32Array>): void {
this.embeddingProvider = provider;
}
/**
* Generate embedding using external provider or fallback to hash-based
* Performance: <100ms with external provider, <1ms with hash fallback
*/
private generateEmbedding(text: string): Float32Array {
// Use synchronous hash-based fallback for immediate returns
// Async embeddings are handled by generateEmbeddingAsync
return this.generateHashEmbedding(text);
}
/**
* Generate embedding asynchronously using external provider if available
*/
async generateEmbeddingAsync(text: string): Promise<Float32Array> {
if (this.embeddingProvider) {
try {
return await this.embeddingProvider(text);
} catch (error) {
// Fallback to hash-based if provider fails
console.warn('[ReasoningBank] Embedding provider failed, using fallback:', error);
}
}
return this.generateHashEmbedding(text);
}
/**
* Hash-based embedding fallback (fast but low quality)
* Used when @claude-flow/embeddings is not configured
*/
private generateHashEmbedding(text: string): Float32Array {
const embedding = new Float32Array(this.dimensions);
let hash = 0;
for (let i = 0; i < text.length; i++) {
hash = ((hash << 5) - hash) + text.charCodeAt(i);
hash = hash & hash;
}
for (let i = 0; i < this.dimensions; i++) {
embedding[i] = Math.sin(hash * (i + 1) * 0.001) * 0.5 + 0.5;
}
// L2 Normalize
let norm = 0;
for (let i = 0; i < this.dimensions; i++) {
norm += embedding[i] * embedding[i];
}
norm = Math.sqrt(norm);
for (let i = 0; i < this.dimensions; i++) {
embedding[i] /= norm;
}
return embedding;
}
private calculateApplicability(
trajectory: ReasoningTrajectory,
_problem: string,
taskType?: string
): number {
let score = trajectory.score;
if (taskType && trajectory.metadata.taskType === taskType) {
score *= 1.2;
}
if (trajectory.outcome === 'success') {
score *= 1.1;
}
const age = Date.now() - trajectory.metadata.timestamp.getTime();
const daysSinceCreation = age / (1000 * 60 * 60 * 24);
if (daysSinceCreation > 7) {
score *= Math.exp(-0.05 * (daysSinceCreation - 7));
}
return Math.min(1, score);
}
private extractPatterns(trajectories: ReasoningTrajectory[]): string[] {
const patterns: string[] = [];
const sequences = new Map<string, number>();
for (const t of trajectories) {
for (let i = 0; i < t.steps.length - 1; i++) {
const seq = `${t.steps[i].action}${t.steps[i + 1].action}`;
sequences.set(seq, (sequences.get(seq) ?? 0) + 1);
}
}
for (const [seq, count] of sequences) {
if (count >= 2) {
patterns.push(`Common sequence: ${seq} (${count} occurrences)`);
}
}
return patterns.slice(0, 5);
}
}
// ============================================================================
// Plugin Definition
// ============================================================================
let reasoningBankInstance: ReasoningBank | null = null;
async function getReasoningBank(): Promise<ReasoningBank> {
if (!reasoningBankInstance) {
reasoningBankInstance = new ReasoningBank(1536);
await reasoningBankInstance.initialize();
}
return reasoningBankInstance;
}
export const reasoningBankPlugin = new PluginBuilder('reasoning-bank', '1.0.0')
.withDescription('Store and retrieve reasoning trajectories using @ruvector/wasm HNSW indexing')
.withAuthor('Claude Flow Team')
.withTags(['reasoning', 'memory', 'learning', 'ruvector', 'hnsw'])
.withMCPTools([
new MCPToolBuilder('reasoning-store')
.withDescription('Store a reasoning trajectory for future retrieval')
.addStringParam('problem', 'The problem that was solved', { required: true })
.addStringParam('steps', 'JSON array of reasoning steps', { required: true })
.addStringParam('outcome', 'Outcome: success, failure, or partial', {
required: true,
enum: ['success', 'failure', 'partial'],
})
.addNumberParam('score', 'Quality score 0-1', { default: 0.7, minimum: 0, maximum: 1 })
.addStringParam('taskType', 'Type of task (coding, research, planning, etc.)', { required: true })
.withHandler(async (params) => {
try {
const steps = JSON.parse(params.steps as string) as ReasoningStep[];
const rb = await getReasoningBank();
const id = await rb.store({
problem: params.problem as string,
steps,
outcome: params.outcome as 'success' | 'failure' | 'partial',
score: params.score as number,
metadata: {
taskType: params.taskType as string,
duration: 0,
tokensUsed: 0,
timestamp: new Date(),
},
});
return {
content: [{
type: 'text',
text: `✅ Stored reasoning trajectory: ${id}\n` +
`Problem: ${(params.problem as string).substring(0, 100)}...\n` +
`Steps: ${steps.length}\n` +
`Outcome: ${params.outcome}\n` +
`Score: ${params.score}`,
}],
};
} catch (error) {
return {
content: [{ type: 'text', text: `❌ Error: ${error instanceof Error ? error.message : String(error)}` }],
isError: true,
};
}
})
.build(),
new MCPToolBuilder('reasoning-retrieve')
.withDescription('Retrieve similar reasoning trajectories (<1ms with HNSW)')
.addStringParam('problem', 'The problem to find similar reasoning for', { required: true })
.addNumberParam('k', 'Number of results', { default: 5 })
.addNumberParam('minScore', 'Minimum similarity score', { default: 0.5 })
.addStringParam('taskType', 'Filter by task type')
.addStringParam('outcomeFilter', 'Filter by outcome', { enum: ['success', 'failure', 'partial'] })
.withHandler(async (params) => {
try {
const rb = await getReasoningBank();
const results = await rb.retrieve(params.problem as string, {
k: params.k as number,
minScore: params.minScore as number,
taskType: params.taskType as string | undefined,
outcomeFilter: params.outcomeFilter as 'success' | 'failure' | 'partial' | undefined,
});
if (results.length === 0) {
return { content: [{ type: 'text', text: '📭 No similar reasoning found.' }] };
}
const output = results.map((r, i) =>
`**${i + 1}. ${r.trajectory.id}** (similarity: ${(r.similarity * 100).toFixed(1)}%)\n` +
` Problem: ${r.trajectory.problem.substring(0, 80)}...\n` +
` Outcome: ${r.trajectory.outcome} | Steps: ${r.trajectory.steps.length}\n` +
` Actions: ${r.trajectory.steps.map(s => s.action).join(' → ')}`
).join('\n\n');
return {
content: [{ type: 'text', text: `📚 **Found ${results.length} similar trajectories:**\n\n${output}` }],
};
} catch (error) {
return {
content: [{ type: 'text', text: `❌ Error: ${error instanceof Error ? error.message : String(error)}` }],
isError: true,
};
}
})
.build(),
new MCPToolBuilder('reasoning-judge')
.withDescription('Judge a reasoning trajectory and update its score')
.addStringParam('trajectoryId', 'ID of the trajectory to judge', { required: true })
.addStringParam('verdict', 'Verdict: accept, reject, or revise', {
required: true,
enum: ['accept', 'reject', 'revise'],
})
.addStringParam('feedback', 'Feedback about the trajectory')
.withHandler(async (params) => {
try {
const rb = await getReasoningBank();
await rb.judge({
trajectoryId: params.trajectoryId as string,
verdict: params.verdict as 'accept' | 'reject' | 'revise',
score: params.verdict === 'accept' ? 0.1 : params.verdict === 'reject' ? -0.2 : -0.05,
feedback: (params.feedback as string) ?? '',
});
return {
content: [{
type: 'text',
text: `⚖️ Judged trajectory ${params.trajectoryId}: ${params.verdict}`,
}],
};
} catch (error) {
return {
content: [{ type: 'text', text: `❌ Error: ${error instanceof Error ? error.message : String(error)}` }],
isError: true,
};
}
})
.build(),
new MCPToolBuilder('reasoning-distill')
.withDescription('Extract common patterns from successful reasoning trajectories')
.addStringParam('taskType', 'Filter by task type (optional)')
.withHandler(async (params) => {
try {
const rb = await getReasoningBank();
const distilled = await rb.distill(params.taskType as string | undefined);
return {
content: [{
type: 'text',
text: `🧬 **Distilled Patterns${params.taskType ? ` for ${params.taskType}` : ''}:**\n\n` +
`**Success Rate:** ${(distilled.successRate * 100).toFixed(1)}%\n` +
`**Average Steps:** ${distilled.avgSteps.toFixed(1)}\n\n` +
`**Common Actions:**\n${distilled.commonSteps.map((s, i) => `${i + 1}. ${s}`).join('\n')}\n\n` +
`**Patterns:**\n${distilled.patterns.map((p, i) => `${i + 1}. ${p}`).join('\n') || 'None found yet'}`,
}],
};
} catch (error) {
return {
content: [{ type: 'text', text: `❌ Error: ${error instanceof Error ? error.message : String(error)}` }],
isError: true,
};
}
})
.build(),
new MCPToolBuilder('reasoning-stats')
.withDescription('Get statistics about stored reasoning trajectories')
.withHandler(async () => {
const rb = await getReasoningBank();
const stats = rb.getStats();
return {
content: [{
type: 'text',
text: `📊 **ReasoningBank Statistics:**\n\n` +
`**Total Trajectories:** ${stats.total}\n` +
`**Backend:** @ruvector/wasm HNSW\n\n` +
`**By Outcome:**\n` +
` ✅ Success: ${stats.byOutcome.success}\n` +
` ❌ Failure: ${stats.byOutcome.failure}\n` +
` ⚠️ Partial: ${stats.byOutcome.partial}\n\n` +
`**By Task Type:**\n${Object.entries(stats.byTaskType).map(([type, count]) => ` • ${type}: ${count}`).join('\n') || ' None'}\n\n` +
`**Average Score:** ${(stats.avgScore * 100).toFixed(1)}%`,
}],
};
})
.build(),
])
.withHooks([
new HookBuilder(HookEvent.PostTaskComplete)
.withName('reasoning-auto-store')
.withDescription('Automatically store successful task reasoning')
.withPriority(HookPriority.Low)
.when((ctx) => {
const data = ctx.data as { success?: boolean; reasoning?: unknown[] } | undefined;
return data?.success === true && Array.isArray(data?.reasoning) && data.reasoning.length > 0;
})
.handle(async (ctx) => {
const data = ctx.data as { problem?: string; reasoning?: ReasoningStep[]; taskType?: string };
if (!data.problem || !data.reasoning) return { success: true };
try {
const rb = await getReasoningBank();
await rb.store({
problem: data.problem,
steps: data.reasoning,
outcome: 'success',
score: 0.8,
metadata: {
taskType: data.taskType ?? 'general',
duration: 0,
tokensUsed: 0,
timestamp: new Date(),
},
});
} catch {
// Silent fail for auto-store
}
return { success: true };
})
.build(),
])
.onInitialize(async (ctx) => {
ctx.logger.info('ReasoningBank plugin initializing with @ruvector/wasm...');
await getReasoningBank();
ctx.logger.info('ReasoningBank ready - HNSW indexing enabled');
})
.build();
export default reasoningBankPlugin;