@jcode.labs/ragmir 2.7.0 → 2.8.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/access-log.d.ts.map +1 -1
- package/dist/access-log.js +65 -8
- package/dist/access-log.js.map +1 -1
- package/dist/chunking.d.ts.map +1 -1
- package/dist/chunking.js +29 -3
- package/dist/chunking.js.map +1 -1
- package/dist/cli.js +81 -21
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +73 -29
- package/dist/config.js.map +1 -1
- package/dist/defaults.d.ts +1 -0
- package/dist/defaults.d.ts.map +1 -1
- package/dist/defaults.js +6 -1
- package/dist/defaults.js.map +1 -1
- package/dist/destroy.d.ts.map +1 -1
- package/dist/destroy.js +23 -1
- package/dist/destroy.js.map +1 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +40 -9
- package/dist/doctor.js.map +1 -1
- package/dist/embeddings.d.ts +4 -1
- package/dist/embeddings.d.ts.map +1 -1
- package/dist/embeddings.js +62 -14
- package/dist/embeddings.js.map +1 -1
- package/dist/evaluate.d.ts.map +1 -1
- package/dist/evaluate.js +48 -4
- package/dist/evaluate.js.map +1 -1
- package/dist/files.d.ts +8 -1
- package/dist/files.d.ts.map +1 -1
- package/dist/files.js +44 -8
- package/dist/files.js.map +1 -1
- package/dist/index-diagnostics.d.ts +1 -1
- package/dist/index-diagnostics.d.ts.map +1 -1
- package/dist/index-diagnostics.js +8 -3
- package/dist/index-diagnostics.js.map +1 -1
- package/dist/index-policy.d.ts +3 -0
- package/dist/index-policy.d.ts.map +1 -0
- package/dist/index-policy.js +28 -0
- package/dist/index-policy.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/ingest.d.ts.map +1 -1
- package/dist/ingest.js +112 -54
- package/dist/ingest.js.map +1 -1
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +15 -3
- package/dist/init.js.map +1 -1
- package/dist/limits.d.ts +9 -0
- package/dist/limits.d.ts.map +1 -0
- package/dist/limits.js +25 -0
- package/dist/limits.js.map +1 -0
- package/dist/mcp.d.ts +3 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +71 -14
- package/dist/mcp.js.map +1 -1
- package/dist/parsing.d.ts.map +1 -1
- package/dist/parsing.js +124 -24
- package/dist/parsing.js.map +1 -1
- package/dist/permissions.d.ts +3 -0
- package/dist/permissions.d.ts.map +1 -0
- package/dist/permissions.js +13 -0
- package/dist/permissions.js.map +1 -0
- package/dist/query.d.ts +2 -2
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +198 -39
- package/dist/query.js.map +1 -1
- package/dist/research.d.ts.map +1 -1
- package/dist/research.js +33 -4
- package/dist/research.js.map +1 -1
- package/dist/security.d.ts.map +1 -1
- package/dist/security.js +110 -14
- package/dist/security.js.map +1 -1
- package/dist/store.d.ts +3 -0
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +71 -72
- package/dist/store.js.map +1 -1
- package/dist/text.d.ts.map +1 -1
- package/dist/text.js +13 -1
- package/dist/text.js.map +1 -1
- package/dist/types.d.ts +94 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/examples/document-evidence-benchmark/.ragmir/config.json +2 -1
- package/examples/document-evidence-benchmark/README.md +5 -2
- package/examples/document-evidence-benchmark/golden-queries.json +6 -0
- package/examples/document-evidence-benchmark/raw/contracts/pdf-control-evidence.pdf +32 -0
- package/examples/sovereign-rag-demo/.ragmir/config.json +2 -1
- package/examples/sovereign-rag-demo/README.md +9 -1
- package/package.json +3 -3
- package/skills/ragmir/SKILL.md +11 -3
package/dist/access-log.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"access-log.d.ts","sourceRoot":"","sources":["../src/access-log.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"access-log.d.ts","sourceRoot":"","sources":["../src/access-log.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,eAAe,EACf,qBAAqB,EACrB,oBAAoB,EACpB,MAAM,EACP,MAAM,YAAY,CAAA;AAEnB,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,eAAe,CAAA;IACvB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAmCD,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBvF;AA2BD,wBAAsB,oBAAoB,CACxC,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,oBAAoB,CAAC,CA2D/B"}
|
package/dist/access-log.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createHmac, randomBytes } from "node:crypto";
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
|
-
import { appendFile,
|
|
3
|
+
import { appendFile, readFile, stat, writeFile } from "node:fs/promises";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { loadConfig } from "./config.js";
|
|
6
|
+
import { ensurePrivateDirectory, hardenPrivateFile } from "./permissions.js";
|
|
6
7
|
const ACCESS_LOG_ACTIONS = [
|
|
7
8
|
"ingest",
|
|
8
9
|
"search",
|
|
@@ -22,14 +23,19 @@ const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
|
22
23
|
const MAX_ACCESS_LOG_BYTES = 10 * 1024 * 1024;
|
|
23
24
|
/** Number of most recent lines retained when the log exceeds the byte cap. */
|
|
24
25
|
const TRIMMED_ACCESS_LOG_LINES = 50_000;
|
|
26
|
+
const ACCESS_LOG_SALT_FILE = ".ragmir-access-log.salt";
|
|
25
27
|
export async function recordAccess(config, event) {
|
|
26
28
|
if (!config.accessLog) {
|
|
27
29
|
return;
|
|
28
30
|
}
|
|
29
31
|
try {
|
|
30
|
-
await
|
|
32
|
+
await ensurePrivateDirectory(path.dirname(config.accessLogPath));
|
|
31
33
|
await trimAccessLogIfNeeded(config.accessLogPath);
|
|
32
|
-
await appendFile(config.accessLogPath, `${JSON.stringify(toLogLine(event))}\n`,
|
|
34
|
+
await appendFile(config.accessLogPath, `${JSON.stringify(await toLogLine(config, event))}\n`, {
|
|
35
|
+
encoding: "utf8",
|
|
36
|
+
mode: 0o600,
|
|
37
|
+
});
|
|
38
|
+
await hardenPrivateFile(config.accessLogPath);
|
|
33
39
|
}
|
|
34
40
|
catch {
|
|
35
41
|
// Access logging is best-effort so read-only workspaces do not block local use.
|
|
@@ -64,6 +70,7 @@ export async function accessLogUsageReport(options = {}) {
|
|
|
64
70
|
const since = new Date(until.getTime() - days * MILLISECONDS_PER_DAY);
|
|
65
71
|
const eventsByAction = emptyEventsByAction();
|
|
66
72
|
const queryHashes = new Set();
|
|
73
|
+
const resultCountsByAction = emptyResultCountsByAction();
|
|
67
74
|
let totalEvents = 0;
|
|
68
75
|
let invalidLines = 0;
|
|
69
76
|
let resultCountTotal = 0;
|
|
@@ -91,6 +98,8 @@ export async function accessLogUsageReport(options = {}) {
|
|
|
91
98
|
if (typeof event.resultCount === "number") {
|
|
92
99
|
resultCountTotal += event.resultCount;
|
|
93
100
|
resultCountEvents += 1;
|
|
101
|
+
resultCountsByAction[event.action].total += event.resultCount;
|
|
102
|
+
resultCountsByAction[event.action].events += 1;
|
|
94
103
|
}
|
|
95
104
|
if (lastEventAt === null || event.timestamp > lastEventAt) {
|
|
96
105
|
lastEventAt = event.timestamp;
|
|
@@ -106,21 +115,69 @@ export async function accessLogUsageReport(options = {}) {
|
|
|
106
115
|
eventsByAction,
|
|
107
116
|
uniqueQueryHashes: queryHashes.size,
|
|
108
117
|
averageResultCount: resultCountEvents === 0 ? null : resultCountTotal / resultCountEvents,
|
|
118
|
+
averageResultCountByAction: averageResultCounts(resultCountsByAction),
|
|
109
119
|
lastEventAt,
|
|
110
120
|
};
|
|
111
121
|
}
|
|
112
|
-
function
|
|
122
|
+
function emptyResultCountsByAction() {
|
|
123
|
+
return {
|
|
124
|
+
ingest: { total: 0, events: 0 },
|
|
125
|
+
search: { total: 0, events: 0 },
|
|
126
|
+
ask: { total: 0, events: 0 },
|
|
127
|
+
research: { total: 0, events: 0 },
|
|
128
|
+
evaluate: { total: 0, events: 0 },
|
|
129
|
+
"destroy-index": { total: 0, events: 0 },
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
function averageResultCounts(stats) {
|
|
133
|
+
return {
|
|
134
|
+
ingest: averageResultCount(stats.ingest),
|
|
135
|
+
search: averageResultCount(stats.search),
|
|
136
|
+
ask: averageResultCount(stats.ask),
|
|
137
|
+
research: averageResultCount(stats.research),
|
|
138
|
+
evaluate: averageResultCount(stats.evaluate),
|
|
139
|
+
"destroy-index": averageResultCount(stats["destroy-index"]),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function averageResultCount(stats) {
|
|
143
|
+
return stats.events === 0 ? null : stats.total / stats.events;
|
|
144
|
+
}
|
|
145
|
+
async function toLogLine(config, event) {
|
|
113
146
|
return {
|
|
114
147
|
timestamp: new Date().toISOString(),
|
|
115
148
|
action: event.action,
|
|
116
|
-
queryHash: event.query ? hashQuery(event.query) : undefined,
|
|
149
|
+
queryHash: event.query ? await hashQuery(config, event.query) : undefined,
|
|
117
150
|
topK: event.topK,
|
|
118
151
|
resultCount: event.resultCount,
|
|
119
152
|
redactions: event.redactions,
|
|
120
153
|
};
|
|
121
154
|
}
|
|
122
|
-
function hashQuery(query) {
|
|
123
|
-
|
|
155
|
+
async function hashQuery(config, query) {
|
|
156
|
+
const salt = await accessLogSalt(config);
|
|
157
|
+
return createHmac("sha256", salt).update(query).digest("hex");
|
|
158
|
+
}
|
|
159
|
+
async function accessLogSalt(config) {
|
|
160
|
+
const saltPath = path.join(path.dirname(config.accessLogPath), ACCESS_LOG_SALT_FILE);
|
|
161
|
+
try {
|
|
162
|
+
return await readFile(saltPath);
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
if (!isNodeError(error) || error.code !== "ENOENT") {
|
|
166
|
+
throw error;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
const salt = randomBytes(32);
|
|
170
|
+
try {
|
|
171
|
+
await writeFile(saltPath, salt, { flag: "wx", mode: 0o600 });
|
|
172
|
+
await hardenPrivateFile(saltPath);
|
|
173
|
+
return salt;
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
if (isNodeError(error) && error.code === "EEXIST") {
|
|
177
|
+
return readFile(saltPath);
|
|
178
|
+
}
|
|
179
|
+
throw error;
|
|
180
|
+
}
|
|
124
181
|
}
|
|
125
182
|
function emptyEventsByAction() {
|
|
126
183
|
return {
|
package/dist/access-log.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"access-log.js","sourceRoot":"","sources":["../src/access-log.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"access-log.js","sourceRoot":"","sources":["../src/access-log.ts"],"names":[],"mappings":"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"}
|
package/dist/chunking.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunking.d.ts","sourceRoot":"","sources":["../src/chunking.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"chunking.d.ts","sourceRoot":"","sources":["../src/chunking.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAQ3D,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,cAAc,EACxB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GACnB,SAAS,EAAE,CA2Cb"}
|
package/dist/chunking.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
const PARAGRAPH_BREAK_MIN_RATIO = 0.45;
|
|
3
3
|
const SENTENCE_BREAK_MIN_RATIO = 0.55;
|
|
4
|
+
const LINE_BREAK_MIN_RATIO = 0.65;
|
|
4
5
|
const WHITESPACE_BREAK_MIN_RATIO = 0.75;
|
|
6
|
+
const SENTENCE_BOUNDARIES = [". ", "? ", "! ", "。", "?", "!"];
|
|
5
7
|
export function chunkDocument(document, chunkSize, chunkOverlap) {
|
|
6
8
|
if (!document.text) {
|
|
7
9
|
return [];
|
|
@@ -27,6 +29,7 @@ export function chunkDocument(document, chunkSize, chunkOverlap) {
|
|
|
27
29
|
charEnd: span.end,
|
|
28
30
|
lineStart: lineNumberForOffset(lineStarts, span.start),
|
|
29
31
|
lineEnd: lineNumberForOffset(lineStarts, Math.max(span.start, span.end - 1)),
|
|
32
|
+
...pageRangeForSpan(document, span.start, span.end),
|
|
30
33
|
checksum: document.file.checksum,
|
|
31
34
|
bytes: document.file.bytes,
|
|
32
35
|
mtimeMs: document.file.mtimeMs,
|
|
@@ -40,6 +43,15 @@ export function chunkDocument(document, chunkSize, chunkOverlap) {
|
|
|
40
43
|
}
|
|
41
44
|
return chunks;
|
|
42
45
|
}
|
|
46
|
+
function pageRangeForSpan(document, start, end) {
|
|
47
|
+
if (!document.pages || document.pages.length === 0) {
|
|
48
|
+
return {};
|
|
49
|
+
}
|
|
50
|
+
const overlapping = document.pages.filter((page) => page.charStart < end && page.charEnd > start);
|
|
51
|
+
const first = overlapping[0];
|
|
52
|
+
const last = overlapping.at(-1);
|
|
53
|
+
return first && last ? { pageStart: first.pageNumber, pageEnd: last.pageNumber } : {};
|
|
54
|
+
}
|
|
43
55
|
function chooseChunkEnd(text, cursor, chunkSize) {
|
|
44
56
|
const hardEnd = Math.min(cursor + chunkSize, text.length);
|
|
45
57
|
if (hardEnd === text.length) {
|
|
@@ -50,9 +62,13 @@ function chooseChunkEnd(text, cursor, chunkSize) {
|
|
|
50
62
|
if (paragraphBreak > chunkSize * PARAGRAPH_BREAK_MIN_RATIO) {
|
|
51
63
|
return cursor + paragraphBreak;
|
|
52
64
|
}
|
|
53
|
-
const
|
|
54
|
-
if (
|
|
55
|
-
return cursor +
|
|
65
|
+
const sentenceBreakEnd = lastSentenceBreakEnd(window);
|
|
66
|
+
if (sentenceBreakEnd > chunkSize * SENTENCE_BREAK_MIN_RATIO) {
|
|
67
|
+
return cursor + sentenceBreakEnd;
|
|
68
|
+
}
|
|
69
|
+
const lineBreak = window.lastIndexOf("\n");
|
|
70
|
+
if (lineBreak > chunkSize * LINE_BREAK_MIN_RATIO) {
|
|
71
|
+
return cursor + lineBreak;
|
|
56
72
|
}
|
|
57
73
|
const whitespace = window.lastIndexOf(" ");
|
|
58
74
|
if (whitespace > chunkSize * WHITESPACE_BREAK_MIN_RATIO) {
|
|
@@ -60,6 +76,16 @@ function chooseChunkEnd(text, cursor, chunkSize) {
|
|
|
60
76
|
}
|
|
61
77
|
return hardEnd;
|
|
62
78
|
}
|
|
79
|
+
function lastSentenceBreakEnd(text) {
|
|
80
|
+
let end = -1;
|
|
81
|
+
for (const boundary of SENTENCE_BOUNDARIES) {
|
|
82
|
+
const index = text.lastIndexOf(boundary);
|
|
83
|
+
if (index >= 0) {
|
|
84
|
+
end = Math.max(end, index + (boundary.endsWith(" ") ? boundary.length - 1 : boundary.length));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return end;
|
|
88
|
+
}
|
|
63
89
|
function trimmedSpan(text, start, end) {
|
|
64
90
|
let trimmedStart = start;
|
|
65
91
|
let trimmedEnd = end;
|
package/dist/chunking.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunking.js","sourceRoot":"","sources":["../src/chunking.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAGxC,MAAM,yBAAyB,GAAG,IAAI,CAAA;AACtC,MAAM,wBAAwB,GAAG,IAAI,CAAA;AACrC,MAAM,0BAA0B,GAAG,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"chunking.js","sourceRoot":"","sources":["../src/chunking.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAGxC,MAAM,yBAAyB,GAAG,IAAI,CAAA;AACtC,MAAM,wBAAwB,GAAG,IAAI,CAAA;AACrC,MAAM,oBAAoB,GAAG,IAAI,CAAA;AACjC,MAAM,0BAA0B,GAAG,IAAI,CAAA;AACvC,MAAM,mBAAmB,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;AAE7D,MAAM,UAAU,aAAa,CAC3B,QAAwB,EACxB,SAAiB,EACjB,YAAoB;IAEpB,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnB,OAAO,EAAE,CAAA;IACX,CAAC;IAED,MAAM,MAAM,GAAgB,EAAE,CAAA;IAC9B,MAAM,UAAU,GAAG,gBAAgB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;IAClD,IAAI,MAAM,GAAG,CAAC,CAAA;IACd,IAAI,UAAU,GAAG,CAAC,CAAA;IAElB,OAAO,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,cAAc,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,CAAA;QAC5D,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,CAAA;QAEpD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,MAAM,EAAE,GAAG,UAAU,CAAC,QAAQ,CAAC;iBAC5B,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,YAAY,IAAI,UAAU,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;iBAClE,MAAM,CAAC,KAAK,CAAC,CAAA;YAChB,MAAM,CAAC,IAAI,CAAC;gBACV,EAAE;gBACF,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM;gBAC5B,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,YAAY;gBACxC,UAAU;gBACV,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,SAAS,EAAE,IAAI,CAAC,KAAK;gBACrB,OAAO,EAAE,IAAI,CAAC,GAAG;gBACjB,SAAS,EAAE,mBAAmB,CAAC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC;gBACtD,OAAO,EAAE,mBAAmB,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;gBAC5E,GAAG,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC;gBACnD,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ;gBAChC,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK;gBAC1B,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,OAAO;aAC/B,CAAC,CAAA;YACF,UAAU,IAAI,CAAC,CAAA;QACjB,CAAC;QAED,IAAI,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YAChC,MAAK;QACP,CAAC;QACD,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,YAAY,EAAE,MAAM,GAAG,CAAC,CAAC,CAAA;IACnD,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAS,gBAAgB,CACvB,QAAwB,EACxB,KAAa,EACb,GAAW;IAEX,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnD,OAAO,EAAE,CAAA;IACX,CAAC;IACD,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,GAAG,GAAG,IAAI,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,CAAA;IACjG,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC,CAAA;IAC5B,MAAM,IAAI,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;IAC/B,OAAO,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;AACvF,CAAC;AAED,SAAS,cAAc,CAAC,IAAY,EAAE,MAAc,EAAE,SAAiB;IACrE,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;IACzD,IAAI,OAAO,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;QAC5B,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC1C,MAAM,cAAc,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;IACjD,IAAI,cAAc,GAAG,SAAS,GAAG,yBAAyB,EAAE,CAAC;QAC3D,OAAO,MAAM,GAAG,cAAc,CAAA;IAChC,CAAC;IAED,MAAM,gBAAgB,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAA;IACrD,IAAI,gBAAgB,GAAG,SAAS,GAAG,wBAAwB,EAAE,CAAC;QAC5D,OAAO,MAAM,GAAG,gBAAgB,CAAA;IAClC,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;IAC1C,IAAI,SAAS,GAAG,SAAS,GAAG,oBAAoB,EAAE,CAAC;QACjD,OAAO,MAAM,GAAG,SAAS,CAAA;IAC3B,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;IAC1C,IAAI,UAAU,GAAG,SAAS,GAAG,0BAA0B,EAAE,CAAC;QACxD,OAAO,MAAM,GAAG,UAAU,CAAA;IAC5B,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAY;IACxC,IAAI,GAAG,GAAG,CAAC,CAAC,CAAA;IACZ,KAAK,MAAM,QAAQ,IAAI,mBAAmB,EAAE,CAAC;QAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAA;QACxC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;YACf,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAA;QAC/F,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAQD,SAAS,WAAW,CAAC,IAAY,EAAE,KAAa,EAAE,GAAW;IAC3D,IAAI,YAAY,GAAG,KAAK,CAAA;IACxB,IAAI,UAAU,GAAG,GAAG,CAAA;IACpB,OAAO,YAAY,GAAG,UAAU,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;QACzE,YAAY,IAAI,CAAC,CAAA;IACnB,CAAC;IACD,OAAO,UAAU,GAAG,YAAY,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;QAC3E,UAAU,IAAI,CAAC,CAAA;IACjB,CAAC;IACD,OAAO;QACL,KAAK,EAAE,YAAY;QACnB,GAAG,EAAE,UAAU;QACf,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,UAAU,CAAC;KAC3C,CAAA;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAY;IACpC,MAAM,MAAM,GAAG,CAAC,CAAC,CAAC,CAAA;IAClB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpD,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,IAAI,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;YACpD,MAAM,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAA;QACxB,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAS,mBAAmB,CAAC,UAAoB,EAAE,MAAc;IAC/D,IAAI,GAAG,GAAG,CAAC,CAAA;IACX,IAAI,IAAI,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,CAAA;IAChC,OAAO,GAAG,IAAI,IAAI,EAAE,CAAC;QACnB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;QACxC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACtC,IAAI,SAAS,IAAI,MAAM,EAAE,CAAC;YACxB,GAAG,GAAG,GAAG,GAAG,CAAC,CAAA;QACf,CAAC;aAAM,CAAC;YACN,IAAI,GAAG,GAAG,GAAG,CAAC,CAAA;QAChB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,CAAA;AAC9B,CAAC"}
|
package/dist/cli.js
CHANGED
|
@@ -14,6 +14,7 @@ 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 { ingestionLimits } from "./limits.js";
|
|
17
18
|
import { serveMcp } from "./mcp.js";
|
|
18
19
|
import { rgrCommand } from "./package-manager.js";
|
|
19
20
|
import { routePrompt } from "./prompt-routing.js";
|
|
@@ -217,7 +218,7 @@ program
|
|
|
217
218
|
}
|
|
218
219
|
return;
|
|
219
220
|
}
|
|
220
|
-
console.log(pc.green(`Done. discoveredFiles=${result.discoveredFiles} supportedFiles=${result.supportedFiles} indexedFiles=${result.indexedFiles} rebuiltFiles=${result.rebuiltFiles} reusedFiles=${result.reusedFiles} chunks=${result.chunks} skippedFiles=${result.skippedFiles} unsupportedFiles=${result.unsupportedFiles} oversizedFiles=${result.oversizedFiles} sensitiveFiles=${result.sensitiveFiles} emptyTextFiles=${result.emptyTextFiles.length} redactions=${result.redactions} errors=${result.errors.length}`));
|
|
221
|
+
console.log(pc.green(`Done. discoveredFiles=${result.discoveredFiles} supportedFiles=${result.supportedFiles} supportedBytes=${result.supportedBytes} largestFileBytes=${result.largestFileBytes} indexedFiles=${result.indexedFiles} rebuiltFiles=${result.rebuiltFiles} reusedFiles=${result.reusedFiles} chunks=${result.chunks} skippedFiles=${result.skippedFiles} unsupportedFiles=${result.unsupportedFiles} oversizedFiles=${result.oversizedFiles} sensitiveFiles=${result.sensitiveFiles} emptyTextFiles=${result.emptyTextFiles.length} redactions=${result.redactions} errors=${result.errors.length}`));
|
|
221
222
|
printUnsupportedSummary(result.unsupportedExtensions);
|
|
222
223
|
printEmptyTextFiles(result.emptyTextFiles);
|
|
223
224
|
if (result.vectorIndexWarning) {
|
|
@@ -243,6 +244,8 @@ program
|
|
|
243
244
|
.argument("<query>", "Search query.")
|
|
244
245
|
.option("-k, --top-k <number>", "Number of passages to return.", parsePositiveInt)
|
|
245
246
|
.option("--context-radius <number>", "Include neighboring chunks around each matched passage.", parseNonNegativeInt)
|
|
247
|
+
.option("--include-path <prefix>", "Search only indexed source paths under this prefix. Repeat for multiple prefixes.", collectOptionValue, [])
|
|
248
|
+
.option("--exclude-path <prefix>", "Exclude indexed source paths under this prefix. Repeat for multiple prefixes.", collectOptionValue, [])
|
|
246
249
|
.option("--compact", "Return short snippets instead of full passages.")
|
|
247
250
|
.option("--json", "Print machine-readable JSON.")
|
|
248
251
|
.action(async (query, options, command) => {
|
|
@@ -275,6 +278,8 @@ program
|
|
|
275
278
|
.argument("<query>", "Question to answer.")
|
|
276
279
|
.option("-k, --top-k <number>", "Number of passages to use.", parsePositiveInt)
|
|
277
280
|
.option("--context-radius <number>", "Include neighboring chunks around each matched passage.", parseNonNegativeInt)
|
|
281
|
+
.option("--include-path <prefix>", "Use only indexed source paths under this prefix. Repeat for multiple prefixes.", collectOptionValue, [])
|
|
282
|
+
.option("--exclude-path <prefix>", "Exclude indexed source paths under this prefix. Repeat for multiple prefixes.", collectOptionValue, [])
|
|
278
283
|
.option("--json", "Print machine-readable JSON.")
|
|
279
284
|
.action(async (query, options, command) => {
|
|
280
285
|
const cwd = projectRoot(command);
|
|
@@ -303,6 +308,8 @@ program
|
|
|
303
308
|
.argument("<query>", "Research question or topic.")
|
|
304
309
|
.option("-k, --top-k <number>", "Maximum number of evidence passages to keep.", parsePositiveInt)
|
|
305
310
|
.option("--no-code", "Skip the lightweight repository code search.")
|
|
311
|
+
.option("--include-path <prefix>", "Use only indexed source paths under this prefix. Repeat for multiple prefixes.", collectOptionValue, [])
|
|
312
|
+
.option("--exclude-path <prefix>", "Exclude indexed source paths under this prefix. Repeat for multiple prefixes.", collectOptionValue, [])
|
|
306
313
|
.option("--compact", "Return snippets instead of full retrieved passages.")
|
|
307
314
|
.option("--json", "Print machine-readable JSON.")
|
|
308
315
|
.action(async (query, options, command) => {
|
|
@@ -310,6 +317,7 @@ program
|
|
|
310
317
|
const researchOptions = { cwd };
|
|
311
318
|
addOption(researchOptions, "topK", options.topK);
|
|
312
319
|
addOption(researchOptions, "includeCode", options.code);
|
|
320
|
+
addPathFilters(researchOptions, options);
|
|
313
321
|
const report = await research(query, researchOptions);
|
|
314
322
|
const output = options.compact ? compactResearchReport(report) : report;
|
|
315
323
|
if (options.json) {
|
|
@@ -367,25 +375,25 @@ program
|
|
|
367
375
|
};
|
|
368
376
|
addOption(evaluationOptions, "topK", options.topK);
|
|
369
377
|
const result = await evaluateGoldenQueries(evaluationOptions);
|
|
370
|
-
const minimumRecall = options.failUnder
|
|
371
|
-
const passed = result.recall >= minimumRecall;
|
|
378
|
+
const minimumRecall = options.failUnder;
|
|
379
|
+
const passed = minimumRecall === undefined || result.recall >= minimumRecall;
|
|
372
380
|
if (options.json) {
|
|
373
|
-
const payload =
|
|
381
|
+
const payload = minimumRecall === undefined ? result : { ...result, minimumRecall, passed };
|
|
374
382
|
console.log(JSON.stringify(payload, null, 2));
|
|
375
383
|
if (!passed) {
|
|
376
384
|
process.exitCode = 1;
|
|
377
385
|
}
|
|
378
386
|
return;
|
|
379
387
|
}
|
|
380
|
-
const thresholdSummary =
|
|
388
|
+
const thresholdSummary = minimumRecall === undefined
|
|
381
389
|
? ""
|
|
382
390
|
: ` minimumRecall=${minimumRecall.toFixed(3)} passed=${passed}`;
|
|
383
|
-
console.log(`golden=${result.goldenPath} total=${result.total} hits=${result.hits} misses=${result.misses} recall=${result.recall.toFixed(3)} mrr=${result.meanReciprocalRank.toFixed(3)} ndcg=${result.ndcg.toFixed(3)}${thresholdSummary}`);
|
|
391
|
+
console.log(`golden=${result.goldenPath} total=${result.total} hits=${result.hits} misses=${result.misses} hitRate=${result.hitRate.toFixed(3)} recall=${result.recall.toFixed(3)} precision=${result.precision.toFixed(3)} mrr=${result.meanReciprocalRank.toFixed(3)} ndcg=${result.ndcg.toFixed(3)} p50Ms=${result.p50LatencyMs.toFixed(1)} p95Ms=${result.p95LatencyMs.toFixed(1)}${thresholdSummary}`);
|
|
384
392
|
for (const testCase of result.cases) {
|
|
385
393
|
const label = testCase.id ? `${testCase.id}: ${testCase.query}` : testCase.query;
|
|
386
394
|
const status = testCase.hit ? pc.green("hit") : pc.red("miss");
|
|
387
395
|
const rank = testCase.bestRank === null ? "n/a" : String(testCase.bestRank);
|
|
388
|
-
console.log(`${status} rank=${rank} rr=${testCase.reciprocalRank.toFixed(3)} ndcg=${testCase.ndcg.toFixed(3)} topK=${testCase.topK} ${label}`);
|
|
396
|
+
console.log(`${status} rank=${rank} recall=${testCase.recall.toFixed(3)} precision=${testCase.precision.toFixed(3)} rr=${testCase.reciprocalRank.toFixed(3)} ndcg=${testCase.ndcg.toFixed(3)} latencyMs=${testCase.latencyMs.toFixed(1)} topK=${testCase.topK} ${label}`);
|
|
389
397
|
if (!testCase.hit) {
|
|
390
398
|
const expected = testCase.expectedCitations === undefined
|
|
391
399
|
? testCase.expectedPaths
|
|
@@ -413,9 +421,14 @@ program
|
|
|
413
421
|
console.log(JSON.stringify(report, null, 2));
|
|
414
422
|
return;
|
|
415
423
|
}
|
|
424
|
+
console.log(`discoveredFiles=${report.discoveredFiles}`);
|
|
416
425
|
console.log(`supportedFiles=${report.supportedFiles.length}`);
|
|
426
|
+
console.log(`supportedBytes=${report.supportedBytes}`);
|
|
427
|
+
console.log(`largestFileBytes=${report.largestFileBytes}`);
|
|
417
428
|
console.log(`skippedFiles=${report.skippedFiles.length}`);
|
|
418
429
|
console.log(`unsupportedFiles=${countSkippedByReason(report.skippedFiles, "unsupported-extension")}`);
|
|
430
|
+
console.log(`oversizedFiles=${countSkippedByReason(report.skippedFiles, "oversized")}`);
|
|
431
|
+
console.log(`sensitiveFiles=${countSkippedByReason(report.skippedFiles, "sensitive-name")}`);
|
|
419
432
|
console.log(`indexedFiles=${report.indexedFiles.length}`);
|
|
420
433
|
console.log(`totalChunks=${report.totalChunks}`);
|
|
421
434
|
console.log(`emptyTextFiles=${report.emptyTextFiles.length}`);
|
|
@@ -475,6 +488,33 @@ program
|
|
|
475
488
|
for (const [action, count] of Object.entries(report.eventsByAction)) {
|
|
476
489
|
console.log(`events.${action}=${count}`);
|
|
477
490
|
}
|
|
491
|
+
for (const [action, average] of Object.entries(report.averageResultCountByAction)) {
|
|
492
|
+
console.log(`averageResults.${action}=${average ?? "n/a"}`);
|
|
493
|
+
}
|
|
494
|
+
});
|
|
495
|
+
program
|
|
496
|
+
.command("limits")
|
|
497
|
+
.description("Show active ingestion limits and practical corpus scaling boundaries.")
|
|
498
|
+
.option("--json", "Print machine-readable JSON.")
|
|
499
|
+
.action(async (options, command) => {
|
|
500
|
+
const cwd = projectRoot(command);
|
|
501
|
+
const report = ingestionLimits(await loadConfig(cwd));
|
|
502
|
+
if (options.json) {
|
|
503
|
+
console.log(JSON.stringify(report, null, 2));
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
console.log(`maxFileBytes=${report.maxFileBytes}`);
|
|
507
|
+
console.log(`maxFiles=${report.maxFiles ?? "unbounded"}`);
|
|
508
|
+
console.log(`maxCorpusBytes=${report.maxCorpusBytes ?? "unbounded"}`);
|
|
509
|
+
console.log(`maxPdfPages=${report.maxPdfPages}`);
|
|
510
|
+
console.log(`maxPdfTextCharacters=${report.maxPdfTextCharacters}`);
|
|
511
|
+
console.log(`maxOfficeTextEntries=${report.maxOfficeTextEntries}`);
|
|
512
|
+
console.log(`maxOfficeEntryBytes=${report.maxOfficeEntryBytes}`);
|
|
513
|
+
console.log(`maxOfficeTotalTextBytes=${report.maxOfficeTotalTextBytes}`);
|
|
514
|
+
console.log(`maxExternalTextOutputBytes=${report.maxExternalTextOutputBytes}`);
|
|
515
|
+
for (const note of report.notes) {
|
|
516
|
+
console.log(`note: ${note}`);
|
|
517
|
+
}
|
|
478
518
|
});
|
|
479
519
|
program
|
|
480
520
|
.command("status")
|
|
@@ -594,16 +634,17 @@ program
|
|
|
594
634
|
});
|
|
595
635
|
program
|
|
596
636
|
.command("chat")
|
|
597
|
-
.description("Answer with a local
|
|
637
|
+
.description("Answer with a verified local model grounded in Ragmir citations.")
|
|
598
638
|
.argument("[input...]", "Question to answer, or `setup` / `doctor`.")
|
|
599
639
|
.option("-k, --top-k <number>", "Number of passages to retrieve.", parsePositiveInt)
|
|
600
|
-
.option("--
|
|
601
|
-
.option("--
|
|
602
|
-
.option("--
|
|
603
|
-
.option("--
|
|
640
|
+
.option("--profile <profile>", "Local chat profile: lite, fast, or quality.")
|
|
641
|
+
.option("--thinking <mode>", "Thinking mode: off, standard, or deep.")
|
|
642
|
+
.option("--model-path <path>", "Local Gemma model root.")
|
|
643
|
+
.option("--offline", "Require an already verified local model.")
|
|
644
|
+
.option("--allow-remote-models", "Compatibility flag for explicit chat setup; normal answers stay local.")
|
|
645
|
+
.option("--verify", "Recompute the full model SHA256 during doctor.")
|
|
604
646
|
.option("--max-new-tokens <number>", "Maximum generated tokens.", parsePositiveInt)
|
|
605
647
|
.option("--context-limit <number>", "Maximum context characters sent to the model.", parsePositiveInt)
|
|
606
|
-
.option("--dtype <dtype>", "Transformers.js dtype. Default q4.")
|
|
607
648
|
.option("--json", "Print machine-readable JSON.")
|
|
608
649
|
.action(async (input, options, command) => {
|
|
609
650
|
const cwd = projectRoot(command);
|
|
@@ -611,17 +652,18 @@ program
|
|
|
611
652
|
const mode = chatMode(input);
|
|
612
653
|
if (mode === "doctor") {
|
|
613
654
|
const doctorOptions = { cwd };
|
|
655
|
+
addOption(doctorOptions, "profile", options.profile);
|
|
614
656
|
addOption(doctorOptions, "modelPath", options.modelPath);
|
|
657
|
+
addOption(doctorOptions, "verifyHash", options.verify);
|
|
615
658
|
const report = await chat.doctor(doctorOptions);
|
|
616
659
|
printMaybeJson(report, options.json);
|
|
617
660
|
return;
|
|
618
661
|
}
|
|
619
662
|
if (mode === "setup") {
|
|
620
663
|
const setupOptions = { cwd };
|
|
621
|
-
addOption(setupOptions, "
|
|
664
|
+
addOption(setupOptions, "profile", options.profile);
|
|
622
665
|
addOption(setupOptions, "modelPath", options.modelPath);
|
|
623
|
-
addOption(setupOptions, "
|
|
624
|
-
addOption(setupOptions, "allowRemoteModels", options.offline ? false : undefined);
|
|
666
|
+
addOption(setupOptions, "allowRemoteModels", options.offline ? false : options.allowRemoteModels);
|
|
625
667
|
const result = await chat.setupChatModel(setupOptions);
|
|
626
668
|
printMaybeJson(result, options.json);
|
|
627
669
|
return;
|
|
@@ -638,9 +680,9 @@ program
|
|
|
638
680
|
question,
|
|
639
681
|
sources: sources.map(toChatSource),
|
|
640
682
|
};
|
|
641
|
-
addOption(chatOptions, "
|
|
683
|
+
addOption(chatOptions, "profile", options.profile);
|
|
684
|
+
addOption(chatOptions, "thinking", options.thinking);
|
|
642
685
|
addOption(chatOptions, "modelPath", options.modelPath);
|
|
643
|
-
addOption(chatOptions, "dtype", options.dtype);
|
|
644
686
|
addOption(chatOptions, "allowRemoteModels", chatAllowRemoteModels(options));
|
|
645
687
|
addOption(chatOptions, "maxNewTokens", options.maxNewTokens);
|
|
646
688
|
addOption(chatOptions, "contextCharLimit", options.contextLimit);
|
|
@@ -653,9 +695,12 @@ program
|
|
|
653
695
|
return;
|
|
654
696
|
}
|
|
655
697
|
console.log(`\n${result.answer}\n`);
|
|
656
|
-
if (
|
|
698
|
+
if (!result.emptyContext && result.citationStatus !== "valid") {
|
|
699
|
+
console.error(pc.yellow(`Citation status: ${result.citationStatus}. Review the answer against the retrieved passages.`));
|
|
700
|
+
}
|
|
701
|
+
if (result.sources.length > 0) {
|
|
657
702
|
console.log(pc.dim("Sources:"));
|
|
658
|
-
for (const [index, source] of sources.entries()) {
|
|
703
|
+
for (const [index, source] of result.sources.entries()) {
|
|
659
704
|
console.log(` [${index + 1}] ${source.relativePath} chunk=${source.chunkIndex}`);
|
|
660
705
|
}
|
|
661
706
|
}
|
|
@@ -843,8 +888,17 @@ function withSearchOptions(cwd, options) {
|
|
|
843
888
|
const result = { cwd };
|
|
844
889
|
addOption(result, "topK", options.topK);
|
|
845
890
|
addOption(result, "contextRadius", options.contextRadius);
|
|
891
|
+
addPathFilters(result, options);
|
|
846
892
|
return result;
|
|
847
893
|
}
|
|
894
|
+
function addPathFilters(target, options) {
|
|
895
|
+
if (options.includePath && options.includePath.length > 0) {
|
|
896
|
+
target.includePaths = options.includePath;
|
|
897
|
+
}
|
|
898
|
+
if (options.excludePath && options.excludePath.length > 0) {
|
|
899
|
+
target.excludePaths = options.excludePath;
|
|
900
|
+
}
|
|
901
|
+
}
|
|
848
902
|
async function loadChat() {
|
|
849
903
|
const module = await import(CHAT_PACKAGE_NAME);
|
|
850
904
|
if (!isChatModule(module)) {
|
|
@@ -929,8 +983,14 @@ function printDoctor(report) {
|
|
|
929
983
|
console.log(`redactionEnabled=${report.redactionEnabled}`);
|
|
930
984
|
console.log(`accessLog=${report.accessLog}`);
|
|
931
985
|
console.log(`supportedFiles=${report.supportedFiles}`);
|
|
986
|
+
console.log(`supportedBytes=${report.supportedBytes}`);
|
|
987
|
+
console.log(`largestFileBytes=${report.largestFileBytes}`);
|
|
988
|
+
console.log(`maxFileBytes=${report.maxFileBytes}`);
|
|
932
989
|
console.log(`skippedFiles=${report.skippedFiles}`);
|
|
933
990
|
console.log(`unsupportedFiles=${report.unsupportedFiles}`);
|
|
991
|
+
console.log(`oversizedFiles=${report.oversizedFiles}`);
|
|
992
|
+
console.log(`sensitiveFiles=${report.sensitiveFiles}`);
|
|
993
|
+
console.log(`emptyTextFiles=${report.emptyTextFiles}`);
|
|
934
994
|
console.log(`indexedFiles=${report.indexedFiles}`);
|
|
935
995
|
console.log(`chunksIndexed=${report.chunksIndexed}`);
|
|
936
996
|
console.log(`missingFromIndex=${report.missingFromIndex}`);
|
|
@@ -954,7 +1014,7 @@ function printResearchReport(report) {
|
|
|
954
1014
|
console.log(`query=${report.query}`);
|
|
955
1015
|
console.log(`ready=${report.ready}`);
|
|
956
1016
|
console.log(`generatedQueries=${report.generatedQueries.length}`);
|
|
957
|
-
console.log(`audit.supportedFiles=${report.audit.supportedFiles} audit.indexedFiles=${report.audit.indexedFiles} audit.totalChunks=${report.audit.totalChunks} audit.skippedFiles=${report.audit.skippedFiles} audit.missingFromIndex=${report.audit.missingFromIndex} audit.staleInIndex=${report.audit.staleInIndex}`);
|
|
1017
|
+
console.log(`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}`);
|
|
958
1018
|
console.log(`securityWarnings=${report.securityWarnings.length}`);
|
|
959
1019
|
console.log(`sourceDiagnostics.duplicates=${report.sourceDiagnostics.duplicateCandidates.length} sourceDiagnostics.archives=${report.sourceDiagnostics.archiveCandidates.length} sourceDiagnostics.mirrors=${report.sourceDiagnostics.mirrorCandidates.length}`);
|
|
960
1020
|
if (report.sourceDiagnostics.duplicateCandidates.length > 0) {
|