@jcode.labs/ragmir 4.2.2 → 5.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.
Files changed (197) hide show
  1. package/README.md +67 -160
  2. package/dist/chunking.d.ts +1 -1
  3. package/dist/chunking.d.ts.map +1 -1
  4. package/dist/chunking.js +17 -1
  5. package/dist/chunking.js.map +1 -1
  6. package/dist/cli-entry.js +1 -1
  7. package/dist/cli-entry.js.map +1 -1
  8. package/dist/cli-fast.d.ts +1 -3
  9. package/dist/cli-fast.d.ts.map +1 -1
  10. package/dist/cli-fast.js +2 -104
  11. package/dist/cli-fast.js.map +1 -1
  12. package/dist/cli-options.d.ts +0 -37
  13. package/dist/cli-options.d.ts.map +1 -1
  14. package/dist/cli-options.js +0 -53
  15. package/dist/cli-options.js.map +1 -1
  16. package/dist/cli.js +9 -701
  17. package/dist/cli.js.map +1 -1
  18. package/dist/client.d.ts +1 -3
  19. package/dist/client.d.ts.map +1 -1
  20. package/dist/client.js +7 -36
  21. package/dist/client.js.map +1 -1
  22. package/dist/config-migration.d.ts +6 -0
  23. package/dist/config-migration.d.ts.map +1 -0
  24. package/dist/config-migration.js +31 -0
  25. package/dist/config-migration.js.map +1 -0
  26. package/dist/config.d.ts +2 -0
  27. package/dist/config.d.ts.map +1 -1
  28. package/dist/config.js +17 -65
  29. package/dist/config.js.map +1 -1
  30. package/dist/context-resources.d.ts.map +1 -1
  31. package/dist/context-resources.js +2 -14
  32. package/dist/context-resources.js.map +1 -1
  33. package/dist/defaults.d.ts +0 -3
  34. package/dist/defaults.d.ts.map +1 -1
  35. package/dist/defaults.js +0 -13
  36. package/dist/defaults.js.map +1 -1
  37. package/dist/destroy.d.ts.map +1 -1
  38. package/dist/destroy.js +0 -2
  39. package/dist/destroy.js.map +1 -1
  40. package/dist/doctor.d.ts.map +1 -1
  41. package/dist/doctor.js +1 -9
  42. package/dist/doctor.js.map +1 -1
  43. package/dist/document-structure.js.map +1 -1
  44. package/dist/embeddings.d.ts.map +1 -1
  45. package/dist/embeddings.js +9 -1
  46. package/dist/embeddings.js.map +1 -1
  47. package/dist/errors.d.ts +1 -1
  48. package/dist/errors.d.ts.map +1 -1
  49. package/dist/errors.js.map +1 -1
  50. package/dist/evaluate.d.ts.map +1 -1
  51. package/dist/evaluate.js +0 -7
  52. package/dist/evaluate.js.map +1 -1
  53. package/dist/files.js.map +1 -1
  54. package/dist/generation-retention.js.map +1 -1
  55. package/dist/gitignore.js.map +1 -1
  56. package/dist/index-diagnostics.js +1 -1
  57. package/dist/index-diagnostics.js.map +1 -1
  58. package/dist/index-policy.d.ts.map +1 -1
  59. package/dist/index-policy.js +3 -4
  60. package/dist/index-policy.js.map +1 -1
  61. package/dist/index-write-lock.js.map +1 -1
  62. package/dist/index.d.ts +4 -15
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js +2 -8
  65. package/dist/index.js.map +1 -1
  66. package/dist/ingest.d.ts.map +1 -1
  67. package/dist/ingest.js +3 -18
  68. package/dist/ingest.js.map +1 -1
  69. package/dist/ingestion-metrics.d.ts +1 -1
  70. package/dist/ingestion-metrics.d.ts.map +1 -1
  71. package/dist/ingestion-metrics.js +0 -1
  72. package/dist/ingestion-metrics.js.map +1 -1
  73. package/dist/ingestion-state.d.ts +1 -2
  74. package/dist/ingestion-state.d.ts.map +1 -1
  75. package/dist/ingestion-state.js +0 -2
  76. package/dist/ingestion-state.js.map +1 -1
  77. package/dist/lexical-scoring.d.ts +13 -0
  78. package/dist/lexical-scoring.d.ts.map +1 -0
  79. package/dist/lexical-scoring.js +35 -0
  80. package/dist/lexical-scoring.js.map +1 -0
  81. package/dist/mcp-output.d.ts +4 -31
  82. package/dist/mcp-output.d.ts.map +1 -1
  83. package/dist/mcp-output.js +4 -123
  84. package/dist/mcp-output.js.map +1 -1
  85. package/dist/mcp-summaries.d.ts +1 -12
  86. package/dist/mcp-summaries.d.ts.map +1 -1
  87. package/dist/mcp-summaries.js +0 -112
  88. package/dist/mcp-summaries.js.map +1 -1
  89. package/dist/mcp.d.ts +1 -5
  90. package/dist/mcp.d.ts.map +1 -1
  91. package/dist/mcp.js +22 -329
  92. package/dist/mcp.js.map +1 -1
  93. package/dist/ocr.d.ts +0 -1
  94. package/dist/ocr.d.ts.map +1 -1
  95. package/dist/ocr.js +0 -4
  96. package/dist/ocr.js.map +1 -1
  97. package/dist/parsing.js +13 -0
  98. package/dist/parsing.js.map +1 -1
  99. package/dist/preview.d.ts.map +1 -1
  100. package/dist/preview.js +2 -5
  101. package/dist/preview.js.map +1 -1
  102. package/dist/query-sanitizer.d.ts +2 -1
  103. package/dist/query-sanitizer.d.ts.map +1 -1
  104. package/dist/query-sanitizer.js +9 -127
  105. package/dist/query-sanitizer.js.map +1 -1
  106. package/dist/query.d.ts +1 -3
  107. package/dist/query.d.ts.map +1 -1
  108. package/dist/query.js +95 -71
  109. package/dist/query.js.map +1 -1
  110. package/dist/ranking.d.ts +1 -1
  111. package/dist/ranking.d.ts.map +1 -1
  112. package/dist/ranking.js +52 -41
  113. package/dist/ranking.js.map +1 -1
  114. package/dist/runtime-info.js.map +1 -1
  115. package/dist/search-output.d.ts +3 -0
  116. package/dist/search-output.d.ts.map +1 -0
  117. package/dist/search-output.js +26 -0
  118. package/dist/search-output.js.map +1 -0
  119. package/dist/security.d.ts.map +1 -1
  120. package/dist/security.js +5 -37
  121. package/dist/security.js.map +1 -1
  122. package/dist/setup-prompt.d.ts +1 -1
  123. package/dist/setup-prompt.d.ts.map +1 -1
  124. package/dist/setup-prompt.js +22 -25
  125. package/dist/setup-prompt.js.map +1 -1
  126. package/dist/setup.js +1 -1
  127. package/dist/setup.js.map +1 -1
  128. package/dist/skill.d.ts +1 -4
  129. package/dist/skill.d.ts.map +1 -1
  130. package/dist/skill.js +3 -71
  131. package/dist/skill.js.map +1 -1
  132. package/dist/storage-maintenance.js.map +1 -1
  133. package/dist/store.js +9 -1
  134. package/dist/store.js.map +1 -1
  135. package/dist/types.d.ts +19 -156
  136. package/dist/types.d.ts.map +1 -1
  137. package/dist/upgrade.d.ts +3 -2
  138. package/dist/upgrade.d.ts.map +1 -1
  139. package/dist/upgrade.js +20 -2
  140. package/dist/upgrade.js.map +1 -1
  141. package/dist/vector-index.js.map +1 -1
  142. package/dist/version.d.ts +1 -1
  143. package/dist/version.js +1 -1
  144. package/dist/workload.js.map +1 -1
  145. package/examples/document-evidence-benchmark/.ragmir/config.json +0 -9
  146. package/examples/document-evidence-benchmark/README.md +5 -3
  147. package/examples/document-evidence-benchmark/raw/rfp/security-questionnaire.md +1 -1
  148. package/examples/library-api-demo/README.md +17 -8
  149. package/examples/library-api-demo/run.mjs +6 -6
  150. package/examples/sovereign-rag-demo/.ragmir/config.json +3 -10
  151. package/examples/sovereign-rag-demo/README.md +21 -12
  152. package/package.json +21 -30
  153. package/skills/ragmir/SKILL.md +67 -199
  154. package/dist/access-log.d.ts +0 -30
  155. package/dist/access-log.d.ts.map +0 -1
  156. package/dist/access-log.js +0 -415
  157. package/dist/access-log.js.map +0 -1
  158. package/dist/cli-stdin.d.ts +0 -3
  159. package/dist/cli-stdin.d.ts.map +0 -1
  160. package/dist/cli-stdin.js +0 -15
  161. package/dist/cli-stdin.js.map +0 -1
  162. package/dist/portable-entry.d.ts +0 -5
  163. package/dist/portable-entry.d.ts.map +0 -1
  164. package/dist/portable-entry.js +0 -337
  165. package/dist/portable-entry.js.map +0 -1
  166. package/dist/portable.d.ts +0 -89
  167. package/dist/portable.d.ts.map +0 -1
  168. package/dist/portable.js +0 -1290
  169. package/dist/portable.js.map +0 -1
  170. package/dist/prompt-routing.d.ts +0 -12
  171. package/dist/prompt-routing.d.ts.map +0 -1
  172. package/dist/prompt-routing.js +0 -150
  173. package/dist/prompt-routing.js.map +0 -1
  174. package/dist/redaction.d.ts +0 -12
  175. package/dist/redaction.d.ts.map +0 -1
  176. package/dist/redaction.js +0 -253
  177. package/dist/redaction.js.map +0 -1
  178. package/dist/research.d.ts +0 -21
  179. package/dist/research.d.ts.map +0 -1
  180. package/dist/research.js +0 -667
  181. package/dist/research.js.map +0 -1
  182. package/dist/team-diagnostics.d.ts +0 -119
  183. package/dist/team-diagnostics.d.ts.map +0 -1
  184. package/dist/team-diagnostics.js +0 -515
  185. package/dist/team-diagnostics.js.map +0 -1
  186. package/dist/team-sync.d.ts +0 -49
  187. package/dist/team-sync.d.ts.map +0 -1
  188. package/dist/team-sync.js +0 -436
  189. package/dist/team-sync.js.map +0 -1
  190. package/skills/ragmir-audio-summary/SKILL.md +0 -80
  191. package/skills/ragmir-audio-summary/forge-voice.sh +0 -150
  192. package/skills/ragmir-audio-summary/listening-style.md +0 -92
  193. package/skills/ragmir-audio-summary/narration-templates.md +0 -162
  194. package/skills/ragmir-audio-summary/split-lines.py +0 -14
  195. package/skills/ragmir-audio-summary/xtts-voice.py +0 -46
  196. package/skills/ragmir-legal-dossier/SKILL.md +0 -143
  197. package/skills/ragmir-markdown-report/SKILL.md +0 -110
