@vibgrate/cli 2026.803.1 → 2026.803.4

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 (106) hide show
  1. package/dist/agent-WYBWUBCC.js +26 -0
  2. package/dist/{agent-HNV2VUCO.js.map → agent-WYBWUBCC.js.map} +1 -1
  3. package/dist/baseline-3HECX4Q6.js +9 -0
  4. package/dist/{baseline-6WTULHM5.js.map → baseline-3HECX4Q6.js.map} +1 -1
  5. package/dist/{chunk-FKFRASAB.js → chunk-23UPIFRU.js} +8 -8
  6. package/dist/{chunk-FKFRASAB.js.map → chunk-23UPIFRU.js.map} +1 -1
  7. package/dist/chunk-2A7XCANX.js +375 -0
  8. package/dist/chunk-2A7XCANX.js.map +1 -0
  9. package/dist/{chunk-AJ2KE3NT.js → chunk-4LGDQBYK.js} +14 -102
  10. package/dist/chunk-4LGDQBYK.js.map +1 -0
  11. package/dist/{chunk-B2KLJPFY.js → chunk-4ZMJKR74.js} +451 -22
  12. package/dist/chunk-4ZMJKR74.js.map +1 -0
  13. package/dist/{chunk-DIU3MXB3.js → chunk-537JBQVB.js} +4 -4
  14. package/dist/{chunk-DIU3MXB3.js.map → chunk-537JBQVB.js.map} +1 -1
  15. package/dist/{chunk-4HFSUIIN.js → chunk-5TS7N7J2.js} +59 -9
  16. package/dist/chunk-5TS7N7J2.js.map +1 -0
  17. package/dist/{chunk-BWMMR5XA.js → chunk-5WMFX7TY.js} +4 -4
  18. package/dist/{chunk-BWMMR5XA.js.map → chunk-5WMFX7TY.js.map} +1 -1
  19. package/dist/{chunk-SNKTD23L.js → chunk-66B4ZQA3.js} +9 -8
  20. package/dist/chunk-66B4ZQA3.js.map +1 -0
  21. package/dist/{chunk-536J6HUR.js → chunk-7BU7CWXC.js} +39 -12
  22. package/dist/chunk-7BU7CWXC.js.map +1 -0
  23. package/dist/{chunk-N4IDP2M2.js → chunk-7TOIESUT.js} +5 -4
  24. package/dist/chunk-7TOIESUT.js.map +1 -0
  25. package/dist/{chunk-CE45STY5.js → chunk-BRUMBQV7.js} +4 -4
  26. package/dist/{chunk-CE45STY5.js.map → chunk-BRUMBQV7.js.map} +1 -1
  27. package/dist/{chunk-CC6F75GI.js → chunk-BUCNKYTW.js} +5 -5
  28. package/dist/{chunk-CC6F75GI.js.map → chunk-BUCNKYTW.js.map} +1 -1
  29. package/dist/{chunk-2TLQDF6C.js → chunk-FAA7RBIG.js} +9 -9
  30. package/dist/{chunk-2TLQDF6C.js.map → chunk-FAA7RBIG.js.map} +1 -1
  31. package/dist/chunk-FZ5Y4KEI.js +6 -0
  32. package/dist/{chunk-QT2PMGN3.js.map → chunk-FZ5Y4KEI.js.map} +1 -1
  33. package/dist/{chunk-S4NSF5AZ.js → chunk-HBQC4XQJ.js} +6 -6
  34. package/dist/{chunk-S4NSF5AZ.js.map → chunk-HBQC4XQJ.js.map} +1 -1
  35. package/dist/{chunk-O7MTBC52.js → chunk-HVHCXM2E.js} +9 -9
  36. package/dist/{chunk-O7MTBC52.js.map → chunk-HVHCXM2E.js.map} +1 -1
  37. package/dist/{chunk-NJFQCDGA.js → chunk-INIULQEP.js} +3 -3
  38. package/dist/{chunk-NJFQCDGA.js.map → chunk-INIULQEP.js.map} +1 -1
  39. package/dist/{chunk-Y7YKUZ3T.js → chunk-JZGVUH57.js} +30 -10
  40. package/dist/chunk-JZGVUH57.js.map +1 -0
  41. package/dist/{chunk-JUSXLCSE.js → chunk-KFK7KCAH.js} +3 -3
  42. package/dist/{chunk-JUSXLCSE.js.map → chunk-KFK7KCAH.js.map} +1 -1
  43. package/dist/{chunk-6I4TXAI6.js → chunk-OVDL76LB.js} +3 -3
  44. package/dist/{chunk-6I4TXAI6.js.map → chunk-OVDL76LB.js.map} +1 -1
  45. package/dist/{chunk-SJFBXCII.js → chunk-QUI3E3TQ.js} +54 -9
  46. package/dist/chunk-QUI3E3TQ.js.map +1 -0
  47. package/dist/chunk-RBMKBYGV.js +102 -0
  48. package/dist/chunk-RBMKBYGV.js.map +1 -0
  49. package/dist/{chunk-5VH3Y4QC.js → chunk-TVRM57CE.js} +78 -381
  50. package/dist/chunk-TVRM57CE.js.map +1 -0
  51. package/dist/{chunk-BBFQZ7CA.js → chunk-UWVFLVZX.js} +4 -4
  52. package/dist/{chunk-BBFQZ7CA.js.map → chunk-UWVFLVZX.js.map} +1 -1
  53. package/dist/{chunk-6JP7HGIF.js → chunk-Y4JO6LYP.js} +3 -3
  54. package/dist/{chunk-6JP7HGIF.js.map → chunk-Y4JO6LYP.js.map} +1 -1
  55. package/dist/cli.js +555 -351
  56. package/dist/cli.js.map +1 -1
  57. package/dist/embed-worker-main.d.ts +2 -0
  58. package/dist/embed-worker-main.js +64 -0
  59. package/dist/embed-worker-main.js.map +1 -0
  60. package/dist/ensure-map-DZ53QXRT.js +31 -0
  61. package/dist/{ensure-map-5YEI7R7V.js.map → ensure-map-DZ53QXRT.js.map} +1 -1
  62. package/dist/graph-backend-3A2M22QN.js +13 -0
  63. package/dist/{graph-backend-CPHLUKUC.js.map → graph-backend-3A2M22QN.js.map} +1 -1
  64. package/dist/index.d.ts +27 -2
  65. package/dist/index.js +16 -14
  66. package/dist/index.js.map +1 -1
  67. package/dist/{interactive-TNRE4OEK.js → interactive-DB7IC3BL.js} +35 -29
  68. package/dist/interactive-DB7IC3BL.js.map +1 -0
  69. package/dist/load-6KVGUQMU.js +11 -0
  70. package/dist/{load-MWG6WZTK.js.map → load-6KVGUQMU.js.map} +1 -1
  71. package/dist/{run-outcome-375HMSQG.js → run-outcome-YOYRC32U.js} +7 -6
  72. package/dist/run-outcome-YOYRC32U.js.map +1 -0
  73. package/dist/runtime-session-XEP7IPGP.js +22 -0
  74. package/dist/{runtime-session-3MPWXNRL.js.map → runtime-session-XEP7IPGP.js.map} +1 -1
  75. package/dist/session-5WKEACIF.js +17 -0
  76. package/dist/{session-2NGJLI5Y.js.map → session-5WKEACIF.js.map} +1 -1
  77. package/dist/{stream-json-AUMU3NLV.js → stream-json-3OJCPBWY.js} +13 -11
  78. package/dist/stream-json-3OJCPBWY.js.map +1 -0
  79. package/dist/{vg-mcp-bridge-D463EHQI.js → vg-mcp-bridge-PM3C4FQL.js} +12 -10
  80. package/dist/vg-mcp-bridge-PM3C4FQL.js.map +1 -0
  81. package/dist/{vgd-Z23PXSP4.js → vgd-UTLMMPIZ.js} +12 -10
  82. package/dist/vgd-UTLMMPIZ.js.map +1 -0
  83. package/package.json +1 -1
  84. package/scripts/postinstall.mjs +22 -1
  85. package/dist/agent-HNV2VUCO.js +0 -24
  86. package/dist/baseline-6WTULHM5.js +0 -9
  87. package/dist/chunk-4HFSUIIN.js.map +0 -1
  88. package/dist/chunk-536J6HUR.js.map +0 -1
  89. package/dist/chunk-5VH3Y4QC.js.map +0 -1
  90. package/dist/chunk-AJ2KE3NT.js.map +0 -1
  91. package/dist/chunk-B2KLJPFY.js.map +0 -1
  92. package/dist/chunk-N4IDP2M2.js.map +0 -1
  93. package/dist/chunk-QT2PMGN3.js +0 -6
  94. package/dist/chunk-SJFBXCII.js.map +0 -1
  95. package/dist/chunk-SNKTD23L.js.map +0 -1
  96. package/dist/chunk-Y7YKUZ3T.js.map +0 -1
  97. package/dist/ensure-map-5YEI7R7V.js +0 -29
  98. package/dist/graph-backend-CPHLUKUC.js +0 -11
  99. package/dist/interactive-TNRE4OEK.js.map +0 -1
  100. package/dist/load-MWG6WZTK.js +0 -10
  101. package/dist/run-outcome-375HMSQG.js.map +0 -1
  102. package/dist/runtime-session-3MPWXNRL.js +0 -20
  103. package/dist/session-2NGJLI5Y.js +0 -15
  104. package/dist/stream-json-AUMU3NLV.js.map +0 -1
  105. package/dist/vg-mcp-bridge-D463EHQI.js.map +0 -1
  106. package/dist/vgd-Z23PXSP4.js.map +0 -1
