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

151 lines
6.7 KiB
JavaScript

/**
* Transfer Hook - Cross-project pattern transfer
* Enables knowledge sharing between projects
*/
import { z } from 'zod';
import * as path from 'path';
import * as fs from 'fs';
import { loadIntelligence, saveIntelligence, simpleEmbed } from './shared.js';
const INTELLIGENCE_PATH = '.agentic-flow/intelligence.json';
export const hookTransferTool = {
name: 'hook_transfer',
description: 'Transfer learned patterns from another project',
parameters: z.object({
sourceProject: z.string().describe('Path to source project'),
minConfidence: z.number().optional().default(0.5).describe('Minimum pattern score to transfer'),
maxPatterns: z.number().optional().default(50).describe('Maximum patterns to transfer'),
mode: z.enum(['merge', 'replace', 'additive']).optional().default('merge')
.describe('Transfer mode: merge combines, replace overwrites, additive only adds new')
}),
execute: async ({ sourceProject, minConfidence, maxPatterns, mode }, { onProgress }) => {
const startTime = Date.now();
onProgress?.({ progress: 0.1, message: 'Loading source intelligence...' });
// Load source intelligence
const sourcePath = path.join(sourceProject, INTELLIGENCE_PATH);
if (!fs.existsSync(sourcePath)) {
throw new Error(`Source intelligence not found at ${sourcePath}. Run pretrain on source project first.`);
}
let sourceIntel;
try {
sourceIntel = JSON.parse(fs.readFileSync(sourcePath, 'utf-8'));
}
catch (e) {
throw new Error(`Failed to parse source intelligence: ${e}`);
}
// Load target (current) intelligence
const targetIntel = loadIntelligence();
onProgress?.({ progress: 0.3, message: 'Analyzing patterns...' });
// Track transfer stats
const stats = {
patternsTransferred: 0,
memoriesTransferred: 0,
sequencesTransferred: 0,
errorsTransferred: 0,
skipped: 0
};
// Transfer patterns
const patternsToTransfer = [];
for (const [state, agents] of Object.entries(sourceIntel.patterns || {})) {
for (const [agent, score] of Object.entries(agents)) {
if (typeof score === 'number' && score >= minConfidence) {
patternsToTransfer.push({ state, agent, score });
}
}
}
// Sort by score and limit
patternsToTransfer.sort((a, b) => b.score - a.score);
const selectedPatterns = patternsToTransfer.slice(0, maxPatterns);
onProgress?.({ progress: 0.5, message: 'Transferring patterns...' });
// Apply patterns based on mode
for (const pattern of selectedPatterns) {
if (!targetIntel.patterns[pattern.state]) {
targetIntel.patterns[pattern.state] = {};
}
const currentValue = targetIntel.patterns[pattern.state][pattern.agent] || 0;
switch (mode) {
case 'replace':
// Overwrite with source value (reduced confidence)
targetIntel.patterns[pattern.state][pattern.agent] = pattern.score * 0.7;
stats.patternsTransferred++;
break;
case 'additive':
// Only add if not present
if (currentValue === 0) {
targetIntel.patterns[pattern.state][pattern.agent] = pattern.score * 0.5;
stats.patternsTransferred++;
}
else {
stats.skipped++;
}
break;
case 'merge':
default:
// Weighted average
targetIntel.patterns[pattern.state][pattern.agent] =
currentValue * 0.6 + pattern.score * 0.4;
stats.patternsTransferred++;
break;
}
}
onProgress?.({ progress: 0.7, message: 'Transferring memories...' });
// Transfer high-quality memories
if (sourceIntel.memories && sourceIntel.memories.length > 0) {
const existingContents = new Set(targetIntel.memories.map(m => m.content.slice(0, 50)));
for (const mem of sourceIntel.memories) {
// Skip duplicates
if (existingContents.has(mem.content.slice(0, 50))) {
continue;
}
// Only transfer project-type memories (not ephemeral)
if (mem.type === 'project' || mem.type === 'success') {
targetIntel.memories.push({
...mem,
type: 'transferred',
created: new Date().toISOString(),
embedding: mem.embedding || simpleEmbed(mem.content)
});
stats.memoriesTransferred++;
if (stats.memoriesTransferred >= 20)
break; // Limit
}
}
}
// Transfer error patterns (valuable for learning)
if (sourceIntel.errorPatterns && sourceIntel.errorPatterns.length > 0) {
const existingErrors = new Set(targetIntel.errorPatterns.map(e => e.errorType));
for (const ep of sourceIntel.errorPatterns) {
if (!existingErrors.has(ep.errorType) && ep.resolution) {
targetIntel.errorPatterns.push(ep);
stats.errorsTransferred++;
if (stats.errorsTransferred >= 10)
break; // Limit
}
}
}
onProgress?.({ progress: 0.9, message: 'Saving intelligence...' });
// Save updated intelligence
saveIntelligence(targetIntel);
onProgress?.({ progress: 1.0, message: 'Transfer complete!' });
const latency = Date.now() - startTime;
return {
success: true,
sourceProject,
mode,
transferred: {
patterns: stats.patternsTransferred,
memories: stats.memoriesTransferred,
sequences: stats.sequencesTransferred,
errorPatterns: stats.errorsTransferred
},
skipped: stats.skipped,
targetStats: {
totalPatterns: Object.keys(targetIntel.patterns).length,
totalMemories: targetIntel.memories.length,
totalErrors: targetIntel.errorPatterns.length
},
latencyMs: latency,
timestamp: new Date().toISOString()
};
}
};
//# sourceMappingURL=transfer.js.map