package/dist/cli.js CHANGED
@@ -2,9 +2,7 @@
2
2
  import path from "node:path";
3
3
  import { Command } from "commander";
4
4
  import pc from "picocolors";
5
- import { accessLogUsageReport } from "./access-log.js";
6
- import { audioAllowRemoteModels, audioEngine, audioLanguage, parseAgentInstallMode, parseAgentInstallScope, parseIncrementalFailurePolicy, parseNonNegativeInt, parseNumber, parsePositiveInt, parseRecallThreshold, } from "./cli-options.js";
7
- import { readBoundedStdin } from "./cli-stdin.js";
5
+ import { parseAgentInstallMode, parseAgentInstallScope, parseIncrementalFailurePolicy, parseNonNegativeInt, parsePositiveInt, parseRecallThreshold, } from "./cli-options.js";
8
6
  import { loadConfig } from "./config.js";
9
7
  import { DEFAULT_SKILL_TARGET_DIR } from "./defaults.js";
10
8
  import { destroyIndex } from "./destroy.js";
@@ -22,11 +20,9 @@ import { ingestionLimits } from "./limits.js";
22
20
  import { serveMcp } from "./mcp.js";
23
21
  import { configurePdfOcr, extractPdfPage, extractPdfPages, inspectPdfOcr, parsePdfOcrEngine, parsePdfOcrPages, } from "./ocr.js";
24
22
  import { rgrCommand } from "./package-manager.js";
25
- import { exportPortableKnowledgeBase, verifyPortableKnowledgeBase } from "./portable.js";
26
23
  import { previewChunks } from "./preview.js";
27
- import { routePrompt } from "./prompt-routing.js";
28
- import { ask, search } from "./query.js";
29
- import { compactResearchReport, compactSearchResults, research } from "./research.js";
24
+ import { search } from "./query.js";
25
+ import { compactSearchResults } from "./search-output.js";
30
26
  import { securityAudit } from "./security.js";
31
27
  import { enableSemanticEmbeddings } from "./semantic-config.js";
32
28
  import { setupProject } from "./setup.js";
@@ -34,21 +30,11 @@ import { bundledSkillPath, installAgentSkills, installSkill, parseAgentTargets,
34
30
  import { addSourceEntries, listSourceEntries } from "./sources.js";
35
31
  import { optimizeStorage } from "./storage-maintenance.js";
36
32
  import { readIndexManifestHeader } from "./store.js";
37
- import { compareTeamSnapshots, createTeamSnapshot, readTeamSnapshot, writeTeamSnapshot, } from "./team-diagnostics.js";
38
- import { syncTeamKnowledge, } from "./team-sync.js";
39
33
  import { inspectUpgrade, upgradeProject } from "./upgrade.js";
40
34
  import { VERSION } from "./version.js";
41
35
  const SEARCH_TEXT_PREVIEW_LENGTH = 900;
42
- const CHAT_PACKAGE_NAME = "@jcode.labs/ragmir-chat";
43
- const TTS_PACKAGE_NAME = "@jcode.labs/ragmir-tts";
44
- const DEPRECATED_CLI_NAMES = new Set(["ragmir", "kb"]);
45
36
  const PUBLIC_CLI_NAME = "rgr";
46
- const TEAM_DIFF_PREVIEW_LIMIT = 20;
47
37
  const program = new Command();
48
- const deprecatedCliName = deprecatedCliInvocation();
49
- if (deprecatedCliName !== null) {
50
- console.error(pc.yellow(`The \`${deprecatedCliName}\` CLI command is deprecated and will be removed in a future release. Use \`rgr\` instead.`));
51
- }
52
38
  program
53
39
  .name(PUBLIC_CLI_NAME)
54
40
  .description("Local-first RAG knowledge base for private project documents.")
@@ -175,7 +161,7 @@ ocrCommand
175
161
  });
176
162
  program
177
163
  .command("doctor")
178
- .description("Diagnose setup, index freshness, privacy posture, and next steps.")
164
+ .description("Diagnose setup, index freshness, and next steps.")
179
165
  .option("--fix", "Create missing scaffolding, install the agent kit, and rebuild stale indexes.")
180
166
  .option("--deep", "Run the O(corpus) source inventory and executable security probes.")
181
167
  .option("--json", "Print machine-readable JSON.")
@@ -215,7 +201,6 @@ program
215
201
  console.log(`runtimeRagmirVersion=${inspection.runtimeRagmirVersion}`);
216
202
  console.log(`indexedWithRagmirVersion=${inspection.indexedWithRagmirVersion ?? "unavailable"}`);
217
203
  console.log(`ready=${inspection.ready}`);
218
- console.log(`privacyCompliant=${inspection.privacyCompliant}`);
219
204
  console.log(`safeActivation=${inspection.safeActivation}`);
