@vibgrate/cli 2026.819.2 → 2026.824.3
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/{agent-ZJRWCMR6.js → agent-6SJVWFPV.js} +12 -12
- package/dist/{agent-ZJRWCMR6.js.map → agent-6SJVWFPV.js.map} +1 -1
- package/dist/{approvals-YTUXBZWQ.js → approvals-5UBLBNJF.js} +5 -5
- package/dist/{approvals-YTUXBZWQ.js.map → approvals-5UBLBNJF.js.map} +1 -1
- package/dist/{attach-WOA25VNH.js → attach-PSGCCJMA.js} +3 -3
- package/dist/{attach-WOA25VNH.js.map → attach-PSGCCJMA.js.map} +1 -1
- package/dist/baseline-HPXACNFU.js +9 -0
- package/dist/{baseline-TVRRUZGA.js.map → baseline-HPXACNFU.js.map} +1 -1
- package/dist/{chunk-24HKTTFV.js → chunk-2IY24TTR.js} +3 -3
- package/dist/{chunk-24HKTTFV.js.map → chunk-2IY24TTR.js.map} +1 -1
- package/dist/{chunk-7BSUPHX6.js → chunk-3PNAQUZM.js} +3 -3
- package/dist/{chunk-7BSUPHX6.js.map → chunk-3PNAQUZM.js.map} +1 -1
- package/dist/{chunk-W6ASIMG5.js → chunk-4PDWV4AE.js} +10 -12
- package/dist/chunk-4PDWV4AE.js.map +1 -0
- package/dist/{chunk-2ZBLZ2S3.js → chunk-5QO2GFAE.js} +27 -23
- package/dist/chunk-5QO2GFAE.js.map +1 -0
- package/dist/{chunk-GBXOAO5V.js → chunk-5UG4UHKU.js} +40 -10
- package/dist/chunk-5UG4UHKU.js.map +1 -0
- package/dist/chunk-AGOKTI77.js +6 -0
- package/dist/{chunk-ZUZHYAJK.js.map → chunk-AGOKTI77.js.map} +1 -1
- package/dist/{chunk-C2EZIAA3.js → chunk-B5GOCQFB.js} +9 -9
- package/dist/{chunk-C2EZIAA3.js.map → chunk-B5GOCQFB.js.map} +1 -1
- package/dist/{chunk-MMJFHEZ4.js → chunk-CJ2R3LVX.js} +4 -4
- package/dist/{chunk-MMJFHEZ4.js.map → chunk-CJ2R3LVX.js.map} +1 -1
- package/dist/{chunk-2C4QT5D7.js → chunk-III7S75O.js} +53 -463
- package/dist/chunk-III7S75O.js.map +1 -0
- package/dist/{chunk-IMI2VHHZ.js → chunk-IKB5U3AH.js} +3 -3
- package/dist/{chunk-IMI2VHHZ.js.map → chunk-IKB5U3AH.js.map} +1 -1
- package/dist/{chunk-AP3JN33O.js → chunk-JL66EPZ4.js} +221 -10
- package/dist/chunk-JL66EPZ4.js.map +1 -0
- package/dist/{chunk-QE6F62FR.js → chunk-KBLKNR3V.js} +3 -3
- package/dist/{chunk-QE6F62FR.js.map → chunk-KBLKNR3V.js.map} +1 -1
- package/dist/{chunk-JPOYXG7Z.js → chunk-KRE7SXSA.js} +12 -13
- package/dist/chunk-KRE7SXSA.js.map +1 -0
- package/dist/{chunk-XW2XQM3C.js → chunk-LA4CETXN.js} +3 -3
- package/dist/{chunk-XW2XQM3C.js.map → chunk-LA4CETXN.js.map} +1 -1
- package/dist/{chunk-OGFOJG4H.js → chunk-LMHKIQA5.js} +3 -3
- package/dist/{chunk-OGFOJG4H.js.map → chunk-LMHKIQA5.js.map} +1 -1
- package/dist/{chunk-FCMWHSQ6.js → chunk-M5QSBXA6.js} +17 -4
- package/dist/chunk-M5QSBXA6.js.map +1 -0
- package/dist/{chunk-R5TQBIR6.js → chunk-QLNJ3VWO.js} +3 -3
- package/dist/{chunk-R5TQBIR6.js.map → chunk-QLNJ3VWO.js.map} +1 -1
- package/dist/{chunk-XLQ4YHS3.js → chunk-QP3P4V4I.js} +10 -8
- package/dist/chunk-QP3P4V4I.js.map +1 -0
- package/dist/{chunk-BQ6NTRRK.js → chunk-RAEHWCN6.js} +6 -6
- package/dist/{chunk-BQ6NTRRK.js.map → chunk-RAEHWCN6.js.map} +1 -1
- package/dist/{chunk-USPMMVNH.js → chunk-SGIFJIII.js} +3 -3
- package/dist/{chunk-USPMMVNH.js.map → chunk-SGIFJIII.js.map} +1 -1
- package/dist/{chunk-CBL3VY7J.js → chunk-TWWVTKA7.js} +35 -14
- package/dist/chunk-TWWVTKA7.js.map +1 -0
- package/dist/chunk-USW5WHUG.js +605 -0
- package/dist/chunk-USW5WHUG.js.map +1 -0
- package/dist/{chunk-NKKOGJ63.js → chunk-UUNEUEPQ.js} +71 -9
- package/dist/chunk-UUNEUEPQ.js.map +1 -0
- package/dist/{chunk-WPLOEFZU.js → chunk-WATYIYWP.js} +3 -3
- package/dist/{chunk-WPLOEFZU.js.map → chunk-WATYIYWP.js.map} +1 -1
- package/dist/{chunk-PJRPSYFQ.js → chunk-XHIWQGRE.js} +5 -5
- package/dist/{chunk-PJRPSYFQ.js.map → chunk-XHIWQGRE.js.map} +1 -1
- package/dist/{chunk-AQZYDFEK.js → chunk-YJ23GGAJ.js} +3 -3
- package/dist/{chunk-AQZYDFEK.js.map → chunk-YJ23GGAJ.js.map} +1 -1
- package/dist/cli.js +379 -544
- package/dist/cli.js.map +1 -1
- package/dist/{daemon-YKOEP3XA.js → daemon-AEL5N4SJ.js} +9 -9
- package/dist/{daemon-YKOEP3XA.js.map → daemon-AEL5N4SJ.js.map} +1 -1
- package/dist/embed-worker-main.js +3 -3
- package/dist/{ensure-map-BLRJDO2Y.js → ensure-map-YL5NR6UH.js} +15 -15
- package/dist/{ensure-map-BLRJDO2Y.js.map → ensure-map-YL5NR6UH.js.map} +1 -1
- package/dist/{graph-backend-NTYONTWW.js → graph-backend-LEPXFPXQ.js} +7 -7
- package/dist/{graph-backend-NTYONTWW.js.map → graph-backend-LEPXFPXQ.js.map} +1 -1
- package/dist/index.d.ts +72 -130
- package/dist/index.js +15 -15
- package/dist/{interactive-B3WTC7LB.js → interactive-YJ37ZWTA.js} +27 -26
- package/dist/interactive-YJ37ZWTA.js.map +1 -0
- package/dist/load-LT6R73IZ.js +11 -0
- package/dist/{load-AJROS77R.js.map → load-LT6R73IZ.js.map} +1 -1
- package/dist/parse-worker.js +3 -2
- package/dist/parse-worker.js.map +1 -1
- package/dist/{run-outcome-SBBSTSH3.js → run-outcome-YQBPYNEY.js} +5 -5
- package/dist/{run-outcome-SBBSTSH3.js.map → run-outcome-YQBPYNEY.js.map} +1 -1
- package/dist/{runtime-session-JYYKQVDX.js → runtime-session-JSH5UL7Z.js} +9 -9
- package/dist/{runtime-session-JYYKQVDX.js.map → runtime-session-JSH5UL7Z.js.map} +1 -1
- package/dist/{session-2ZMHZ2O6.js → session-3FLVZRMM.js} +8 -8
- package/dist/{session-2ZMHZ2O6.js.map → session-3FLVZRMM.js.map} +1 -1
- package/dist/{stream-json-ZWGB4C47.js → stream-json-VJ2O52CR.js} +12 -12
- package/dist/{stream-json-ZWGB4C47.js.map → stream-json-VJ2O52CR.js.map} +1 -1
- package/dist/version-VUTM46C5.js +4 -0
- package/dist/{version-5QIEUXU6.js.map → version-VUTM46C5.js.map} +1 -1
- package/dist/{vg-mcp-bridge-4FETMJ6M.js → vg-mcp-bridge-UUMEOJSO.js} +9 -9
- package/dist/{vg-mcp-bridge-4FETMJ6M.js.map → vg-mcp-bridge-UUMEOJSO.js.map} +1 -1
- package/dist/{vgd-R524P5BJ.js → vgd-XFT574U6.js} +8 -8
- package/dist/vgd-XFT574U6.js.map +1 -0
- package/package.json +2 -1
- package/dist/baseline-TVRRUZGA.js +0 -9
- package/dist/chunk-2C4QT5D7.js.map +0 -1
- package/dist/chunk-2ZBLZ2S3.js.map +0 -1
- package/dist/chunk-AP3JN33O.js.map +0 -1
- package/dist/chunk-CA4YQBA7.js +0 -699
- package/dist/chunk-CA4YQBA7.js.map +0 -1
- package/dist/chunk-CBL3VY7J.js.map +0 -1
- package/dist/chunk-FCMWHSQ6.js.map +0 -1
- package/dist/chunk-GBXOAO5V.js.map +0 -1
- package/dist/chunk-JPOYXG7Z.js.map +0 -1
- package/dist/chunk-NKKOGJ63.js.map +0 -1
- package/dist/chunk-W6ASIMG5.js.map +0 -1
- package/dist/chunk-XLQ4YHS3.js.map +0 -1
- package/dist/chunk-ZUZHYAJK.js +0 -6
- package/dist/interactive-B3WTC7LB.js.map +0 -1
- package/dist/load-AJROS77R.js +0 -11
- package/dist/version-5QIEUXU6.js +0 -4
- package/dist/vgd-R524P5BJ.js.map +0 -1
|
@@ -0,0 +1,605 @@
|
|
|
1
|
+
import { cosine } from './chunk-3PNAQUZM.js';
|
|
2
|
+
|
|
3
|
+
// src/engine/relations.ts
|
|
4
|
+
var GraphIndex = class {
|
|
5
|
+
constructor(graph) {
|
|
6
|
+
this.graph = graph;
|
|
7
|
+
for (const n of graph.nodes) this.nodeById.set(n.id, n);
|
|
8
|
+
for (const e of graph.edges) {
|
|
9
|
+
push(this.outById, e.src, e);
|
|
10
|
+
push(this.inById, e.dst, e);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
graph;
|
|
14
|
+
nodeById = /* @__PURE__ */ new Map();
|
|
15
|
+
outById = /* @__PURE__ */ new Map();
|
|
16
|
+
inById = /* @__PURE__ */ new Map();
|
|
17
|
+
out(id, kind) {
|
|
18
|
+
const all = this.outById.get(id) ?? [];
|
|
19
|
+
return kind ? all.filter((e) => e.kind === kind) : all;
|
|
20
|
+
}
|
|
21
|
+
in(id, kind) {
|
|
22
|
+
const all = this.inById.get(id) ?? [];
|
|
23
|
+
return kind ? all.filter((e) => e.kind === kind) : all;
|
|
24
|
+
}
|
|
25
|
+
node(id) {
|
|
26
|
+
return this.nodeById.get(id);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Resolved nodes called by `id` — invocations (`call`) plus structural
|
|
30
|
+
* dependency references (`references`, e.g. a constructor-injected field's
|
|
31
|
+
* type), since both represent real usage a caller/impact question cares
|
|
32
|
+
* about. `references` is otherwise only emitted by the precise SCIP/tsc
|
|
33
|
+
* rungs and (for Java DI wiring) the heuristic rung — never a guess.
|
|
34
|
+
*/
|
|
35
|
+
callees(id) {
|
|
36
|
+
return this.resolveTargets(this.out(id).filter(isUsageEdge), "dst");
|
|
37
|
+
}
|
|
38
|
+
/** Resolved nodes that call or structurally reference `id`. */
|
|
39
|
+
callers(id) {
|
|
40
|
+
return this.resolveTargets(this.in(id).filter(isUsageEdge), "src");
|
|
41
|
+
}
|
|
42
|
+
resolveTargets(edges, end) {
|
|
43
|
+
const out = [];
|
|
44
|
+
for (const e of edges) {
|
|
45
|
+
const node = this.nodeById.get(e[end]);
|
|
46
|
+
if (node) out.push({ edge: e, node });
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
var USAGE_KINDS = /* @__PURE__ */ new Set(["call", "references"]);
|
|
52
|
+
function isUsageEdge(e) {
|
|
53
|
+
return USAGE_KINDS.has(e.kind);
|
|
54
|
+
}
|
|
55
|
+
function push(map, key, value) {
|
|
56
|
+
const list = map.get(key);
|
|
57
|
+
if (list) list.push(value);
|
|
58
|
+
else map.set(key, [value]);
|
|
59
|
+
}
|
|
60
|
+
var INDEX_CACHE = /* @__PURE__ */ new WeakMap();
|
|
61
|
+
function indexFor(graph) {
|
|
62
|
+
let idx = INDEX_CACHE.get(graph);
|
|
63
|
+
if (!idx) {
|
|
64
|
+
idx = new GraphIndex(graph);
|
|
65
|
+
INDEX_CACHE.set(graph, idx);
|
|
66
|
+
}
|
|
67
|
+
return idx;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// src/engine/user-ask.ts
|
|
71
|
+
function userAskFromInstruction(instruction) {
|
|
72
|
+
if (!instruction) return instruction;
|
|
73
|
+
const fenced = /\n---\s*\n## User attachments\b[^\n]*\n?/;
|
|
74
|
+
const m = fenced.exec(instruction);
|
|
75
|
+
if (m && m.index != null) {
|
|
76
|
+
return instruction.slice(0, m.index).trimEnd();
|
|
77
|
+
}
|
|
78
|
+
const bare = instruction.search(/(?:^|\n)## User attachments\b/);
|
|
79
|
+
if (bare > 0) {
|
|
80
|
+
return instruction.slice(0, bare).trimEnd();
|
|
81
|
+
}
|
|
82
|
+
if (bare === 0) {
|
|
83
|
+
return "";
|
|
84
|
+
}
|
|
85
|
+
return instruction;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// src/engine/query.ts
|
|
89
|
+
var FUNCTION_WORDS = /* @__PURE__ */ new Set([
|
|
90
|
+
// Closed-class English: could only ever match by coincidence.
|
|
91
|
+
"the",
|
|
92
|
+
"a",
|
|
93
|
+
"an",
|
|
94
|
+
"is",
|
|
95
|
+
"are",
|
|
96
|
+
"was",
|
|
97
|
+
"were",
|
|
98
|
+
"be",
|
|
99
|
+
"to",
|
|
100
|
+
"of",
|
|
101
|
+
"in",
|
|
102
|
+
"on",
|
|
103
|
+
"for",
|
|
104
|
+
"and",
|
|
105
|
+
"or",
|
|
106
|
+
"where",
|
|
107
|
+
"what",
|
|
108
|
+
"which",
|
|
109
|
+
"how",
|
|
110
|
+
"do",
|
|
111
|
+
"does",
|
|
112
|
+
"did",
|
|
113
|
+
"i",
|
|
114
|
+
"we",
|
|
115
|
+
"it",
|
|
116
|
+
"this",
|
|
117
|
+
"that",
|
|
118
|
+
"with",
|
|
119
|
+
"when",
|
|
120
|
+
"who",
|
|
121
|
+
"why",
|
|
122
|
+
"can",
|
|
123
|
+
"should",
|
|
124
|
+
"my",
|
|
125
|
+
"our",
|
|
126
|
+
"you",
|
|
127
|
+
"your",
|
|
128
|
+
"from",
|
|
129
|
+
"by",
|
|
130
|
+
"at",
|
|
131
|
+
"as",
|
|
132
|
+
// Process verbs. A caller says what they want DONE with these; they never
|
|
133
|
+
// name the code it should be done to. Left in, bare `add` seeds every
|
|
134
|
+
// Add*/*Add* symbol in the repo ahead of the terms that carry the subject.
|
|
135
|
+
"add",
|
|
136
|
+
"adds",
|
|
137
|
+
"added",
|
|
138
|
+
"adding",
|
|
139
|
+
"create",
|
|
140
|
+
"creates",
|
|
141
|
+
"created",
|
|
142
|
+
"creating",
|
|
143
|
+
"make",
|
|
144
|
+
"makes",
|
|
145
|
+
"making",
|
|
146
|
+
"made",
|
|
147
|
+
"remove",
|
|
148
|
+
"removes",
|
|
149
|
+
"removed",
|
|
150
|
+
"removing",
|
|
151
|
+
"delete",
|
|
152
|
+
"deletes",
|
|
153
|
+
"deleted",
|
|
154
|
+
"deleting",
|
|
155
|
+
"update",
|
|
156
|
+
"updates",
|
|
157
|
+
"updated",
|
|
158
|
+
"updating",
|
|
159
|
+
"change",
|
|
160
|
+
"changes",
|
|
161
|
+
"changed",
|
|
162
|
+
"changing",
|
|
163
|
+
"set",
|
|
164
|
+
"sets",
|
|
165
|
+
"setting",
|
|
166
|
+
"setup",
|
|
167
|
+
"get",
|
|
168
|
+
"gets",
|
|
169
|
+
"getting",
|
|
170
|
+
"use",
|
|
171
|
+
"uses",
|
|
172
|
+
"used",
|
|
173
|
+
"using",
|
|
174
|
+
"want",
|
|
175
|
+
"wants",
|
|
176
|
+
"wanted",
|
|
177
|
+
"doing",
|
|
178
|
+
"done",
|
|
179
|
+
"support",
|
|
180
|
+
"supports",
|
|
181
|
+
"supported",
|
|
182
|
+
"supporting",
|
|
183
|
+
"enable",
|
|
184
|
+
"enables",
|
|
185
|
+
"enabled",
|
|
186
|
+
"enabling",
|
|
187
|
+
"disable",
|
|
188
|
+
"disables",
|
|
189
|
+
"disabled",
|
|
190
|
+
"disabling",
|
|
191
|
+
"allow",
|
|
192
|
+
"allows",
|
|
193
|
+
"allowed",
|
|
194
|
+
"handle",
|
|
195
|
+
"handles",
|
|
196
|
+
"handling",
|
|
197
|
+
"implement",
|
|
198
|
+
"implements",
|
|
199
|
+
"implemented",
|
|
200
|
+
"implementing",
|
|
201
|
+
"build",
|
|
202
|
+
"builds",
|
|
203
|
+
"building",
|
|
204
|
+
"built",
|
|
205
|
+
"need",
|
|
206
|
+
"needs",
|
|
207
|
+
"needed",
|
|
208
|
+
// Filler nouns and connectives: the generic scaffolding of a request.
|
|
209
|
+
"new",
|
|
210
|
+
"newly",
|
|
211
|
+
"via",
|
|
212
|
+
"through",
|
|
213
|
+
"into",
|
|
214
|
+
"onto",
|
|
215
|
+
"way",
|
|
216
|
+
"ways",
|
|
217
|
+
"thing",
|
|
218
|
+
"things",
|
|
219
|
+
"stuff",
|
|
220
|
+
"feature",
|
|
221
|
+
"features",
|
|
222
|
+
"functionality",
|
|
223
|
+
"method",
|
|
224
|
+
"methods",
|
|
225
|
+
"option",
|
|
226
|
+
"options",
|
|
227
|
+
"ability",
|
|
228
|
+
"form",
|
|
229
|
+
"forms",
|
|
230
|
+
"page",
|
|
231
|
+
"pages",
|
|
232
|
+
"screen",
|
|
233
|
+
"screens",
|
|
234
|
+
"button",
|
|
235
|
+
"buttons",
|
|
236
|
+
"help",
|
|
237
|
+
"start",
|
|
238
|
+
"begin",
|
|
239
|
+
"work",
|
|
240
|
+
"works",
|
|
241
|
+
"working",
|
|
242
|
+
"also",
|
|
243
|
+
"currently",
|
|
244
|
+
"properly",
|
|
245
|
+
"correctly",
|
|
246
|
+
"please",
|
|
247
|
+
"happens",
|
|
248
|
+
"happen",
|
|
249
|
+
"something",
|
|
250
|
+
"somewhere",
|
|
251
|
+
"step",
|
|
252
|
+
"steps",
|
|
253
|
+
"flow",
|
|
254
|
+
"process",
|
|
255
|
+
// Discovery-question scaffolding: words that FRAME the search itself
|
|
256
|
+
// ("find the code responsible for X", "explain how X works").
|
|
257
|
+
"find",
|
|
258
|
+
"code",
|
|
259
|
+
"responsible",
|
|
260
|
+
"modify",
|
|
261
|
+
"me",
|
|
262
|
+
"implementation",
|
|
263
|
+
"explain",
|
|
264
|
+
"codebase",
|
|
265
|
+
"contains",
|
|
266
|
+
"file",
|
|
267
|
+
// Bug-report framing: says something is WRONG, never what is wrong.
|
|
268
|
+
// `fix` alone lit up `export_fixed_width_records`, `out` lit up every
|
|
269
|
+
// *Router*/*rollout* symbol (vg code prompt-relevance corpus).
|
|
270
|
+
"fix",
|
|
271
|
+
"fixes",
|
|
272
|
+
"fixing",
|
|
273
|
+
"bug",
|
|
274
|
+
"bugs",
|
|
275
|
+
"broken",
|
|
276
|
+
"busted",
|
|
277
|
+
"borked",
|
|
278
|
+
"wrong",
|
|
279
|
+
"incorrect",
|
|
280
|
+
"incorrectly",
|
|
281
|
+
"figure",
|
|
282
|
+
"out",
|
|
283
|
+
"sure"
|
|
284
|
+
]);
|
|
285
|
+
function cleanUrlNeedle(raw) {
|
|
286
|
+
let s = raw.trim();
|
|
287
|
+
s = s.replace(/[.,;:!)\]}>]+$/g, "");
|
|
288
|
+
if (s.endsWith("?")) {
|
|
289
|
+
const qi = s.lastIndexOf("?");
|
|
290
|
+
if (qi === s.length - 1) s = s.slice(0, -1);
|
|
291
|
+
}
|
|
292
|
+
return s;
|
|
293
|
+
}
|
|
294
|
+
function extractLiteralNeedles(question) {
|
|
295
|
+
const out = [];
|
|
296
|
+
const seen = /* @__PURE__ */ new Set();
|
|
297
|
+
const push2 = (raw, kind) => {
|
|
298
|
+
let s = raw.trim();
|
|
299
|
+
s = kind === "url" ? cleanUrlNeedle(s) : s.replace(/[.,;:!)\]}>?]+$/g, "");
|
|
300
|
+
if (s.length < 2 || seen.has(s)) return;
|
|
301
|
+
seen.add(s);
|
|
302
|
+
out.push(s);
|
|
303
|
+
};
|
|
304
|
+
for (const m of question.matchAll(/https?:\/\/[^\s"'`<>]+/gi)) push2(m[0], "url");
|
|
305
|
+
for (const m of question.matchAll(/(["'`])((?:(?!\1)[^\\]|\\.){2,})\1/g)) {
|
|
306
|
+
push2(m[2].replace(/\\(.)/g, "$1"), "quote");
|
|
307
|
+
}
|
|
308
|
+
return out;
|
|
309
|
+
}
|
|
310
|
+
function stripLiteralNeedles(question) {
|
|
311
|
+
let s = question;
|
|
312
|
+
for (const m of question.matchAll(/https?:\/\/[^\s"'`<>]+/gi)) {
|
|
313
|
+
s = s.split(m[0]).join(" ");
|
|
314
|
+
}
|
|
315
|
+
for (const lit of extractLiteralNeedles(question)) {
|
|
316
|
+
s = s.split(lit).join(" ");
|
|
317
|
+
}
|
|
318
|
+
s = s.replace(/(["'`])\s*\1/g, " ");
|
|
319
|
+
return s.replace(/\s+/g, " ").trim();
|
|
320
|
+
}
|
|
321
|
+
function residualForSymbolSearch(question) {
|
|
322
|
+
const literals = extractLiteralNeedles(question);
|
|
323
|
+
if (literals.length === 0) return question.trim();
|
|
324
|
+
const stripped = stripLiteralNeedles(question);
|
|
325
|
+
return tokenize(stripped).length === 0 ? "" : stripped;
|
|
326
|
+
}
|
|
327
|
+
function isLocateOnlyInstruction(instruction) {
|
|
328
|
+
const q = userAskFromInstruction(instruction).trim();
|
|
329
|
+
if (!q) return false;
|
|
330
|
+
const needles = extractLiteralNeedles(q);
|
|
331
|
+
const hasLocateFrame = /\b(where\s+is|where\s+are|find\s+(all\s+|every\s+)?occurrence|find\s+occurrences|does\s+not\s+exist|locate|search\s+for)\b/i.test(
|
|
332
|
+
q
|
|
333
|
+
) || needles.length > 0 && /^https?:\/\//i.test(q);
|
|
334
|
+
const withoutExist = q.replace(/\bdoes\s+not\s+exist\b/gi, " ");
|
|
335
|
+
if (/\b(fix|edit|change|replace|implement|refactor|rename|patch|create\s+file|delete\s+file|add\s+a\b|remove\s+the\b)\b/i.test(
|
|
336
|
+
withoutExist
|
|
337
|
+
)) {
|
|
338
|
+
return false;
|
|
339
|
+
}
|
|
340
|
+
if (needles.some((n) => /^https?:\/\//i.test(n))) return true;
|
|
341
|
+
return hasLocateFrame && needles.length > 0;
|
|
342
|
+
}
|
|
343
|
+
function queryGraph(graph, question, options = {}) {
|
|
344
|
+
const budget = options.budget ?? 2e3;
|
|
345
|
+
const limit = options.limit ?? 12;
|
|
346
|
+
const literals = extractLiteralNeedles(question);
|
|
347
|
+
const index = indexFor(graph);
|
|
348
|
+
let seeds;
|
|
349
|
+
if (options.ranked) {
|
|
350
|
+
const byId = /* @__PURE__ */ new Map();
|
|
351
|
+
for (const node of graph.nodes) byId.set(node.id, node);
|
|
352
|
+
seeds = options.ranked.hasContent ? options.ranked.seeds.map((s) => {
|
|
353
|
+
const node = byId.get(s.id);
|
|
354
|
+
return node ? { node, score: s.score, why: s.why } : null;
|
|
355
|
+
}).filter((m) => m !== null).slice(0, limit) : [];
|
|
356
|
+
} else {
|
|
357
|
+
seeds = mechanicalRank(graph, question, literals).slice(0, limit);
|
|
358
|
+
}
|
|
359
|
+
const { context, tokensEstimate } = buildContext(graph, index, question, seeds, budget, literals);
|
|
360
|
+
return { question, matches: seeds, context, tokensEstimate };
|
|
361
|
+
}
|
|
362
|
+
function mechanicalRank(graph, question, literals) {
|
|
363
|
+
const forTokens = literals.length > 0 ? stripLiteralNeedles(question) : question;
|
|
364
|
+
let tokens = tokenize(forTokens);
|
|
365
|
+
if (literals.length > 0) tokens = tokens.filter((t) => !LOCATE_SCAFFOLD.has(t));
|
|
366
|
+
if (tokens.length === 0) return [];
|
|
367
|
+
const scored = [];
|
|
368
|
+
for (const node of graph.nodes) {
|
|
369
|
+
if (node.kind === "file" || node.kind === "external") continue;
|
|
370
|
+
const name = node.name.toLowerCase();
|
|
371
|
+
const qn = node.qualifiedName.toLowerCase();
|
|
372
|
+
const parts = identifierParts(node.name);
|
|
373
|
+
let score = 0;
|
|
374
|
+
const hits = [];
|
|
375
|
+
for (const t of tokens) {
|
|
376
|
+
if (name === t) {
|
|
377
|
+
score += 10;
|
|
378
|
+
hits.push(t);
|
|
379
|
+
} else if (parts.has(t)) {
|
|
380
|
+
score += 6;
|
|
381
|
+
hits.push(t);
|
|
382
|
+
} else if (t.length >= 4 && qn.includes(t)) {
|
|
383
|
+
score += 3;
|
|
384
|
+
hits.push(t);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
if (score > 0) {
|
|
388
|
+
scored.push({
|
|
389
|
+
node,
|
|
390
|
+
score: round(score * (1 + IMPORTANCE_WEIGHT * node.importance)),
|
|
391
|
+
why: `matched: ${hits.join(", ")}`
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
scored.sort((a, b) => b.score - a.score || a.node.qualifiedName.localeCompare(b.node.qualifiedName));
|
|
396
|
+
return diversifyByFile(scored);
|
|
397
|
+
}
|
|
398
|
+
function tokenize(q) {
|
|
399
|
+
return [
|
|
400
|
+
...new Set(
|
|
401
|
+
q.toLowerCase().split(/[^\p{L}\p{N}]+/u).filter((t) => t.length >= 1 && !FUNCTION_WORDS.has(t))
|
|
402
|
+
)
|
|
403
|
+
];
|
|
404
|
+
}
|
|
405
|
+
var IMPORTANCE_WEIGHT = 0.4;
|
|
406
|
+
var LOCATE_SCAFFOLD = /* @__PURE__ */ new Set([
|
|
407
|
+
"not",
|
|
408
|
+
"no",
|
|
409
|
+
"exist",
|
|
410
|
+
"exists",
|
|
411
|
+
"existing",
|
|
412
|
+
"occurrence",
|
|
413
|
+
"occurrences",
|
|
414
|
+
"occurence",
|
|
415
|
+
"occurences",
|
|
416
|
+
"find",
|
|
417
|
+
"every",
|
|
418
|
+
"place",
|
|
419
|
+
"places",
|
|
420
|
+
"string",
|
|
421
|
+
"literal",
|
|
422
|
+
"text",
|
|
423
|
+
"search",
|
|
424
|
+
"locate",
|
|
425
|
+
"look",
|
|
426
|
+
"looking",
|
|
427
|
+
"show",
|
|
428
|
+
"list",
|
|
429
|
+
"all"
|
|
430
|
+
]);
|
|
431
|
+
function diversifyByFile(matches) {
|
|
432
|
+
const seen = /* @__PURE__ */ new Set();
|
|
433
|
+
const firstPerFile = [];
|
|
434
|
+
const rest = [];
|
|
435
|
+
for (const m of matches) {
|
|
436
|
+
if (seen.has(m.node.file)) {
|
|
437
|
+
rest.push(m);
|
|
438
|
+
} else {
|
|
439
|
+
seen.add(m.node.file);
|
|
440
|
+
firstPerFile.push(m);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
return firstPerFile.concat(rest);
|
|
444
|
+
}
|
|
445
|
+
var RRF_K = 60;
|
|
446
|
+
function ranksOf(scores, nameOf) {
|
|
447
|
+
const ids = [...scores.entries()].filter(([, s]) => s > 0).sort((a, b) => b[1] - a[1] || nameOf(a[0]).localeCompare(nameOf(b[0]))).map(([id]) => id);
|
|
448
|
+
return new Map(ids.map((id, i) => [id, i + 1]));
|
|
449
|
+
}
|
|
450
|
+
async function queryGraphSemantic(graph, question, options) {
|
|
451
|
+
const budget = options.budget ?? 2e3;
|
|
452
|
+
const limit = options.limit ?? 12;
|
|
453
|
+
const literals = extractLiteralNeedles(question);
|
|
454
|
+
const forTokens = literals.length > 0 ? stripLiteralNeedles(question) : question;
|
|
455
|
+
const residualTokens = tokenize(forTokens);
|
|
456
|
+
const queryVec = options.semanticRanked ? null : await options.embedder?.embedQuery(forTokens || question);
|
|
457
|
+
const index = indexFor(graph);
|
|
458
|
+
const lexRaw = /* @__PURE__ */ new Map();
|
|
459
|
+
const whyById = /* @__PURE__ */ new Map();
|
|
460
|
+
const lexSeeds = options.ranked ? options.ranked.hasContent ? options.ranked.seeds.map((s) => ({ id: s.id, score: s.score, why: s.why })) : [] : mechanicalRank(graph, question, literals).map((m) => ({ id: m.node.id, score: m.score, why: m.why }));
|
|
461
|
+
for (const s of lexSeeds) {
|
|
462
|
+
lexRaw.set(s.id, s.score);
|
|
463
|
+
whyById.set(s.id, s.why);
|
|
464
|
+
}
|
|
465
|
+
const scored = [];
|
|
466
|
+
if (residualTokens.length > 0 || literals.length === 0) {
|
|
467
|
+
const semRaw = /* @__PURE__ */ new Map();
|
|
468
|
+
const nodeById = /* @__PURE__ */ new Map();
|
|
469
|
+
for (const node of graph.nodes) {
|
|
470
|
+
if (node.kind === "file" || node.kind === "external") continue;
|
|
471
|
+
nodeById.set(node.id, node);
|
|
472
|
+
if (options.semanticRanked || !queryVec) continue;
|
|
473
|
+
const vec = options.nodeVectors?.get(node.id);
|
|
474
|
+
const sem = vec && residualTokens.length > 0 ? Math.max(0, cosine(queryVec, vec)) : 0;
|
|
475
|
+
if (sem > 0) semRaw.set(node.id, sem);
|
|
476
|
+
}
|
|
477
|
+
if (options.semanticRanked && residualTokens.length > 0) {
|
|
478
|
+
for (const { id, score } of options.semanticRanked) {
|
|
479
|
+
if (score > 0 && nodeById.has(id)) semRaw.set(id, score);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
const nameOf = (id) => nodeById.get(id)?.qualifiedName ?? id;
|
|
483
|
+
const lexRanks = ranksOf(lexRaw, nameOf);
|
|
484
|
+
const semRanks = ranksOf(semRaw, nameOf);
|
|
485
|
+
for (const [id, node] of nodeById) {
|
|
486
|
+
const lr = lexRanks.get(id);
|
|
487
|
+
const sr = semRanks.get(id);
|
|
488
|
+
if (lr === void 0 && sr === void 0) continue;
|
|
489
|
+
const fused = (lr !== void 0 ? 1 / (RRF_K + lr) : 0) + (sr !== void 0 ? 1 / (RRF_K + sr) : 0);
|
|
490
|
+
const sem = semRaw.get(id) ?? 0;
|
|
491
|
+
const lexWhy = whyById.get(id);
|
|
492
|
+
const why = lexWhy || (sem > 0.3 ? `semantic match (${sem.toFixed(2)})` : "weak match");
|
|
493
|
+
scored.push({ node, score: round(fused * (1 + IMPORTANCE_WEIGHT * node.importance)), why });
|
|
494
|
+
}
|
|
495
|
+
scored.sort((a, b) => b.score - a.score || a.node.qualifiedName.localeCompare(b.node.qualifiedName));
|
|
496
|
+
}
|
|
497
|
+
const seeds = diversifyByFile(scored).slice(0, limit);
|
|
498
|
+
const { context, tokensEstimate } = buildContext(graph, index, question, seeds, budget, literals);
|
|
499
|
+
return { question, matches: seeds, context, tokensEstimate };
|
|
500
|
+
}
|
|
501
|
+
function identifierParts(name) {
|
|
502
|
+
return new Set(
|
|
503
|
+
name.split(/[^\p{L}\p{N}]+|(?<=[a-z0-9])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])|(?<=[\p{L}])(?=[0-9])|(?<=[0-9])(?=[\p{L}])/u).filter(Boolean).map((s) => s.toLowerCase())
|
|
504
|
+
);
|
|
505
|
+
}
|
|
506
|
+
function buildContext(graph, index, question, seeds, budget, literals = []) {
|
|
507
|
+
const lines = [];
|
|
508
|
+
lines.push(`# Context for: ${question}`);
|
|
509
|
+
lines.push("");
|
|
510
|
+
if (literals.length) {
|
|
511
|
+
lines.push("## Literal string(s) to locate (exact text, not symbol names)");
|
|
512
|
+
for (const lit of literals) lines.push(`- \`${lit}\``);
|
|
513
|
+
lines.push(
|
|
514
|
+
"_Use a quoted phrase / URL search (`search_symbols` or `search_code` with the exact needle) for occurrences. Graph symbols below (if any) are residual identifier hints only._"
|
|
515
|
+
);
|
|
516
|
+
lines.push("");
|
|
517
|
+
}
|
|
518
|
+
if (seeds.length === 0) {
|
|
519
|
+
lines.push(
|
|
520
|
+
literals.length ? "_No graph symbols matched residual terms \u2014 this is expected for a pure string/URL occurrence search. Run a literal sweep on the needle(s) above._" : "_No matching symbols found in the map. Try different terms, or `vg hubs` for the most important code._"
|
|
521
|
+
);
|
|
522
|
+
const text2 = lines.join("\n");
|
|
523
|
+
return { context: text2, tokensEstimate: estimateTokens(text2) };
|
|
524
|
+
}
|
|
525
|
+
for (const { node, why } of seeds) {
|
|
526
|
+
const block = [];
|
|
527
|
+
block.push(`## ${node.qualifiedName} (${node.kind}, ${node.file}:${node.span.start})`);
|
|
528
|
+
if (node.signature) block.push("`" + node.signature + "`");
|
|
529
|
+
const callees = index.callees(node.id).map((x) => x.node.qualifiedName);
|
|
530
|
+
const callers = index.callers(node.id).map((x) => x.node.qualifiedName);
|
|
531
|
+
if (callees.length) block.push(`calls: ${unique(callees).slice(0, 8).join(", ")}`);
|
|
532
|
+
if (callers.length) block.push(`called by: ${unique(callers).slice(0, 8).join(", ")}`);
|
|
533
|
+
block.push(`importance ${node.importance.toFixed(3)} \xB7 area #${node.area}${node.isHub ? " \xB7 hub" : ""} \xB7 ${why}`);
|
|
534
|
+
block.push("");
|
|
535
|
+
const candidate = lines.concat(block).join("\n");
|
|
536
|
+
if (estimateTokens(candidate) > budget && lines.length > 2) break;
|
|
537
|
+
lines.push(...block);
|
|
538
|
+
}
|
|
539
|
+
const text = lines.join("\n");
|
|
540
|
+
return { context: text, tokensEstimate: estimateTokens(text) };
|
|
541
|
+
}
|
|
542
|
+
function unique(xs) {
|
|
543
|
+
return [...new Set(xs)];
|
|
544
|
+
}
|
|
545
|
+
function estimateTokens(text) {
|
|
546
|
+
return Math.ceil(text.length / 4);
|
|
547
|
+
}
|
|
548
|
+
function round(x) {
|
|
549
|
+
return Math.round(x * 1e6) / 1e6;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// src/engine/impact.ts
|
|
553
|
+
var DEPEND_EDGES = /* @__PURE__ */ new Set(["call", "import", "extends", "implements", "references"]);
|
|
554
|
+
function impactOf(graph, rootId, opts = {}) {
|
|
555
|
+
const maxDepth = Math.max(1, opts.depth ?? 4);
|
|
556
|
+
const index = indexFor(graph);
|
|
557
|
+
const root = index.node(rootId);
|
|
558
|
+
const affected = /* @__PURE__ */ new Map();
|
|
559
|
+
let minEdgeConfidence = 1;
|
|
560
|
+
let frontier = [{ id: rootId, conf: 1 }];
|
|
561
|
+
for (let depth = 1; depth <= maxDepth; depth++) {
|
|
562
|
+
const nextFrontier = [];
|
|
563
|
+
for (const { id, conf } of frontier) {
|
|
564
|
+
for (const e of index.in(id)) {
|
|
565
|
+
if (!DEPEND_EDGES.has(e.kind)) continue;
|
|
566
|
+
minEdgeConfidence = Math.min(minEdgeConfidence, e.confidence);
|
|
567
|
+
const dependentId = e.src;
|
|
568
|
+
if (dependentId === rootId || affected.has(dependentId)) continue;
|
|
569
|
+
const node = index.node(dependentId);
|
|
570
|
+
if (!node) continue;
|
|
571
|
+
const conf2 = round2(conf * e.confidence * 0.9);
|
|
572
|
+
affected.set(dependentId, {
|
|
573
|
+
id: node.id,
|
|
574
|
+
name: node.qualifiedName,
|
|
575
|
+
kind: node.kind,
|
|
576
|
+
file: node.file,
|
|
577
|
+
line: node.span.start,
|
|
578
|
+
depth,
|
|
579
|
+
confidence: conf2
|
|
580
|
+
});
|
|
581
|
+
nextFrontier.push({ id: dependentId, conf: conf2 });
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
frontier = nextFrontier;
|
|
585
|
+
if (frontier.length === 0) break;
|
|
586
|
+
}
|
|
587
|
+
const items = [...affected.values()].sort(
|
|
588
|
+
(a, b) => a.depth - b.depth || b.confidence - a.confidence || a.name.localeCompare(b.name)
|
|
589
|
+
);
|
|
590
|
+
return {
|
|
591
|
+
root: { id: rootId, name: root?.qualifiedName ?? rootId },
|
|
592
|
+
depth: maxDepth,
|
|
593
|
+
affected: items,
|
|
594
|
+
direct: items.filter((i) => i.depth === 1).length,
|
|
595
|
+
transitive: items.filter((i) => i.depth > 1).length,
|
|
596
|
+
minEdgeConfidence: round2(minEdgeConfidence)
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
function round2(x) {
|
|
600
|
+
return Math.round(x * 1e6) / 1e6;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
export { GraphIndex, extractLiteralNeedles, identifierParts, impactOf, indexFor, isLocateOnlyInstruction, queryGraph, queryGraphSemantic, residualForSymbolSearch, userAskFromInstruction };
|
|
604
|
+
//# sourceMappingURL=chunk-USW5WHUG.js.map
|
|
605
|
+
//# sourceMappingURL=chunk-USW5WHUG.js.map
|