@vivantel/rag-core 1.1.3 → 2.0.0
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/dist/bin/rag-update.d.ts +3 -0
- package/dist/bin/rag-update.d.ts.map +1 -0
- package/dist/bin/rag-update.js +116 -0
- package/dist/bin/rag-update.js.map +1 -0
- package/dist/cli/init.d.ts +2 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +262 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/validate.d.ts +2 -0
- package/dist/cli/validate.d.ts.map +1 -0
- package/dist/cli/validate.js +54 -0
- package/dist/cli/validate.js.map +1 -0
- package/dist/config-loader.d.ts.map +1 -1
- package/dist/config-loader.js +73 -5
- package/dist/config-loader.js.map +1 -1
- package/dist/core/chunk-processor.d.ts +1 -1
- package/dist/core/chunk-processor.d.ts.map +1 -1
- package/dist/core/chunk-processor.js +23 -1
- package/dist/core/chunk-processor.js.map +1 -1
- package/dist/core/embedder.d.ts +5 -1
- package/dist/core/embedder.d.ts.map +1 -1
- package/dist/core/embedder.js +33 -29
- package/dist/core/embedder.js.map +1 -1
- package/dist/core/errors.d.ts +16 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +17 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/orchestrator.d.ts +8 -0
- package/dist/core/orchestrator.d.ts.map +1 -1
- package/dist/core/orchestrator.js +134 -39
- package/dist/core/orchestrator.js.map +1 -1
- package/dist/core/plugin-discovery.d.ts +19 -0
- package/dist/core/plugin-discovery.d.ts.map +1 -0
- package/dist/core/plugin-discovery.js +47 -0
- package/dist/core/plugin-discovery.js.map +1 -0
- package/dist/core/telemetry.d.ts +61 -0
- package/dist/core/telemetry.d.ts.map +1 -0
- package/dist/core/telemetry.js +50 -0
- package/dist/core/telemetry.js.map +1 -0
- package/dist/core/uploader.d.ts +5 -1
- package/dist/core/uploader.d.ts.map +1 -1
- package/dist/core/uploader.js +11 -4
- package/dist/core/uploader.js.map +1 -1
- package/dist/core/utils.d.ts +7 -0
- package/dist/core/utils.d.ts.map +1 -1
- package/dist/core/utils.js +35 -0
- package/dist/core/utils.js.map +1 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -2
- package/dist/index.js.map +1 -1
- package/dist/interfaces/embedder.d.ts +2 -0
- package/dist/interfaces/embedder.d.ts.map +1 -1
- package/dist/interfaces/vector-store.d.ts +2 -0
- package/dist/interfaces/vector-store.d.ts.map +1 -1
- package/package.json +8 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rag-update.d.ts","sourceRoot":"","sources":["../../src/bin/rag-update.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { config } from "dotenv";
|
|
4
|
+
import { loadConfig } from "../config-loader.js";
|
|
5
|
+
import { Orchestrator } from "../core/orchestrator.js";
|
|
6
|
+
import { RagError } from "../core/errors.js";
|
|
7
|
+
import { runInit } from "../cli/init.js";
|
|
8
|
+
import { runValidate } from "../cli/validate.js";
|
|
9
|
+
config();
|
|
10
|
+
const program = new Command();
|
|
11
|
+
function handleError(error) {
|
|
12
|
+
console.error("❌ Error:", error instanceof Error ? error.message : error);
|
|
13
|
+
if (error instanceof RagError && error.suggestion) {
|
|
14
|
+
console.error(" 💡", error.suggestion);
|
|
15
|
+
}
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
async function runOnce(options) {
|
|
19
|
+
const cfg = await loadConfig(options.config);
|
|
20
|
+
const orchestrator = new Orchestrator({
|
|
21
|
+
...cfg,
|
|
22
|
+
options: {
|
|
23
|
+
...cfg.options,
|
|
24
|
+
force: options.force || cfg.options?.force,
|
|
25
|
+
skipUpload: options.noUpload || cfg.options?.skipUpload,
|
|
26
|
+
dryRun: options.dryRun || cfg.options?.dryRun,
|
|
27
|
+
chunksFile: options.chunksOut || cfg.options?.chunksFile,
|
|
28
|
+
embeddingsFile: options.embeddingsOut || cfg.options?.embeddingsFile,
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
await orchestrator.run();
|
|
32
|
+
}
|
|
33
|
+
program
|
|
34
|
+
.name("rag-update")
|
|
35
|
+
.description("Update RAG index with latest changes")
|
|
36
|
+
.version("2.0.0")
|
|
37
|
+
.option("-c, --config <path>", "Path to config file", "./rag.config.ts")
|
|
38
|
+
.option("-f, --force", "Force full rebuild", false)
|
|
39
|
+
.option("--no-upload", "Skip upload to vector store", false)
|
|
40
|
+
.option("--dry-run", "Show what would change without uploading", false)
|
|
41
|
+
.option("--chunks-out <path>", "Output path for chunks.json")
|
|
42
|
+
.option("--embeddings-out <path>", "Output path for embeddings.json")
|
|
43
|
+
.option("--watch", "Re-run pipeline on file changes", false)
|
|
44
|
+
.action(async () => {
|
|
45
|
+
const opts = program.opts();
|
|
46
|
+
const runOptions = {
|
|
47
|
+
config: opts.config,
|
|
48
|
+
force: opts.force,
|
|
49
|
+
noUpload: !opts.upload,
|
|
50
|
+
dryRun: opts.dryRun,
|
|
51
|
+
chunksOut: opts.chunksOut,
|
|
52
|
+
embeddingsOut: opts.embeddingsOut,
|
|
53
|
+
};
|
|
54
|
+
console.log("🚀 RAG Update Tool\n");
|
|
55
|
+
try {
|
|
56
|
+
await runOnce(runOptions);
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
handleError(error);
|
|
60
|
+
}
|
|
61
|
+
if (!opts.watch)
|
|
62
|
+
return;
|
|
63
|
+
// Watch mode
|
|
64
|
+
const { default: chokidar } = await import("chokidar");
|
|
65
|
+
const cfg = await loadConfig(opts.config).catch(() => null);
|
|
66
|
+
const patterns = cfg
|
|
67
|
+
? cfg.chunkers.flatMap((c) => c.patterns)
|
|
68
|
+
: [];
|
|
69
|
+
const watched = [opts.config, ...patterns];
|
|
70
|
+
console.log("\n👁️ Watching for changes...");
|
|
71
|
+
let debounce = null;
|
|
72
|
+
chokidar
|
|
73
|
+
.watch(watched, { ignoreInitial: true })
|
|
74
|
+
.on("all", (event, path) => {
|
|
75
|
+
if (debounce)
|
|
76
|
+
clearTimeout(debounce);
|
|
77
|
+
debounce = setTimeout(async () => {
|
|
78
|
+
console.log(`\n🔄 Change detected (${event}: ${path}), re-running...\n`);
|
|
79
|
+
try {
|
|
80
|
+
await runOnce(runOptions);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
console.error("❌ Error:", error instanceof Error ? error.message : error);
|
|
84
|
+
}
|
|
85
|
+
}, 500);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
program
|
|
89
|
+
.command("init")
|
|
90
|
+
.description("Generate a rag.config.ts template interactively")
|
|
91
|
+
.action(async () => {
|
|
92
|
+
try {
|
|
93
|
+
await runInit();
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
if (error.name === "ExitPromptError") {
|
|
97
|
+
console.log("\nCancelled.");
|
|
98
|
+
process.exit(0);
|
|
99
|
+
}
|
|
100
|
+
handleError(error);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
program
|
|
104
|
+
.command("validate")
|
|
105
|
+
.description("Validate config without running the pipeline")
|
|
106
|
+
.option("-c, --config <path>", "Path to config file", "./rag.config.ts")
|
|
107
|
+
.action(async (opts) => {
|
|
108
|
+
try {
|
|
109
|
+
await runValidate(opts.config);
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
handleError(error);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
program.parse();
|
|
116
|
+
//# sourceMappingURL=rag-update.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rag-update.js","sourceRoot":"","sources":["../../src/bin/rag-update.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAgOA,wBAAsB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAqE7C"}
|
package/dist/cli/init.js
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { checkbox, select, input } from "@inquirer/prompts";
|
|
2
|
+
import { writeFile } from "fs/promises";
|
|
3
|
+
import { existsSync } from "fs";
|
|
4
|
+
const STRATEGY_INFO = {
|
|
5
|
+
token: {
|
|
6
|
+
fn: "tokenStrategy",
|
|
7
|
+
description: "Token-based chunking (source code, structured text)",
|
|
8
|
+
patterns: ["src/**/*.ts", "src/**/*.js"],
|
|
9
|
+
},
|
|
10
|
+
markdown: {
|
|
11
|
+
fn: "markdownHeadersStrategy",
|
|
12
|
+
description: "Markdown header-aware chunking (documentation)",
|
|
13
|
+
patterns: ["docs/**/*.md", "*.md"],
|
|
14
|
+
},
|
|
15
|
+
semantic: {
|
|
16
|
+
fn: "semanticStrategy",
|
|
17
|
+
description: "Semantic paragraph chunking (prose, articles)",
|
|
18
|
+
patterns: ["**/*.txt"],
|
|
19
|
+
},
|
|
20
|
+
"whole-file": {
|
|
21
|
+
fn: "wholeFileStrategy",
|
|
22
|
+
description: "Treat each file as one chunk (small configs, YAML)",
|
|
23
|
+
patterns: ["**/*.yaml", "**/*.yml"],
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
function buildEmbedderSection(provider) {
|
|
27
|
+
switch (provider) {
|
|
28
|
+
case "openai":
|
|
29
|
+
return `// Install: npm install openai
|
|
30
|
+
// import OpenAI from 'openai';
|
|
31
|
+
// const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
|
|
32
|
+
|
|
33
|
+
const embedder: EmbeddingProvider = {
|
|
34
|
+
name: 'openai',
|
|
35
|
+
dimensions: 1536, // text-embedding-3-small
|
|
36
|
+
async embed(text: string): Promise<number[]> {
|
|
37
|
+
// const res = await openai.embeddings.create({ model: 'text-embedding-3-small', input: text });
|
|
38
|
+
// return res.data[0].embedding;
|
|
39
|
+
throw new Error('Configure your OpenAI embedder — uncomment and adapt the lines above');
|
|
40
|
+
},
|
|
41
|
+
async embedBatch(texts: string[]): Promise<number[][]> {
|
|
42
|
+
// const res = await openai.embeddings.create({ model: 'text-embedding-3-small', input: texts });
|
|
43
|
+
// return res.data.map(d => d.embedding);
|
|
44
|
+
throw new Error('Configure your OpenAI embedder — uncomment and adapt the lines above');
|
|
45
|
+
},
|
|
46
|
+
};`;
|
|
47
|
+
case "github-models":
|
|
48
|
+
return `// Requires GITHUB_TOKEN in your environment (.env or CI secret)
|
|
49
|
+
|
|
50
|
+
const embedder: EmbeddingProvider = {
|
|
51
|
+
name: 'github-models',
|
|
52
|
+
dimensions: 1536, // text-embedding-3-small
|
|
53
|
+
async embed(text: string): Promise<number[]> {
|
|
54
|
+
const res = await fetch('https://models.inference.ai.azure.com/embeddings', {
|
|
55
|
+
method: 'POST',
|
|
56
|
+
headers: {
|
|
57
|
+
'Content-Type': 'application/json',
|
|
58
|
+
Authorization: \`Bearer \${process.env.GITHUB_TOKEN}\`,
|
|
59
|
+
},
|
|
60
|
+
body: JSON.stringify({ model: 'text-embedding-3-small', input: text }),
|
|
61
|
+
});
|
|
62
|
+
if (!res.ok) throw new Error(\`GitHub Models error: \${res.statusText}\`);
|
|
63
|
+
const json = await res.json() as { data: Array<{ embedding: number[] }> };
|
|
64
|
+
return json.data[0].embedding;
|
|
65
|
+
},
|
|
66
|
+
};`;
|
|
67
|
+
default:
|
|
68
|
+
return `const embedder: EmbeddingProvider = {
|
|
69
|
+
name: 'custom',
|
|
70
|
+
dimensions: 1536, // update to match your model's output size
|
|
71
|
+
async embed(text: string): Promise<number[]> {
|
|
72
|
+
// TODO: call your embedding API and return a number[]
|
|
73
|
+
void text;
|
|
74
|
+
throw new Error('Not implemented');
|
|
75
|
+
},
|
|
76
|
+
// Optional batch method for better performance:
|
|
77
|
+
// async embedBatch(texts: string[]): Promise<number[][]> {
|
|
78
|
+
// // TODO: batch embed and return number[][]
|
|
79
|
+
// throw new Error('Not implemented');
|
|
80
|
+
// },
|
|
81
|
+
};`;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function buildVectorStoreSection(store) {
|
|
85
|
+
switch (store) {
|
|
86
|
+
case "supabase":
|
|
87
|
+
return `// Install: npm install @vivantel/rag-store-supabase @supabase/supabase-js
|
|
88
|
+
// import { SupabaseVectorStore } from '@vivantel/rag-store-supabase';
|
|
89
|
+
// const vectorStore = new SupabaseVectorStore({
|
|
90
|
+
// url: process.env.SUPABASE_URL!,
|
|
91
|
+
// key: process.env.SUPABASE_KEY!,
|
|
92
|
+
// table: 'documents',
|
|
93
|
+
// });
|
|
94
|
+
|
|
95
|
+
const vectorStore: VectorStore = {
|
|
96
|
+
name: 'supabase',
|
|
97
|
+
async initialize() {
|
|
98
|
+
throw new Error('Configure your Supabase vector store — uncomment the lines above');
|
|
99
|
+
},
|
|
100
|
+
async upsert(_docs) { throw new Error('Not implemented'); },
|
|
101
|
+
async deleteBySourceFile(_files) { throw new Error('Not implemented'); },
|
|
102
|
+
async getCurrentState() { return new Map(); },
|
|
103
|
+
async search(_embedding, _topK) { return []; },
|
|
104
|
+
};`;
|
|
105
|
+
case "pinecone":
|
|
106
|
+
return `// Install: npm install @pinecone-database/pinecone
|
|
107
|
+
// import { Pinecone } from '@pinecone-database/pinecone';
|
|
108
|
+
// const pc = new Pinecone({ apiKey: process.env.PINECONE_API_KEY! });
|
|
109
|
+
// const index = pc.index(process.env.PINECONE_INDEX!);
|
|
110
|
+
|
|
111
|
+
const vectorStore: VectorStore = {
|
|
112
|
+
name: 'pinecone',
|
|
113
|
+
async initialize() {
|
|
114
|
+
throw new Error('Configure your Pinecone vector store — uncomment the lines above');
|
|
115
|
+
},
|
|
116
|
+
async upsert(_docs) { throw new Error('Not implemented'); },
|
|
117
|
+
async deleteBySourceFile(_files) { throw new Error('Not implemented'); },
|
|
118
|
+
async getCurrentState() { return new Map(); },
|
|
119
|
+
async search(_embedding, _topK) { return []; },
|
|
120
|
+
};`;
|
|
121
|
+
default:
|
|
122
|
+
return `const vectorStore: VectorStore = {
|
|
123
|
+
name: 'custom',
|
|
124
|
+
async initialize(): Promise<void> {
|
|
125
|
+
// TODO: initialize your vector store connection
|
|
126
|
+
},
|
|
127
|
+
async upsert(docs): Promise<void> {
|
|
128
|
+
// TODO: store \`docs\` in your vector database
|
|
129
|
+
void docs;
|
|
130
|
+
},
|
|
131
|
+
async deleteBySourceFile(files): Promise<void> {
|
|
132
|
+
// TODO: remove all documents whose sourceFile is in \`files\`
|
|
133
|
+
void files;
|
|
134
|
+
},
|
|
135
|
+
async getCurrentState(): Promise<Map<string, string>> {
|
|
136
|
+
// TODO: return Map<sourceFile, commitHash> of what is currently stored
|
|
137
|
+
return new Map();
|
|
138
|
+
},
|
|
139
|
+
async search(embedding, topK): Promise<VectorSearchResult[]> {
|
|
140
|
+
// TODO: return the topK most similar documents
|
|
141
|
+
void embedding; void topK;
|
|
142
|
+
return [];
|
|
143
|
+
},
|
|
144
|
+
};`;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function buildChunkersSection(strategies) {
|
|
148
|
+
if (strategies.length === 0) {
|
|
149
|
+
strategies = ["token"];
|
|
150
|
+
}
|
|
151
|
+
const entries = strategies.map((s) => {
|
|
152
|
+
const info = STRATEGY_INFO[s];
|
|
153
|
+
const patterns = JSON.stringify(info.patterns);
|
|
154
|
+
return ` createChunker({
|
|
155
|
+
name: '${s}',
|
|
156
|
+
patterns: ${patterns},
|
|
157
|
+
process: async (content) => ${info.fn}()(content),
|
|
158
|
+
}),`;
|
|
159
|
+
});
|
|
160
|
+
return entries.join("\n");
|
|
161
|
+
}
|
|
162
|
+
function generateConfig(answers) {
|
|
163
|
+
const selectedStrategies = answers.strategies.length > 0 ? answers.strategies : ["token"];
|
|
164
|
+
const strategyFns = [
|
|
165
|
+
...new Set(selectedStrategies.map((s) => STRATEGY_INFO[s].fn)),
|
|
166
|
+
];
|
|
167
|
+
const imports = [
|
|
168
|
+
"RAGPipelineConfig",
|
|
169
|
+
"EmbeddingProvider",
|
|
170
|
+
"VectorStore",
|
|
171
|
+
"VectorSearchResult",
|
|
172
|
+
"createChunker",
|
|
173
|
+
...strategyFns,
|
|
174
|
+
].join(", ");
|
|
175
|
+
const embedderSection = buildEmbedderSection(answers.embedder);
|
|
176
|
+
const vectorStoreSection = buildVectorStoreSection(answers.vectorStore);
|
|
177
|
+
const chunkersSection = buildChunkersSection(selectedStrategies);
|
|
178
|
+
return `import { ${imports} } from '@vivantel/rag-core';
|
|
179
|
+
|
|
180
|
+
${embedderSection}
|
|
181
|
+
|
|
182
|
+
${vectorStoreSection}
|
|
183
|
+
|
|
184
|
+
const config: RAGPipelineConfig = {
|
|
185
|
+
chunkers: [
|
|
186
|
+
${chunkersSection}
|
|
187
|
+
],
|
|
188
|
+
embedder,
|
|
189
|
+
vectorStore,
|
|
190
|
+
options: {
|
|
191
|
+
chunksFile: './docs/rag/chunks.json',
|
|
192
|
+
embeddingsFile: './docs/rag/embeddings.json',
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
export default config;
|
|
197
|
+
`;
|
|
198
|
+
}
|
|
199
|
+
export async function runInit() {
|
|
200
|
+
console.log("\n🚀 RAG Config Generator\n");
|
|
201
|
+
const strategies = await checkbox({
|
|
202
|
+
message: "Which chunking strategies do you need?",
|
|
203
|
+
choices: [
|
|
204
|
+
{ name: "Token (source code, structured text)", value: "token" },
|
|
205
|
+
{ name: "Markdown headers (documentation)", value: "markdown" },
|
|
206
|
+
{ name: "Semantic paragraphs (prose, articles)", value: "semantic" },
|
|
207
|
+
{ name: "Whole file (small configs, YAML)", value: "whole-file" },
|
|
208
|
+
],
|
|
209
|
+
});
|
|
210
|
+
const embedder = await select({
|
|
211
|
+
message: "Which embedding provider?",
|
|
212
|
+
choices: [
|
|
213
|
+
{ name: "OpenAI (text-embedding-3-small)", value: "openai" },
|
|
214
|
+
{
|
|
215
|
+
name: "GitHub Models (Azure-compatible endpoint)",
|
|
216
|
+
value: "github-models",
|
|
217
|
+
},
|
|
218
|
+
{ name: "Custom (implement the interface yourself)", value: "custom" },
|
|
219
|
+
],
|
|
220
|
+
});
|
|
221
|
+
const vectorStore = await select({
|
|
222
|
+
message: "Which vector store?",
|
|
223
|
+
choices: [
|
|
224
|
+
{
|
|
225
|
+
name: "Supabase pgvector (@vivantel/rag-store-supabase)",
|
|
226
|
+
value: "supabase",
|
|
227
|
+
},
|
|
228
|
+
{ name: "Pinecone (@pinecone-database/pinecone)", value: "pinecone" },
|
|
229
|
+
{ name: "Custom (implement the interface yourself)", value: "custom" },
|
|
230
|
+
],
|
|
231
|
+
});
|
|
232
|
+
const outputPath = await input({
|
|
233
|
+
message: "Output path for the config file?",
|
|
234
|
+
default: "./rag.config.ts",
|
|
235
|
+
});
|
|
236
|
+
if (existsSync(outputPath)) {
|
|
237
|
+
const overwrite = await select({
|
|
238
|
+
message: `${outputPath} already exists. Overwrite?`,
|
|
239
|
+
choices: [
|
|
240
|
+
{ name: "Yes, overwrite", value: "yes" },
|
|
241
|
+
{ name: "No, cancel", value: "no" },
|
|
242
|
+
],
|
|
243
|
+
});
|
|
244
|
+
if (overwrite === "no") {
|
|
245
|
+
console.log("\n❌ Cancelled.");
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
const config = generateConfig({
|
|
250
|
+
strategies,
|
|
251
|
+
embedder,
|
|
252
|
+
vectorStore,
|
|
253
|
+
outputPath,
|
|
254
|
+
});
|
|
255
|
+
await writeFile(outputPath, config, "utf-8");
|
|
256
|
+
console.log(`\n✅ Created ${outputPath}`);
|
|
257
|
+
console.log("\nNext steps:");
|
|
258
|
+
console.log(" 1. Fill in the TODO sections in the config file");
|
|
259
|
+
console.log(" 2. Run `rag-update validate` to check the config");
|
|
260
|
+
console.log(" 3. Run `rag-update` to start indexing\n");
|
|
261
|
+
}
|
|
262
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/cli/validate.ts"],"names":[],"mappings":"AAKA,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwDnE"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { glob } from "glob";
|
|
2
|
+
import { loadConfig } from "../config-loader.js";
|
|
3
|
+
import { GitTracker } from "../core/git-tracker.js";
|
|
4
|
+
import { ConfigError } from "../core/errors.js";
|
|
5
|
+
export async function runValidate(configPath) {
|
|
6
|
+
console.log(`\n🔍 Validating RAG config: ${configPath}\n`);
|
|
7
|
+
let config;
|
|
8
|
+
try {
|
|
9
|
+
process.stdout.write("📦 Loading config... ");
|
|
10
|
+
config = await loadConfig(configPath);
|
|
11
|
+
console.log("✅");
|
|
12
|
+
}
|
|
13
|
+
catch (err) {
|
|
14
|
+
console.log("❌");
|
|
15
|
+
throw new ConfigError(`Failed to load config: ${err instanceof Error ? err.message : String(err)}`, {
|
|
16
|
+
suggestion: "Run `rag-update init` to generate a new config file.",
|
|
17
|
+
cause: err,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
console.log("\n📂 Scanning files...\n");
|
|
21
|
+
let hasWarnings = false;
|
|
22
|
+
for (const chunker of config.chunkers) {
|
|
23
|
+
const files = await glob(chunker.patterns, { nodir: true });
|
|
24
|
+
const unique = [...new Set(files)];
|
|
25
|
+
const patternsDisplay = chunker.patterns.join(", ");
|
|
26
|
+
console.log(` Chunker: ${chunker.name} (patterns: ${patternsDisplay})`);
|
|
27
|
+
if (unique.length === 0) {
|
|
28
|
+
console.log(` ⚠️ No files matched — check your patterns\n`);
|
|
29
|
+
hasWarnings = true;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
console.log(` ✅ Found ${unique.length} matching file(s)\n`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const gitTracker = new GitTracker(config.chunkers);
|
|
36
|
+
const allFiles = await gitTracker.getAllTrackedFiles();
|
|
37
|
+
console.log(` Total: ${allFiles.length} file(s) tracked across ${config.chunkers.length} chunker(s)`);
|
|
38
|
+
console.log("\n🔌 Checking vector store...");
|
|
39
|
+
try {
|
|
40
|
+
await config.vectorStore.initialize();
|
|
41
|
+
console.log(" ✅ Vector store connected");
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
console.log(" ⚠️ Could not connect — check credentials");
|
|
45
|
+
hasWarnings = true;
|
|
46
|
+
}
|
|
47
|
+
if (hasWarnings) {
|
|
48
|
+
console.log("\n⚠️ Config loaded with warnings.");
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
console.log("\n✅ Config is valid!");
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/cli/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,UAAkB;IAClD,OAAO,CAAC,GAAG,CAAC,+BAA+B,UAAU,IAAI,CAAC,CAAC;IAE3D,IAAI,MAAM,CAAC;IACX,IAAI,CAAC;QACH,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAC9C,MAAM,GAAG,MAAM,UAAU,CAAC,UAAU,CAAC,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjB,MAAM,IAAI,WAAW,CACnB,0BAA0B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAC5E;YACE,UAAU,EAAE,sDAAsD;YAClE,KAAK,EAAE,GAAG;SACX,CACF,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;IACxC,IAAI,WAAW,GAAG,KAAK,CAAC;IAExB,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACtC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;QACnC,MAAM,eAAe,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,cAAc,OAAO,CAAC,IAAI,eAAe,eAAe,GAAG,CAAC,CAAC;QAEzE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC;YAC9D,WAAW,GAAG,IAAI,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,MAAM,qBAAqB,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACnD,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,kBAAkB,EAAE,CAAC;IACvD,OAAO,CAAC,GAAG,CACT,YAAY,QAAQ,CAAC,MAAM,2BAA2B,MAAM,CAAC,QAAQ,CAAC,MAAM,aAAa,CAC1F,CAAC;IAEF,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;IAC7C,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;QAC3D,WAAW,GAAG,IAAI,CAAC;IACrB,CAAC;IAED,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;IACpD,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IACtC,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../src/config-loader.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../src/config-loader.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAqF3D,wBAAsB,UAAU,CAC9B,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,iBAAiB,CAAC,CAgB5B"}
|
package/dist/config-loader.js
CHANGED
|
@@ -1,11 +1,79 @@
|
|
|
1
1
|
import { pathToFileURL } from "url";
|
|
2
|
+
import { ConfigError } from "./core/errors.js";
|
|
3
|
+
function validateConfig(config) {
|
|
4
|
+
if (!config || typeof config !== "object") {
|
|
5
|
+
throw new ConfigError("Config must be a non-null object", {
|
|
6
|
+
suggestion: "Ensure your config file has a default export: `export default { chunkers, embedder, vectorStore }`.",
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
const c = config;
|
|
10
|
+
if (!Array.isArray(c.chunkers) || c.chunkers.length === 0) {
|
|
11
|
+
throw new ConfigError("config.chunkers must be a non-empty array", {
|
|
12
|
+
suggestion: "Add at least one chunker using createChunker() or implementing FileChunker.",
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
for (let i = 0; i < c.chunkers.length; i++) {
|
|
16
|
+
const chunker = c.chunkers[i];
|
|
17
|
+
if (typeof chunker.name !== "string" || !chunker.name) {
|
|
18
|
+
throw new ConfigError(`config.chunkers[${i}].name must be a non-empty string`);
|
|
19
|
+
}
|
|
20
|
+
if (!Array.isArray(chunker.patterns) || chunker.patterns.length === 0) {
|
|
21
|
+
throw new ConfigError(`config.chunkers[${i}] ("${chunker.name}") must have a non-empty patterns array`);
|
|
22
|
+
}
|
|
23
|
+
if (typeof chunker.chunk !== "function") {
|
|
24
|
+
throw new ConfigError(`config.chunkers[${i}] ("${chunker.name}") must implement chunk(filePath, commitHash)`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (!c.embedder || typeof c.embedder !== "object") {
|
|
28
|
+
throw new ConfigError("config.embedder is required", {
|
|
29
|
+
suggestion: "Provide an object implementing EmbeddingProvider with at least name, dimensions, and embed().",
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
const emb = c.embedder;
|
|
33
|
+
if (typeof emb.name !== "string") {
|
|
34
|
+
throw new ConfigError("config.embedder.name must be a string");
|
|
35
|
+
}
|
|
36
|
+
if (typeof emb.dimensions !== "number") {
|
|
37
|
+
throw new ConfigError("config.embedder.dimensions must be a number (the vector output size)");
|
|
38
|
+
}
|
|
39
|
+
if (typeof emb.embed !== "function") {
|
|
40
|
+
throw new ConfigError("config.embedder must implement embed(text: string): Promise<number[]>");
|
|
41
|
+
}
|
|
42
|
+
if (!c.vectorStore || typeof c.vectorStore !== "object") {
|
|
43
|
+
throw new ConfigError("config.vectorStore is required", {
|
|
44
|
+
suggestion: "Provide an object implementing VectorStore with initialize, upsert, deleteBySourceFile, getCurrentState, and search.",
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
const vs = c.vectorStore;
|
|
48
|
+
const required = [
|
|
49
|
+
"initialize",
|
|
50
|
+
"upsert",
|
|
51
|
+
"deleteBySourceFile",
|
|
52
|
+
"getCurrentState",
|
|
53
|
+
"search",
|
|
54
|
+
];
|
|
55
|
+
for (const method of required) {
|
|
56
|
+
if (typeof vs[method] !== "function") {
|
|
57
|
+
throw new ConfigError(`config.vectorStore.${method} must be a function`, {
|
|
58
|
+
suggestion: `Implement ${method}() on your VectorStore object.`,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
2
63
|
export async function loadConfig(configPath) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
64
|
+
let configModule;
|
|
65
|
+
try {
|
|
66
|
+
const configUrl = pathToFileURL(configPath).href;
|
|
67
|
+
configModule = await import(configUrl);
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
throw new ConfigError(`Cannot load config file: ${configPath}`, {
|
|
71
|
+
suggestion: "Run `rag-update init` to generate a starter config, or check that the path is correct.",
|
|
72
|
+
cause: err,
|
|
73
|
+
});
|
|
8
74
|
}
|
|
75
|
+
const config = configModule.default;
|
|
76
|
+
validateConfig(config);
|
|
9
77
|
return config;
|
|
10
78
|
}
|
|
11
79
|
//# sourceMappingURL=config-loader.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-loader.js","sourceRoot":"","sources":["../src/config-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"config-loader.js","sourceRoot":"","sources":["../src/config-loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,7 +6,7 @@ export declare class ChunkProcessor {
|
|
|
6
6
|
processFiles(files: string[], fileState: Map<string, {
|
|
7
7
|
commitHash: string;
|
|
8
8
|
chunker: FileChunker;
|
|
9
|
-
}
|
|
9
|
+
}>, existingChunks?: Chunk[]): Promise<Chunk[]>;
|
|
10
10
|
saveChunksLocal(chunks: Chunk[], outputFile: string): Promise<void>;
|
|
11
11
|
}
|
|
12
12
|
//# sourceMappingURL=chunk-processor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunk-processor.d.ts","sourceRoot":"","sources":["../../src/core/chunk-processor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAO5D,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAA2B;gBAE/B,QAAQ,EAAE,WAAW,EAAE;IAI7B,WAAW,CACf,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,KAAK,EAAE,CAAC;IAYb,YAAY,CAChB,KAAK,EAAE,MAAM,EAAE,EACf,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,WAAW,CAAA;KAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"chunk-processor.d.ts","sourceRoot":"","sources":["../../src/core/chunk-processor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAO5D,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAA2B;gBAE/B,QAAQ,EAAE,WAAW,EAAE;IAI7B,WAAW,CACf,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,KAAK,EAAE,CAAC;IAYb,YAAY,CAChB,KAAK,EAAE,MAAM,EAAE,EACf,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,WAAW,CAAA;KAAE,CAAC,EACpE,cAAc,GAAE,KAAK,EAAO,GAC3B,OAAO,CAAC,KAAK,EAAE,CAAC;IAmEb,eAAe,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAyB1E"}
|
|
@@ -16,9 +16,23 @@ export class ChunkProcessor {
|
|
|
16
16
|
}
|
|
17
17
|
return chunks;
|
|
18
18
|
}
|
|
19
|
-
async processFiles(files, fileState) {
|
|
19
|
+
async processFiles(files, fileState, existingChunks = []) {
|
|
20
20
|
const allChunks = [];
|
|
21
21
|
let errorCount = 0;
|
|
22
|
+
// Build resume cache: sourceFile → { commitHash, chunks }
|
|
23
|
+
const resumeCache = new Map();
|
|
24
|
+
for (const chunk of existingChunks) {
|
|
25
|
+
const entry = resumeCache.get(chunk.sourceFile);
|
|
26
|
+
if (!entry) {
|
|
27
|
+
resumeCache.set(chunk.sourceFile, {
|
|
28
|
+
commitHash: chunk.commitHash,
|
|
29
|
+
chunks: [chunk],
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
entry.chunks.push(chunk);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
22
36
|
for (let i = 0; i < files.length; i++) {
|
|
23
37
|
const filePath = files[i];
|
|
24
38
|
const info = fileState.get(filePath);
|
|
@@ -26,6 +40,14 @@ export class ChunkProcessor {
|
|
|
26
40
|
console.log(` ⚠️ No chunker for: ${filePath}`);
|
|
27
41
|
continue;
|
|
28
42
|
}
|
|
43
|
+
// Resume: reuse cached chunks when commitHash matches
|
|
44
|
+
const cached = resumeCache.get(filePath);
|
|
45
|
+
if (cached && cached.commitHash === info.commitHash) {
|
|
46
|
+
console.log(` [${i + 1}/${files.length}] ${filePath}`);
|
|
47
|
+
console.log(` ⏭️ Cached (${cached.chunks.length} chunk(s))`);
|
|
48
|
+
allChunks.push(...cached.chunks);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
29
51
|
console.log(` [${i + 1}/${files.length}] ${filePath}`);
|
|
30
52
|
try {
|
|
31
53
|
const chunks = await this.processFile(filePath, info.commitHash, info.chunker);
|