220
205
  if (inspection.reason) {
221
206
  console.log(`reason=${inspection.reason}`);
@@ -237,7 +222,6 @@ program
237
222
  console.log(`runtimeRagmirVersion=${result.runtimeRagmirVersion}`);
238
223
  console.log(`indexedWithRagmirVersion=${result.indexedWithRagmirVersion ?? "unavailable"}`);
239
224
  console.log(`ready=${result.ready}`);
240
- console.log(`privacyCompliant=${result.privacyCompliant}`);
241
225
  console.log(`safeActivation=${result.safeActivation}`);
242
226
  console.log(`action=${result.action}`);
243
227
  console.log(`previousIndexedWithRagmirVersion=${result.previousIndexedWithRagmirVersion ?? "unavailable"}`);
@@ -358,7 +342,7 @@ sourcesCommand
358
342
  });
359
343
  program
360
344
  .command("ingest")
361
- .description("Parse changed documents, redact, chunk, embed locally, and update LanceDB.")
345
+ .description("Parse changed documents, chunk, embed locally, and update LanceDB.")
362
346
  .option("--rebuild", "Force a full local index rebuild instead of reusing unchanged rows.")
363
347
  .option("--batch-size <number>", "Files committed per resumable batch.", parsePositiveInt)
364
348
  .option("--incremental-failure-policy <policy>", "Preserve last-good rows after a file failure, or remove stale rows.", parseIncrementalFailurePolicy)
@@ -379,7 +363,7 @@ program
379
363
  }
380
364
  return;
381
365
  }
382
- console.log(pc.green(`Done. runId=${result.runId} resumed=${result.resumed} batchSize=${result.batchSize} discoveredFiles=${result.discoveredFiles} supportedFiles=${result.supportedFiles} supportedBytes=${result.supportedBytes} largestFileBytes=${result.largestFileBytes} indexedFiles=${result.indexedFiles} rebuiltFiles=${result.rebuiltFiles} reusedFiles=${result.reusedFiles} staleLastKnownGood=${result.staleLastKnownGood.length} chunks=${result.chunks} skippedFiles=${result.skippedFiles} unsupportedFiles=${result.unsupportedFiles} oversizedFiles=${result.oversizedFiles} sensitiveFiles=${result.sensitiveFiles} emptyTextFiles=${result.emptyTextFiles.length} redactions=${result.redactions} ocrPages=${result.ocr.pages} ocrCacheHits=${result.ocr.cacheHits} ocrBatches=${result.ocr.batches} ocrSubprocesses=${result.ocr.subprocesses} ocrDurationMs=${result.ocr.durationMs} errors=${result.errors.length}`));
366
+ console.log(pc.green(`Done. runId=${result.runId} resumed=${result.resumed} batchSize=${result.batchSize} discoveredFiles=${result.discoveredFiles} supportedFiles=${result.supportedFiles} supportedBytes=${result.supportedBytes} largestFileBytes=${result.largestFileBytes} indexedFiles=${result.indexedFiles} rebuiltFiles=${result.rebuiltFiles} reusedFiles=${result.reusedFiles} staleLastKnownGood=${result.staleLastKnownGood.length} chunks=${result.chunks} skippedFiles=${result.skippedFiles} unsupportedFiles=${result.unsupportedFiles} oversizedFiles=${result.oversizedFiles} sensitiveFiles=${result.sensitiveFiles} emptyTextFiles=${result.emptyTextFiles.length} ocrPages=${result.ocr.pages} ocrCacheHits=${result.ocr.cacheHits} ocrBatches=${result.ocr.batches} ocrSubprocesses=${result.ocr.subprocesses} ocrDurationMs=${result.ocr.durationMs} errors=${result.errors.length}`));
383
367
  printUnsupportedSummary(result.unsupportedExtensions);
384
368
  printEmptyTextFiles(result.emptyTextFiles);
385
369
  if (result.vectorIndexWarning) {
@@ -404,7 +388,7 @@ program
404
388
  });
405
389
  program
406
390
  .command("preview")
407
- .description("Preview redacted chunks and structure without writing the index.")
391
+ .description("Preview source chunks and structure without writing the index.")
408
392
  .option("--path <prefix>", "Preview only source paths under this prefix. Repeat for multiple prefixes.", collectOptionValue, [])
409
393
  .option("--max-files <number>", "Maximum number of matching files to parse.", parsePositiveInt)
410
394
  .option("--max-chunks <number>", "Maximum number of chunks to show per file.", parsePositiveInt)
@@ -434,7 +418,7 @@ program
434
418
  console.log(pc.yellow(`unmatched: ${unmatchedPath}`));
435
419
  }
