grepmax 0.24.0 → 0.25.1
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/.claude-plugin/marketplace.json +1 -1
- package/README.md +15 -6
- package/dist/commands/add.js +38 -31
- package/dist/commands/config.js +22 -15
- package/dist/commands/context.js +38 -13
- package/dist/commands/doctor.js +86 -83
- package/dist/commands/extract.js +12 -1
- package/dist/commands/index.js +23 -24
- package/dist/commands/list.js +31 -14
- package/dist/commands/mcp.js +278 -143
- package/dist/commands/peek.js +16 -5
- package/dist/commands/repair.js +54 -120
- package/dist/commands/search-output.js +30 -9
- package/dist/commands/search-run.js +75 -47
- package/dist/commands/search-skeletons.js +28 -18
- package/dist/commands/search.js +45 -49
- package/dist/commands/serve.js +415 -373
- package/dist/commands/setup.js +2 -2
- package/dist/commands/similar.js +5 -5
- package/dist/commands/skeleton.js +67 -41
- package/dist/commands/status.js +11 -2
- package/dist/commands/summarize.js +6 -0
- package/dist/commands/watch.js +102 -38
- package/dist/config.js +3 -0
- package/dist/lib/daemon/daemon.js +1108 -379
- package/dist/lib/daemon/ipc-handler.js +122 -13
- package/dist/lib/daemon/mlx-server-manager.js +268 -125
- package/dist/lib/daemon/process-manager.js +7 -4
- package/dist/lib/daemon/search-handler.js +23 -9
- package/dist/lib/daemon/watcher-manager.js +353 -110
- package/dist/lib/index/batch-processor.js +231 -67
- package/dist/lib/index/embedding-generation.js +109 -0
- package/dist/lib/index/embedding-status.js +37 -0
- package/dist/lib/index/file-policy.js +273 -0
- package/dist/lib/index/ignore-patterns.js +4 -0
- package/dist/lib/index/index-config.js +18 -4
- package/dist/lib/index/syncer.js +256 -79
- package/dist/lib/index/walker.js +66 -86
- package/dist/lib/index/watcher-batch.js +9 -0
- package/dist/lib/index/watcher.js +129 -3
- package/dist/lib/llm/server.js +6 -0
- package/dist/lib/search/searcher.js +30 -19
- package/dist/lib/store/store-lease.js +473 -0
- package/dist/lib/store/vector-db.js +302 -57
- package/dist/lib/utils/blocked-roots.js +63 -0
- package/dist/lib/utils/cross-project.js +7 -3
- package/dist/lib/utils/daemon-client.js +24 -1
- package/dist/lib/utils/daemon-launcher.js +38 -13
- package/dist/lib/utils/doctor-status.js +76 -0
- package/dist/lib/utils/file-utils.js +74 -4
- package/dist/lib/utils/keyed-mutex.js +101 -0
- package/dist/lib/utils/logger.js +57 -1
- package/dist/lib/utils/mlx-hf-cache.js +114 -0
- package/dist/lib/utils/operation-coordinator.js +146 -0
- package/dist/lib/utils/path-containment.js +106 -0
- package/dist/lib/utils/process.js +44 -0
- package/dist/lib/utils/project-registry.js +351 -3
- package/dist/lib/utils/scope-filter.js +3 -9
- package/dist/lib/utils/stale-hint.js +12 -19
- package/dist/lib/utils/watcher-launcher.js +5 -1
- package/dist/lib/utils/watcher-store.js +2 -2
- package/dist/lib/workers/colbert-math.js +15 -12
- package/dist/lib/workers/embeddings/colbert.js +3 -2
- package/dist/lib/workers/embeddings/granite.js +4 -3
- package/dist/lib/workers/embeddings/mlx-client.js +59 -16
- package/dist/lib/workers/orchestrator.js +39 -8
- package/dist/lib/workers/pool.js +146 -82
- package/dist/lib/workers/process-child.js +11 -2
- package/dist/lib/workers/serialized-handler.js +10 -0
- package/dist/lib/workers/worker.js +13 -4
- package/mlx-embed-server/server.py +21 -3
- package/mlx-embed-server/summarizer.py +8 -0
- package/package.json +4 -3
- package/plugins/grepmax/.claude-plugin/plugin.json +1 -1
- package/plugins/grepmax/hooks/start.js +3 -170
package/dist/commands/doctor.js
CHANGED
|
@@ -48,9 +48,12 @@ const os = __importStar(require("node:os"));
|
|
|
48
48
|
const path = __importStar(require("node:path"));
|
|
49
49
|
const commander_1 = require("commander");
|
|
50
50
|
const config_1 = require("../config");
|
|
51
|
+
const embedding_status_1 = require("../lib/index/embedding-status");
|
|
51
52
|
const index_config_1 = require("../lib/index/index-config");
|
|
53
|
+
const doctor_status_1 = require("../lib/utils/doctor-status");
|
|
52
54
|
const exit_1 = require("../lib/utils/exit");
|
|
53
55
|
const lock_1 = require("../lib/utils/lock");
|
|
56
|
+
const mlx_hf_cache_1 = require("../lib/utils/mlx-hf-cache");
|
|
54
57
|
const project_registry_1 = require("../lib/utils/project-registry");
|
|
55
58
|
const project_root_1 = require("../lib/utils/project-root");
|
|
56
59
|
function formatSize(bytes) {
|
|
@@ -85,7 +88,7 @@ exports.doctor = new commander_1.Command("doctor")
|
|
|
85
88
|
.option("--fix", "Auto-fix detected issues (compact, prune, remove stale locks)", false)
|
|
86
89
|
.option("--agent", "Compact output for AI agents", false)
|
|
87
90
|
.action((opts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
88
|
-
var _a, _b, _c, _d, _e, _f;
|
|
91
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
89
92
|
if (!opts.agent)
|
|
90
93
|
console.log("gmax Doctor\n");
|
|
91
94
|
const root = config_1.PATHS.globalRoot;
|
|
@@ -106,33 +109,29 @@ exports.doctor = new commander_1.Command("doctor")
|
|
|
106
109
|
if (!config_1.MODEL_TIERS[globalConfig.modelTier]) {
|
|
107
110
|
console.log(`WARN Unknown model tier '${globalConfig.modelTier}', falling back to 'small'`);
|
|
108
111
|
}
|
|
109
|
-
const embedModel = globalConfig.embedMode === "gpu"
|
|
112
|
+
const embedModel = globalConfig.embedMode === "gpu"
|
|
113
|
+
? ((_b = globalConfig.mlxModel) !== null && _b !== void 0 ? _b : tier.mlxModel)
|
|
114
|
+
: tier.onnxModel;
|
|
110
115
|
if (!opts.agent) {
|
|
111
116
|
console.log(`\nEmbed mode: ${globalConfig.embedMode} | Model tier: ${globalConfig.modelTier} (${tier.vectorDim}d)`);
|
|
112
117
|
console.log(`Embed model: ${embedModel}`);
|
|
113
118
|
console.log(`ColBERT model: ${config_1.MODEL_IDS.colbert}`);
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
});
|
|
118
|
-
modelStatuses.forEach(({ id, exists }) => {
|
|
119
|
-
console.log(`${exists ? "ok" : "WARN"} ${id}: ${exists ? "downloaded" : "will download on first use"}`);
|
|
120
|
-
});
|
|
121
|
-
console.log(`\nLocal Project: ${process.cwd()}`);
|
|
122
|
-
const projectRoot = (0, project_root_1.findProjectRoot)(process.cwd());
|
|
123
|
-
if (projectRoot) {
|
|
124
|
-
console.log(`ok Project root: ${projectRoot}`);
|
|
125
|
-
console.log(` Centralized index at: ~/.gmax/lancedb/`);
|
|
126
|
-
}
|
|
127
|
-
else {
|
|
128
|
-
console.log(`INFO No index found in current directory (run 'gmax index' to create one)`);
|
|
129
|
-
}
|
|
130
|
-
// Check MLX embed server
|
|
119
|
+
// Probe the MLX embed server once, up front: the gpu-mode embed model
|
|
120
|
+
// status is derived from it (the server, not the ONNX models dir, is the
|
|
121
|
+
// source of truth in gpu mode). Reused below for the "MLX Embed" line.
|
|
131
122
|
let embedUp = false;
|
|
132
123
|
let embedError = "";
|
|
133
124
|
try {
|
|
134
125
|
const res = yield fetch("http://127.0.0.1:8100/health");
|
|
135
|
-
|
|
126
|
+
const health = (yield res.json());
|
|
127
|
+
embedUp =
|
|
128
|
+
res.ok && health.status === "ok" && health.model === embedModel;
|
|
129
|
+
if (res.ok && health.model !== embedModel) {
|
|
130
|
+
embedError = `wrong model ${String(health.model)}; expected ${embedModel}`;
|
|
131
|
+
}
|
|
132
|
+
else if (res.ok && health.status !== "ok") {
|
|
133
|
+
embedError = "invalid health response";
|
|
134
|
+
}
|
|
136
135
|
}
|
|
137
136
|
catch (err) {
|
|
138
137
|
embedError =
|
|
@@ -140,6 +139,28 @@ exports.doctor = new commander_1.Command("doctor")
|
|
|
140
139
|
? "connection refused"
|
|
141
140
|
: err.message || String(err);
|
|
142
141
|
}
|
|
142
|
+
// Embed model availability. In gpu mode the model is served by MLX from
|
|
143
|
+
// the pinned HF cache (~/.gmax/hf), never the ONNX models dir — report
|
|
144
|
+
// from the live server / HF cache. In cpu mode it's an ONNX model in
|
|
145
|
+
// ~/.gmax/models. ColBERT is always ONNX in-worker regardless of mode.
|
|
146
|
+
const onnxExists = (id) => fs.existsSync(path.join(models, ...id.split("/")));
|
|
147
|
+
const embedStatus = globalConfig.embedMode === "gpu"
|
|
148
|
+
? (0, doctor_status_1.gpuEmbedModelStatus)(embedModel, { up: embedUp }, (0, mlx_hf_cache_1.isMlxModelCached)(embedModel))
|
|
149
|
+
: (0, doctor_status_1.onnxModelStatus)(embedModel, onnxExists(embedModel));
|
|
150
|
+
const colbertStatus = (0, doctor_status_1.onnxModelStatus)(config_1.MODEL_IDS.colbert, onnxExists(config_1.MODEL_IDS.colbert));
|
|
151
|
+
for (const s of [embedStatus, colbertStatus]) {
|
|
152
|
+
console.log(`${s.symbol} ${s.message}`);
|
|
153
|
+
}
|
|
154
|
+
console.log(`\nLocal Project: ${process.cwd()}`);
|
|
155
|
+
const projectRoot = (0, project_root_1.findProjectRoot)(process.cwd());
|
|
156
|
+
if (projectRoot) {
|
|
157
|
+
console.log(`ok Project root: ${projectRoot}`);
|
|
158
|
+
console.log(` Centralized index at: ~/.gmax/lancedb/`);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
console.log(`INFO No index found in current directory (run 'gmax index' to create one)`);
|
|
162
|
+
}
|
|
163
|
+
// MLX embed server (probed once above).
|
|
143
164
|
console.log(`${embedUp ? "ok" : "WARN"} MLX Embed: ${embedUp ? "running (port 8100)" : `not running${embedError ? ` (${embedError})` : ""}`}`);
|
|
144
165
|
if (embedUp) {
|
|
145
166
|
try {
|
|
@@ -150,7 +171,7 @@ exports.doctor = new commander_1.Command("doctor")
|
|
|
150
171
|
body: JSON.stringify({ texts: ["gmax health check"] }),
|
|
151
172
|
});
|
|
152
173
|
const embedData = yield embedRes.json();
|
|
153
|
-
const dim = (
|
|
174
|
+
const dim = (_e = (_d = (_c = embedData === null || embedData === void 0 ? void 0 : embedData.vectors) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.length) !== null && _e !== void 0 ? _e : 0;
|
|
154
175
|
const ms = Date.now() - start;
|
|
155
176
|
const expectedDim = tier.vectorDim || 384;
|
|
156
177
|
if (dim === expectedDim) {
|
|
@@ -164,11 +185,13 @@ exports.doctor = new commander_1.Command("doctor")
|
|
|
164
185
|
console.log(`FAIL Embedding: test failed (${err.message || err})`);
|
|
165
186
|
}
|
|
166
187
|
}
|
|
167
|
-
// Check summarizer server
|
|
188
|
+
// Check summarizer server. Down is INFO, not WARN — opt-in, respawns on
|
|
189
|
+
// demand, idles out after 10min (see summarizerServerStatus).
|
|
168
190
|
const summarizerUp = yield fetch("http://127.0.0.1:8101/health")
|
|
169
191
|
.then((r) => r.ok)
|
|
170
192
|
.catch(() => false);
|
|
171
|
-
|
|
193
|
+
const summarizerStatus = (0, doctor_status_1.summarizerServerStatus)(summarizerUp);
|
|
194
|
+
console.log(`${summarizerStatus.symbol} ${summarizerStatus.message}`);
|
|
172
195
|
}
|
|
173
196
|
// --- Index Health ---
|
|
174
197
|
let needsOptimize = false;
|
|
@@ -193,9 +216,8 @@ exports.doctor = new commander_1.Command("doctor")
|
|
|
193
216
|
.where("length(summary) > 5")
|
|
194
217
|
.select(["id"])
|
|
195
218
|
.toArray()).length;
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
console.log(`${symbol} Summary coverage: ${withSummary}/${totalChunks} (${pct}%)`);
|
|
219
|
+
const coverage = (0, doctor_status_1.summaryCoverageStatus)(withSummary, totalChunks);
|
|
220
|
+
console.log(`${coverage.symbol} ${coverage.message}`);
|
|
199
221
|
}
|
|
200
222
|
else if (!opts.agent && totalChunks === 0) {
|
|
201
223
|
console.log("INFO No indexed chunks yet");
|
|
@@ -251,21 +273,15 @@ exports.doctor = new commander_1.Command("doctor")
|
|
|
251
273
|
? "LOW"
|
|
252
274
|
: "ok";
|
|
253
275
|
}
|
|
254
|
-
catch (
|
|
276
|
+
catch (_j) { }
|
|
255
277
|
const staleChunkerProjects = projects.filter((p) => {
|
|
256
278
|
var _a;
|
|
257
279
|
return p.status === "indexed" &&
|
|
258
280
|
((_a = p.chunkerVersion) !== null && _a !== void 0 ? _a : 1) < config_1.CONFIG.CHUNKER_VERSION;
|
|
259
281
|
});
|
|
260
|
-
// Projects whose stored embedding model/dim no longer matches the global
|
|
261
|
-
// config. Visibility only — recovery is a manual `gmax index --reset`
|
|
262
|
-
// (a dim change can't be auto-fixed in the shared fixed-dim table; that's
|
|
263
|
-
// the deferred Phase 1B re-embed work).
|
|
264
282
|
const staleEmbeddingProjects = projects.filter((p) => p.status === "indexed" &&
|
|
265
|
-
(0,
|
|
266
|
-
|
|
267
|
-
vectorDim: globalConfig.vectorDim,
|
|
268
|
-
}) !== null);
|
|
283
|
+
(0, embedding_status_1.projectEmbeddingStatus)(p, globalConfig).state === "stale");
|
|
284
|
+
const legacyEmbeddingCount = (0, embedding_status_1.countLegacyEmbeddingProjects)(projects, globalConfig);
|
|
269
285
|
if (opts.agent) {
|
|
270
286
|
const fields = [
|
|
271
287
|
"index_health",
|
|
@@ -282,6 +298,7 @@ exports.doctor = new commander_1.Command("doctor")
|
|
|
282
298
|
`orphaned=${orphanedProjects.length}`,
|
|
283
299
|
`stale_chunker=${staleChunkerProjects.length}`,
|
|
284
300
|
`stale_embedding=${staleEmbeddingProjects.length}`,
|
|
301
|
+
`legacy_embedding=${legacyEmbeddingCount}`,
|
|
285
302
|
`schema_dim=${physicalDim !== null && physicalDim !== void 0 ? physicalDim : "none"}`,
|
|
286
303
|
`schema_dim_ok=${schemaGap ? "false" : "true"}`,
|
|
287
304
|
];
|
|
@@ -304,35 +321,35 @@ exports.doctor = new commander_1.Command("doctor")
|
|
|
304
321
|
].join("\t"));
|
|
305
322
|
}
|
|
306
323
|
for (const p of staleEmbeddingProjects) {
|
|
307
|
-
const
|
|
308
|
-
|
|
309
|
-
vectorDim: globalConfig.vectorDim,
|
|
310
|
-
});
|
|
311
|
-
if (!gap)
|
|
324
|
+
const identity = (0, embedding_status_1.projectEmbeddingStatus)(p, globalConfig);
|
|
325
|
+
if (!identity.built)
|
|
312
326
|
continue;
|
|
313
327
|
console.log([
|
|
314
328
|
"stale_embedding_project",
|
|
315
329
|
`name=${p.name || path.basename(p.root)}`,
|
|
316
|
-
`indexed_model=${
|
|
317
|
-
`current_model=${
|
|
318
|
-
`indexed_dim=${
|
|
319
|
-
`current_dim=${
|
|
320
|
-
`
|
|
321
|
-
`
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
`fix=${gap.dimChanged ? config_1.REBUILD_COMMAND : `gmax index --reset (in ${p.root})`}`,
|
|
330
|
+
`indexed_model=${identity.built.tier}`,
|
|
331
|
+
`current_model=${identity.configured.tier}`,
|
|
332
|
+
`indexed_dim=${identity.built.vectorDim}`,
|
|
333
|
+
`current_dim=${identity.configured.vectorDim}`,
|
|
334
|
+
`indexed_fingerprint=${identity.built.fingerprint}`,
|
|
335
|
+
`current_fingerprint=${identity.configured.fingerprint}`,
|
|
336
|
+
"severity=breaking",
|
|
337
|
+
"fix=gmax repair --rebuild",
|
|
325
338
|
].join("\t"));
|
|
326
339
|
}
|
|
340
|
+
const legacyNotice = (0, embedding_status_1.formatLegacyEmbeddingNotice)(legacyEmbeddingCount, {
|
|
341
|
+
agent: true,
|
|
342
|
+
});
|
|
343
|
+
if (legacyNotice)
|
|
344
|
+
console.log(legacyNotice);
|
|
327
345
|
}
|
|
328
346
|
else {
|
|
329
347
|
console.log("\nIndex Health\n");
|
|
330
|
-
// Physical schema width
|
|
331
|
-
//
|
|
332
|
-
// per-project reset). Surfaced first because it's the most severe.
|
|
348
|
+
// Physical schema width mismatch remains fail-closed until the user
|
|
349
|
+
// explicitly runs the guarded whole-corpus rebuild.
|
|
333
350
|
if (schemaGap) {
|
|
334
351
|
console.log(`FAIL Schema: vector table is ${schemaGap.tableDim}d, config expects ${schemaGap.configDim}d`);
|
|
335
|
-
console.log(
|
|
352
|
+
console.log(" run 'gmax repair --rebuild' to rebuild the whole corpus");
|
|
336
353
|
}
|
|
337
354
|
else if (physicalDim) {
|
|
338
355
|
console.log(`ok Schema: vector table is ${physicalDim}d`);
|
|
@@ -392,36 +409,18 @@ exports.doctor = new commander_1.Command("doctor")
|
|
|
392
409
|
console.log(` run 'gmax index --reset' in ${p.root}`);
|
|
393
410
|
}
|
|
394
411
|
}
|
|
395
|
-
// Index built with a different embedding model/dim than the current
|
|
396
|
-
// config. A dim change is breaking (search scores are invalid until a
|
|
397
|
-
// re-embed); a same-dim model swap is additive. Recovery differs by kind:
|
|
398
|
-
// a same-dim model swap is fixed by a per-project `gmax index --reset`,
|
|
399
|
-
// but a dim change can't be — the shared table is fixed-width, so it
|
|
400
|
-
// needs the global rebuild (see the Schema check above).
|
|
401
412
|
if (staleEmbeddingProjects.length > 0) {
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
const anyBreaking = gaps.some((g) => (g === null || g === void 0 ? void 0 : g.severity) === "breaking");
|
|
407
|
-
const anyDimChange = gaps.some((g) => g === null || g === void 0 ? void 0 : g.dimChanged);
|
|
408
|
-
const headerFix = anyDimChange
|
|
409
|
-
? `run '${config_1.REBUILD_COMMAND}' (dim change needs a full rebuild)`
|
|
410
|
-
: "run 'gmax index --reset' per project";
|
|
411
|
-
console.log(`${anyBreaking ? "WARN" : "INFO"} Stale embedding: ${staleEmbeddingProjects.length} project(s) indexed with a different embedding model/dim — ${headerFix}`);
|
|
412
|
-
staleEmbeddingProjects.forEach((p, i) => {
|
|
413
|
-
const gap = gaps[i];
|
|
414
|
-
if (!gap)
|
|
413
|
+
console.log(`WARN Stale embedding: ${staleEmbeddingProjects.length} project(s) use a different embedding generation — run 'gmax repair --rebuild'`);
|
|
414
|
+
staleEmbeddingProjects.forEach((p) => {
|
|
415
|
+
const identity = (0, embedding_status_1.projectEmbeddingStatus)(p, globalConfig);
|
|
416
|
+
if (!identity.built)
|
|
415
417
|
return;
|
|
416
|
-
|
|
417
|
-
? `${gap.fromDim}d→${gap.toDim}d`
|
|
418
|
-
: `model ${gap.fromModel}→${gap.toModel}`;
|
|
419
|
-
console.log(` - ${p.name || path.basename(p.root)} (${change}, ${gap.severity})`);
|
|
420
|
-
console.log(gap.dimChanged
|
|
421
|
-
? ` run '${config_1.REBUILD_COMMAND}'`
|
|
422
|
-
: ` run 'gmax index --reset' in ${p.root}`);
|
|
418
|
+
console.log(` - ${p.name || path.basename(p.root)} (${identity.built.tier} ${identity.built.vectorDim}d → ${identity.configured.tier} ${identity.configured.vectorDim}d, breaking)`);
|
|
423
419
|
});
|
|
424
420
|
}
|
|
421
|
+
const legacyNotice = (0, embedding_status_1.formatLegacyEmbeddingNotice)(legacyEmbeddingCount);
|
|
422
|
+
if (legacyNotice)
|
|
423
|
+
console.log(legacyNotice);
|
|
425
424
|
// Projects
|
|
426
425
|
if (orphanedProjects.length > 0) {
|
|
427
426
|
console.log(`WARN Orphaned projects: ${orphanedProjects.length} (directories no longer exist)`);
|
|
@@ -452,7 +451,7 @@ exports.doctor = new commander_1.Command("doctor")
|
|
|
452
451
|
}
|
|
453
452
|
yield mc.close();
|
|
454
453
|
}
|
|
455
|
-
catch (
|
|
454
|
+
catch (_k) { }
|
|
456
455
|
}
|
|
457
456
|
}
|
|
458
457
|
// --fix auto-remediation
|
|
@@ -497,8 +496,8 @@ exports.doctor = new commander_1.Command("doctor")
|
|
|
497
496
|
if (!opts.agent)
|
|
498
497
|
console.log(`... Reindexing ${name} (--reset)...`);
|
|
499
498
|
const done = yield sendStreamingCommand({ cmd: "index", root: p.root, reset: true }, () => { }).catch((e) => ({ ok: false, error: String(e) }));
|
|
500
|
-
if (done.ok
|
|
501
|
-
(
|
|
499
|
+
if (done.ok &&
|
|
500
|
+
(!("degraded" in done) || done.degraded !== true)) {
|
|
502
501
|
const chunks = (_f = done.indexed) !== null && _f !== void 0 ? _f : 0;
|
|
503
502
|
if (opts.agent) {
|
|
504
503
|
console.log(`stale_chunker_reindexed\tname=${name}\tchunks=${chunks}`);
|
|
@@ -509,7 +508,11 @@ exports.doctor = new commander_1.Command("doctor")
|
|
|
509
508
|
fixed++;
|
|
510
509
|
}
|
|
511
510
|
else if (!opts.agent) {
|
|
512
|
-
|
|
511
|
+
const degraded = "degraded" in done && done.degraded === true;
|
|
512
|
+
const reason = degraded
|
|
513
|
+
? `${(_g = ("scanErrors" in done ? done.scanErrors : 0)) !== null && _g !== void 0 ? _g : 0} scan errors, ${(_h = ("failedFiles" in done ? done.failedFiles : 0)) !== null && _h !== void 0 ? _h : 0} file failures`
|
|
514
|
+
: done.error;
|
|
515
|
+
console.log(`FAIL ${name}: reindex failed (${reason})`);
|
|
513
516
|
}
|
|
514
517
|
}
|
|
515
518
|
}
|
package/dist/commands/extract.js
CHANGED
|
@@ -51,6 +51,7 @@ const exit_1 = require("../lib/utils/exit");
|
|
|
51
51
|
const filter_builder_1 = require("../lib/utils/filter-builder");
|
|
52
52
|
const import_extractor_1 = require("../lib/utils/import-extractor");
|
|
53
53
|
const language_1 = require("../lib/utils/language");
|
|
54
|
+
const path_containment_1 = require("../lib/utils/path-containment");
|
|
54
55
|
const project_registry_1 = require("../lib/utils/project-registry");
|
|
55
56
|
const project_root_1 = require("../lib/utils/project-root");
|
|
56
57
|
const useColors = process.stdout.isTTY && !process.env.NO_COLOR;
|
|
@@ -129,7 +130,17 @@ exports.extract = new commander_1.Command("extract")
|
|
|
129
130
|
exclude: opts.exclude,
|
|
130
131
|
});
|
|
131
132
|
const where = buildScopeWhere(scope, `array_contains(defined_symbols, '${(0, filter_builder_1.escapeSqlString)(symbol)}')`);
|
|
132
|
-
const
|
|
133
|
+
const indexedChunks = yield findSymbolChunks(vectorDb, where);
|
|
134
|
+
const chunks = indexedChunks.flatMap((chunk) => {
|
|
135
|
+
try {
|
|
136
|
+
return [
|
|
137
|
+
Object.assign(Object.assign({}, chunk), { path: (0, path_containment_1.resolveContainedFile)(projectRoot, chunk.path) }),
|
|
138
|
+
];
|
|
139
|
+
}
|
|
140
|
+
catch (_a) {
|
|
141
|
+
return [];
|
|
142
|
+
}
|
|
143
|
+
});
|
|
133
144
|
if (chunks.length === 0) {
|
|
134
145
|
console.log((0, agent_errors_1.symbolNotFoundLines)(symbol, {
|
|
135
146
|
agent: opts.agent,
|
package/dist/commands/index.js
CHANGED
|
@@ -47,7 +47,6 @@ const path = __importStar(require("node:path"));
|
|
|
47
47
|
const commander_1 = require("commander");
|
|
48
48
|
const config_1 = require("../config");
|
|
49
49
|
const grammar_loader_1 = require("../lib/index/grammar-loader");
|
|
50
|
-
const index_config_1 = require("../lib/index/index-config");
|
|
51
50
|
const sync_helpers_1 = require("../lib/index/sync-helpers");
|
|
52
51
|
const syncer_1 = require("../lib/index/syncer");
|
|
53
52
|
const setup_helpers_1 = require("../lib/setup/setup-helpers");
|
|
@@ -71,7 +70,7 @@ Examples:
|
|
|
71
70
|
gmax index --reset Full re-index from scratch
|
|
72
71
|
`)
|
|
73
72
|
.action((_args, cmd) => __awaiter(void 0, void 0, void 0, function* () {
|
|
74
|
-
var _a, _b, _c, _d, _e;
|
|
73
|
+
var _a, _b, _c, _d, _e, _f;
|
|
75
74
|
const options = cmd.optsWithGlobals();
|
|
76
75
|
let vectorDb = null;
|
|
77
76
|
const ac = new AbortController();
|
|
@@ -134,19 +133,12 @@ Examples:
|
|
|
134
133
|
spinner.succeed(`Dry run complete(${done.processed} / ${done.total}) • would have indexed ${done.indexed} `);
|
|
135
134
|
return;
|
|
136
135
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
embedMode: globalConfig.embedMode,
|
|
144
|
-
lastIndexed: new Date().toISOString(),
|
|
145
|
-
chunkCount: (_d = done.indexed) !== null && _d !== void 0 ? _d : 0,
|
|
146
|
-
status: "indexed",
|
|
147
|
-
chunkerVersion: stampedChunkerVersion,
|
|
148
|
-
});
|
|
149
|
-
const failedFiles = (_e = done.failedFiles) !== null && _e !== void 0 ? _e : 0;
|
|
136
|
+
if (done.degraded === true) {
|
|
137
|
+
spinner.warn(`Indexing incomplete • ${(_d = done.scanErrors) !== null && _d !== void 0 ? _d : 0} scan errors • ${(_e = done.failedFiles) !== null && _e !== void 0 ? _e : 0} failed`);
|
|
138
|
+
process.exitCode = 1;
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const failedFiles = (_f = done.failedFiles) !== null && _f !== void 0 ? _f : 0;
|
|
150
142
|
const failedSuffix = failedFiles > 0 ? ` • ${failedFiles} failed` : "";
|
|
151
143
|
spinner.succeed(`Indexing complete(${done.processed} / ${done.total}) • indexed ${done.indexed}${failedSuffix} `);
|
|
152
144
|
}
|
|
@@ -166,7 +158,7 @@ Examples:
|
|
|
166
158
|
try {
|
|
167
159
|
process.kill(watcher.pid, "SIGTERM");
|
|
168
160
|
}
|
|
169
|
-
catch (
|
|
161
|
+
catch (_g) { }
|
|
170
162
|
for (let i = 0; i < 50; i++) {
|
|
171
163
|
if (!(0, watcher_store_1.isProcessRunning)(watcher.pid))
|
|
172
164
|
break;
|
|
@@ -196,17 +188,24 @@ Examples:
|
|
|
196
188
|
}));
|
|
197
189
|
return;
|
|
198
190
|
}
|
|
199
|
-
|
|
200
|
-
|
|
191
|
+
if (result.degraded) {
|
|
192
|
+
spinner.warn(`Indexing incomplete • ${result.scanErrors} scan errors • ${result.failedFiles} failed`);
|
|
193
|
+
process.exitCode = 1;
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
const prefix = projectRoot.endsWith("/")
|
|
197
|
+
? projectRoot
|
|
198
|
+
: `${projectRoot}/`;
|
|
199
|
+
const chunkCount = yield vectorDb.countRowsForPath(prefix);
|
|
200
|
+
(0, project_registry_1.stampProjectFullSync)({
|
|
201
201
|
root: projectRoot,
|
|
202
202
|
name: path.basename(projectRoot),
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
lastIndexed: new Date().toISOString(),
|
|
207
|
-
chunkCount: result.indexed,
|
|
208
|
-
status: "indexed",
|
|
203
|
+
generation: result.generation,
|
|
204
|
+
embedMode: result.embedMode,
|
|
205
|
+
chunkCount,
|
|
209
206
|
chunkerVersion: stampedChunkerVersion,
|
|
207
|
+
expectedFingerprint: result.registryExpectation.embeddingFingerprint,
|
|
208
|
+
expectedRebuildId: result.registryExpectation.rebuildId,
|
|
210
209
|
});
|
|
211
210
|
const failedSuffix = result.failedFiles > 0 ? ` • ${result.failedFiles} failed` : "";
|
|
212
211
|
spinner.succeed(`Indexing complete(${result.processed} / ${result.total}) • indexed ${result.indexed}${failedSuffix} `);
|
package/dist/commands/list.js
CHANGED
|
@@ -47,6 +47,7 @@ const fs = __importStar(require("node:fs"));
|
|
|
47
47
|
const os = __importStar(require("node:os"));
|
|
48
48
|
const path = __importStar(require("node:path"));
|
|
49
49
|
const commander_1 = require("commander");
|
|
50
|
+
const embedding_status_1 = require("../lib/index/embedding-status");
|
|
50
51
|
const index_config_1 = require("../lib/index/index-config");
|
|
51
52
|
const exit_1 = require("../lib/utils/exit");
|
|
52
53
|
const project_registry_1 = require("../lib/utils/project-registry");
|
|
@@ -123,7 +124,7 @@ exports.list = new commander_1.Command("list")
|
|
|
123
124
|
}));
|
|
124
125
|
function showCurrentProject() {
|
|
125
126
|
return __awaiter(this, void 0, void 0, function* () {
|
|
126
|
-
var _a
|
|
127
|
+
var _a;
|
|
127
128
|
const projectRoot = (_a = (0, project_root_1.findProjectRoot)(process.cwd())) !== null && _a !== void 0 ? _a : process.cwd();
|
|
128
129
|
const paths = (0, project_root_1.ensureProjectPaths)(projectRoot);
|
|
129
130
|
const entries = [
|
|
@@ -132,13 +133,22 @@ function showCurrentProject() {
|
|
|
132
133
|
];
|
|
133
134
|
console.log(`\n${style.bold("Project")}: ${style.green(projectRoot)}`);
|
|
134
135
|
console.log(`${style.dim("Data directory")}: ${paths.dataDir}\n`);
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
136
|
+
const globalConfig = (0, index_config_1.readGlobalConfig)();
|
|
137
|
+
const project = (0, project_registry_1.getProject)(projectRoot);
|
|
138
|
+
if (project) {
|
|
139
|
+
const identity = (0, embedding_status_1.projectEmbeddingStatus)(project, globalConfig);
|
|
140
|
+
console.log(`${style.dim("Configured embedding")}: ${identity.configured.tier} (${identity.configured.vectorDim}d)`);
|
|
141
|
+
if (identity.built) {
|
|
142
|
+
console.log(`${style.dim("Built embedding")}: ${identity.built.tier} (${identity.built.vectorDim}d, ${identity.state})`);
|
|
143
|
+
}
|
|
144
|
+
if (identity.state === "legacy") {
|
|
145
|
+
const notice = (0, embedding_status_1.formatLegacyEmbeddingNotice)(1);
|
|
146
|
+
if (notice)
|
|
147
|
+
console.log(style.yellow(notice));
|
|
141
148
|
}
|
|
149
|
+
console.log(`${style.dim("Mode")}: ${globalConfig.embedMode}`);
|
|
150
|
+
if (project.lastIndexed)
|
|
151
|
+
console.log(`${style.dim("Indexed")}: ${formatDate(new Date(project.lastIndexed))}`);
|
|
142
152
|
console.log();
|
|
143
153
|
}
|
|
144
154
|
for (const entry of entries) {
|
|
@@ -167,17 +177,24 @@ function showAllProjects() {
|
|
|
167
177
|
// Header
|
|
168
178
|
console.log(`${style.bold(pad("Project", nameWidth))} ${style.bold(pad("Path", pathWidth))} ${style.bold("Dims")} ${style.bold("Status")}`);
|
|
169
179
|
for (const project of projects) {
|
|
170
|
-
const
|
|
180
|
+
const identity = (0, embedding_status_1.projectEmbeddingStatus)(project, globalConfig);
|
|
171
181
|
const dimsStr = `${project.vectorDim}d`;
|
|
172
|
-
const status =
|
|
173
|
-
? style.green("
|
|
174
|
-
:
|
|
182
|
+
const status = identity.state === "current"
|
|
183
|
+
? style.green("current")
|
|
184
|
+
: identity.state === "legacy"
|
|
185
|
+
? style.yellow("legacy")
|
|
186
|
+
: identity.state === "stale"
|
|
187
|
+
? style.red("stale")
|
|
188
|
+
: style.dim("unbuilt");
|
|
175
189
|
console.log(`${pad(project.name, nameWidth)} ${style.dim(pad(shortenPath(project.root), pathWidth))} ${pad(dimsStr, 4)} ${status}`);
|
|
176
190
|
}
|
|
177
191
|
console.log(`\n${style.dim("Global config")}: ${globalConfig.modelTier} (${globalConfig.vectorDim}d), ${globalConfig.embedMode}`);
|
|
178
|
-
const
|
|
179
|
-
if (
|
|
180
|
-
console.log(style.yellow(`\n${
|
|
192
|
+
const legacyNotice = (0, embedding_status_1.formatLegacyEmbeddingNotice)((0, embedding_status_1.countLegacyEmbeddingProjects)(projects, globalConfig));
|
|
193
|
+
if (legacyNotice)
|
|
194
|
+
console.log(style.yellow(`\n${legacyNotice}`));
|
|
195
|
+
const stale = projects.filter((project) => (0, embedding_status_1.projectEmbeddingStatus)(project, globalConfig).state === "stale");
|
|
196
|
+
if (stale.length > 0) {
|
|
197
|
+
console.log(style.yellow(`\n${stale.length} project(s) use a stale embedding generation. Existing indexes are preserved; run 'gmax repair --rebuild' to rebuild the whole corpus.`));
|
|
181
198
|
}
|
|
182
199
|
});
|
|
183
200
|
}
|