@jcode.labs/ragmir 2.10.0 → 2.12.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/README.md +12 -1
- package/dist/chunk-stats.d.ts +8 -0
- package/dist/chunk-stats.d.ts.map +1 -0
- package/dist/chunk-stats.js +31 -0
- package/dist/chunk-stats.js.map +1 -0
- package/dist/cli.js +125 -8
- package/dist/cli.js.map +1 -1
- package/dist/context-resources.d.ts +4 -0
- package/dist/context-resources.d.ts.map +1 -0
- package/dist/context-resources.js +87 -0
- package/dist/context-resources.js.map +1 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +15 -4
- package/dist/doctor.js.map +1 -1
- package/dist/evaluate.d.ts.map +1 -1
- package/dist/evaluate.js +8 -0
- package/dist/evaluate.js.map +1 -1
- package/dist/gitignore.d.ts +1 -1
- package/dist/gitignore.d.ts.map +1 -1
- package/dist/gitignore.js +3 -2
- package/dist/gitignore.js.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/ingest.d.ts.map +1 -1
- package/dist/ingest.js +7 -1
- package/dist/ingest.js.map +1 -1
- package/dist/knowledge-bases.d.ts +4 -0
- package/dist/knowledge-bases.d.ts.map +1 -0
- package/dist/knowledge-bases.js +113 -0
- package/dist/knowledge-bases.js.map +1 -0
- package/dist/mcp.d.ts +3 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +38 -7
- package/dist/mcp.js.map +1 -1
- package/dist/package-manager.d.ts +2 -0
- package/dist/package-manager.d.ts.map +1 -1
- package/dist/package-manager.js +18 -1
- package/dist/package-manager.js.map +1 -1
- package/dist/preview.d.ts +3 -0
- package/dist/preview.d.ts.map +1 -0
- package/dist/preview.js +115 -0
- package/dist/preview.js.map +1 -0
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +70 -21
- package/dist/query.js.map +1 -1
- package/dist/research.d.ts.map +1 -1
- package/dist/research.js +2 -0
- package/dist/research.js.map +1 -1
- package/dist/setup.d.ts +3 -1
- package/dist/setup.d.ts.map +1 -1
- package/dist/setup.js +10 -5
- package/dist/setup.js.map +1 -1
- package/dist/skill.d.ts +16 -3
- package/dist/skill.d.ts.map +1 -1
- package/dist/skill.js +319 -20
- package/dist/skill.js.map +1 -1
- package/dist/types.d.ts +142 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
- package/skills/ragmir/SKILL.md +28 -0
package/README.md
CHANGED
|
@@ -55,7 +55,10 @@ npx rgr audit --unsupported
|
|
|
55
55
|
npx rgr security-audit
|
|
56
56
|
|
|
57
57
|
# Retrieval
|
|
58
|
+
npx rgr preview --path docs --max-chunks 3
|
|
58
59
|
npx rgr search "deployment decision"
|
|
60
|
+
npx rgr search "deployment decision" --explain
|
|
61
|
+
npx rgr search "deployment decision" --context-path "Operations > Deployment"
|
|
59
62
|
npx rgr ask "What evidence supports the deployment decision?"
|
|
60
63
|
npx rgr research "deployment obligations" --compact
|
|
61
64
|
|
|
@@ -88,7 +91,10 @@ Frequently used exports:
|
|
|
88
91
|
| Export | Purpose |
|
|
89
92
|
| --- | --- |
|
|
90
93
|
| `setupProject`, `addSourceEntries` | Initialize project state and select files |
|
|
94
|
+
| `discoverKnowledgeBases`, `knowledgeBaseIdentity` | Route root and nested monorepo bases |
|
|
95
|
+
| `getKnowledgeBaseContext`, `getKnowledgeBaseSourceCatalog` | Give agents bounded readiness and source context |
|
|
91
96
|
| `ingest`, `audit` | Build the index and compare it with files on disk |
|
|
97
|
+
| `previewChunks` | Inspect redacted chunks and distributions without writing storage |
|
|
92
98
|
| `search`, `ask`, `research`, `expandCitation` | Retrieve or expand cited passages |
|
|
93
99
|
| `doctor`, `securityAudit` | Inspect readiness and local privacy posture |
|
|
94
100
|
| `serveMcp` | Start the read-focused local MCP server |
|
|
@@ -104,11 +110,16 @@ npx rgr setup --agents claude,codex,kimi,opencode,cline
|
|
|
104
110
|
npx rgr doctor
|
|
105
111
|
```
|
|
106
112
|
|
|
107
|
-
Ragmir
|
|
113
|
+
Ragmir links the canonical skills into each selected client's native project folder, writes a local
|
|
114
|
+
runner plus MCP helpers, and points them at the current project. MCP
|
|
108
115
|
exposes status, search, ask, research, exact citation expansion, audit, evaluation, usage, and
|
|
109
116
|
security tools. Retrieval responses have a global byte ceiling and expose metadata-only output
|
|
110
117
|
metrics. The server does not expose index deletion.
|
|
111
118
|
|
|
119
|
+
For a monorepo with root and app-specific bases, run `rgr bases --json` before retrieval when scope
|
|
120
|
+
is unclear. The nearest configured base is active, nested MCP helpers get unique names, and every
|
|
121
|
+
helper pins `RAGMIR_PROJECT_ROOT` so clients cannot drift to a sibling index.
|
|
122
|
+
|
|
112
123
|
## Retrieval modes
|
|
113
124
|
|
|
114
125
|
| Mode | Network requirement | Best for |
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk-stats.d.ts","sourceRoot":"","sources":["../src/chunk-stats.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C,UAAU,UAAU;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;CACb;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,GAAG,UAAU,CA2B7E"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export function summarizeChunkStats(chunks) {
|
|
2
|
+
if (chunks.length === 0) {
|
|
3
|
+
return {
|
|
4
|
+
count: 0,
|
|
5
|
+
minChars: 0,
|
|
6
|
+
averageChars: 0,
|
|
7
|
+
p50Chars: 0,
|
|
8
|
+
p95Chars: 0,
|
|
9
|
+
maxChars: 0,
|
|
10
|
+
contextualChunks: 0,
|
|
11
|
+
contextualRatio: 0,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
const lengths = chunks.map((chunk) => chunk.text.length).sort((left, right) => left - right);
|
|
15
|
+
const contextualChunks = chunks.filter((chunk) => chunk.contextPath.trim().length > 0).length;
|
|
16
|
+
return {
|
|
17
|
+
count: chunks.length,
|
|
18
|
+
minChars: lengths[0] ?? 0,
|
|
19
|
+
averageChars: lengths.reduce((sum, length) => sum + length, 0) / lengths.length,
|
|
20
|
+
p50Chars: percentile(lengths, 0.5),
|
|
21
|
+
p95Chars: percentile(lengths, 0.95),
|
|
22
|
+
maxChars: lengths.at(-1) ?? 0,
|
|
23
|
+
contextualChunks,
|
|
24
|
+
contextualRatio: contextualChunks / chunks.length,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function percentile(sortedValues, quantile) {
|
|
28
|
+
const index = Math.ceil(quantile * sortedValues.length) - 1;
|
|
29
|
+
return sortedValues[Math.max(0, index)] ?? 0;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=chunk-stats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk-stats.js","sourceRoot":"","sources":["../src/chunk-stats.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,mBAAmB,CAAC,MAA6B;IAC/D,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO;YACL,KAAK,EAAE,CAAC;YACR,QAAQ,EAAE,CAAC;YACX,YAAY,EAAE,CAAC;YACf,QAAQ,EAAE,CAAC;YACX,QAAQ,EAAE,CAAC;YACX,QAAQ,EAAE,CAAC;YACX,gBAAgB,EAAE,CAAC;YACnB,eAAe,EAAE,CAAC;SACnB,CAAA;IACH,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,GAAG,KAAK,CAAC,CAAA;IAC5F,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,CAAA;IAE7F,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,MAAM;QACpB,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;QACzB,YAAY,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,GAAG,GAAG,MAAM,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM;QAC/E,QAAQ,EAAE,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC;QAClC,QAAQ,EAAE,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC;QACnC,QAAQ,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC7B,gBAAgB;QAChB,eAAe,EAAE,gBAAgB,GAAG,MAAM,CAAC,MAAM;KAClD,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,YAAsB,EAAE,QAAgB;IAC1D,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,GAAG,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IAC3D,OAAO,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,CAAA;AAC9C,CAAC"}
|
package/dist/cli.js
CHANGED
|
@@ -14,10 +14,12 @@ import { countSkippedByReason } from "./files.js";
|
|
|
14
14
|
import { getIndexFreshnessWarning, getLexicalScanWarning } from "./index-diagnostics.js";
|
|
15
15
|
import { audit, ingest } from "./ingest.js";
|
|
16
16
|
import { initProject } from "./init.js";
|
|
17
|
+
import { discoverKnowledgeBases, knowledgeBaseIdentity } from "./knowledge-bases.js";
|
|
17
18
|
import { ingestionLimits } from "./limits.js";
|
|
18
19
|
import { serveMcp } from "./mcp.js";
|
|
19
20
|
import { configurePdfOcr, extractPdfPage, inspectPdfOcr, parsePdfOcrEngine } from "./ocr.js";
|
|
20
21
|
import { rgrCommand } from "./package-manager.js";
|
|
22
|
+
import { previewChunks } from "./preview.js";
|
|
21
23
|
import { routePrompt } from "./prompt-routing.js";
|
|
22
24
|
import { ask, search } from "./query.js";
|
|
23
25
|
import { compactResearchReport, compactSearchResults, research } from "./research.js";
|
|
@@ -163,14 +165,15 @@ program
|
|
|
163
165
|
});
|
|
164
166
|
program
|
|
165
167
|
.command("setup")
|
|
166
|
-
.description("Initialize Ragmir,
|
|
168
|
+
.description("Initialize Ragmir, expose native agent skills, generate MCP helpers, and ingest when safe.")
|
|
167
169
|
.option("--target-dir <path>", "Directory where the skill folder should be copied.", DEFAULT_SKILL_TARGET_DIR)
|
|
168
|
-
.option("--agents <list>", `
|
|
169
|
-
.option("--mcp-name <name>", "MCP server name
|
|
170
|
+
.option("--agents <list>", `Native agent skills and MCP helpers to install: all, ${SUPPORTED_AGENT_TARGETS.join(", ")}.`, "all")
|
|
171
|
+
.option("--mcp-name <name>", "MCP server name. Nested monorepo bases get a unique name by default.")
|
|
170
172
|
.option("--mcp-command <command>", "Custom MCP stdio command for generated helper files.")
|
|
171
173
|
.option("--mcp-arg <arg>", "Argument for --mcp-command. Repeat for multiple arguments.", collectOptionValue, [])
|
|
172
174
|
.option("--semantic", "Download the configured Transformers.js embedding model and enable higher-quality semantic retrieval.")
|
|
173
175
|
.option("--no-ingest", "Skip automatic indexing even when supported files are present.")
|
|
176
|
+
.option("--force-agent-skills", "Replace same-name native skills after reviewing that they can be overwritten.")
|
|
174
177
|
.option("--json", "Print machine-readable JSON.")
|
|
175
178
|
.action(async (options, command) => {
|
|
176
179
|
const cwd = projectRoot(command);
|
|
@@ -178,11 +181,12 @@ program
|
|
|
178
181
|
cwd,
|
|
179
182
|
targetDir: options.targetDir,
|
|
180
183
|
agents: parseAgentTargets(options.agents),
|
|
181
|
-
mcpServerName: options.mcpName,
|
|
182
184
|
};
|
|
185
|
+
addOption(setupOptions, "mcpServerName", options.mcpName);
|
|
183
186
|
addOption(setupOptions, "semantic", options.semantic);
|
|
184
187
|
addOption(setupOptions, "ingest", options.ingest);
|
|
185
188
|
addOption(setupOptions, "mcpCommand", options.mcpCommand);
|
|
189
|
+
addOption(setupOptions, "forceAgentSkills", options.forceAgentSkills);
|
|
186
190
|
if (options.mcpArg.length > 0) {
|
|
187
191
|
setupOptions.mcpArgs = options.mcpArg;
|
|
188
192
|
}
|
|
@@ -300,6 +304,56 @@ program
|
|
|
300
304
|
process.exitCode = 1;
|
|
301
305
|
}
|
|
302
306
|
});
|
|
307
|
+
program
|
|
308
|
+
.command("preview")
|
|
309
|
+
.description("Preview redacted chunks and structure without writing the index.")
|
|
310
|
+
.option("--path <prefix>", "Preview only source paths under this prefix. Repeat for multiple prefixes.", collectOptionValue, [])
|
|
311
|
+
.option("--max-files <number>", "Maximum number of matching files to parse.", parsePositiveInt)
|
|
312
|
+
.option("--max-chunks <number>", "Maximum number of chunks to show per file.", parsePositiveInt)
|
|
313
|
+
.option("--json", "Print machine-readable JSON.")
|
|
314
|
+
.action(async (options, command) => {
|
|
315
|
+
const cwd = projectRoot(command);
|
|
316
|
+
const previewOptions = { cwd };
|
|
317
|
+
if (options.path.length > 0) {
|
|
318
|
+
previewOptions.paths = options.path;
|
|
319
|
+
}
|
|
320
|
+
addOption(previewOptions, "maxFiles", options.maxFiles);
|
|
321
|
+
addOption(previewOptions, "maxChunksPerFile", options.maxChunks);
|
|
322
|
+
const report = await previewChunks(previewOptions);
|
|
323
|
+
if (options.json) {
|
|
324
|
+
console.log(JSON.stringify(report, null, 2));
|
|
325
|
+
if (report.errors.length > 0 ||
|
|
326
|
+
(report.requestedPaths.length > 0 && report.matchedFiles === 0)) {
|
|
327
|
+
process.exitCode = 1;
|
|
328
|
+
}
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
console.log(`chunkSize=${report.chunkSize}`);
|
|
332
|
+
console.log(`chunkOverlap=${report.chunkOverlap}`);
|
|
333
|
+
console.log(`matchedFiles=${report.matchedFiles}`);
|
|
334
|
+
console.log(`omittedFiles=${report.omittedFiles}`);
|
|
335
|
+
for (const unmatchedPath of report.unmatchedPaths) {
|
|
336
|
+
console.log(pc.yellow(`unmatched: ${unmatchedPath}`));
|
|
337
|
+
}
|
|
338
|
+
for (const file of report.files) {
|
|
339
|
+
console.log(`\n${pc.cyan(file.relativePath)} chunks=${file.chunkStats.count} redactions=${file.redactions} minChars=${file.chunkStats.minChars} p50Chars=${file.chunkStats.p50Chars} p95Chars=${file.chunkStats.p95Chars} maxChars=${file.chunkStats.maxChars} contextualRatio=${file.chunkStats.contextualRatio.toFixed(3)}`);
|
|
340
|
+
for (const chunk of file.chunks) {
|
|
341
|
+
const context = chunk.contextPath ? ` context=${chunk.contextPath}` : "";
|
|
342
|
+
console.log(`\n${pc.dim(chunk.citation)}${context}`);
|
|
343
|
+
console.log(chunk.text.slice(0, SEARCH_TEXT_PREVIEW_LENGTH));
|
|
344
|
+
}
|
|
345
|
+
if (file.omittedChunks > 0) {
|
|
346
|
+
console.log(pc.dim(`omittedChunks=${file.omittedChunks}`));
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
for (const error of report.errors) {
|
|
350
|
+
console.error(pc.red(`${error.path}: ${error.message}`));
|
|
351
|
+
}
|
|
352
|
+
if (report.errors.length > 0 ||
|
|
353
|
+
(report.requestedPaths.length > 0 && report.matchedFiles === 0)) {
|
|
354
|
+
process.exitCode = 1;
|
|
355
|
+
}
|
|
356
|
+
});
|
|
303
357
|
program
|
|
304
358
|
.command("search")
|
|
305
359
|
.description("Retrieve the most relevant passages without calling an LLM.")
|
|
@@ -308,6 +362,8 @@ program
|
|
|
308
362
|
.option("--context-radius <number>", "Include neighboring chunks around each matched passage.", parseNonNegativeInt)
|
|
309
363
|
.option("--include-path <prefix>", "Search only indexed source paths under this prefix. Repeat for multiple prefixes.", collectOptionValue, [])
|
|
310
364
|
.option("--exclude-path <prefix>", "Exclude indexed source paths under this prefix. Repeat for multiple prefixes.", collectOptionValue, [])
|
|
365
|
+
.option("--context-path <prefix>", "Search only chunks under this structural context. Repeat for multiple prefixes.", collectOptionValue, [])
|
|
366
|
+
.option("--explain", "Include hybrid score contributions, ranks, and matched terms.")
|
|
311
367
|
.option("--compact", "Return short snippets instead of full passages.")
|
|
312
368
|
.option("--json", "Print machine-readable JSON.")
|
|
313
369
|
.action(async (query, options, command) => {
|
|
@@ -332,6 +388,11 @@ program
|
|
|
332
388
|
const distance = result.distance === null ? "n/a" : result.distance.toFixed(4);
|
|
333
389
|
console.log(`\n${pc.cyan(`[${index + 1}] ${result.citation}`)} chunk=${result.chunkIndex} distance=${distance}`);
|
|
334
390
|
console.log("snippet" in result ? result.snippet : result.text.slice(0, SEARCH_TEXT_PREVIEW_LENGTH));
|
|
391
|
+
if (result.score) {
|
|
392
|
+
const vectorRank = result.score.vectorRank ?? "n/a";
|
|
393
|
+
const lexicalRank = result.score.lexicalRank ?? "n/a";
|
|
394
|
+
console.log(pc.dim(`score=${result.score.combinedScore.toFixed(6)} fusion=${result.score.fusion} vector=${result.score.vectorContribution.toFixed(6)} lexical=${result.score.lexicalContribution.toFixed(6)} vectorRank=${vectorRank} lexicalRank=${lexicalRank} matchedTerms=${result.score.matchedTerms.join(",") || "n/a"}`));
|
|
395
|
+
}
|
|
335
396
|
}
|
|
336
397
|
});
|
|
337
398
|
program
|
|
@@ -342,6 +403,8 @@ program
|
|
|
342
403
|
.option("--context-radius <number>", "Include neighboring chunks around each matched passage.", parseNonNegativeInt)
|
|
343
404
|
.option("--include-path <prefix>", "Use only indexed source paths under this prefix. Repeat for multiple prefixes.", collectOptionValue, [])
|
|
344
405
|
.option("--exclude-path <prefix>", "Exclude indexed source paths under this prefix. Repeat for multiple prefixes.", collectOptionValue, [])
|
|
406
|
+
.option("--context-path <prefix>", "Use only chunks under this structural context. Repeat for multiple prefixes.", collectOptionValue, [])
|
|
407
|
+
.option("--explain", "Include hybrid score contributions, ranks, and matched terms.")
|
|
345
408
|
.option("--json", "Print machine-readable JSON.")
|
|
346
409
|
.action(async (query, options, command) => {
|
|
347
410
|
const cwd = projectRoot(command);
|
|
@@ -360,7 +423,8 @@ program
|
|
|
360
423
|
if (result.sources.length > 0) {
|
|
361
424
|
console.log(pc.dim("Sources:"));
|
|
362
425
|
for (const [index, source] of result.sources.entries()) {
|
|
363
|
-
|
|
426
|
+
const score = source.score ? ` score=${source.score.combinedScore.toFixed(6)}` : "";
|
|
427
|
+
console.log(` [${index + 1}] ${source.citation} chunk=${source.chunkIndex}${score}`);
|
|
364
428
|
}
|
|
365
429
|
}
|
|
366
430
|
});
|
|
@@ -372,6 +436,7 @@ program
|
|
|
372
436
|
.option("--no-code", "Skip the lightweight repository code search.")
|
|
373
437
|
.option("--include-path <prefix>", "Use only indexed source paths under this prefix. Repeat for multiple prefixes.", collectOptionValue, [])
|
|
374
438
|
.option("--exclude-path <prefix>", "Exclude indexed source paths under this prefix. Repeat for multiple prefixes.", collectOptionValue, [])
|
|
439
|
+
.option("--context-path <prefix>", "Use only chunks under this structural context. Repeat for multiple prefixes.", collectOptionValue, [])
|
|
375
440
|
.option("--compact", "Return snippets instead of full retrieved passages.")
|
|
376
441
|
.option("--json", "Print machine-readable JSON.")
|
|
377
442
|
.action(async (query, options, command) => {
|
|
@@ -493,6 +558,13 @@ program
|
|
|
493
558
|
console.log(`sensitiveFiles=${countSkippedByReason(report.skippedFiles, "sensitive-name")}`);
|
|
494
559
|
console.log(`indexedFiles=${report.indexedFiles.length}`);
|
|
495
560
|
console.log(`totalChunks=${report.totalChunks}`);
|
|
561
|
+
console.log(`chunkStats.minChars=${report.chunkStats.minChars}`);
|
|
562
|
+
console.log(`chunkStats.averageChars=${report.chunkStats.averageChars.toFixed(1)}`);
|
|
563
|
+
console.log(`chunkStats.p50Chars=${report.chunkStats.p50Chars}`);
|
|
564
|
+
console.log(`chunkStats.p95Chars=${report.chunkStats.p95Chars}`);
|
|
565
|
+
console.log(`chunkStats.maxChars=${report.chunkStats.maxChars}`);
|
|
566
|
+
console.log(`chunkStats.contextualChunks=${report.chunkStats.contextualChunks}`);
|
|
567
|
+
console.log(`chunkStats.contextualRatio=${report.chunkStats.contextualRatio.toFixed(3)}`);
|
|
496
568
|
console.log(`emptyTextFiles=${report.emptyTextFiles.length}`);
|
|
497
569
|
console.log(`missingFromIndex=${report.missingFromIndex.length}`);
|
|
498
570
|
console.log(`staleInIndex=${report.staleInIndex.length}`);
|
|
@@ -578,6 +650,25 @@ program
|
|
|
578
650
|
console.log(`note: ${note}`);
|
|
579
651
|
}
|
|
580
652
|
});
|
|
653
|
+
program
|
|
654
|
+
.command("bases")
|
|
655
|
+
.description("List Ragmir knowledge bases in the active monorepo and mark the selected base.")
|
|
656
|
+
.option("--json", "Print machine-readable JSON.")
|
|
657
|
+
.action(async (options, command) => {
|
|
658
|
+
const inventory = await discoverKnowledgeBases(projectRoot(command));
|
|
659
|
+
if (options.json) {
|
|
660
|
+
console.log(JSON.stringify(inventory, null, 2));
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
console.log(`workspaceRoot=${inventory.workspaceRoot}`);
|
|
664
|
+
console.log(`activeBase=${inventory.activeId ?? "none"}`);
|
|
665
|
+
console.log(`bases=${inventory.bases.length}`);
|
|
666
|
+
for (const base of inventory.bases) {
|
|
667
|
+
const marker = base.active ? "*" : "-";
|
|
668
|
+
const format = base.legacy ? "legacy" : "ragmir";
|
|
669
|
+
console.log(`${marker} ${base.id} format=${format} root=${base.projectRoot}`);
|
|
670
|
+
}
|
|
671
|
+
});
|
|
581
672
|
program
|
|
582
673
|
.command("status")
|
|
583
674
|
.description("Show active configuration and index row count.")
|
|
@@ -585,8 +676,10 @@ program
|
|
|
585
676
|
.action(async (options, command) => {
|
|
586
677
|
const cwd = projectRoot(command);
|
|
587
678
|
const config = await loadConfig(cwd);
|
|
679
|
+
const identity = knowledgeBaseIdentity(config.projectRoot);
|
|
588
680
|
const rows = await countRows(config);
|
|
589
681
|
const status = {
|
|
682
|
+
knowledgeBaseId: identity?.id ?? null,
|
|
590
683
|
projectRoot: config.projectRoot,
|
|
591
684
|
rawDir: config.rawDir,
|
|
592
685
|
storageDir: config.storageDir,
|
|
@@ -619,6 +712,7 @@ program
|
|
|
619
712
|
console.log(JSON.stringify(status, null, 2));
|
|
620
713
|
return;
|
|
621
714
|
}
|
|
715
|
+
console.log(`knowledgeBaseId=${identity?.id ?? "none"}`);
|
|
622
716
|
console.log(`projectRoot=${config.projectRoot}`);
|
|
623
717
|
console.log(`rawDir=${config.rawDir}`);
|
|
624
718
|
console.log(`storageDir=${config.storageDir}`);
|
|
@@ -840,7 +934,7 @@ program
|
|
|
840
934
|
.description("Copy the bundled agent skill and MCP config snippet into the current repository.")
|
|
841
935
|
.option("--target-dir <path>", "Directory where the skill folder should be copied.", DEFAULT_SKILL_TARGET_DIR)
|
|
842
936
|
.option("--agents <list>", `Agent MCP helpers to generate: all, ${SUPPORTED_AGENT_TARGETS.join(", ")}.`, "all")
|
|
843
|
-
.option("--mcp-name <name>", "MCP server name
|
|
937
|
+
.option("--mcp-name <name>", "MCP server name. Nested monorepo bases get a unique name by default.")
|
|
844
938
|
.option("--mcp-command <command>", "Custom MCP stdio command for generated helper files.")
|
|
845
939
|
.option("--mcp-arg <arg>", "Argument for --mcp-command. Repeat for multiple arguments.", collectOptionValue, [])
|
|
846
940
|
.action(async (options, command) => {
|
|
@@ -849,8 +943,8 @@ program
|
|
|
849
943
|
cwd,
|
|
850
944
|
targetDir: options.targetDir,
|
|
851
945
|
agents: parseAgentTargets(options.agents),
|
|
852
|
-
mcpServerName: options.mcpName,
|
|
853
946
|
};
|
|
947
|
+
addOption(installOptions, "mcpServerName", options.mcpName);
|
|
854
948
|
addOption(installOptions, "mcpCommand", options.mcpCommand);
|
|
855
949
|
if (options.mcpArg.length > 0) {
|
|
856
950
|
installOptions.mcpArgs = options.mcpArg;
|
|
@@ -881,13 +975,20 @@ program
|
|
|
881
975
|
.option("--agents <list>", `Comma-separated agents: all, ${SUPPORTED_AGENT_TARGETS.join(", ")}.`, "all")
|
|
882
976
|
.option("--scope <scope>", "Install scope: project or user.", "project")
|
|
883
977
|
.option("--mode <mode>", "Expose skills as links or physical copies: link or copy.", "link")
|
|
978
|
+
.option("--force", "Replace same-name native skills after reviewing that they can be overwritten.")
|
|
884
979
|
.option("--json", "Print machine-readable JSON.")
|
|
885
980
|
.action(async (options, command) => {
|
|
886
981
|
const cwd = projectRoot(command);
|
|
887
982
|
const scope = parseAgentInstallScope(options.scope);
|
|
888
983
|
const mode = parseAgentInstallMode(options.mode);
|
|
889
984
|
const agents = parseAgentTargets(options.agents);
|
|
890
|
-
const result = await installAgentSkills({
|
|
985
|
+
const result = await installAgentSkills({
|
|
986
|
+
cwd,
|
|
987
|
+
agents,
|
|
988
|
+
scope,
|
|
989
|
+
mode,
|
|
990
|
+
force: options.force ?? false,
|
|
991
|
+
});
|
|
891
992
|
if (options.json) {
|
|
892
993
|
console.log(JSON.stringify(result, null, 2));
|
|
893
994
|
return;
|
|
@@ -954,6 +1055,7 @@ function withSearchOptions(cwd, options) {
|
|
|
954
1055
|
addOption(result, "topK", options.topK);
|
|
955
1056
|
addOption(result, "contextRadius", options.contextRadius);
|
|
956
1057
|
addPathFilters(result, options);
|
|
1058
|
+
addOption(result, "explain", options.explain);
|
|
957
1059
|
return result;
|
|
958
1060
|
}
|
|
959
1061
|
function addPathFilters(target, options) {
|
|
@@ -963,6 +1065,9 @@ function addPathFilters(target, options) {
|
|
|
963
1065
|
if (options.excludePath && options.excludePath.length > 0) {
|
|
964
1066
|
target.excludePaths = options.excludePath;
|
|
965
1067
|
}
|
|
1068
|
+
if (options.contextPath && options.contextPath.length > 0) {
|
|
1069
|
+
target.contextPaths = options.contextPath;
|
|
1070
|
+
}
|
|
966
1071
|
}
|
|
967
1072
|
async function loadChat() {
|
|
968
1073
|
const module = await import(CHAT_PACKAGE_NAME);
|
|
@@ -1043,6 +1148,15 @@ function printDoctor(report) {
|
|
|
1043
1148
|
console.log(`packageManager=${report.packageManager}`);
|
|
1044
1149
|
console.log(`runCommand=${report.runCommand}`);
|
|
1045
1150
|
console.log(`agentKitInstalled=${report.agentKitInstalled}`);
|
|
1151
|
+
console.log(`agentIntegration.ready=${report.agentIntegration.ready}`);
|
|
1152
|
+
console.log(`agentIntegration.runnerReady=${report.agentIntegration.runnerReady}`);
|
|
1153
|
+
console.log(`agentIntegration.runnerMode=${report.agentIntegration.runnerMode ?? "none"}`);
|
|
1154
|
+
console.log(`agentIntegration.projectAgents=${report.agentIntegration.projectAgents.join(",")}`);
|
|
1155
|
+
console.log(`agentIntegration.userAgents=${report.agentIntegration.userAgents.join(",")}`);
|
|
1156
|
+
console.log(`agentIntegration.nativeAgents=${report.agentIntegration.nativeAgents.join(",")}`);
|
|
1157
|
+
for (const warning of report.agentIntegration.warnings) {
|
|
1158
|
+
console.log(pc.yellow(`agentIntegration.warning: ${warning}`));
|
|
1159
|
+
}
|
|
1046
1160
|
console.log(`embeddingProvider=${report.embeddingProvider}`);
|
|
1047
1161
|
console.log(`transformersAllowRemoteModels=${report.transformersAllowRemoteModels}`);
|
|
1048
1162
|
console.log(`redactionEnabled=${report.redactionEnabled}`);
|
|
@@ -1172,6 +1286,9 @@ function printSetup(result, title) {
|
|
|
1172
1286
|
console.log(` - ${helper.label} MCP helper: ${helper.path}`);
|
|
1173
1287
|
}
|
|
1174
1288
|
console.log(` - agent setup guide: ${result.agentKit.agentSetupPath}`);
|
|
1289
|
+
for (const installation of result.agentInstallations) {
|
|
1290
|
+
console.log(` - ${installation.label} skills: ${installation.targetDir} (${installation.mode})`);
|
|
1291
|
+
}
|
|
1175
1292
|
console.log("");
|
|
1176
1293
|
if (result.semantic) {
|
|
1177
1294
|
console.log(pc.cyan("Semantic retrieval:"));
|