436
420
  for (const file of report.files) {
437
- 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)}`);
421
+ console.log(`\n${pc.cyan(file.relativePath)} chunks=${file.chunkStats.count} minChars=${file.chunkStats.minChars} p50Chars=${file.chunkStats.p50Chars} p95Chars=${file.chunkStats.p95Chars} maxChars=${file.chunkStats.maxChars} contextualRatio=${file.chunkStats.contextualRatio.toFixed(3)}`);
438
422
  if (file.ocr) {
439
423
  console.log(`ocrPages=${file.ocr.pages} ocrCacheHits=${file.ocr.cacheHits} ocrBatches=${file.ocr.batches} ocrSubprocesses=${file.ocr.subprocesses} ocrDurationMs=${file.ocr.durationMs}`);
440
424
  }
@@ -497,112 +481,6 @@ program
497
481
  }
498
482
  }
499
483
  });
500
- program
501
- .command("ask")
502
- .description("Return cited retrieval context for a question without calling an LLM.")
503
- .argument("<query>", "Question to answer.")
504
- .option("-k, --top-k <number>", "Number of passages to use.", parsePositiveInt)
505
- .option("--max-chunks-per-document <number>", "Maximum primary passages per document before ranked backfill.", parsePositiveInt)
506
- .option("--context-radius <number>", "Include neighboring chunks around each matched passage.", parseNonNegativeInt)
507
- .option("--include-path <prefix>", "Use only indexed source paths under this prefix. Repeat for multiple prefixes.", collectOptionValue, [])
508
- .option("--exclude-path <prefix>", "Exclude indexed source paths under this prefix. Repeat for multiple prefixes.", collectOptionValue, [])
509
- .option("--context-path <prefix>", "Use only chunks under this structural context. Repeat for multiple prefixes.", collectOptionValue, [])
510
- .option("--explain", "Include hybrid score contributions, ranks, and matched terms.")
511
- .option("--exact-vector-search", "Bypass ANN and use exhaustive vector search for diagnostics.")
512
- .option("--json", "Print machine-readable JSON.")
513
- .action(async (query, options, command) => {
514
- const cwd = projectRoot(command);
515
- const result = await ask(query, withSearchOptions(cwd, options));
516
- if (options.json) {
517
- console.log(JSON.stringify({ query, ...result }, null, 2));
518
- if (result.sources.length === 0) {
519
- process.exitCode = 1;
520
- }
521
- return;
522
- }
523
- console.log(`\n${result.answer}\n`);
524
- if (result.staleWarning) {
525
- console.error(pc.yellow(result.staleWarning));
526
- }
527
- if (result.sources.length > 0) {
528
- console.log(pc.dim("Sources:"));
529
- for (const [index, source] of result.sources.entries()) {
530
- const score = source.score ? ` score=${source.score.combinedScore.toFixed(6)}` : "";
531
- console.log(` [${index + 1}] ${source.citation} chunk=${source.chunkIndex}${score}`);
532
- }
533
- }
534
- });
535
- program
536
- .command("research")
537
- .description("Run a bounded multi-query research pass with cited evidence.")
538
- .argument("<query>", "Research question or topic.")
539
- .option("-k, --top-k <number>", "Maximum number of evidence passages to keep.", parsePositiveInt)
540
- .option("--no-code", "Skip the lightweight repository code search.")
541
- .option("--full-audit", "Run a full source inventory instead of manifest health checks.")
542
- .option("--timeout-ms <number>", "Bound the complete research operation.", parsePositiveInt)
543
- .option("--code-top-k <number>", "Maximum number of code matches to keep.", parsePositiveInt)
544
- .option("--code-scan-max-files <number>", "Maximum code files to read.", parsePositiveInt)
545
- .option("--code-scan-max-bytes <number>", "Maximum total code bytes to read.", parsePositiveInt)
546
- .option("--code-scan-concurrency <number>", "Maximum concurrent code file reads.", parsePositiveInt)
547
- .option("--include-path <prefix>", "Use only indexed source paths under this prefix. Repeat for multiple prefixes.", collectOptionValue, [])
548
- .option("--exclude-path <prefix>", "Exclude indexed source paths under this prefix. Repeat for multiple prefixes.", collectOptionValue, [])
549
- .option("--context-path <prefix>", "Use only chunks under this structural context. Repeat for multiple prefixes.", collectOptionValue, [])
550
- .option("--compact", "Return snippets instead of full retrieved passages.")
551
- .option("--json", "Print machine-readable JSON.")
552
- .action(async (query, options, command) => {
553
- const cwd = projectRoot(command);
554
- const researchOptions = { cwd };
555
- addOption(researchOptions, "topK", options.topK);
556
- addOption(researchOptions, "includeCode", options.code);
557
- addOption(researchOptions, "fullAudit", options.fullAudit);
558
- addOption(researchOptions, "timeoutMs", options.timeoutMs);
559
- addOption(researchOptions, "codeTopK", options.codeTopK);
560
- addOption(researchOptions, "codeScanMaxFiles", options.codeScanMaxFiles);
561
- addOption(researchOptions, "codeScanMaxBytes", options.codeScanMaxBytes);
562
- addOption(researchOptions, "codeScanConcurrency", options.codeScanConcurrency);
563
- addPathFilters(researchOptions, options);
564
- const report = await research(query, researchOptions);
565
- const output = options.compact ? compactResearchReport(report) : report;
566
- if (options.json) {
567
- console.log(JSON.stringify(output, null, 2));
568
- if (!report.ready) {
569
- process.exitCode = 1;
570
- }
571
- return;
572
- }
573
- printResearchReport(output);
574
- if (!report.ready) {
575
- process.exitCode = 1;
576
- }
577
- });
578
- program
579
- .command("route-prompt")
580
- .description("Classify a prompt and suggest whether an agent should use Ragmir local context.")
581
- .argument("[prompt...]", "Prompt text to classify. Reads stdin when omitted.")
582
- .option("--json", "Print machine-readable JSON.")
583
- .action(async (promptParts, options) => {
584
- const prompt = await promptInput(promptParts);
585
- if (prompt.trim().length === 0) {
586
- console.error(pc.red("Missing prompt. Pass text or pipe it on stdin."));
587
- process.exitCode = 1;
588
- return;
589
- }
590
- const decision = routePrompt(prompt);
591
- if (options.json) {
592
- console.log(JSON.stringify(decision, null, 2));
593
- return;
594
- }
595
- console.log(`shouldUseRagmir=${decision.shouldUseRagmir}`);
596
- console.log(`confidence=${decision.confidence.toFixed(2)}`);
597
- console.log(`tool=${decision.tool}`);
598
- if (decision.query !== null) {
599
- console.log(`query=${decision.query}`);
600
- }
601
- console.log(`reason=${decision.reason}`);
602
- if (decision.matchedSignals.length > 0) {
603
- console.log(`matchedSignals=${decision.matchedSignals.join(", ")}`);
604
- }
605
- });
606
484
  program
607
485
  .command("evaluate")
608
486
  .description("Measure retrieval quality against a JSON golden query file.")
@@ -724,33 +602,6 @@ program
724
602
  process.exitCode = 1;
725
603
  }
726
604
  });
727
- program
728
- .command("usage-report")
729
- .description("Summarize the metadata-only local access log.")
730
- .option("--days <number>", "Number of recent days to include.", parsePositiveInt, 7)
731
- .option("--json", "Print machine-readable JSON.")
732
- .action(async (options, command) => {
733
- const cwd = projectRoot(command);
734
- const report = await accessLogUsageReport({ cwd, days: options.days });
735
- if (options.json) {
736
- console.log(JSON.stringify(report, null, 2));
737
- return;
738
- }
739
- console.log(`accessLogEnabled=${report.accessLogEnabled}`);
740
- console.log(`since=${report.since}`);
741
- console.log(`until=${report.until}`);
742
- console.log(`totalEvents=${report.totalEvents}`);
743
- console.log(`invalidLines=${report.invalidLines}`);
744
- console.log(`uniqueQueryHashes=${report.uniqueQueryHashes}`);
745
- console.log(`averageResultCount=${report.averageResultCount ?? "n/a"}`);
746
- console.log(`lastEventAt=${report.lastEventAt ?? "n/a"}`);
747
- for (const [action, count] of Object.entries(report.eventsByAction)) {
748
- console.log(`events.${action}=${count}`);
749
- }
750
- for (const [action, average] of Object.entries(report.averageResultCountByAction)) {
751
- console.log(`averageResults.${action}=${average ?? "n/a"}`);
752
- }
753
- });
754
605
  program
755
606
  .command("limits")
756
607
  .description("Show active ingestion limits and practical corpus scaling boundaries.")
@@ -802,84 +653,6 @@ program
802
653
  console.log(`${marker} ${base.id} format=${format} root=${base.projectRoot}`);
803
654
  }
804
655
  });
805
- const teamCommand = program
806
- .command("team")
807
- .description("Synchronize Git-backed team knowledge or inspect advanced index drift.");
808
- teamCommand
809
- .command("sync")
810
- .description("Safely fast-forward from Git upstream and refresh the local index.")
811
- .option("--no-pull", "Fetch and compare without changing the checked-out branch.")
812
- .option("--no-fetch", "Use only the cached upstream reference and local worktree.")
813
- .option("--check", "Fetch and report without changing the worktree or index.")
814
- .option("--git-timeout-ms <number>", "Bound each Git command.", parsePositiveInt)
815
- .option("--json", "Print machine-readable JSON.")
816
- .option("--strict", "Exit with code 1 unless Git and the local index are synchronized.")
817
- .action(async (options, command) => {
818
- const syncOptions = {
819
- cwd: projectRoot(command),
820
- autoPull: options.pull,
821
- fetch: options.fetch,
822
- check: options.check === true,
823
- };
824
- addOption(syncOptions, "gitTimeoutMs", options.gitTimeoutMs);
825
- const report = await syncTeamKnowledge(syncOptions);
826
- if (options.json) {
827
- console.log(JSON.stringify(report, null, 2));
828
- }
829
- else {
830
- printTeamSync(report);
831
- }
832
- if (options.strict && !report.synchronized) {
833
- process.exitCode = 1;
834
- }
835
- });
836
- teamCommand
837
- .command("snapshot")
838
- .description("Export relative paths, checksums, configuration, readiness, and corpus identity.")
839
- .requiredOption("--output <path>", "Snapshot file to create or replace.")
840
- .option("--label <label>", "Human-readable environment label.", "local")
841
- .option("--json", "Print machine-readable JSON.")
842
- .action(async (options, command) => {
843
- const cwd = projectRoot(command);
844
- const snapshot = await createTeamSnapshot({ cwd, label: options.label });
845
- const outputPath = await writeTeamSnapshot(snapshot, path.resolve(cwd, options.output));
846
- if (options.json) {
847
- console.log(JSON.stringify({ outputPath, snapshot }, null, 2));
848
- return;
849
- }
850
- console.log(pc.green("Team snapshot ready."));
851
- console.log(`outputPath=${outputPath}`);
852
- console.log(`label=${snapshot.label}`);
853
- console.log(`ready=${snapshot.ready}`);
854
- console.log(`securityAdvisories=${snapshot.health.securityWarnings}`);
855
- console.log(`corpusFingerprint=${snapshot.corpus.fingerprint ?? "unavailable"}`);
856
- console.log(`indexedFiles=${snapshot.corpus.indexedFiles}`);
857
- console.log(`notice=${snapshot.notice}`);
858
- });
859
- teamCommand
860
- .command("compare")
861
- .description("Compare the current local index with a peer snapshot and print actionable drift.")
862
- .argument("<snapshot>", "Peer snapshot created by `rgr team snapshot`.")
863
- .option("--local-label <label>", "Human-readable label for this environment.", "local")
864
- .option("--json", "Print machine-readable JSON.")
865
- .option("--strict", "Exit with code 1 unless both indexes are synchronized.")
866
- .action(async (snapshotPath, options, command) => {
867
- const cwd = projectRoot(command);
868
- const [local, peer] = await Promise.all([
869
- createTeamSnapshot({ cwd, label: options.localLabel }),
870
- readTeamSnapshot(path.resolve(cwd, snapshotPath)),
871
- ]);
872
- const comparison = compareTeamSnapshots(local, peer);
873
- if (options.json) {
874
- console.log(JSON.stringify(comparison, null, 2));
875
- }
876
- else {
877
- printTeamComparison(comparison);
878
- }
879
- if (options.strict && !comparison.synchronized) {
880
- process.exitCode = 1;
881
- }
882
- });
883
656
  program
884
657
  .command("status")
885
658
  .description("Show active configuration, readiness, corpus fingerprint, and index counts.")
@@ -907,13 +680,10 @@ program
907
680
  rawDir: config.rawDir,
908
681
  storageDir: config.storageDir,
909
682
  sourcesFile: config.sourcesFile,
910
- accessLogPath: config.accessLogPath,
911
683
  embeddingModelPath: config.embeddingModelPath,
912
684
  embeddingProvider: config.embeddingProvider,
913
685
  embeddingModel: config.embeddingModel,
914
686
  transformersAllowRemoteModels: config.transformersAllowRemoteModels,
915
- redactionEnabled: config.redaction.enabled,
916
- accessLog: config.accessLog,
917
687
  mcpMaxTopK: config.mcpMaxTopK,
918
688
  mcpMaxOutputBytes: config.mcpMaxOutputBytes,
919
689
  topK: config.topK,
@@ -949,13 +719,10 @@ program
949
719
  console.log(`rawDir=${config.rawDir}`);
950
720
  console.log(`storageDir=${config.storageDir}`);
951
721
  console.log(`sourcesFile=${config.sourcesFile}`);
952
- console.log(`accessLogPath=${config.accessLogPath}`);
953
722
  console.log(`embeddingModelPath=${config.embeddingModelPath}`);
954
723
  console.log(`embeddingProvider=${config.embeddingProvider}`);
955
724
  console.log(`embeddingModel=${config.embeddingModel}`);
956
725
  console.log(`transformersAllowRemoteModels=${config.transformersAllowRemoteModels}`);
957
- console.log(`redactionEnabled=${config.redaction.enabled}`);
958
- console.log(`accessLog=${config.accessLog}`);
959
726
  console.log(`mcpMaxTopK=${config.mcpMaxTopK}`);
960
727
  console.log(`mcpMaxOutputBytes=${config.mcpMaxOutputBytes}`);
961
728
  console.log(`topK=${config.topK}`);
@@ -992,7 +759,7 @@ program
992
759
  });
993
760
  program
994
761
  .command("security-audit")
995
- .description("Show local privacy, provider, redaction, MCP, and gitignore posture.")
762
+ .description("Show local providers, file permissions, MCP bounds, and Git exclusions.")
996
763
  .option("--json", "Print machine-readable JSON.")
997
764
  .option("--strict", "Exit with code 1 when warnings are present.")
998
765
  .action(async (options, command) => {
@@ -1008,10 +775,6 @@ program
1008
775
  console.log(`embeddingModelPath=${report.providers.embeddingModelPath}`);
1009
776
  console.log(`transformersAllowRemoteModels=${report.providers.transformersAllowRemoteModels}`);
1010
777
  console.log(`llmGeneration=${report.providers.llmGeneration}`);
1011
- console.log(`redactionEnabled=${report.redaction.enabled}`);
1012
- console.log(`redactionBuiltIn=${report.redaction.builtIn}`);
1013
- console.log(`accessLog=${report.accessLog.enabled}`);
1014
- console.log(`accessLogStoresRawQueries=${report.accessLog.storesRawQueries}`);
1015
778
  console.log(`storageGitIgnored=${report.storage.gitIgnored}`);
1016
779
  console.log(`mcpMaxTopK=${report.mcp.maxTopK}`);
1017
780
  console.log(`mcpMaxOutputBytes=${report.mcp.maxOutputBytes}`);
@@ -1100,131 +863,6 @@ program
1100
863
  console.log(`removed=${result.removed}`);
1101
864
  console.log(result.note);
1102
865
  });
1103
- program
1104
- .command("chat")
1105
- .description("Answer with a verified local model grounded in Ragmir citations.")
1106
- .argument("[input...]", "Question to answer, or `setup` / `doctor`.")
1107
- .option("-k, --top-k <number>", "Number of passages to retrieve.", parsePositiveInt)
1108
- .option("--profile <profile>", "Local chat profile: lite, fast, or quality.")
1109
- .option("--thinking <mode>", "Thinking mode: off, standard, or deep.")
1110
- .option("--model-path <path>", "Local Gemma model root.")
1111
- .option("--offline", "Require an already verified local model.")
1112
- .option("--allow-remote-models", "Compatibility flag for explicit chat setup; normal answers stay local.")
1113
- .option("--verify", "Recompute the full model SHA256 during doctor.")
1114
- .option("--max-new-tokens <number>", "Maximum generated tokens.", parsePositiveInt)
1115
- .option("--context-limit <number>", "Maximum context characters sent to the model.", parsePositiveInt)
1116
- .option("--json", "Print machine-readable JSON.")
1117
- .action(async (input, options, command) => {
1118
- const cwd = projectRoot(command);
1119
- const chat = await loadChat();
1120
- const mode = chatMode(input);
1121
- if (mode === "doctor") {
1122
- const doctorOptions = { cwd };
1123
- addOption(doctorOptions, "profile", options.profile);
1124
- addOption(doctorOptions, "modelPath", options.modelPath);
1125
- addOption(doctorOptions, "verifyHash", options.verify);
1126
- const report = await chat.doctor(doctorOptions);
1127
- printMaybeJson(report, options.json);
1128
- return;
1129
- }
1130
- if (mode === "setup") {
1131
- const setupOptions = { cwd };
1132
- addOption(setupOptions, "profile", options.profile);
1133
- addOption(setupOptions, "modelPath", options.modelPath);
1134
- addOption(setupOptions, "allowRemoteModels", options.offline ? false : options.allowRemoteModels);
1135
- const result = await chat.setupChatModel(setupOptions);
1136
- printMaybeJson(result, options.json);
1137
- return;
1138
- }
1139
- const question = await promptInput(input);
1140
- if (question.trim().length === 0) {
1141
- console.error(pc.red('Missing question. Use `rgr chat "your question"`.'));
1142
- process.exitCode = 1;
1143
- return;
1144
- }
1145
- const sources = await search(question, withTopK(cwd, options.topK));
1146
- const chatOptions = {
1147
- cwd,
1148
- question,
1149
- sources: sources.map(toChatSource),
1150
- };
1151
- addOption(chatOptions, "profile", options.profile);
1152
- addOption(chatOptions, "thinking", options.thinking);
1153
- addOption(chatOptions, "modelPath", options.modelPath);
1154
- addOption(chatOptions, "allowRemoteModels", chatAllowRemoteModels(options));
1155
- addOption(chatOptions, "maxNewTokens", options.maxNewTokens);
1156
- addOption(chatOptions, "contextCharLimit", options.contextLimit);
1157
- const result = await chat.generateChatAnswer(chatOptions);
1158
- if (options.json) {
1159
- console.log(JSON.stringify({ query: question, ...result }, null, 2));
1160
- if (result.emptyContext) {
1161
- process.exitCode = 1;
1162
- }
1163
- return;
1164
- }
1165
- console.log(`\n${result.answer}\n`);
1166
- if (!result.emptyContext && result.citationStatus !== "valid") {
1167
- console.error(pc.yellow(`Citation status: ${result.citationStatus}. Review the answer against the retrieved passages.`));
1168
- }
1169
- if (result.sources.length > 0) {
1170
- console.log(pc.dim("Sources:"));
1171
- for (const [index, source] of result.sources.entries()) {
1172
- console.log(` [${index + 1}] ${source.relativePath} chunk=${source.chunkIndex}`);
1173
- }
1174
- }
1175
- else {
1176
- const repairCommand = await rgrCommand(cwd, ["doctor", "--fix"]);
1177
- console.error(pc.yellow(`No Ragmir context found. Run \`${repairCommand.display}\`.`));
1178
- process.exitCode = 1;
1179
- }
1180
- });
1181
- program
1182
- .command("audio")
1183
- .description("Render narration as offline WAV or explicitly selected online Edge MP3.")
1184
- .argument("[text-file]", "Narration text file to render.")
1185
- .option("-o, --out <path>", "Output MP3 or WAV path.")
1186
- .option("--engine <engine>", "TTS engine: auto, edge, or transformers.")
1187
- .option("--lang <language>", "TTS language. Offline: en, es, fr. Edge also: ja, th, zh. Default: fr.")
1188
- .option("--model <id>", "Transformers.js TTS model ID.")
1189
- .option("--model-path <path>", "Local model/cache path.")
1190
- .option("--offline", "Force the Transformers.js local/offline WAV path.")
1191
- .option("--allow-remote-models", "Explicitly allow remote model downloads.")
1192
- .option("--voice <voice>", "Edge voice override. Default matches --lang.")
1193
- .option("--rate <rate>", "Edge rate. Defaults to +0%.")
1194
- .option("--speaker-embeddings <path>", "Optional model-specific speaker embedding path or URL.")
1195
- .option("--speed <number>", "Optional model-specific speech speed.", parseNumber)
1196
- .option("--doctor", "Show TTS runtime readiness instead of rendering.")
1197
- .option("--json", "Print machine-readable JSON.")
1198
- .action(async (textFile, options, command) => {
1199
- const cwd = projectRoot(command);
1200
- const tts = await loadTts();
1201
- if (options.doctor) {
1202
- const report = await tts.doctor();
1203
- printMaybeJson(report, options.json);
1204
- return;
1205
- }
1206
- if (!textFile) {
1207
- console.error(pc.red("Missing text file. Use `rgr audio <text-file>`."));
1208
- process.exitCode = 1;
1209
- return;
1210
- }
1211
- const renderOptions = {
1212
- cwd,
1213
- textFile,
1214
- engine: audioEngine(options),
1215
- };
1216
- addOption(renderOptions, "language", audioLanguage(options));
1217
- addOption(renderOptions, "outputPath", options.out);
1218
- addOption(renderOptions, "model", options.model);
1219
- addOption(renderOptions, "modelPath", options.modelPath);
1220
- addOption(renderOptions, "allowRemoteModels", audioAllowRemoteModels(options));
1221
- addOption(renderOptions, "voice", options.voice);
1222
- addOption(renderOptions, "rate", options.rate);
1223
- addOption(renderOptions, "speakerEmbeddings", options.speakerEmbeddings);
1224
- addOption(renderOptions, "speed", options.speed);
1225
- const result = await tts.renderSpeech(renderOptions);
1226
- printMaybeJson(result, options.json);
1227
- });
1228
866
  program
