151 lines
6.7 KiB
JavaScript
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
|