claude-flow-novice 2.18.2 → 2.18.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +106 -712
- package/claude-assets/agents/AGENT_LIFECYCLE.md +2 -0
- package/claude-assets/agents/SHARED_PROTOCOL.md +64 -0
- package/claude-assets/agents/cfn-dev-team/analysts/analyst.md +2 -0
- package/claude-assets/agents/cfn-dev-team/analysts/root-cause-analyst.md +2 -0
- package/claude-assets/agents/cfn-dev-team/architecture/api-designer-persona.md +2 -0
- package/claude-assets/agents/cfn-dev-team/architecture/base-template-generator.md +2 -0
- package/claude-assets/agents/cfn-dev-team/architecture/goal-planner.md +2 -0
- package/claude-assets/agents/cfn-dev-team/architecture/planner.md +2 -0
- package/claude-assets/agents/cfn-dev-team/architecture/system-architect.md +2 -0
- package/claude-assets/agents/cfn-dev-team/coordinators/cfn-frontend-coordinator.md +2 -0
- package/claude-assets/agents/cfn-dev-team/coordinators/consensus-builder.md +2 -0
- package/claude-assets/agents/cfn-dev-team/coordinators/handoff-coordinator.md +2 -0
- package/claude-assets/agents/cfn-dev-team/coordinators/multi-sprint-coordinator.md +2 -0
- package/claude-assets/agents/cfn-dev-team/dev-ops/devops-engineer.md +2 -0
- package/claude-assets/agents/cfn-dev-team/dev-ops/docker-specialist.md +2 -0
- package/claude-assets/agents/cfn-dev-team/dev-ops/github-commit-agent.md +2 -0
- package/claude-assets/agents/cfn-dev-team/dev-ops/kubernetes-specialist.md +2 -0
- package/claude-assets/agents/cfn-dev-team/developers/api-gateway-specialist.md +2 -0
- package/claude-assets/agents/cfn-dev-team/developers/backend-developer.md +2 -0
- package/claude-assets/agents/cfn-dev-team/developers/data/data-engineer.md +2 -0
- package/claude-assets/agents/cfn-dev-team/developers/database/database-architect.md +2 -0
- package/claude-assets/agents/cfn-dev-team/developers/database/supabase-specialist.md +2 -0
- package/claude-assets/agents/cfn-dev-team/developers/frontend/mobile-dev.md +2 -0
- package/claude-assets/agents/cfn-dev-team/developers/frontend/react-frontend-engineer.md +2 -0
- package/claude-assets/agents/cfn-dev-team/developers/frontend/typescript-specialist.md +2 -0
- package/claude-assets/agents/cfn-dev-team/developers/frontend/ui-designer.md +2 -0
- package/claude-assets/agents/cfn-dev-team/developers/graphql-specialist.md +2 -0
- package/claude-assets/agents/cfn-dev-team/developers/rust-developer.md +2 -0
- package/claude-assets/agents/cfn-dev-team/documentation/agent-type-guidelines.md +2 -0
- package/claude-assets/agents/cfn-dev-team/documentation/api-documentation.md +2 -0
- package/claude-assets/agents/cfn-dev-team/documentation/pseudocode.md +2 -0
- package/claude-assets/agents/cfn-dev-team/documentation/specification-agent.md +2 -0
- package/claude-assets/agents/cfn-dev-team/product-owners/accessibility-advocate-persona.md +2 -0
- package/claude-assets/agents/cfn-dev-team/product-owners/cto-agent.md +2 -0
- package/claude-assets/agents/cfn-dev-team/product-owners/power-user-persona.md +2 -0
- package/claude-assets/agents/cfn-dev-team/product-owners/product-owner.md +2 -0
- package/claude-assets/agents/cfn-dev-team/reviewers/code-reviewer.md +2 -0
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/code-quality-validator.md +2 -0
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/cyclomatic-complexity-reducer.md +2 -0
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/perf-analyzer.md +2 -0
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/performance-benchmarker.md +2 -0
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/quality-metrics.md +2 -0
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/security-specialist.md +2 -0
- package/claude-assets/agents/cfn-dev-team/testers/api-testing-specialist.md +2 -0
- package/claude-assets/agents/cfn-dev-team/testers/chaos-engineering-specialist.md +2 -0
- package/claude-assets/agents/cfn-dev-team/testers/contract-tester.md +2 -0
- package/claude-assets/agents/cfn-dev-team/testers/e2e/playwright-tester.md +2 -0
- package/claude-assets/agents/cfn-dev-team/testers/integration-tester.md +2 -0
- package/claude-assets/agents/cfn-dev-team/testers/interaction-tester.md +2 -0
- package/claude-assets/agents/cfn-dev-team/testers/load-testing-specialist.md +2 -0
- package/claude-assets/agents/cfn-dev-team/testers/mutation-testing-specialist.md +2 -0
- package/claude-assets/agents/cfn-dev-team/testers/playwright-tester.md +2 -0
- package/claude-assets/agents/cfn-dev-team/testers/tester.md +2 -0
- package/claude-assets/agents/cfn-dev-team/testers/unit/tdd-london-unit-swarm.md +2 -0
- package/claude-assets/agents/cfn-dev-team/testers/validation/validation-production-validator.md +2 -0
- package/claude-assets/agents/cfn-dev-team/testing/test-validation-agent.md +2 -0
- package/claude-assets/agents/cfn-dev-team/utility/agent-builder.md +39 -16
- package/claude-assets/agents/cfn-dev-team/utility/context-curator.md +2 -0
- package/claude-assets/agents/cfn-dev-team/utility/epic-creator.md +2 -0
- package/claude-assets/agents/cfn-dev-team/utility/memory-leak-specialist.md +2 -0
- package/claude-assets/agents/cfn-dev-team/utility/researcher.md +2 -0
- package/claude-assets/agents/cfn-dev-team/utility/z-ai-specialist.md +2 -0
- package/claude-assets/agents/custom/cfn-docker-expert.md +2 -0
- package/claude-assets/agents/custom/cfn-loops-cli-expert.md +2 -0
- package/claude-assets/agents/custom/cfn-redis-operations.md +2 -0
- package/claude-assets/agents/custom/cfn-system-expert.md +2 -0
- package/claude-assets/agents/custom/claude-code-expert.md +2 -0
- package/claude-assets/agents/custom/mdap-trigger-specialist.md +2 -0
- package/claude-assets/agents/custom/trigger-dev-expert.md +2 -0
- package/claude-assets/agents/docker-coordinators/cfn-docker-v3-coordinator.md +2 -0
- package/claude-assets/agents/docker-ts-fixer.md +2 -0
- package/claude-assets/agents/project-only-agents/npm-package-specialist.md +2 -0
- package/claude-assets/skills/cfn-cerebras-mcp/SKILL.md +58 -0
- package/claude-assets/skills/cfn-ruvector-codebase-index/.cfn-manifest.json +37 -0
- package/claude-assets/skills/cfn-ruvector-codebase-index/check-db.js +8 -0
- package/claude-assets/skills/cfn-ruvector-codebase-index/config.json +1 -1
- package/claude-assets/skills/cfn-ruvector-codebase-index/data/codebase_index.db +0 -0
- package/claude-assets/skills/cfn-ruvector-codebase-index/debug-search.js +19 -0
- package/claude-assets/skills/cfn-ruvector-codebase-index/get-embedding-text.js +26 -0
- package/claude-assets/skills/cfn-ruvector-codebase-index/index.sh +22 -11
- package/claude-assets/skills/cfn-ruvector-codebase-index/search.js +55 -0
- package/claude-assets/skills/cfn-ruvector-codebase-index/search.sh +32 -36
- package/claude-assets/skills/cfn-ruvector-codebase-index/standalone-indexer.js +129 -0
- package/dist/agents/agent-loader.js +165 -146
- package/dist/agents/agent-loader.js.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/ruvector/cli.js +62 -0
- package/dist/ruvector/cli.js.map +1 -0
- package/dist/ruvector/core/file-processor.js +72 -0
- package/dist/ruvector/core/file-processor.js.map +1 -0
- package/dist/ruvector/core/index.js +133 -0
- package/dist/ruvector/core/index.js.map +1 -0
- package/dist/ruvector/embeddings/index.js +24 -0
- package/dist/ruvector/embeddings/index.js.map +1 -0
- package/dist/ruvector/embeddings/openai.js +67 -0
- package/dist/ruvector/embeddings/openai.js.map +1 -0
- package/dist/ruvector/embeddings/provider.js +12 -0
- package/dist/ruvector/embeddings/provider.js.map +1 -0
- package/dist/ruvector/index.js +9 -0
- package/dist/ruvector/index.js.map +1 -0
- package/package.json +13 -5
- package/readme/README.md +25 -15
- package/scripts/update-agent-protocols.sh +116 -0
- package/LICENSE +0 -21
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CFN RuVector CLI - Semantic codebase search
|
|
4
|
+
*/ import { Command } from 'commander';
|
|
5
|
+
import { RuVectorIndex } from './core/index.js';
|
|
6
|
+
const program = new Command();
|
|
7
|
+
program.name('cfn-ruvector').description('Semantic codebase search using vector embeddings').version('1.0.0');
|
|
8
|
+
program.command('index').description('Index the codebase').argument('[directory]', 'Directory to index', '.').option('-v, --verbose', 'Verbose output').action(async (directory, options)=>{
|
|
9
|
+
try {
|
|
10
|
+
const index = new RuVectorIndex({
|
|
11
|
+
verbose: options.verbose
|
|
12
|
+
});
|
|
13
|
+
console.log(`Indexing ${directory}...`);
|
|
14
|
+
const stats = await index.indexDirectory(directory);
|
|
15
|
+
console.log(`\nDone: ${stats.indexedFiles}/${stats.totalFiles} indexed, ${stats.failedFiles} failed`);
|
|
16
|
+
} catch (error) {
|
|
17
|
+
console.error('Error:', error.message);
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
program.command('search').description('Search the codebase').argument('<query>', 'Search query').option('-n, --limit <n>', 'Number of results', '10').action(async (query, options)=>{
|
|
22
|
+
try {
|
|
23
|
+
const index = new RuVectorIndex();
|
|
24
|
+
const limit = parseInt(options.limit ?? '10', 10);
|
|
25
|
+
const results = await index.search(query, {
|
|
26
|
+
limit
|
|
27
|
+
});
|
|
28
|
+
if (results.length === 0) {
|
|
29
|
+
console.log('No results found.');
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
console.log(`\nResults for: "${query}"\n`);
|
|
33
|
+
for (const r of results){
|
|
34
|
+
console.log(`[${(r.score * 100).toFixed(1)}%] ${r.path}`);
|
|
35
|
+
}
|
|
36
|
+
} catch (error) {
|
|
37
|
+
console.error('Error:', error.message);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
program.command('status').description('Show index stats').action(async ()=>{
|
|
42
|
+
try {
|
|
43
|
+
const index = new RuVectorIndex();
|
|
44
|
+
const stats = await index.getStats();
|
|
45
|
+
console.log(`Indexed files: ${stats.indexedFiles}`);
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.error('Error:', error.message);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
program.command('clear').description('Clear the index').option('-f, --force', 'Force clear').action(async (options)=>{
|
|
52
|
+
if (!options.force) {
|
|
53
|
+
console.log('Use --force to confirm.');
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
const index = new RuVectorIndex();
|
|
57
|
+
await index.clear();
|
|
58
|
+
console.log('Index cleared.');
|
|
59
|
+
});
|
|
60
|
+
program.parse();
|
|
61
|
+
|
|
62
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/ruvector/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * CFN RuVector CLI - Semantic codebase search\n */\n\nimport { Command } from 'commander';\nimport { RuVectorIndex } from './core/index.js';\n\nconst program = new Command();\n\nprogram\n .name('cfn-ruvector')\n .description('Semantic codebase search using vector embeddings')\n .version('1.0.0');\n\nprogram\n .command('index')\n .description('Index the codebase')\n .argument('[directory]', 'Directory to index', '.')\n .option('-v, --verbose', 'Verbose output')\n .action(async (directory: string, options: { verbose?: boolean }) => {\n try {\n const index = new RuVectorIndex({ verbose: options.verbose });\n console.log(`Indexing ${directory}...`);\n const stats = await index.indexDirectory(directory);\n console.log(`\\nDone: ${stats.indexedFiles}/${stats.totalFiles} indexed, ${stats.failedFiles} failed`);\n } catch (error) {\n console.error('Error:', (error as Error).message);\n process.exit(1);\n }\n });\n\nprogram\n .command('search')\n .description('Search the codebase')\n .argument('<query>', 'Search query')\n .option('-n, --limit <n>', 'Number of results', '10')\n .action(async (query: string, options: { limit?: string }) => {\n try {\n const index = new RuVectorIndex();\n const limit = parseInt(options.limit ?? '10', 10);\n const results = await index.search(query, { limit });\n \n if (results.length === 0) {\n console.log('No results found.');\n return;\n }\n \n console.log(`\\nResults for: \"${query}\"\\n`);\n for (const r of results) {\n console.log(`[${(r.score * 100).toFixed(1)}%] ${r.path}`);\n }\n } catch (error) {\n console.error('Error:', (error as Error).message);\n process.exit(1);\n }\n });\n\nprogram\n .command('status')\n .description('Show index stats')\n .action(async () => {\n try {\n const index = new RuVectorIndex();\n const stats = await index.getStats();\n console.log(`Indexed files: ${stats.indexedFiles}`);\n } catch (error) {\n console.error('Error:', (error as Error).message);\n process.exit(1);\n }\n });\n\nprogram\n .command('clear')\n .description('Clear the index')\n .option('-f, --force', 'Force clear')\n .action(async (options: { force?: boolean }) => {\n if (!options.force) {\n console.log('Use --force to confirm.');\n process.exit(1);\n }\n const index = new RuVectorIndex();\n await index.clear();\n console.log('Index cleared.');\n });\n\nprogram.parse();"],"names":["Command","RuVectorIndex","program","name","description","version","command","argument","option","action","directory","options","index","verbose","console","log","stats","indexDirectory","indexedFiles","totalFiles","failedFiles","error","message","process","exit","query","limit","parseInt","results","search","length","r","score","toFixed","path","getStats","force","clear","parse"],"mappings":";AACA;;CAEC,GAED,SAASA,OAAO,QAAQ,YAAY;AACpC,SAASC,aAAa,QAAQ,kBAAkB;AAEhD,MAAMC,UAAU,IAAIF;AAEpBE,QACGC,IAAI,CAAC,gBACLC,WAAW,CAAC,oDACZC,OAAO,CAAC;AAEXH,QACGI,OAAO,CAAC,SACRF,WAAW,CAAC,sBACZG,QAAQ,CAAC,eAAe,sBAAsB,KAC9CC,MAAM,CAAC,iBAAiB,kBACxBC,MAAM,CAAC,OAAOC,WAAmBC;IAChC,IAAI;QACF,MAAMC,QAAQ,IAAIX,cAAc;YAAEY,SAASF,QAAQE,OAAO;QAAC;QAC3DC,QAAQC,GAAG,CAAC,CAAC,SAAS,EAAEL,UAAU,GAAG,CAAC;QACtC,MAAMM,QAAQ,MAAMJ,MAAMK,cAAc,CAACP;QACzCI,QAAQC,GAAG,CAAC,CAAC,QAAQ,EAAEC,MAAME,YAAY,CAAC,CAAC,EAAEF,MAAMG,UAAU,CAAC,UAAU,EAAEH,MAAMI,WAAW,CAAC,OAAO,CAAC;IACtG,EAAE,OAAOC,OAAO;QACdP,QAAQO,KAAK,CAAC,UAAU,AAACA,MAAgBC,OAAO;QAChDC,QAAQC,IAAI,CAAC;IACf;AACF;AAEFtB,QACGI,OAAO,CAAC,UACRF,WAAW,CAAC,uBACZG,QAAQ,CAAC,WAAW,gBACpBC,MAAM,CAAC,mBAAmB,qBAAqB,MAC/CC,MAAM,CAAC,OAAOgB,OAAed;IAC5B,IAAI;QACF,MAAMC,QAAQ,IAAIX;QAClB,MAAMyB,QAAQC,SAAShB,QAAQe,KAAK,IAAI,MAAM;QAC9C,MAAME,UAAU,MAAMhB,MAAMiB,MAAM,CAACJ,OAAO;YAAEC;QAAM;QAElD,IAAIE,QAAQE,MAAM,KAAK,GAAG;YACxBhB,QAAQC,GAAG,CAAC;YACZ;QACF;QAEAD,QAAQC,GAAG,CAAC,CAAC,gBAAgB,EAAEU,MAAM,GAAG,CAAC;QACzC,KAAK,MAAMM,KAAKH,QAAS;YACvBd,QAAQC,GAAG,CAAC,CAAC,CAAC,EAAE,AAACgB,CAAAA,EAAEC,KAAK,GAAG,GAAE,EAAGC,OAAO,CAAC,GAAG,IAAI,EAAEF,EAAEG,IAAI,EAAE;QAC3D;IACF,EAAE,OAAOb,OAAO;QACdP,QAAQO,KAAK,CAAC,UAAU,AAACA,MAAgBC,OAAO;QAChDC,QAAQC,IAAI,CAAC;IACf;AACF;AAEFtB,QACGI,OAAO,CAAC,UACRF,WAAW,CAAC,oBACZK,MAAM,CAAC;IACN,IAAI;QACF,MAAMG,QAAQ,IAAIX;QAClB,MAAMe,QAAQ,MAAMJ,MAAMuB,QAAQ;QAClCrB,QAAQC,GAAG,CAAC,CAAC,eAAe,EAAEC,MAAME,YAAY,EAAE;IACpD,EAAE,OAAOG,OAAO;QACdP,QAAQO,KAAK,CAAC,UAAU,AAACA,MAAgBC,OAAO;QAChDC,QAAQC,IAAI,CAAC;IACf;AACF;AAEFtB,QACGI,OAAO,CAAC,SACRF,WAAW,CAAC,mBACZI,MAAM,CAAC,eAAe,eACtBC,MAAM,CAAC,OAAOE;IACb,IAAI,CAACA,QAAQyB,KAAK,EAAE;QAClBtB,QAAQC,GAAG,CAAC;QACZQ,QAAQC,IAAI,CAAC;IACf;IACA,MAAMZ,QAAQ,IAAIX;IAClB,MAAMW,MAAMyB,KAAK;IACjBvB,QAAQC,GAAG,CAAC;AACd;AAEFb,QAAQoC,KAAK"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File Processor - Extracts indexable text from source files
|
|
3
|
+
*/ import * as fs from 'fs/promises';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
const LANGUAGE_MAP = {
|
|
6
|
+
'.ts': 'typescript',
|
|
7
|
+
'.tsx': 'typescript',
|
|
8
|
+
'.js': 'javascript',
|
|
9
|
+
'.jsx': 'javascript',
|
|
10
|
+
'.mjs': 'javascript',
|
|
11
|
+
'.py': 'python',
|
|
12
|
+
'.rb': 'ruby',
|
|
13
|
+
'.go': 'go',
|
|
14
|
+
'.rs': 'rust',
|
|
15
|
+
'.java': 'java',
|
|
16
|
+
'.kt': 'kotlin',
|
|
17
|
+
'.swift': 'swift',
|
|
18
|
+
'.c': 'c',
|
|
19
|
+
'.cpp': 'cpp',
|
|
20
|
+
'.h': 'c',
|
|
21
|
+
'.hpp': 'cpp',
|
|
22
|
+
'.cs': 'csharp',
|
|
23
|
+
'.php': 'php',
|
|
24
|
+
'.md': 'markdown',
|
|
25
|
+
'.mdx': 'markdown',
|
|
26
|
+
'.json': 'json',
|
|
27
|
+
'.yaml': 'yaml',
|
|
28
|
+
'.yml': 'yaml',
|
|
29
|
+
'.html': 'html',
|
|
30
|
+
'.css': 'css',
|
|
31
|
+
'.scss': 'scss',
|
|
32
|
+
'.sql': 'sql',
|
|
33
|
+
'.sh': 'shell',
|
|
34
|
+
'.bash': 'shell'
|
|
35
|
+
};
|
|
36
|
+
export class SourceFileProcessor {
|
|
37
|
+
maxFileSize;
|
|
38
|
+
constructor(maxFileSize = 100 * 1024){
|
|
39
|
+
this.maxFileSize = maxFileSize;
|
|
40
|
+
}
|
|
41
|
+
canProcess(filePath) {
|
|
42
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
43
|
+
return ext in LANGUAGE_MAP;
|
|
44
|
+
}
|
|
45
|
+
async process(filePath) {
|
|
46
|
+
try {
|
|
47
|
+
const stats = await fs.stat(filePath);
|
|
48
|
+
if (stats.size > this.maxFileSize || !stats.isFile()) return null;
|
|
49
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
50
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
51
|
+
const language = LANGUAGE_MAP[ext] ?? 'unknown';
|
|
52
|
+
let processed = content.replace(/\n{3,}/g, '\n\n');
|
|
53
|
+
const maxChars = 8000;
|
|
54
|
+
if (processed.length > maxChars) {
|
|
55
|
+
processed = processed.slice(0, maxChars) + '\n[truncated]';
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
path: filePath,
|
|
59
|
+
content: processed.trim(),
|
|
60
|
+
language,
|
|
61
|
+
size: stats.size
|
|
62
|
+
};
|
|
63
|
+
} catch {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export function createFileProcessor(maxFileSize) {
|
|
69
|
+
return new SourceFileProcessor(maxFileSize);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
//# sourceMappingURL=file-processor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/ruvector/core/file-processor.ts"],"sourcesContent":["/**\n * File Processor - Extracts indexable text from source files\n */\n\nimport * as fs from 'fs/promises';\nimport * as path from 'path';\n\nexport interface ProcessedFile {\n path: string;\n content: string;\n language: string;\n size: number;\n}\n\nexport interface FileProcessor {\n process(filePath: string): Promise<ProcessedFile | null>;\n canProcess(filePath: string): boolean;\n}\n\nconst LANGUAGE_MAP: Record<string, string> = {\n '.ts': 'typescript', '.tsx': 'typescript',\n '.js': 'javascript', '.jsx': 'javascript', '.mjs': 'javascript',\n '.py': 'python', '.rb': 'ruby', '.go': 'go', '.rs': 'rust',\n '.java': 'java', '.kt': 'kotlin', '.swift': 'swift',\n '.c': 'c', '.cpp': 'cpp', '.h': 'c', '.hpp': 'cpp',\n '.cs': 'csharp', '.php': 'php',\n '.md': 'markdown', '.mdx': 'markdown',\n '.json': 'json', '.yaml': 'yaml', '.yml': 'yaml',\n '.html': 'html', '.css': 'css', '.scss': 'scss',\n '.sql': 'sql', '.sh': 'shell', '.bash': 'shell',\n};\n\nexport class SourceFileProcessor implements FileProcessor {\n private maxFileSize: number;\n \n constructor(maxFileSize: number = 100 * 1024) {\n this.maxFileSize = maxFileSize;\n }\n \n canProcess(filePath: string): boolean {\n const ext = path.extname(filePath).toLowerCase();\n return ext in LANGUAGE_MAP;\n }\n \n async process(filePath: string): Promise<ProcessedFile | null> {\n try {\n const stats = await fs.stat(filePath);\n if (stats.size > this.maxFileSize || !stats.isFile()) return null;\n \n const content = await fs.readFile(filePath, 'utf-8');\n const ext = path.extname(filePath).toLowerCase();\n const language = LANGUAGE_MAP[ext] ?? 'unknown';\n \n let processed = content.replace(/\\n{3,}/g, '\\n\\n');\n const maxChars = 8000;\n if (processed.length > maxChars) {\n processed = processed.slice(0, maxChars) + '\\n[truncated]';\n }\n \n return { path: filePath, content: processed.trim(), language, size: stats.size };\n } catch {\n return null;\n }\n }\n}\n\nexport function createFileProcessor(maxFileSize?: number): FileProcessor {\n return new SourceFileProcessor(maxFileSize);\n}"],"names":["fs","path","LANGUAGE_MAP","SourceFileProcessor","maxFileSize","canProcess","filePath","ext","extname","toLowerCase","process","stats","stat","size","isFile","content","readFile","language","processed","replace","maxChars","length","slice","trim","createFileProcessor"],"mappings":"AAAA;;CAEC,GAED,YAAYA,QAAQ,cAAc;AAClC,YAAYC,UAAU,OAAO;AAc7B,MAAMC,eAAuC;IAC3C,OAAO;IAAc,QAAQ;IAC7B,OAAO;IAAc,QAAQ;IAAc,QAAQ;IACnD,OAAO;IAAU,OAAO;IAAQ,OAAO;IAAM,OAAO;IACpD,SAAS;IAAQ,OAAO;IAAU,UAAU;IAC5C,MAAM;IAAK,QAAQ;IAAO,MAAM;IAAK,QAAQ;IAC7C,OAAO;IAAU,QAAQ;IACzB,OAAO;IAAY,QAAQ;IAC3B,SAAS;IAAQ,SAAS;IAAQ,QAAQ;IAC1C,SAAS;IAAQ,QAAQ;IAAO,SAAS;IACzC,QAAQ;IAAO,OAAO;IAAS,SAAS;AAC1C;AAEA,OAAO,MAAMC;IACHC,YAAoB;IAE5B,YAAYA,cAAsB,MAAM,IAAI,CAAE;QAC5C,IAAI,CAACA,WAAW,GAAGA;IACrB;IAEAC,WAAWC,QAAgB,EAAW;QACpC,MAAMC,MAAMN,KAAKO,OAAO,CAACF,UAAUG,WAAW;QAC9C,OAAOF,OAAOL;IAChB;IAEA,MAAMQ,QAAQJ,QAAgB,EAAiC;QAC7D,IAAI;YACF,MAAMK,QAAQ,MAAMX,GAAGY,IAAI,CAACN;YAC5B,IAAIK,MAAME,IAAI,GAAG,IAAI,CAACT,WAAW,IAAI,CAACO,MAAMG,MAAM,IAAI,OAAO;YAE7D,MAAMC,UAAU,MAAMf,GAAGgB,QAAQ,CAACV,UAAU;YAC5C,MAAMC,MAAMN,KAAKO,OAAO,CAACF,UAAUG,WAAW;YAC9C,MAAMQ,WAAWf,YAAY,CAACK,IAAI,IAAI;YAEtC,IAAIW,YAAYH,QAAQI,OAAO,CAAC,WAAW;YAC3C,MAAMC,WAAW;YACjB,IAAIF,UAAUG,MAAM,GAAGD,UAAU;gBAC/BF,YAAYA,UAAUI,KAAK,CAAC,GAAGF,YAAY;YAC7C;YAEA,OAAO;gBAAEnB,MAAMK;gBAAUS,SAASG,UAAUK,IAAI;gBAAIN;gBAAUJ,MAAMF,MAAME,IAAI;YAAC;QACjF,EAAE,OAAM;YACN,OAAO;QACT;IACF;AACF;AAEA,OAAO,SAASW,oBAAoBpB,WAAoB;IACtD,OAAO,IAAID,oBAAoBC;AACjC"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RuVectorIndex - Core API for semantic codebase search
|
|
3
|
+
*/ import { glob } from 'glob';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
import * as fs from 'fs/promises';
|
|
6
|
+
import { createEmbeddingProvider } from '../embeddings/index.js';
|
|
7
|
+
import { createFileProcessor } from './file-processor.js';
|
|
8
|
+
export class RuVectorIndex {
|
|
9
|
+
embeddingProvider;
|
|
10
|
+
fileProcessor;
|
|
11
|
+
db = null;
|
|
12
|
+
workingDir;
|
|
13
|
+
storagePath;
|
|
14
|
+
include;
|
|
15
|
+
exclude;
|
|
16
|
+
batchSize;
|
|
17
|
+
verbose;
|
|
18
|
+
constructor(options = {}, workingDir = process.cwd()){
|
|
19
|
+
this.workingDir = workingDir;
|
|
20
|
+
this.storagePath = options.storagePath ?? './data/codebase.db';
|
|
21
|
+
this.include = options.indexing?.include ?? [
|
|
22
|
+
'**/*.ts',
|
|
23
|
+
'**/*.js',
|
|
24
|
+
'**/*.md'
|
|
25
|
+
];
|
|
26
|
+
this.exclude = options.indexing?.exclude ?? [
|
|
27
|
+
'node_modules/**',
|
|
28
|
+
'dist/**',
|
|
29
|
+
'.git/**'
|
|
30
|
+
];
|
|
31
|
+
this.batchSize = options.indexing?.batchSize ?? 50;
|
|
32
|
+
this.verbose = options.verbose ?? false;
|
|
33
|
+
this.embeddingProvider = createEmbeddingProvider({
|
|
34
|
+
provider: options.embedding?.provider ?? 'openai',
|
|
35
|
+
model: options.embedding?.model,
|
|
36
|
+
apiKey: options.embedding?.apiKey,
|
|
37
|
+
baseUrl: options.embedding?.baseUrl
|
|
38
|
+
});
|
|
39
|
+
this.fileProcessor = createFileProcessor(options.indexing?.maxFileSize);
|
|
40
|
+
}
|
|
41
|
+
async getDb() {
|
|
42
|
+
if (this.db) return this.db;
|
|
43
|
+
const { VectorDB } = await import('@ruvector/core');
|
|
44
|
+
const storagePath = path.resolve(this.workingDir, this.storagePath);
|
|
45
|
+
await fs.mkdir(path.dirname(storagePath), {
|
|
46
|
+
recursive: true
|
|
47
|
+
});
|
|
48
|
+
this.db = new VectorDB({
|
|
49
|
+
dimensions: 1536,
|
|
50
|
+
storagePath
|
|
51
|
+
});
|
|
52
|
+
return this.db;
|
|
53
|
+
}
|
|
54
|
+
log(msg) {
|
|
55
|
+
if (this.verbose) console.log(`[ruvector] ${msg}`);
|
|
56
|
+
}
|
|
57
|
+
async indexDirectory(directory = '.') {
|
|
58
|
+
const absoluteDir = path.resolve(this.workingDir, directory);
|
|
59
|
+
this.log(`Indexing: ${absoluteDir}`);
|
|
60
|
+
const patterns = this.include.map((p)=>path.join(absoluteDir, p));
|
|
61
|
+
const files = await glob(patterns, {
|
|
62
|
+
ignore: this.exclude,
|
|
63
|
+
nodir: true,
|
|
64
|
+
absolute: true
|
|
65
|
+
});
|
|
66
|
+
this.log(`Found ${files.length} files`);
|
|
67
|
+
const stats = {
|
|
68
|
+
totalFiles: files.length,
|
|
69
|
+
indexedFiles: 0,
|
|
70
|
+
failedFiles: 0,
|
|
71
|
+
lastIndexedAt: new Date()
|
|
72
|
+
};
|
|
73
|
+
const db = await this.getDb();
|
|
74
|
+
for(let i = 0; i < files.length; i += this.batchSize){
|
|
75
|
+
const batch = files.slice(i, i + this.batchSize);
|
|
76
|
+
const processed = [];
|
|
77
|
+
for (const file of batch){
|
|
78
|
+
const result = await this.fileProcessor.process(file);
|
|
79
|
+
if (result) processed.push(result);
|
|
80
|
+
else stats.failedFiles++;
|
|
81
|
+
}
|
|
82
|
+
if (processed.length === 0) continue;
|
|
83
|
+
try {
|
|
84
|
+
const texts = processed.map((p)=>p.content);
|
|
85
|
+
const embeddings = await this.embeddingProvider.embedBatch(texts);
|
|
86
|
+
const items = processed.map((p, idx)=>({
|
|
87
|
+
id: path.relative(this.workingDir, p.path),
|
|
88
|
+
vector: new Float32Array(embeddings[idx].embedding)
|
|
89
|
+
}));
|
|
90
|
+
await db.upsert(items);
|
|
91
|
+
stats.indexedFiles += processed.length;
|
|
92
|
+
this.log(`Indexed ${stats.indexedFiles}/${stats.totalFiles}`);
|
|
93
|
+
} catch (error) {
|
|
94
|
+
this.log(`Batch failed: ${error.message}`);
|
|
95
|
+
stats.failedFiles += processed.length;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return stats;
|
|
99
|
+
}
|
|
100
|
+
async search(query, options = {}) {
|
|
101
|
+
const limit = options.limit ?? 10;
|
|
102
|
+
const { embedding } = await this.embeddingProvider.embed(query);
|
|
103
|
+
const db = await this.getDb();
|
|
104
|
+
const results = await db.search({
|
|
105
|
+
vector: new Float32Array(embedding),
|
|
106
|
+
k: limit
|
|
107
|
+
});
|
|
108
|
+
return results.map((r)=>({
|
|
109
|
+
path: r.id,
|
|
110
|
+
score: r.score
|
|
111
|
+
}));
|
|
112
|
+
}
|
|
113
|
+
async getStats() {
|
|
114
|
+
const db = await this.getDb();
|
|
115
|
+
const count = await db.count();
|
|
116
|
+
return {
|
|
117
|
+
totalFiles: count,
|
|
118
|
+
indexedFiles: count,
|
|
119
|
+
failedFiles: 0,
|
|
120
|
+
lastIndexedAt: null
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
async clear() {
|
|
124
|
+
const storagePath = path.resolve(this.workingDir, this.storagePath);
|
|
125
|
+
try {
|
|
126
|
+
await fs.unlink(storagePath);
|
|
127
|
+
this.db = null;
|
|
128
|
+
} catch {}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
export { createFileProcessor } from './file-processor.js';
|
|
132
|
+
|
|
133
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/ruvector/core/index.ts"],"sourcesContent":["/**\n * RuVectorIndex - Core API for semantic codebase search\n */\n\nimport { glob } from 'glob';\nimport * as path from 'path';\nimport * as fs from 'fs/promises';\n\nimport { createEmbeddingProvider, type EmbeddingProvider } from '../embeddings/index.js';\nimport { createFileProcessor, type FileProcessor, type ProcessedFile } from './file-processor.js';\n\nexport interface SearchResult {\n path: string;\n score: number;\n}\n\nexport interface IndexStats {\n totalFiles: number;\n indexedFiles: number;\n failedFiles: number;\n lastIndexedAt: Date | null;\n}\n\nexport interface RuVectorIndexOptions {\n storagePath?: string;\n embedding?: {\n provider?: 'openai' | 'ollama' | 'transformers';\n model?: string;\n apiKey?: string;\n baseUrl?: string;\n };\n indexing?: {\n include?: string[];\n exclude?: string[];\n maxFileSize?: number;\n batchSize?: number;\n };\n verbose?: boolean;\n}\n\ninterface VectorDB {\n upsert(items: Array<{ id: string; vector: Float32Array }>): Promise<void>;\n search(params: { vector: Float32Array; k: number }): Promise<Array<{ id: string; score: number }>>;\n count(): Promise<number>;\n}\n\nexport class RuVectorIndex {\n private embeddingProvider: EmbeddingProvider;\n private fileProcessor: FileProcessor;\n private db: VectorDB | null = null;\n private workingDir: string;\n private storagePath: string;\n private include: string[];\n private exclude: string[];\n private batchSize: number;\n private verbose: boolean;\n \n constructor(options: RuVectorIndexOptions = {}, workingDir: string = process.cwd()) {\n this.workingDir = workingDir;\n this.storagePath = options.storagePath ?? './data/codebase.db';\n this.include = options.indexing?.include ?? ['**/*.ts', '**/*.js', '**/*.md'];\n this.exclude = options.indexing?.exclude ?? ['node_modules/**', 'dist/**', '.git/**'];\n this.batchSize = options.indexing?.batchSize ?? 50;\n this.verbose = options.verbose ?? false;\n \n this.embeddingProvider = createEmbeddingProvider({\n provider: options.embedding?.provider ?? 'openai',\n model: options.embedding?.model,\n apiKey: options.embedding?.apiKey,\n baseUrl: options.embedding?.baseUrl,\n });\n \n this.fileProcessor = createFileProcessor(options.indexing?.maxFileSize);\n }\n \n private async getDb(): Promise<VectorDB> {\n if (this.db) return this.db;\n \n const { VectorDB } = await import('@ruvector/core');\n const storagePath = path.resolve(this.workingDir, this.storagePath);\n await fs.mkdir(path.dirname(storagePath), { recursive: true });\n \n this.db = new VectorDB({ dimensions: 1536, storagePath });\n return this.db;\n }\n \n private log(msg: string): void {\n if (this.verbose) console.log(`[ruvector] ${msg}`);\n }\n \n async indexDirectory(directory: string = '.'): Promise<IndexStats> {\n const absoluteDir = path.resolve(this.workingDir, directory);\n this.log(`Indexing: ${absoluteDir}`);\n \n const patterns = this.include.map(p => path.join(absoluteDir, p));\n const files = await glob(patterns, { ignore: this.exclude, nodir: true, absolute: true });\n \n this.log(`Found ${files.length} files`);\n \n const stats: IndexStats = { totalFiles: files.length, indexedFiles: 0, failedFiles: 0, lastIndexedAt: new Date() };\n const db = await this.getDb();\n \n for (let i = 0; i < files.length; i += this.batchSize) {\n const batch = files.slice(i, i + this.batchSize);\n const processed: ProcessedFile[] = [];\n \n for (const file of batch) {\n const result = await this.fileProcessor.process(file);\n if (result) processed.push(result);\n else stats.failedFiles++;\n }\n \n if (processed.length === 0) continue;\n \n try {\n const texts = processed.map(p => p.content);\n const embeddings = await this.embeddingProvider.embedBatch(texts);\n \n const items = processed.map((p, idx) => ({\n id: path.relative(this.workingDir, p.path),\n vector: new Float32Array(embeddings[idx].embedding),\n }));\n \n await db.upsert(items);\n stats.indexedFiles += processed.length;\n this.log(`Indexed ${stats.indexedFiles}/${stats.totalFiles}`);\n } catch (error) {\n this.log(`Batch failed: ${(error as Error).message}`);\n stats.failedFiles += processed.length;\n }\n }\n \n return stats;\n }\n \n async search(query: string, options: { limit?: number } = {}): Promise<SearchResult[]> {\n const limit = options.limit ?? 10;\n const { embedding } = await this.embeddingProvider.embed(query);\n const db = await this.getDb();\n \n const results = await db.search({ vector: new Float32Array(embedding), k: limit });\n return results.map(r => ({ path: r.id, score: r.score }));\n }\n \n async getStats(): Promise<IndexStats> {\n const db = await this.getDb();\n const count = await db.count();\n return { totalFiles: count, indexedFiles: count, failedFiles: 0, lastIndexedAt: null };\n }\n \n async clear(): Promise<void> {\n const storagePath = path.resolve(this.workingDir, this.storagePath);\n try { await fs.unlink(storagePath); this.db = null; } catch {}\n }\n}\n\nexport { createFileProcessor, type ProcessedFile, type FileProcessor } from './file-processor.js';"],"names":["glob","path","fs","createEmbeddingProvider","createFileProcessor","RuVectorIndex","embeddingProvider","fileProcessor","db","workingDir","storagePath","include","exclude","batchSize","verbose","options","process","cwd","indexing","provider","embedding","model","apiKey","baseUrl","maxFileSize","getDb","VectorDB","resolve","mkdir","dirname","recursive","dimensions","log","msg","console","indexDirectory","directory","absoluteDir","patterns","map","p","join","files","ignore","nodir","absolute","length","stats","totalFiles","indexedFiles","failedFiles","lastIndexedAt","Date","i","batch","slice","processed","file","result","push","texts","content","embeddings","embedBatch","items","idx","id","relative","vector","Float32Array","upsert","error","message","search","query","limit","embed","results","k","r","score","getStats","count","clear","unlink"],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedding Providers Module
|
|
3
|
+
*/ export * from './provider.js';
|
|
4
|
+
export * from './openai.js';
|
|
5
|
+
import { EmbeddingError } from './provider.js';
|
|
6
|
+
import { createOpenAIProvider } from './openai.js';
|
|
7
|
+
export function createEmbeddingProvider(config) {
|
|
8
|
+
switch(config.provider){
|
|
9
|
+
case 'openai':
|
|
10
|
+
return createOpenAIProvider({
|
|
11
|
+
apiKey: config.apiKey,
|
|
12
|
+
baseUrl: config.baseUrl,
|
|
13
|
+
model: config.model,
|
|
14
|
+
dimensions: config.dimensions
|
|
15
|
+
});
|
|
16
|
+
case 'ollama':
|
|
17
|
+
case 'transformers':
|
|
18
|
+
throw new EmbeddingError(`${config.provider} provider not yet implemented`, config.provider);
|
|
19
|
+
default:
|
|
20
|
+
throw new EmbeddingError(`Unknown provider: ${config.provider}`, 'unknown');
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/ruvector/embeddings/index.ts"],"sourcesContent":["/**\n * Embedding Providers Module\n */\n\nexport * from './provider.js';\nexport * from './openai.js';\n\nimport type { EmbeddingProvider, EmbeddingProviderConfig } from './provider.js';\nimport { EmbeddingError } from './provider.js';\nimport { createOpenAIProvider } from './openai.js';\n\nexport function createEmbeddingProvider(config: EmbeddingProviderConfig): EmbeddingProvider {\n switch (config.provider) {\n case 'openai':\n return createOpenAIProvider({\n apiKey: config.apiKey,\n baseUrl: config.baseUrl,\n model: config.model,\n dimensions: config.dimensions,\n });\n case 'ollama':\n case 'transformers':\n throw new EmbeddingError(`${config.provider} provider not yet implemented`, config.provider);\n default:\n throw new EmbeddingError(`Unknown provider: ${(config as any).provider}`, 'unknown');\n }\n}"],"names":["EmbeddingError","createOpenAIProvider","createEmbeddingProvider","config","provider","apiKey","baseUrl","model","dimensions"],"mappings":"AAAA;;CAEC,GAED,cAAc,gBAAgB;AAC9B,cAAc,cAAc;AAG5B,SAASA,cAAc,QAAQ,gBAAgB;AAC/C,SAASC,oBAAoB,QAAQ,cAAc;AAEnD,OAAO,SAASC,wBAAwBC,MAA+B;IACrE,OAAQA,OAAOC,QAAQ;QACrB,KAAK;YACH,OAAOH,qBAAqB;gBAC1BI,QAAQF,OAAOE,MAAM;gBACrBC,SAASH,OAAOG,OAAO;gBACvBC,OAAOJ,OAAOI,KAAK;gBACnBC,YAAYL,OAAOK,UAAU;YAC/B;QACF,KAAK;QACL,KAAK;YACH,MAAM,IAAIR,eAAe,GAAGG,OAAOC,QAAQ,CAAC,6BAA6B,CAAC,EAAED,OAAOC,QAAQ;QAC7F;YACE,MAAM,IAAIJ,eAAe,CAAC,kBAAkB,EAAE,AAACG,OAAeC,QAAQ,EAAE,EAAE;IAC9E;AACF"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI Embedding Provider
|
|
3
|
+
*/ import { EmbeddingError } from './provider.js';
|
|
4
|
+
export class OpenAIEmbeddingProvider {
|
|
5
|
+
name = 'openai';
|
|
6
|
+
dimensions;
|
|
7
|
+
apiKey;
|
|
8
|
+
model;
|
|
9
|
+
baseUrl;
|
|
10
|
+
constructor(config){
|
|
11
|
+
this.apiKey = config.apiKey;
|
|
12
|
+
this.model = config.model ?? 'text-embedding-3-small';
|
|
13
|
+
this.baseUrl = config.baseUrl ?? 'https://api.openai.com/v1';
|
|
14
|
+
this.dimensions = config.dimensions ?? 1536;
|
|
15
|
+
}
|
|
16
|
+
async embed(text) {
|
|
17
|
+
const results = await this.embedBatch([
|
|
18
|
+
text
|
|
19
|
+
]);
|
|
20
|
+
return results[0];
|
|
21
|
+
}
|
|
22
|
+
async embedBatch(texts) {
|
|
23
|
+
if (texts.length === 0) return [];
|
|
24
|
+
try {
|
|
25
|
+
const response = await fetch(`${this.baseUrl}/embeddings`, {
|
|
26
|
+
method: 'POST',
|
|
27
|
+
headers: {
|
|
28
|
+
'Content-Type': 'application/json',
|
|
29
|
+
'Authorization': `Bearer ${this.apiKey}`
|
|
30
|
+
},
|
|
31
|
+
body: JSON.stringify({
|
|
32
|
+
model: this.model,
|
|
33
|
+
input: texts,
|
|
34
|
+
dimensions: this.dimensions
|
|
35
|
+
})
|
|
36
|
+
});
|
|
37
|
+
if (!response.ok) {
|
|
38
|
+
const error = await response.text();
|
|
39
|
+
throw new EmbeddingError(`OpenAI API error: ${response.status} ${error}`, this.name);
|
|
40
|
+
}
|
|
41
|
+
const data = await response.json();
|
|
42
|
+
const sorted = data.data.sort((a, b)=>a.index - b.index);
|
|
43
|
+
return sorted.map((item)=>({
|
|
44
|
+
embedding: item.embedding,
|
|
45
|
+
model: data.model,
|
|
46
|
+
tokenCount: Math.floor(data.usage.total_tokens / texts.length)
|
|
47
|
+
}));
|
|
48
|
+
} catch (error) {
|
|
49
|
+
if (error instanceof EmbeddingError) throw error;
|
|
50
|
+
throw new EmbeddingError(`Failed to generate embeddings: ${error.message}`, this.name, error);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
export function createOpenAIProvider(config) {
|
|
55
|
+
const apiKey = config?.apiKey ?? process.env.OPENAI_API_KEY ?? process.env.ZAI_API_KEY;
|
|
56
|
+
if (!apiKey) {
|
|
57
|
+
throw new EmbeddingError('OpenAI API key required. Set OPENAI_API_KEY or ZAI_API_KEY.', 'openai');
|
|
58
|
+
}
|
|
59
|
+
const baseUrl = config?.baseUrl ?? (process.env.ZAI_API_KEY ? 'https://api.zai.com/v1' : undefined);
|
|
60
|
+
return new OpenAIEmbeddingProvider({
|
|
61
|
+
apiKey,
|
|
62
|
+
baseUrl,
|
|
63
|
+
...config
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
//# sourceMappingURL=openai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/ruvector/embeddings/openai.ts"],"sourcesContent":["/**\n * OpenAI Embedding Provider\n */\n\nimport type { EmbeddingProvider, EmbeddingResult } from './provider.js';\nimport { EmbeddingError } from './provider.js';\n\nexport interface OpenAIEmbeddingConfig {\n apiKey: string;\n model?: string;\n baseUrl?: string;\n dimensions?: number;\n}\n\nexport class OpenAIEmbeddingProvider implements EmbeddingProvider {\n readonly name = 'openai';\n readonly dimensions: number;\n \n private readonly apiKey: string;\n private readonly model: string;\n private readonly baseUrl: string;\n \n constructor(config: OpenAIEmbeddingConfig) {\n this.apiKey = config.apiKey;\n this.model = config.model ?? 'text-embedding-3-small';\n this.baseUrl = config.baseUrl ?? 'https://api.openai.com/v1';\n this.dimensions = config.dimensions ?? 1536;\n }\n \n async embed(text: string): Promise<EmbeddingResult> {\n const results = await this.embedBatch([text]);\n return results[0];\n }\n \n async embedBatch(texts: string[]): Promise<EmbeddingResult[]> {\n if (texts.length === 0) return [];\n \n try {\n const response = await fetch(`${this.baseUrl}/embeddings`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify({\n model: this.model,\n input: texts,\n dimensions: this.dimensions,\n }),\n });\n \n if (!response.ok) {\n const error = await response.text();\n throw new EmbeddingError(`OpenAI API error: ${response.status} ${error}`, this.name);\n }\n \n const data = await response.json() as {\n data: Array<{ embedding: number[]; index: number }>;\n model: string;\n usage: { total_tokens: number };\n };\n \n const sorted = data.data.sort((a, b) => a.index - b.index);\n \n return sorted.map((item) => ({\n embedding: item.embedding,\n model: data.model,\n tokenCount: Math.floor(data.usage.total_tokens / texts.length),\n }));\n } catch (error) {\n if (error instanceof EmbeddingError) throw error;\n throw new EmbeddingError(\n `Failed to generate embeddings: ${(error as Error).message}`,\n this.name,\n error as Error\n );\n }\n }\n}\n\nexport function createOpenAIProvider(config?: Partial<OpenAIEmbeddingConfig>): OpenAIEmbeddingProvider {\n const apiKey = config?.apiKey ?? process.env.OPENAI_API_KEY ?? process.env.ZAI_API_KEY;\n \n if (!apiKey) {\n throw new EmbeddingError(\n 'OpenAI API key required. Set OPENAI_API_KEY or ZAI_API_KEY.',\n 'openai'\n );\n }\n \n const baseUrl = config?.baseUrl ?? (process.env.ZAI_API_KEY ? 'https://api.zai.com/v1' : undefined);\n \n return new OpenAIEmbeddingProvider({ apiKey, baseUrl, ...config });\n}"],"names":["EmbeddingError","OpenAIEmbeddingProvider","name","dimensions","apiKey","model","baseUrl","config","embed","text","results","embedBatch","texts","length","response","fetch","method","headers","body","JSON","stringify","input","ok","error","status","data","json","sorted","sort","a","b","index","map","item","embedding","tokenCount","Math","floor","usage","total_tokens","message","createOpenAIProvider","process","env","OPENAI_API_KEY","ZAI_API_KEY","undefined"],"mappings":"AAAA;;CAEC,GAGD,SAASA,cAAc,QAAQ,gBAAgB;AAS/C,OAAO,MAAMC;IACFC,OAAO,SAAS;IAChBC,WAAmB;IAEXC,OAAe;IACfC,MAAc;IACdC,QAAgB;IAEjC,YAAYC,MAA6B,CAAE;QACzC,IAAI,CAACH,MAAM,GAAGG,OAAOH,MAAM;QAC3B,IAAI,CAACC,KAAK,GAAGE,OAAOF,KAAK,IAAI;QAC7B,IAAI,CAACC,OAAO,GAAGC,OAAOD,OAAO,IAAI;QACjC,IAAI,CAACH,UAAU,GAAGI,OAAOJ,UAAU,IAAI;IACzC;IAEA,MAAMK,MAAMC,IAAY,EAA4B;QAClD,MAAMC,UAAU,MAAM,IAAI,CAACC,UAAU,CAAC;YAACF;SAAK;QAC5C,OAAOC,OAAO,CAAC,EAAE;IACnB;IAEA,MAAMC,WAAWC,KAAe,EAA8B;QAC5D,IAAIA,MAAMC,MAAM,KAAK,GAAG,OAAO,EAAE;QAEjC,IAAI;YACF,MAAMC,WAAW,MAAMC,MAAM,GAAG,IAAI,CAACT,OAAO,CAAC,WAAW,CAAC,EAAE;gBACzDU,QAAQ;gBACRC,SAAS;oBACP,gBAAgB;oBAChB,iBAAiB,CAAC,OAAO,EAAE,IAAI,CAACb,MAAM,EAAE;gBAC1C;gBACAc,MAAMC,KAAKC,SAAS,CAAC;oBACnBf,OAAO,IAAI,CAACA,KAAK;oBACjBgB,OAAOT;oBACPT,YAAY,IAAI,CAACA,UAAU;gBAC7B;YACF;YAEA,IAAI,CAACW,SAASQ,EAAE,EAAE;gBAChB,MAAMC,QAAQ,MAAMT,SAASL,IAAI;gBACjC,MAAM,IAAIT,eAAe,CAAC,kBAAkB,EAAEc,SAASU,MAAM,CAAC,CAAC,EAAED,OAAO,EAAE,IAAI,CAACrB,IAAI;YACrF;YAEA,MAAMuB,OAAO,MAAMX,SAASY,IAAI;YAMhC,MAAMC,SAASF,KAAKA,IAAI,CAACG,IAAI,CAAC,CAACC,GAAGC,IAAMD,EAAEE,KAAK,GAAGD,EAAEC,KAAK;YAEzD,OAAOJ,OAAOK,GAAG,CAAC,CAACC,OAAU,CAAA;oBAC3BC,WAAWD,KAAKC,SAAS;oBACzB7B,OAAOoB,KAAKpB,KAAK;oBACjB8B,YAAYC,KAAKC,KAAK,CAACZ,KAAKa,KAAK,CAACC,YAAY,GAAG3B,MAAMC,MAAM;gBAC/D,CAAA;QACF,EAAE,OAAOU,OAAO;YACd,IAAIA,iBAAiBvB,gBAAgB,MAAMuB;YAC3C,MAAM,IAAIvB,eACR,CAAC,+BAA+B,EAAE,AAACuB,MAAgBiB,OAAO,EAAE,EAC5D,IAAI,CAACtC,IAAI,EACTqB;QAEJ;IACF;AACF;AAEA,OAAO,SAASkB,qBAAqBlC,MAAuC;IAC1E,MAAMH,SAASG,QAAQH,UAAUsC,QAAQC,GAAG,CAACC,cAAc,IAAIF,QAAQC,GAAG,CAACE,WAAW;IAEtF,IAAI,CAACzC,QAAQ;QACX,MAAM,IAAIJ,eACR,+DACA;IAEJ;IAEA,MAAMM,UAAUC,QAAQD,WAAYoC,CAAAA,QAAQC,GAAG,CAACE,WAAW,GAAG,2BAA2BC,SAAQ;IAEjG,OAAO,IAAI7C,wBAAwB;QAAEG;QAAQE;QAAS,GAAGC,MAAM;IAAC;AAClE"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedding Provider Interface for RuVector
|
|
3
|
+
*/ export class EmbeddingError extends Error {
|
|
4
|
+
provider;
|
|
5
|
+
cause;
|
|
6
|
+
constructor(message, provider, cause){
|
|
7
|
+
super(message), this.provider = provider, this.cause = cause;
|
|
8
|
+
this.name = 'EmbeddingError';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/ruvector/embeddings/provider.ts"],"sourcesContent":["/**\n * Embedding Provider Interface for RuVector\n */\n\nexport interface EmbeddingResult {\n embedding: number[];\n model: string;\n tokenCount?: number;\n}\n\nexport interface EmbeddingProvider {\n readonly name: string;\n readonly dimensions: number;\n embed(text: string): Promise<EmbeddingResult>;\n embedBatch(texts: string[]): Promise<EmbeddingResult[]>;\n}\n\nexport interface EmbeddingProviderConfig {\n provider: 'openai' | 'ollama' | 'transformers';\n model?: string;\n apiKey?: string;\n baseUrl?: string;\n dimensions?: number;\n}\n\nexport class EmbeddingError extends Error {\n constructor(\n message: string,\n public readonly provider: string,\n public readonly cause?: Error\n ) {\n super(message);\n this.name = 'EmbeddingError';\n }\n}"],"names":["EmbeddingError","Error","message","provider","cause","name"],"mappings":"AAAA;;CAEC,GAuBD,OAAO,MAAMA,uBAAuBC;;;IAClC,YACEC,OAAe,EACf,AAAgBC,QAAgB,EAChC,AAAgBC,KAAa,CAC7B;QACA,KAAK,CAACF,eAHUC,WAAAA,eACAC,QAAAA;QAGhB,IAAI,CAACC,IAAI,GAAG;IACd;AACF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RuVector - Semantic codebase search for CFN
|
|
3
|
+
*/ // Core
|
|
4
|
+
export { RuVectorIndex } from './core/index.js';
|
|
5
|
+
export { createFileProcessor } from './core/file-processor.js';
|
|
6
|
+
// Embeddings
|
|
7
|
+
export { EmbeddingError, createEmbeddingProvider, OpenAIEmbeddingProvider, createOpenAIProvider } from './embeddings/index.js';
|
|
8
|
+
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/ruvector/index.ts"],"sourcesContent":["/**\n * RuVector - Semantic codebase search for CFN\n */\n\n// Core\nexport { RuVectorIndex } from './core/index.js';\nexport type { SearchResult, IndexStats, RuVectorIndexOptions } from './core/index.js';\nexport { createFileProcessor } from './core/file-processor.js';\nexport type { ProcessedFile, FileProcessor } from './core/file-processor.js';\n\n// Embeddings\nexport { EmbeddingError, createEmbeddingProvider, OpenAIEmbeddingProvider, createOpenAIProvider } from './embeddings/index.js';\nexport type { EmbeddingProvider, EmbeddingResult, EmbeddingProviderConfig } from './embeddings/index.js';"],"names":["RuVectorIndex","createFileProcessor","EmbeddingError","createEmbeddingProvider","OpenAIEmbeddingProvider","createOpenAIProvider"],"mappings":"AAAA;;CAEC,GAED,OAAO;AACP,SAASA,aAAa,QAAQ,kBAAkB;AAEhD,SAASC,mBAAmB,QAAQ,2BAA2B;AAG/D,aAAa;AACb,SAASC,cAAc,EAAEC,uBAAuB,EAAEC,uBAAuB,EAAEC,oBAAoB,QAAQ,wBAAwB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-flow-novice",
|
|
3
|
-
"version": "2.18.
|
|
3
|
+
"version": "2.18.3",
|
|
4
4
|
"description": "AI agent orchestration framework with namespace-isolated skills, agents, and CFN Loop validation. Safe installation with ~0.01% collision risk.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"cfn-portal": "dist/cli/cfn-portal.js",
|
|
14
14
|
"cfn-context": "dist/cli/cfn-context.js",
|
|
15
15
|
"cfn-metrics": "dist/cli/cfn-metrics.js",
|
|
16
|
-
"cfn-redis": "dist/cli/cfn-redis.js"
|
|
16
|
+
"cfn-redis": "dist/cli/cfn-redis.js",
|
|
17
|
+
"cfn-ruvector": "dist/ruvector/cli.js"
|
|
17
18
|
},
|
|
18
19
|
"files": [
|
|
19
20
|
"dist/",
|
|
@@ -89,7 +90,10 @@
|
|
|
89
90
|
"docker",
|
|
90
91
|
"containers",
|
|
91
92
|
"memory-leaks",
|
|
92
|
-
"concurrent-execution"
|
|
93
|
+
"concurrent-execution",
|
|
94
|
+
"semantic-search",
|
|
95
|
+
"ruvector",
|
|
96
|
+
"vector-embeddings"
|
|
93
97
|
],
|
|
94
98
|
"author": "Claude Flow Novice Team",
|
|
95
99
|
"license": "MIT",
|
|
@@ -105,7 +109,7 @@
|
|
|
105
109
|
"dev": "tsx src/cli/index.ts",
|
|
106
110
|
"build": "npm run clean && npm run build:swc && npm run build:orchestrator",
|
|
107
111
|
"build:swc": "swc src -d dist --config-file .swcrc --ignore '**/*.test.ts' --ignore '**/*.test.tsx' --ignore '**/*.spec.ts'",
|
|
108
|
-
"build:orchestrator": "
|
|
112
|
+
"build:orchestrator": "cd .claude/skills/cfn-loop-orchestration && npm run build 2>/dev/null || echo 'Orchestrator build skipped (optional)'",
|
|
109
113
|
"build:all": "npm run build && npm run build:spawner && npm run build:selector && npm run build:coordination",
|
|
110
114
|
"build:spawner": "cd src/coordination && tsc spawn-agent.ts --outDir ../../dist/coordination --module commonjs --target es2020 --skipLibCheck 2>/dev/null || echo 'Spawner build skipped'",
|
|
111
115
|
"build:selector": "cd .claude/skills/cfn-agent-selection-with-fallback && npm run build 2>/dev/null || echo 'Selector build skipped'",
|
|
@@ -183,7 +187,11 @@
|
|
|
183
187
|
"socket.io": "^4.8.1",
|
|
184
188
|
"sqlite": "^5.1.1",
|
|
185
189
|
"sqlite3": "^5.1.7",
|
|
186
|
-
"uuid": "^10.0.0"
|
|
190
|
+
"uuid": "^10.0.0",
|
|
191
|
+
"@ruvector/core": "^0.1.0",
|
|
192
|
+
"simple-git": "^3.22.0",
|
|
193
|
+
"cosmiconfig": "^9.0.0",
|
|
194
|
+
"zod": "^3.22.0"
|
|
187
195
|
},
|
|
188
196
|
"engines": {
|
|
189
197
|
"node": ">=18.0.0"
|
package/readme/README.md
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
# Claude Flow Novice v2.
|
|
1
|
+
# Claude Flow Novice v2.18.1 Documentation
|
|
2
2
|
|
|
3
|
-
**Version:** 2.
|
|
4
|
-
**Last Updated:** 2025-
|
|
3
|
+
**Version:** 2.18.1 (RuVector Integration)
|
|
4
|
+
**Last Updated:** 2025-12-05
|
|
5
5
|
|
|
6
6
|
**Package Metrics**:
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
7
|
+
- Namespace-isolated installation (~0.01% collision risk)
|
|
8
|
+
- Semantic codebase search via RuVector
|
|
9
|
+
- Multi-provider routing (Z.ai, Kimi, OpenRouter, Anthropic)
|
|
10
10
|
|
|
11
11
|
## Overview
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
AI agent orchestration with semantic codebase search, Redis coordination, and multi-loop consensus validation (CFN Loop).
|
|
14
14
|
|
|
15
15
|
## CFN Loop Execution Modes
|
|
16
16
|
|
|
@@ -85,7 +85,7 @@ npx claude-flow-novice swarm "Task Description" \
|
|
|
85
85
|
### Core Concepts
|
|
86
86
|
- **[Skills System](log-skills.md)** - Modular, reusable agent capabilities
|
|
87
87
|
- **[CFN Loop](cfn-loop-modes.md)** - Three-loop consensus validation framework
|
|
88
|
-
- **[
|
|
88
|
+
- **[RuVector Search](../docs/RUVECTOR_ARCHITECTURE.md)** - Semantic codebase indexing
|
|
89
89
|
- **[Redis Coordination](logs-cli-redis.md)** - Zero-token agent coordination
|
|
90
90
|
|
|
91
91
|
### User Guides
|
|
@@ -111,14 +111,24 @@ npx claude-flow-novice swarm "Task Description" \
|
|
|
111
111
|
- **[Deprecated MCP Logs](deprecated-logs-mcp.md)** - Historical MCP implementation
|
|
112
112
|
- **[v1 Documentation](../legacy/readme-v1/)** - Previous documentation version
|
|
113
113
|
|
|
114
|
-
## Key Features (v2.
|
|
114
|
+
## Key Features (v2.18.1)
|
|
115
115
|
|
|
116
|
-
###
|
|
117
|
-
- **
|
|
118
|
-
- **
|
|
119
|
-
- **
|
|
120
|
-
- **
|
|
121
|
-
|
|
116
|
+
### RuVector Codebase Search (NEW)
|
|
117
|
+
- **Semantic Search**: Natural language queries against codebase
|
|
118
|
+
- **OpenAI Embeddings**: text-embedding-3-small (1536 dimensions)
|
|
119
|
+
- **Manifest System**: `.cfn-manifest.json` tracks CFN vs custom files
|
|
120
|
+
- **Safe Distribution**: Custom files preserved during CFN updates
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
# Index codebase
|
|
124
|
+
./.claude/skills/cfn-ruvector-codebase-index/index.sh --full
|
|
125
|
+
|
|
126
|
+
# Search
|
|
127
|
+
./.claude/skills/cfn-ruvector-codebase-index/search.sh "authentication" --top 5
|
|
128
|
+
|
|
129
|
+
# Incremental reindex
|
|
130
|
+
/cfn-ruvector:codebase-reindex
|
|
131
|
+
```
|
|
122
132
|
|
|
123
133
|
### Skills-First Architecture
|
|
124
134
|
- **Modular Skills**: Independently maintainable, testable capabilities
|