1229
867
  .command("serve-mcp")
1230
868
  .description("Start the MCP server over stdio for Claude, Codex, and other MCP-compatible agents.")
@@ -1232,65 +870,6 @@ program
1232
870
  const explicitRoot = explicitProjectRoot(command);
1233
871
  await serveMcp(explicitRoot);
1234
872
  });
1235
- const portableCommand = program
1236
- .command("portable")
1237
- .description("Export or verify a frozen, relocatable Ragmir knowledge-base folder.");
1238
- portableCommand
1239
- .command("export")
1240
- .description("Export the active index, skills, launcher, and MCP adapters into one folder.")
1241
- .option("-o, --output <directory>", "Destination directory. Defaults under .ragmir/exports/.")
1242
- .option("--name <name>", "Portable knowledge-base display name.")
1243
- .option("--replace", "Replace an existing portable destination after preserving it as a sibling backup.")
1244
- .option("--json", "Print machine-readable JSON.")
1245
- .action(async (options, command) => {
1246
- const exportOptions = {
1247
- cwd: projectRoot(command),
1248
- replaceExisting: options.replace === true,
1249
- };
1250
- addOption(exportOptions, "outputDir", options.output);
1251
- addOption(exportOptions, "name", options.name);
1252
- const result = await exportPortableKnowledgeBase(exportOptions);
1253
- if (options.json) {
1254
- console.log(JSON.stringify(result, null, 2));
1255
- return;
1256
- }
1257
- console.log(pc.green("Portable knowledge base exported."));
1258
- console.log(`outputDir=${result.outputDir}`);
1259
- if (result.previousOutputDir) {
1260
- console.log(`previousOutputDir=${result.previousOutputDir}`);
1261
- }
1262
- console.log(`manifestPath=${result.manifestPath}`);
1263
- console.log(`fileCount=${result.fileCount}`);
1264
- console.log(`totalBytes=${result.totalBytes}`);
1265
- console.log(`embeddingModelIncluded=${result.embeddingModelIncluded}`);
1266
- console.log(result.previousOutputDir
1267
- ? "Next: verify the active destination, restart its consumers, then retire the preserved previous folder when safe."
1268
- : "Next: move the folder, then run `node bin/rgr.cjs portable verify . --json`.");
1269
- });
1270
- portableCommand
1271
- .command("verify")
1272
- .description("Verify file integrity, index compatibility, and active table readability.")
1273
- .argument("[directory]", "Portable knowledge-base directory.", ".")
1274
- .option("--json", "Print machine-readable JSON.")
1275
- .action(async (directory, options) => {
1276
- const result = await verifyPortableKnowledgeBase(directory);
1277
- if (options.json) {
1278
- console.log(JSON.stringify(result, null, 2));
1279
- }
1280
- else {
1281
- console.log(result.valid
1282
- ? pc.green("Portable knowledge base is valid.")
1283
- : pc.red("Portable knowledge base is invalid."));
1284
- console.log(`root=${result.root}`);
1285
- console.log(`checkedFiles=${result.checkedFiles}`);
1286
- for (const warning of result.warnings)
1287
- console.log(pc.yellow(`warning=${warning}`));
1288
- for (const error of result.errors)
1289
- console.log(pc.red(`error=${error}`));
1290
- }
1291
- if (!result.valid)
1292
- process.exitCode = 1;
1293
- });
1294
873
  program