@@ -1,10 +1,5 @@
1
- import { cacheDir, WEAK_TERMS, expandConcepts } from './chunk-AJ2KE3NT.js';
2
- import { hashString } from './chunk-JFGYT6BI.js';
3
- import * as fs2 from 'fs';
4
- import { createRequire } from 'module';
5
- import * as os from 'os';
6
- import * as path2 from 'path';
7
- import { pathToFileURL } from 'url';
1
+ import { cosine } from './chunk-2A7XCANX.js';
2
+ import { bigramConsumedTokens, WEAK_TERMS, expandConcepts } from './chunk-4LGDQBYK.js';
8
3
 
9
4
  // src/engine/relations.ts
10
5
  var GraphIndex = class {
@@ -72,369 +67,6 @@ function indexFor(graph) {
72
67
  }
73
68
  return idx;
74
69
  }
75
- var DEFAULT_LOCK_STALE_MS = 15 * 60 * 1e3;
76
- function isProcessAlive(pid) {
77
- try {
78
- process.kill(pid, 0);
79
- return true;
80
- } catch (e) {
81
- return e.code === "EPERM";
82
- }
83
- }
84
- function lockIsStale(file, staleMs) {
85
- try {
86
- const { pid, at } = JSON.parse(fs2.readFileSync(file, "utf8"));
87
- if (typeof at === "number" && Date.now() - at > staleMs) return true;
88
- if (typeof pid === "number" && !isProcessAlive(pid)) return true;
89
- return false;
90
- } catch {
91
- return true;
92
- }
93
- }
94
- function acquireLock(file, staleMs = DEFAULT_LOCK_STALE_MS) {
95
- const write = () => {
96
- try {
97
- fs2.mkdirSync(path2.dirname(file), { recursive: true });
98
- const fd = fs2.openSync(file, "wx");
99
- fs2.writeFileSync(fd, JSON.stringify({ pid: process.pid, at: Date.now() }));
100
- fs2.closeSync(fd);
101
- return true;
102
- } catch {
103
- return false;
104
- }
105
- };
106
- if (write()) return true;
107
- if (lockIsStale(file, staleMs)) {
108
- try {
109
- fs2.rmSync(file, { force: true });
110
- } catch {
111
- }
112
- return write();
113
- }
114
- return false;
115
- }
116
- function releaseLock(file) {
117
- try {
118
- fs2.rmSync(file, { force: true });
119
- } catch {
120
- }
121
- }
122
-
123
- // src/engine/embeddings.ts
124
- function resolveEmbedModel(model) {
125
- return model ?? "bge-small-en-v1.5";
126
- }
127
- function modelCacheDir() {
128
- const base = process.env.XDG_CACHE_HOME || path2.join(os.homedir(), ".cache");
129
- return path2.join(base, "vibgrate", "models");
130
- }
131
- function modelReadyMarker(modelId) {
132
- return path2.join(modelCacheDir(), `.ready-${safe(modelId)}`);
133
- }
134
- function isModelReady(modelId = resolveEmbedModel()) {
135
- return fs2.existsSync(modelReadyMarker(modelId));
136
- }
137
- function unavailableMessage(reason) {
138
- switch (reason) {
139
- case "no-permission":
140
- return `semantic search couldn't write its model cache at ${modelCacheDir()} \u2014 using fast lexical search instead. Relocate it with the standard XDG_CACHE_HOME, or run with --local to stay lexical quietly. (No admin/sudo is ever needed \u2014 the cache lives in your home folder.)`;
141
- case "download-failed":
142
- return `the semantic model isn't downloaded yet and couldn't be fetched (offline?) \u2014 using fast lexical search. It'll try again next time; run with --local to keep lexical without retrying.`;
143
- case "not-installed":
144
- return `the optional semantic backend isn't available here \u2014 using fast lexical search.`;
145
- case "init-failed":
146
- default:
147
- return `the semantic model couldn't load \u2014 using fast lexical search.`;
148
- }
149
- }
150
- function modelCacheInfo(modelId = resolveEmbedModel()) {
151
- const dir = modelCacheDir();
152
- return { dir, present: isModelReady(modelId) || fs2.existsSync(dir), bytes: dirSize(dir) };
153
- }
154
- function clearModelCache() {
155
- const dir = modelCacheDir();
156
- const bytes = dirSize(dir);
157
- try {
158
- fs2.rmSync(dir, { recursive: true, force: true });
159
- } catch {
160
- }
161
- return bytes;
162
- }
163
- function dirSize(dir) {
164
- let total = 0;
165
- let entries;
166
- try {
167
- entries = fs2.readdirSync(dir, { withFileTypes: true });
168
- } catch {
169
- return 0;
170
- }
171
- for (const e of entries) {
172
- const p = path2.join(dir, e.name);
173
- if (e.isDirectory()) total += dirSize(p);
174
- else {
175
- try {
176
- total += fs2.statSync(p).size;
177
- } catch {
178
- }
179
- }
180
- }
181
- return total;
182
- }
183
- function isPermissionError(e) {
184
- const code = e?.code;
185
- return code === "EACCES" || code === "EPERM" || code === "EROFS";
186
- }
187
- function embeddingsCached(root, modelId) {
188
- return fs2.existsSync(path2.join(cacheDir(root), `embeddings-${safe(modelId)}.json`));
189
- }
190
- async function loadEmbedder(options = {}) {
191
- if (options.local) return null;
192
- const modelId = resolveEmbedModel(options.model);
193
- if (options.noDownload && !isModelReady(modelId)) return null;
194
- const fail = (reason) => {
195
- options.onUnavailable?.(reason);
196
- return null;
197
- };
198
- const mod = await importEmbedBackend();
199
- if (!mod?.FlagEmbedding) return fail("not-installed");
200
- const cache = modelCacheDir();
201
- try {
202
- fs2.mkdirSync(cache, { recursive: true });
203
- } catch (e) {
204
- return fail(isPermissionError(e) ? "no-permission" : "init-failed");
205
- }
206
- try {
207
- const model = await withTimeout(
208
- mod.FlagEmbedding.init({
209
- model: mapModel(mod, modelId),
210
- cacheDir: cache,
211
- showDownloadProgress: options.showDownloadProgress ?? false
212
- }),
213
- embedInitTimeoutMs(),
214
- "embedding model init timed out"
215
- );
216
- try {
217
- fs2.writeFileSync(modelReadyMarker(modelId), (/* @__PURE__ */ new Date(0)).toISOString());
218
- } catch {
219
- }
220
- return {
221
- id: modelId,
222
- async embed(texts) {
223
- const out = [];
224
- for await (const batch of model.embed(texts, 64)) {
225
- for (const v of batch) out.push(Array.from(v));
226
- }
227
- return out;
228
- },
229
- async embedQuery(text) {
230
- const v = await model.queryEmbed(text);
231
- return Array.from(v);
232
- }
233
- };
234
- } catch (e) {
235
- return fail(isPermissionError(e) ? "no-permission" : "download-failed");
236
- }
237
- }
238
- async function importEmbedBackend() {
239
- const hostDir = process.env.VIBGRATE_EMBEDDER_PATH;
240
- if (hostDir) {
241
- try {
242
- const req = createRequire(path2.join(hostDir, "package.json"));
243
- const mod = await import(pathToFileURL(req.resolve("fastembed")).href);
244
- const resolved = mod?.FlagEmbedding ? mod : mod?.default;
245
- if (resolved?.FlagEmbedding) return resolved;
246
- } catch {
247
- }
248
- }
249
- return await import('fastembed').catch(() => null);
250
- }
251
- function embedInitTimeoutMs() {
252
- const n = Number(process.env.VG_EMBED_TIMEOUT_MS);
253
- return Number.isFinite(n) && n > 0 ? n : 6e4;
254
- }
255
- async function withTimeout(promise, ms, message) {
256
- let timer;
257
- try {
258
- return await Promise.race([
259
- promise,
260
- new Promise((_, reject) => {
261
- timer = setTimeout(() => reject(new Error(message)), ms);
262
- timer.unref?.();
263
- })
264
- ]);
265
- } finally {
266
- clearTimeout(timer);
267
- }
268
- }
269
- function mapModel(mod, id) {
270
- const m = mod.EmbeddingModel ?? {};
271
- if (/bge-small/i.test(id)) return m.BGESmallENV15 ?? m.BGESmallEN ?? id;
272
- if (/bge-base/i.test(id)) return m.BGEBaseENV15 ?? id;
273
- if (/all-minilm/i.test(id)) return m.AllMiniLML6V2 ?? id;
274
- return id;
275
- }
276
- var PATH_NOISE = /* @__PURE__ */ new Set([
277
- "src",
278
- "app",
279
- "apps",
280
- "lib",
281
- "libs",
282
- "dist",
283
- "build",
284
- "out",
285
- "index",
286
- "main",
287
- "packages",
288
- "pkg",
289
- "test",
290
- "tests",
291
- "__tests__",
292
- "spec",
293
- "node_modules",
294
- "internal",
295
- "com",
296
- "example",
297
- "demo",
298
- "java",
299
- "net",
300
- "org",
301
- "www"
302
- ]);
303
- function pathContext(file) {
304
- const parts = file.split("/");
305
- const stem = (parts.pop() ?? "").replace(/\.[^.]+$/, "");
306
- const dirs = parts.filter((p) => p && !PATH_NOISE.has(p.toLowerCase()));
307
- return [...dirs.slice(-2), stem].filter(Boolean).join(" ");
308
- }
309
- function nodeEmbedText(node, areaLabel) {
310
- if (node.kind === "document") {
311
- const category = (node.signature ?? "document").replace(/^document:/, "");
312
- const categoryHints = {
313
- manifest: "package dependencies scripts install dependencies versions",
314
- docker: "dockerfile container image build runtime",
315
- compose: "docker-compose services containers networking volumes",
316
- ci: "continuous integration github actions workflow pipeline test build deploy",
317
- "build-config": "typescript tsconfig bundler vite webpack eslint prettier test",
318
- "api-contract": "openapi swagger graphql protobuf api schema endpoints",
319
- "task-runner": "makefile justfile tasks build test run commands",
320
- workspace: "monorepo workspace packages pnpm turbo nx",
321
- infra: "deploy infrastructure kubernetes kubernetes terraform helm kubernetes",
322
- "env-example": "environment variables configuration secrets template",
323
- markdown: "documentation readme guide"
324
- };
325
- const hint = categoryHints[category] ?? category;
326
- return [
327
- node.qualifiedName,
328
- "document",
329
- category,
330
- hint,
331
- pathContext(node.file),
332
- (node.doc ?? "").slice(0, 5e3)
333
- ].filter(Boolean).join("\n");
334
- }
335
- return [node.qualifiedName, node.kind, node.signature ?? "", node.doc ?? "", pathContext(node.file), areaLabel ?? ""].filter(Boolean).join(" ");
336
- }
337
- function cosine(a, b) {
338
- let dot = 0;
339
- let na = 0;
340
- let nb = 0;
341
- const n = Math.min(a.length, b.length);
342
- for (let i = 0; i < n; i++) {
343
- dot += a[i] * b[i];
344
- na += a[i] * a[i];
345
- nb += b[i] * b[i];
346
- }
347
- if (na === 0 || nb === 0) return 0;
348
- return dot / (Math.sqrt(na) * Math.sqrt(nb));
349
- }
350
- var EMBED_CHUNK = 256;
351
- var CACHE_WRITE_INTERVAL_MS = 1500;
352
- function vectorCachePath(root, modelId) {
353
- return path2.join(cacheDir(root), `embeddings-${safe(modelId)}.json`);
354
- }
355
- function countPending(graph, root, modelId) {
356
- const entries = readCacheEntries(vectorCachePath(root, modelId), modelId);
357
- const areaLabel = new Map(graph.areas.map((a) => [a.id, a.label]));
358
- let pending = 0;
359
- for (const n of graph.nodes) {
360
- if (n.kind === "file" || n.kind === "external") continue;
361
- const h = hashString(nodeEmbedText(n, areaLabel.get(n.area)));
362
- const cached = entries[n.id];
363
- if (!cached || cached.hash !== h) pending++;
364
- }
365
- return pending;
366
- }
367
- function readCacheEntries(file, modelId) {
368
- if (!fs2.existsSync(file)) return {};
369
- try {
370
- const loaded = JSON.parse(fs2.readFileSync(file, "utf8"));
371
- if (loaded.model === modelId && loaded.entries) return loaded.entries;
372
- } catch {
373
- }
374
- return {};
375
- }
376
- async function getNodeEmbeddings(graph, embedder, root, onProgress) {
377
- const file = vectorCachePath(root, embedder.id);
378
- let cache = { model: embedder.id, entries: {} };
379
- if (fs2.existsSync(file)) {
380
- try {
381
- const loaded = JSON.parse(fs2.readFileSync(file, "utf8"));
382
- if (loaded.model === embedder.id && loaded.entries) cache = loaded;
383
- } catch {
384
- }
385
- }
386
- const areaLabel = new Map(graph.areas.map((a) => [a.id, a.label]));
387
- const targets = graph.nodes.filter((n) => n.kind !== "file" && n.kind !== "external");
388
- const toEmbed = [];
389
- const vectors = /* @__PURE__ */ new Map();
390
- for (const n of targets) {
391
- const text = nodeEmbedText(n, areaLabel.get(n.area));
392
- const h = hashString(text);
393
- const cached = cache.entries[n.id];
394
- if (cached && cached.hash === h) vectors.set(n.id, cached.vec);
395
- else toEmbed.push({ id: n.id, text, hash: h });
396
- }
397
- const persist = () => {
398
- try {
399
- fs2.mkdirSync(cacheDir(root), { recursive: true });
400
- const tmp = `${file}.tmp.${process.pid}`;
401
- fs2.writeFileSync(tmp, JSON.stringify(cache));
402
- fs2.renameSync(tmp, file);
403
- } catch {
404
- }
405
- };
406
- if (toEmbed.length) {
407
- const lock = `${file}.lock`;
408
- if (!acquireLock(lock)) return vectors;
409
- try {
410
- onProgress?.(0, toEmbed.length);
411
- let lastWrite = Date.now();
412
- for (let i = 0; i < toEmbed.length; i += EMBED_CHUNK) {
413
- const slice = toEmbed.slice(i, i + EMBED_CHUNK);
414
- const vecs = await embedder.embed(slice.map((t) => t.text));
415
- slice.forEach((t, j) => {
416
- const vec = vecs[j] ?? [];
417
- vectors.set(t.id, vec);
418
- cache.entries[t.id] = { hash: t.hash, vec };
419
- });
420
- onProgress?.(Math.min(i + EMBED_CHUNK, toEmbed.length), toEmbed.length);
421
- if (Date.now() - lastWrite >= CACHE_WRITE_INTERVAL_MS) {
422
- persist();
423
- lastWrite = Date.now();
424
- }
425
- }
426
- const live = new Set(targets.map((n) => n.id));
427
- for (const id of Object.keys(cache.entries)) if (!live.has(id)) delete cache.entries[id];
428
- persist();
429
- } finally {
430
- releaseLock(lock);
431
- }
432
- }
433
- return vectors;
434
- }
435
- function safe(id) {
436
- return id.replace(/[^a-z0-9.-]+/gi, "_");
437
- }
438
70
 