1295
874
  .command("skill-path")
1296
875
  .description("Print the bundled Ragmir skill path for agents that can load SKILL.md folders.")
@@ -1324,8 +903,6 @@ program
1324
903
  console.log(` - ${file}`);
1325
904
  }
1326
905
  console.log(`Skill path: ${result.skillPath}`);
1327
- console.log(`Optional audio skill path: ${result.audioSkillPath}`);
1328
- console.log(`Optional Markdown report skill path: ${result.reportSkillPath}`);
1329
906
  console.log(`MCP config example: ${result.mcpConfigPath}`);
1330
907
  for (const helper of result.agentHelpers) {
1331
908
  console.log(`${helper.label} MCP helper: ${helper.path}`);
@@ -1395,25 +972,6 @@ function explicitProjectRoot(command) {
1395
972
  const options = command.optsWithGlobals();
1396
973
  return options.projectRoot ? path.resolve(options.projectRoot) : undefined;
1397
974
  }
1398
- function deprecatedCliInvocation() {
1399
- const invokedPath = process.argv[1];
1400
- if (!invokedPath)
1401
- return null;
1402
- const commandName = path.basename(invokedPath).replace(/\.(?:cmd|ps1)$/iu, "");
1403
- return DEPRECATED_CLI_NAMES.has(commandName) ? commandName : null;
1404
- }
1405
- async function promptInput(promptParts) {
1406
- if (promptParts !== undefined && promptParts.length > 0) {
1407
- return promptParts.join(" ");
1408
- }
1409
- if (process.stdin.isTTY) {
1410
- return "";
1411
- }
1412
- return readBoundedStdin(process.stdin);
1413
- }
1414
- function withTopK(cwd, topK) {
1415
- return topK === undefined ? { cwd } : { cwd, topK };
1416
- }
1417
975
  function withSearchOptions(cwd, options) {
1418
976
  const result = { cwd };
1419
977
  addOption(result, "topK", options.topK);
@@ -1437,89 +995,6 @@ function addPathFilters(target, options) {
1437
995
  target.contextPaths = options.contextPath;
1438
996
  }
1439
997
  }
1440
- async function loadChat() {
1441
- let module;
1442
- try {
1443
- module = await import(CHAT_PACKAGE_NAME);
1444
- }
1445
- catch (error) {
1446
- if (isMissingOptionalPackage(error, CHAT_PACKAGE_NAME)) {
1447
- throw new Error(`Ragmir Chat is optional and is not installed. Add ${CHAT_PACKAGE_NAME} to this project before using \`rgr chat\`.`);
1448
- }
1449
- throw error;
1450
- }
1451
- if (!isChatModule(module)) {
1452
- throw new Error(`${CHAT_PACKAGE_NAME} did not expose the expected chat API.`);
1453
- }
1454
- return module;
1455
- }
1456
- function isChatModule(value) {
1457
- return (typeof value === "object" &&
1458
- value !== null &&
1459
- "doctor" in value &&
1460
- typeof value.doctor === "function" &&
1461
- "generateChatAnswer" in value &&
1462
- typeof value.generateChatAnswer === "function" &&
1463
- "setupChatModel" in value &&
1464
- typeof value.setupChatModel === "function");
1465
- }
1466
- function chatMode(input) {
1467
- if (input?.length === 1 && input[0] === "doctor") {
1468
- return "doctor";
1469
- }
1470
- if (input?.length === 1 && input[0] === "setup") {
1471
- return "setup";
1472
- }
1473
- return "ask";
1474
- }
1475
- function chatAllowRemoteModels(options) {
1476
- if (options.offline) {
1477
- return false;
1478
- }
1479
- if (options.allowRemoteModels) {
1480
- return true;
1481
- }
1482
- return undefined;
1483
- }
1484
- function toChatSource(source) {
1485
- return {
1486
- source: source.source,
1487
- relativePath: source.relativePath,
1488
- chunkIndex: source.chunkIndex,
1489
- text: source.text,
1490
- distance: source.distance,
1491
- };
1492
- }
1493
- async function loadTts() {
1494
- let module;
1495
- try {
1496
- module = await import(TTS_PACKAGE_NAME);
1497
- }
1498
- catch (error) {
1499
- if (isMissingOptionalPackage(error, TTS_PACKAGE_NAME)) {
1500
- throw new Error(`Ragmir TTS is optional and is not installed. Add ${TTS_PACKAGE_NAME} to this project before using \`rgr audio\`.`);
1501
- }
1502
- throw error;
1503
- }
1504
- if (!isTtsModule(module)) {
1505
- throw new Error(`${TTS_PACKAGE_NAME} did not expose the expected TTS API.`);
1506
- }
1507
- return module;
1508
- }
1509
- function isMissingOptionalPackage(error, packageName) {
1510
- return (error instanceof Error &&
1511
- "code" in error &&
1512
- error.code === "ERR_MODULE_NOT_FOUND" &&
1513
- error.message.includes(packageName));
1514
- }
1515
- function isTtsModule(value) {
1516
- return (typeof value === "object" &&
1517
- value !== null &&
1518
- "doctor" in value &&
1519
- typeof value.doctor === "function" &&
1520
- "renderSpeech" in value &&
1521
- typeof value.renderSpeech === "function");
1522
- }
1523
998
  function printDoctor(report) {
1524
999
  console.log(`mode=${report.mode}`);
1525
1000
  console.log(`cost=${report.cost}`);
@@ -1551,8 +1026,6 @@ function printDoctor(report) {
1551
1026
  }
1552
1027
  console.log(`embeddingProvider=${report.embeddingProvider}`);
1553
1028
  console.log(`transformersAllowRemoteModels=${report.transformersAllowRemoteModels}`);
1554
- console.log(`redactionEnabled=${report.redactionEnabled}`);
1555
- console.log(`accessLog=${report.accessLog}`);
1556
1029
  console.log(`supportedFiles=${report.supportedFiles}`);
1557
1030
  console.log(`supportedBytes=${report.supportedBytes}`);
1558
1031
  console.log(`largestFileBytes=${report.largestFileBytes}`);
@@ -1633,148 +1106,7 @@ function printGenerationGarbageCollection(report) {
1633
1106
  console.log(pc.yellow(`warning: ${report.warning}`));
1634
1107
  }
1635
1108
  }
1636
- function printResearchReport(report) {
1637
- console.log(`query=${report.query}`);
1638
- console.log(`ready=${report.ready}`);
1639
- console.log(`generatedQueries=${report.generatedQueries.length}`);
1640
- console.log(`audit.mode=${report.audit.mode} audit.inventoryVerified=${report.audit.inventoryVerified} audit.supportedFiles=${report.audit.supportedFiles} audit.supportedBytes=${report.audit.supportedBytes} audit.largestFileBytes=${report.audit.largestFileBytes} audit.indexedFiles=${report.audit.indexedFiles} audit.totalChunks=${report.audit.totalChunks} audit.skippedFiles=${report.audit.skippedFiles} audit.oversizedFiles=${report.audit.oversizedFiles} audit.missingFromIndex=${report.audit.missingFromIndex} audit.staleInIndex=${report.audit.staleInIndex}`);
1641
- console.log(`budgets.timeoutMs=${report.budgets.timeoutMs ?? "none"} budgets.evidenceTopK=${report.budgets.evidenceTopK} budgets.codeEvidenceTopK=${report.budgets.codeEvidenceTopK} budgets.codeFiles=${report.budgets.codeFilesScanned}/${report.budgets.codeScanMaxFiles} budgets.codeBytes=${report.budgets.codeBytesScanned}/${report.budgets.codeScanMaxBytes} budgets.codeConcurrency=${report.budgets.codeScanConcurrency} budgets.codeTruncated=${report.budgets.codeScanTruncated}`);
1642
- console.log(`securityWarnings=${report.securityWarnings.length}`);
1643
- console.log(`sourceDiagnostics.duplicates=${report.sourceDiagnostics.duplicateCandidates.length} sourceDiagnostics.archives=${report.sourceDiagnostics.archiveCandidates.length} sourceDiagnostics.mirrors=${report.sourceDiagnostics.mirrorCandidates.length}`);
1644
- if (report.sourceDiagnostics.duplicateCandidates.length > 0) {
1645
- console.log("");
1646
- console.log(pc.cyan("Duplicate Candidates:"));
1647
- for (const candidate of report.sourceDiagnostics.duplicateCandidates.slice(0, 5)) {
1648
- console.log(` - ${candidate.key}: ${candidate.files.join(", ")}`);
1649
- }
1650
- }
1651
- if (report.evidence.length > 0) {
1652
- console.log("");
1653
- console.log(pc.cyan("Evidence:"));
1654
- for (const [index, evidence] of report.evidence.entries()) {
1655
- const distance = evidence.distance === null ? "n/a" : evidence.distance.toFixed(4);
1656
- console.log(` [${index + 1}] ${evidence.relativePath} chunk=${evidence.chunkIndex} distance=${distance} researchScore=${evidence.researchScore.toFixed(6)} bestRank=${evidence.bestRank}`);
1657
- console.log(` ${researchEvidencePreview(evidence)}`);
1658
- }
1659
- }
1660
- if (report.codeEvidence.length > 0) {
1661
- console.log("");
1662
- console.log(pc.cyan("Code Evidence:"));
1663
- for (const evidence of report.codeEvidence.slice(0, 10)) {
1664
- console.log(` - ${evidence.relativePath}:${evidence.lineNumber} score=${evidence.score} terms=${evidence.matchedTerms.join(",")}`);
1665
- console.log(` ${evidence.snippet}`);
1666
- }
1667
- }
1668
- if (report.gaps.length > 0) {
1669
- console.log("");
1670
- console.log(pc.yellow("Gaps:"));
1671
- for (const gap of report.gaps) {
1672
- console.log(pc.yellow(` - ${gap}`));
1673
- }
1674
- }
1675
- console.log("");
1676
- console.log(pc.cyan("Next Steps:"));
1677
- for (const step of report.nextSteps) {
1678
- console.log(` - ${step}`);
1679
- }
1680
- }
1681
- function researchEvidencePreview(evidence) {
1682
- if ("snippet" in evidence) {
1683
- return evidence.snippet;
1684
- }
1685
- return evidence.text.replace(/\s+/gu, " ").trim().slice(0, SEARCH_TEXT_PREVIEW_LENGTH);
1686
- }
1687
- function printTeamComparison(comparison) {
1688
- const statusColor = comparison.synchronized ? pc.green : pc.yellow;
1689
- console.log(statusColor(`Team status: ${comparison.status}`));
1690
- console.log(`summary=${comparison.summary}`);
1691
- console.log(`local=${comparison.localLabel}`);
1692
- console.log(`peer=${comparison.peerLabel}`);
1693
- console.log(`localSecurityAdvisories=${comparison.securityAdvisories.local}`);
1694
- console.log(`peerSecurityAdvisories=${comparison.securityAdvisories.peer}`);
1695
- console.log(`sameConfiguration=${comparison.sameConfiguration}`);
1696
- console.log(`sameCorpus=${comparison.sameCorpus}`);
1697
- console.log(`authorityDecisionRequired=${comparison.authorityDecisionRequired}`);
1698
- if (comparison.configurationDifferences.length > 0) {
1699
- console.log("");
1700
- console.log(pc.cyan("Configuration differences:"));
1701
- for (const difference of comparison.configurationDifferences) {
1702
- console.log(` - ${difference.field} (${difference.scope}, rebuild=${difference.requiresRebuild}): local=${formatTeamValue(difference.local)} peer=${formatTeamValue(difference.peer)}`);
1703
- }
1704
- }
1705
- printTeamPaths("Local-only files", comparison.files.localOnly);
1706
- printTeamPaths("Peer-only files", comparison.files.peerOnly);
1707
- if (comparison.files.changed.length > 0) {
1708
- console.log("");
1709
- console.log(pc.cyan(`Changed files (${comparison.files.changed.length}):`));
1710
- for (const file of comparison.files.changed.slice(0, TEAM_DIFF_PREVIEW_LIMIT)) {
1711
- console.log(` - ${file.relativePath} local=${file.localChecksum.slice(0, 12)} peer=${file.peerChecksum.slice(0, 12)}`);
1712
- }
1713
- printTeamOmitted(comparison.files.changed.length);
1714
- }
1715
- if (comparison.recommendedActions.length > 0) {
1716
- console.log("");
1717
- console.log(pc.cyan("Recommended actions:"));
1718
- for (const [index, action] of comparison.recommendedActions.entries()) {
1719
- console.log(` ${index + 1}. ${action}`);
1720
- }
1721
- }
1722
- }
1723
- function printTeamSync(report) {
1724
- const statusColor = report.synchronized
1725
- ? pc.green
1726
- : report.status === "index-not-ready"
1727
- ? pc.red
1728
- : pc.yellow;
1729
- console.log(statusColor(`Team sync: ${report.status}`));
1730
- console.log(`summary=${report.summary}`);
1731
- console.log(`gitState=${report.git.state}`);
1732
- console.log(`branch=${report.git.branch ?? "none"}`);
1733
- console.log(`upstream=${report.git.upstream ?? "none"}`);
1734
- console.log(`ahead=${report.git.ahead ?? "unknown"}`);
1735
- console.log(`behind=${report.git.behind ?? "unknown"}`);
1736
- console.log(`dirty=${report.git.dirty ?? "unknown"}`);
1737
- console.log(`fetched=${report.git.fetched}`);
1738
- console.log(`updated=${report.git.updated}`);
1739
- console.log(`indexReady=${report.index.operationalReady && report.index.indexPolicyCurrent}`);
1740
- console.log(`indexedFiles=${report.index.indexedFiles}`);
1741
- console.log(`chunksIndexed=${report.index.chunksIndexed}`);
1742
- console.log(`securityAdvisories=${report.index.securityAdvisories}`);
1743
- if (report.warnings.length > 0) {
1744
- console.log("");
1745
- console.log(pc.yellow("Warnings:"));
1746
- for (const warning of report.warnings) {
1747
- console.log(` - ${warning}`);
1748
- }
1749
- }
1750
- if (report.recommendedActions.length > 0) {
1751
- console.log("");
1752
- console.log(pc.cyan("Next action:"));
1753
- console.log(` ${report.recommendedActions[0]}`);
1754
- }
1755
- }
1756
- function printTeamPaths(title, files) {
1757
- if (files.length === 0) {
1758
- return;
1759
- }
1760
- console.log("");
1761
- console.log(pc.cyan(`${title} (${files.length}):`));
1762
- for (const file of files.slice(0, TEAM_DIFF_PREVIEW_LIMIT)) {
1763
- console.log(` - ${file}`);
1764
- }
1765
- printTeamOmitted(files.length);
1766
- }
1767
- function printTeamOmitted(total) {
1768
- const omitted = total - TEAM_DIFF_PREVIEW_LIMIT;
1769
- if (omitted > 0) {
1770
- console.log(` ... ${omitted} more; use --json for the complete diff.`);
1771
- }
1772
- }
1773
- function formatTeamValue(value) {
1774
- return Array.isArray(value) ? JSON.stringify(value) : String(value);
1775
- }
1776
1109
  function printPdfOcrStatus(status) {
1777
- console.log(`privacyProfile=${status.privacyProfile}`);
1778
1110
  console.log(`configured=${status.configured}`);
1779
1111
  console.log(`recommendedEngine=${status.recommendedEngine ?? "none"}`);
1780
1112
  console.log(`ocrmypdf.available=${status.ocrmypdf.available}`);
@@ -1785,15 +1117,6 @@ function printPdfOcrStatus(status) {
1785
1117
  console.log(`pdftoppm.available=${status.pdftoppm.available}`);
1786
1118
  console.log(`pdftoppm.version=${status.pdftoppm.version ?? "unavailable"}`);
1787
1119
  console.log(`languages=${status.languages.join(",")}`);
1788
- if (status.privacyProfile === "strict") {
1789
- console.log(pc.yellow("The strict privacy profile disables external OCR even when local tools are installed."));
1790
- }
1791
- else if (!status.recommendedEngine) {
1792
- console.log(pc.yellow("Install OCRmyPDF 12.6+ or install both Tesseract and Poppler, then run `rgr ocr setup`."));
1793
- }
1794
- else if (!status.configured) {
1795
- console.log(`Run \`rgr ocr setup --engine ${status.recommendedEngine}\` to enable local PDF OCR.`);
1796
- }
1797
1120
  }
1798
1121
  function printSetup(result, title) {
1799
1122
  console.log(pc.green(title));
@@ -1813,8 +1136,6 @@ function printSetup(result, title) {
1813
1136
  console.log("");
1814
1137
  console.log(pc.cyan("Agent integration:"));
1815
1138
  console.log(` - skill: ${result.agentKit.skillPath}`);
1816
- console.log(` - audio skill: ${result.agentKit.audioSkillPath}`);
1817
- console.log(` - report skill: ${result.agentKit.reportSkillPath}`);
1818
1139
  console.log(` - MCP config: ${result.agentKit.mcpConfigPath}`);
1819
1140
  for (const helper of result.agentKit.agentHelpers) {
1820
1141
  console.log(` - ${helper.label} MCP helper: ${helper.path}`);
@@ -1878,19 +1199,6 @@ function printEmptyTextFiles(files) {
1878
1199
  }
1879
1200
  console.log(pc.yellow("These supported files produced no indexable text. For scanned PDFs, run `rgr ocr doctor` then `rgr ocr setup`; for images, configure imageOcrCommand or store local OCR text beside the source file."));
1880
1201
  }
1881
- function printMaybeJson(value, json) {
1882
- if (json) {
1883
- console.log(JSON.stringify(value, null, 2));
1884
- return;
1885
- }
1886
- if (typeof value === "object" && value !== null) {
1887
- for (const [key, entry] of Object.entries(value)) {
1888
- console.log(`${key}=${String(entry)}`);
1889
- }
1890
- return;
1891
- }
1892
- console.log(String(value));
1893
- }
1894
1202
  function addOption(target, key, value) {
1895
1203
  if (value !== undefined) {
1896
1204
  target[key] = value;