439
71
  // src/engine/query.ts
440
72
  var STOPWORDS = /* @__PURE__ */ new Set([
@@ -587,7 +219,7 @@ function queryGraph(graph, question, options = {}) {
587
219
  const limit = options.limit ?? 12;
588
220
  const literals = extractLiteralNeedles(question);
589
221
  const forTokens = literals.length > 0 ? stripLiteralNeedles(question) : question;
590
- const prep = prepareTerms(forTokens, options.relevance);
222
+ const prep = prepareTerms(forTokens, options.relevance, priorResidual(options.priorQuestion));
591
223
  const weightOf = termWeights(graph, prep.terms.map((t) => t.term));
592
224
  const index = indexFor(graph);
593
225
  const scored = [];
@@ -620,7 +252,7 @@ async function queryGraphSemantic(graph, question, options) {
620
252
  const limit = options.limit ?? 12;
621
253
  const literals = extractLiteralNeedles(question);
622
254
  const forTokens = literals.length > 0 ? stripLiteralNeedles(question) : question;
623
- const prep = prepareTerms(forTokens, options.relevance);
255
+ const prep = prepareTerms(forTokens, options.relevance, priorResidual(options.priorQuestion));
624
256
  const terms = prep.terms.map((t) => t.term);
625
257
  const weightOf = termWeights(graph, terms);
626
258
  const index = indexFor(graph);
@@ -679,11 +311,13 @@ function tokenizeOrdered(q) {
679
311
  var WEAK_TERM_WEIGHT = 0.25;
680
312
  var EXPANSION_WEIGHT = 0.7;
681
313
  var COVERAGE_BONUS = 0.35;
682
- function prepareTerms(forTokens, relevance) {
314
+ var CARRY_WEIGHT = 0.5;
315
+ function prepareTerms(forTokens, relevance, prior) {
683
316
  const base = tokenize(forTokens);
684
317
  const ordered = tokenizeOrdered(forTokens);
685
318
  const baseSet = new Set(base);
686
- const terms = base.map((t) => ({ term: t, weak: WEAK_TERMS.has(t) }));
319
+ const consumed = bigramConsumedTokens(ordered);
320
+ const terms = base.map((t) => ({ term: t, weak: WEAK_TERMS.has(t) || consumed.has(t) }));
687
321
  const have = new Set(base);
688
322
  for (const e of expandConcepts(ordered)) {
689
323
  if (baseSet.has(e.term)) continue;
@@ -695,9 +329,72 @@ function prepareTerms(forTokens, relevance) {
695
329
  terms.push({ term: e.term, weak: false, from: e.from, providerWeight: e.weight });
696
330
  have.add(e.term);
697
331
  }
332
+ if (prior?.trim()) {
333
+ const priorOrdered = tokenizeOrdered(prior);
334
+ const priorConsumed = bigramConsumedTokens(priorOrdered);
335
+ for (const t of tokenize(prior)) {
336
+ if (have.has(t) || WEAK_TERMS.has(t) || priorConsumed.has(t)) continue;
337
+ terms.push({ term: t, weak: false, carried: true });
338
+ have.add(t);
339
+ }
340
+ for (const e of expandConcepts(priorOrdered)) {
341
+ if (have.has(e.term)) continue;
342
+ terms.push({ term: e.term, weak: false, from: e.from, carried: true });
343
+ have.add(e.term);
344
+ }
345
+ }
698
346
  const hasContent = terms.some((t) => !t.weak);
699
347
  return { terms, hasContent };
700
348
  }
349
+ function priorResidual(prior) {
350
+ const raw = prior?.trim();
351
+ if (!raw) return null;
352
+ return extractLiteralNeedles(raw).length > 0 ? stripLiteralNeedles(raw) : raw;
353
+ }
354
+ function conceptMapLines(question, relevance, priorQuestion) {
355
+ const cap = (xs) => [...new Set(xs)].slice(0, 8).join(", ");
356
+ const literals = extractLiteralNeedles(question);
357
+ const residual = literals.length > 0 ? stripLiteralNeedles(question) : question;
358
+ const lines = [];
359
+ const byFrom = /* @__PURE__ */ new Map();
360
+ for (const e of expandConcepts(tokenizeOrdered(residual))) {
361
+ const list = byFrom.get(e.from) ?? [];
362
+ list.push(e.term);
363
+ byFrom.set(e.from, list);
364
+ }
365
+ for (const [from, terms] of byFrom) {
366
+ lines.push(`- "${from}" in the ask implies these codebase identifiers: ${cap(terms)}.`);
367
+ }
368
+ if (relevance?.topics?.length) {
369
+ const topicVocab = /* @__PURE__ */ new Map();
370
+ for (const e of relevance.expansions ?? []) {
371
+ const list = topicVocab.get(e.from) ?? [];
372
+ list.push(e.term);
373
+ topicVocab.set(e.from, list);
374
+ }
375
+ for (const t of relevance.topics.slice(0, 3)) {
376
+ const vocab = topicVocab.get(t.id);
377
+ lines.push(
378
+ vocab?.length ? `- The ask is about the "${t.id}" domain; code for it typically uses: ${cap(vocab)}.` : `- The ask is about the "${t.id}" domain.`
379
+ );
380
+ }
381
+ }
382
+ const priorText = priorResidual(priorQuestion);
383
+ if (priorText) {
384
+ const current = new Set(tokenize(residual));
385
+ const consumed = bigramConsumedTokens(tokenizeOrdered(priorText));
386
+ const carried = tokenize(priorText).filter((t) => !current.has(t) && !WEAK_TERMS.has(t) && !consumed.has(t));
387
+ if (carried.length) {
388
+ lines.push(`- This is a follow-up; topic words carried from the previous ask: ${cap(carried)}.`);
389
+ }
390
+ }
391
+ if (lines.length) {
392
+ lines.push(
393
+ '- Seed notation below: `a\u2192b` = ask term "a" implied identifier "b"; `~t` = word-form match; `\u21A9t` = carried from the previous ask.'
394
+ );
395
+ }
396
+ return lines;
397
+ }
701
398
  function scoreNode(node, terms, weightOf = () => 1) {
702
399
  let score = 0;
703
400
  let contentHits = 0;
@@ -707,10 +404,10 @@ function scoreNode(node, terms, weightOf = () => 1) {
707
404
  const file = node.file.toLowerCase();
708
405
  const dirSegments = new Set(file.split("/").slice(0, -1));
709
406
  const nameParts = identifierParts(node.name);
710
- for (const { term: t, weak, from, providerWeight } of terms) {
407
+ for (const { term: t, weak, from, providerWeight, carried } of terms) {
711
408
  const expansionW = providerWeight !== void 0 ? Math.min(providerWeight, EXPANSION_WEIGHT) : from ? EXPANSION_WEIGHT : 1;
712
- const w = weightOf(t) * (weak ? WEAK_TERM_WEIGHT : 1) * expansionW;
713
- const label = from ? `${from}\u2192${t}` : t;
409
+ const w = weightOf(t) * (weak ? WEAK_TERM_WEIGHT : 1) * expansionW * (carried ? CARRY_WEIGHT : 1);
410
+ const label = (carried ? "\u21A9" : "") + (from ? `${from}\u2192${t}` : t);
714
411
  let contribution = 0;
715
412
  if (name === t) {
716
413
  contribution = 10 * w;
@@ -726,7 +423,7 @@ function scoreNode(node, terms, weightOf = () => 1) {
726
423
  hits.push(label);
727
424
  } else if (fuzzyPartMatch(t, nameParts)) {
728
425
  contribution = 2 * w;
729
- hits.push(from ? `~${from}\u2192${t}` : `~${t}`);
426
+ hits.push((carried ? "\u21A9" : "") + (from ? `~${from}\u2192${t}` : `~${t}`));
730
427
  } else if (dirSegments.has(t)) {
731
428
  contribution = 2 * w;
732
429
  hits.push(label);
@@ -895,6 +592,6 @@ function round2(x) {
895
592
  return Math.round(x * 1e6) / 1e6;
896
593
  }
897
594
 
898
- export { GraphIndex, acquireLock, clearModelCache, cosine, countPending, embeddingsCached, extractLiteralNeedles, getNodeEmbeddings, identifierParts, impactOf, indexFor, isLocateOnlyInstruction, isModelReady, loadEmbedder, modelCacheInfo, nodeEmbedText, queryGraph, queryGraphSemantic, releaseLock, residualForSymbolSearch, resolveEmbedModel, unavailableMessage, withTimeout };
899
- //# sourceMappingURL=chunk-5VH3Y4QC.js.map
900
- //# sourceMappingURL=chunk-5VH3Y4QC.js.map
595
+ export { GraphIndex, conceptMapLines, extractLiteralNeedles, identifierParts, impactOf, indexFor, isLocateOnlyInstruction, queryGraph, queryGraphSemantic, residualForSymbolSearch };
596
+ //# sourceMappingURL=chunk-TVRM57CE.js.map
597
+ //# sourceMappingURL=chunk-TVRM57CE.js.map