@vibgrate/cli 2026.727.3 → 2026.727.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 (62) hide show
  1. package/dist/baseline-ENCOSJYQ.js +8 -0
  2. package/dist/{baseline-ATM5MXBZ.js.map → baseline-ENCOSJYQ.js.map} +1 -1
  3. package/dist/chunk-3SDV6ADQ.js +78 -0
  4. package/dist/chunk-3SDV6ADQ.js.map +1 -0
  5. package/dist/{chunk-6JIKUDWM.js → chunk-6AXHLQBV.js} +219 -22
  6. package/dist/chunk-6AXHLQBV.js.map +1 -0
  7. package/dist/{chunk-C66GOHYB.js → chunk-FPEOIS7K.js} +58 -23
  8. package/dist/chunk-FPEOIS7K.js.map +1 -0
  9. package/dist/{chunk-OOIG3RUM.js → chunk-GYSOQH5C.js} +18 -79
  10. package/dist/chunk-GYSOQH5C.js.map +1 -0
  11. package/dist/{chunk-FFWGT55D.js → chunk-HYRAILGM.js} +3 -3
  12. package/dist/{chunk-FFWGT55D.js.map → chunk-HYRAILGM.js.map} +1 -1
  13. package/dist/{chunk-NDMDSPFX.js → chunk-KKRSQQ3A.js} +4 -3
  14. package/dist/chunk-KKRSQQ3A.js.map +1 -0
  15. package/dist/chunk-KUIBP3LU.js +101 -0
  16. package/dist/chunk-KUIBP3LU.js.map +1 -0
  17. package/dist/{chunk-OFUC6RYN.js → chunk-KXSKFQMI.js} +6 -99
  18. package/dist/chunk-KXSKFQMI.js.map +1 -0
  19. package/dist/{chunk-AVQSHIJ5.js → chunk-LJP2EPKM.js} +4 -4
  20. package/dist/{chunk-AVQSHIJ5.js.map → chunk-LJP2EPKM.js.map} +1 -1
  21. package/dist/{chunk-Z7GP7XTJ.js → chunk-MAUJTPQW.js} +5 -5
  22. package/dist/{chunk-Z7GP7XTJ.js.map → chunk-MAUJTPQW.js.map} +1 -1
  23. package/dist/{chunk-3V24O47U.js → chunk-PVZBYZZR.js} +19 -9
  24. package/dist/chunk-PVZBYZZR.js.map +1 -0
  25. package/dist/{chunk-2VFWXNS5.js → chunk-R6ZRVVZT.js} +3 -3
  26. package/dist/{chunk-2VFWXNS5.js.map → chunk-R6ZRVVZT.js.map} +1 -1
  27. package/dist/{chunk-Y23HMSWU.js → chunk-T3AYRS7J.js} +14 -7
  28. package/dist/chunk-T3AYRS7J.js.map +1 -0
  29. package/dist/chunk-YCJIIGLP.js +356 -0
  30. package/dist/chunk-YCJIIGLP.js.map +1 -0
  31. package/dist/{chunk-MAY5HLDH.js → chunk-YKVH2PGF.js} +68 -23
  32. package/dist/chunk-YKVH2PGF.js.map +1 -0
  33. package/dist/cli.js +68 -199
  34. package/dist/cli.js.map +1 -1
  35. package/dist/index.d.ts +1 -1
  36. package/dist/index.js +7 -6
  37. package/dist/index.js.map +1 -1
  38. package/dist/{interactive-INGJNSON.js → interactive-SMHVURYK.js} +44 -14
  39. package/dist/interactive-SMHVURYK.js.map +1 -0
  40. package/dist/model-manager-PN7HEDXD.js +9 -0
  41. package/dist/{model-orchestrator-TVONAUPS.js.map → model-manager-PN7HEDXD.js.map} +1 -1
  42. package/dist/{model-orchestrator-TVONAUPS.js → model-orchestrator-4VSYP4J4.js} +3 -3
  43. package/dist/model-orchestrator-4VSYP4J4.js.map +1 -0
  44. package/dist/resolve-gguf-Y6FH3CNB.js +9 -0
  45. package/dist/{resolve-gguf-VPL4YQ6J.js.map → resolve-gguf-Y6FH3CNB.js.map} +1 -1
  46. package/dist/{session-M72522AP.js → session-W3646AOV.js} +5 -4
  47. package/dist/{session-M72522AP.js.map → session-W3646AOV.js.map} +1 -1
  48. package/dist/{stream-json-6ZBUA2L3.js → stream-json-X7UQFB4T.js} +7 -6
  49. package/dist/stream-json-X7UQFB4T.js.map +1 -0
  50. package/package.json +1 -1
  51. package/dist/baseline-ATM5MXBZ.js +0 -8
  52. package/dist/chunk-3V24O47U.js.map +0 -1
  53. package/dist/chunk-6JIKUDWM.js.map +0 -1
  54. package/dist/chunk-C66GOHYB.js.map +0 -1
  55. package/dist/chunk-MAY5HLDH.js.map +0 -1
  56. package/dist/chunk-NDMDSPFX.js.map +0 -1
  57. package/dist/chunk-OFUC6RYN.js.map +0 -1
  58. package/dist/chunk-OOIG3RUM.js.map +0 -1
  59. package/dist/chunk-Y23HMSWU.js.map +0 -1
  60. package/dist/interactive-INGJNSON.js.map +0 -1
  61. package/dist/resolve-gguf-VPL4YQ6J.js +0 -8
  62. package/dist/stream-json-6ZBUA2L3.js.map +0 -1
@@ -0,0 +1,356 @@
1
+ import { isPackageInstalled, ensurePackage } from './chunk-KUIBP3LU.js';
2
+ import { isWeightCached, lookupCatalog } from './chunk-GYSOQH5C.js';
3
+ import { spawnSync } from 'child_process';
4
+
5
+ // src/runtime/model-install-plan.ts
6
+ var MODEL_INSTALL_PLAN_SCHEMA_VERSION = "model-install-plan/0";
7
+ function runtimeDepsForBackend(backend) {
8
+ const b = backend.toLowerCase();
9
+ if (b === "llama.cpp" || b === "llama-cpp" || b === "vibgrate") {
10
+ return [
11
+ {
12
+ id: "node-llama-cpp",
13
+ kind: "npm-runtime",
14
+ spec: "node-llama-cpp@^3",
15
+ reason: "in-process llama.cpp binding for the first-party / llama-cpp provider"
16
+ }
17
+ ];
18
+ }
19
+ if (b === "ollama") {
20
+ return [
21
+ {
22
+ id: "ollama",
23
+ kind: "native-binary",
24
+ binary: "ollama",
25
+ reason: "Ollama on PATH (install from https://ollama.com \u2014 third-party apps are not auto-installed)"
26
+ }
27
+ ];
28
+ }
29
+ return [];
30
+ }
31
+ function weightsChannelForBackend(backend, opts) {
32
+ const b = backend.toLowerCase();
33
+ if (b === "ollama") return "ollama";
34
+ if (b === "llama.cpp" || b === "llama-cpp" || b === "vibgrate") {
35
+ if (opts?.downloadUrl || opts?.weightsRef && lookupCatalog(opts.weightsRef)) return "vibgrate";
36
+ return "local-path";
37
+ }
38
+ if (b === "lm-studio" || b === "lmstudio" || b === "foundry-local") return "manual";
39
+ return "manual";
40
+ }
41
+ function weightsInstalled(ref, installedNames) {
42
+ const want = ref.toLowerCase();
43
+ return installedNames.some((n) => {
44
+ const have = n.toLowerCase();
45
+ return have === want || have.includes(want) || want.includes(have);
46
+ });
47
+ }
48
+ function buildModelInstallPlan(input) {
49
+ const hasBinary = input.hasBinary ?? (() => false);
50
+ const pkgInstalled = input.isPackageInstalled ?? isPackageInstalled;
51
+ const installedNames = input.installedNames ?? [];
52
+ const offline = !!input.offline;
53
+ const backend = input.backend;
54
+ const provider = providerLabel(backend);
55
+ const runtimeDeps = runtimeDepsForBackend(backend).map((dep) => {
56
+ if (dep.kind === "npm-runtime" && dep.spec) {
57
+ return { ...dep, status: pkgInstalled(dep.spec) ? "satisfied" : "missing" };
58
+ }
59
+ if (dep.kind === "native-binary" && dep.binary) {
60
+ return { ...dep, status: hasBinary(dep.binary) ? "satisfied" : "unmanaged" };
61
+ }
62
+ return { ...dep, status: "unmanaged" };
63
+ });
64
+ const channel = weightsChannelForBackend(backend, {
65
+ downloadUrl: input.downloadUrl,
66
+ weightsRef: input.weightsRef
67
+ });
68
+ const weightCached = (input.isWeightCached ?? isWeightCached)(input.weightsRef);
69
+ const catalog = lookupCatalog(input.weightsRef);
70
+ const downloadUrl = input.downloadUrl ?? catalog?.url;
71
+ let weightsStatus = "missing";
72
+ if (channel === "ollama") {
73
+ weightsStatus = weightsInstalled(input.weightsRef, installedNames) ? "satisfied" : "missing";
74
+ } else if (channel === "vibgrate") {
75
+ weightsStatus = weightCached || weightsInstalled(input.weightsRef, installedNames) || !!input.modelPath ? "satisfied" : "missing";
76
+ } else if (channel === "local-path") {
77
+ weightsStatus = weightsInstalled(input.weightsRef, installedNames) || !!input.modelPath || weightCached ? "satisfied" : "manual";
78
+ } else {
79
+ weightsStatus = weightsInstalled(input.weightsRef, installedNames) ? "satisfied" : "manual";
80
+ }
81
+ const alreadySatisfied = [];
82
+ const willInstall = [];
83
+ const willDownload = [];
84
+ const blocked = [];
85
+ for (const dep of runtimeDeps) {
86
+ if (dep.status === "satisfied") {
87
+ alreadySatisfied.push(dep.id);
88
+ continue;
89
+ }
90
+ if (dep.kind === "npm-runtime" && dep.spec && dep.status === "missing") {
91
+ if (offline) {
92
+ blocked.push({ id: dep.id, reason: `${dep.spec} needed but --local/offline forbids install` });
93
+ } else {
94
+ willInstall.push(dep.spec);
95
+ }
96
+ continue;
97
+ }
98
+ if (dep.kind === "native-binary" && dep.status === "unmanaged") {
99
+ blocked.push({
100
+ id: dep.id,
101
+ reason: dep.reason
102
+ });
103
+ }
104
+ }
105
+ if (weightsStatus === "satisfied") {
106
+ alreadySatisfied.push(`weights:${input.weightsRef}`);
107
+ } else if (weightsStatus === "missing" && (channel === "ollama" || channel === "vibgrate")) {
108
+ if (offline) {
109
+ blocked.push({ id: `weights:${input.weightsRef}`, reason: "weights missing and --local/offline forbids download" });
110
+ } else if (channel === "ollama" && runtimeDeps.some((d) => d.id === "ollama" && d.status === "unmanaged")) {
111
+ willDownload.push(input.weightsRef);
112
+ } else if (channel === "vibgrate" && !downloadUrl) {
113
+ blocked.push({
114
+ id: `weights:${input.weightsRef}`,
115
+ reason: `no first-party download URL for ${input.weightsRef} \u2014 place a gguf in the weight store or pass --model-path`
116
+ });
117
+ } else {
118
+ willDownload.push(input.weightsRef);
119
+ }
120
+ } else if (weightsStatus === "manual" || weightsStatus === "missing") {
121
+ blocked.push({
122
+ id: `weights:${input.weightsRef}`,
123
+ reason: channel === "local-path" ? `point --model-path at a local gguf for ${input.weightsRef}, or run install when a first-party URL is catalogued` : `install or link weights for ${input.weightsRef} via the backend app`
124
+ });
125
+ }
126
+ const effectiveWillInstall = offline ? [] : willInstall;
127
+ const effectiveWillDownload = offline ? [] : willDownload;
128
+ const offlineBlocked = offline && blocked.some((b) => /offline|forbids/i.test(b.reason));
129
+ const allRuntimeOk = runtimeDeps.every((d) => d.status === "satisfied");
130
+ const fullyReady = allRuntimeOk && weightsStatus === "satisfied" && blocked.length === 0;
131
+ return {
132
+ schemaVersion: MODEL_INSTALL_PLAN_SCHEMA_VERSION,
133
+ provider,
134
+ backend,
135
+ model: input.weightsRef,
136
+ mode: input.mode,
137
+ packId: input.packId,
138
+ license: input.license,
139
+ promise: input.promise,
140
+ fit: input.fit,
141
+ runtimeDeps,
142
+ weights: {
143
+ channel,
144
+ ref: input.weightsRef,
145
+ status: weightsStatus,
146
+ downloadUrl: channel === "vibgrate" ? downloadUrl : void 0
147
+ },
148
+ alreadySatisfied,
149
+ willInstall: effectiveWillInstall,
150
+ willDownload: effectiveWillDownload,
151
+ blocked,
152
+ offlineBlocked,
153
+ ready: fullyReady
154
+ };
155
+ }
156
+ function providerLabel(backend) {
157
+ const b = backend.toLowerCase();
158
+ if (b === "llama.cpp" || b === "llama-cpp") return "llama-cpp";
159
+ if (b === "vibgrate") return "vibgrate";
160
+ if (b === "lm-studio" || b === "lmstudio") return "lmstudio";
161
+ if (b === "foundry-local") return "foundry-local";
162
+ return b === "ollama" ? "ollama" : backend;
163
+ }
164
+
165
+ // src/runtime/model-manager.ts
166
+ var LABELS = {
167
+ vibgrate: {
168
+ label: "Vibgrate",
169
+ note: "Code Mode \xB7 first-party model manager (embedded inference)"
170
+ },
171
+ ollama: {
172
+ label: "Ollama",
173
+ note: "Custom local \xB7 Ollama"
174
+ },
175
+ lmstudio: {
176
+ label: "LM Studio",
177
+ note: "Custom local \xB7 LM Studio"
178
+ },
179
+ "foundry-local": {
180
+ label: "Foundry Local",
181
+ note: "Custom local \xB7 Foundry Local"
182
+ },
183
+ openrouter: {
184
+ label: "OpenRouter",
185
+ note: "Custom hosted \xB7 OpenRouter"
186
+ },
187
+ litellm: {
188
+ label: "LiteLLM",
189
+ note: "Custom hosted \xB7 LiteLLM"
190
+ },
191
+ openai: {
192
+ label: "OpenAI",
193
+ note: "Custom hosted \xB7 OpenAI"
194
+ },
195
+ together: {
196
+ label: "Together",
197
+ note: "Custom hosted \xB7 Together"
198
+ },
199
+ mock: {
200
+ label: "Mock",
201
+ note: "Scripted offline provider"
202
+ },
203
+ other: {
204
+ label: "Custom",
205
+ note: "Custom model backend"
206
+ }
207
+ };
208
+ function managerFromProviderId(providerId) {
209
+ const id = (providerId ?? "").toLowerCase().trim();
210
+ if (id === "llama-cpp" || id === "llama.cpp" || id === "vibgrate" || id === "vibgrate-store") return "vibgrate";
211
+ if (id === "ollama") return "ollama";
212
+ if (id === "lmstudio" || id === "lm-studio") return "lmstudio";
213
+ if (id === "foundry-local" || id === "foundry") return "foundry-local";
214
+ if (id === "openrouter") return "openrouter";
215
+ if (id === "litellm") return "litellm";
216
+ if (id === "openai") return "openai";
217
+ if (id === "together") return "together";
218
+ if (id === "mock" || id === "scripted") return "mock";
219
+ return "other";
220
+ }
221
+ function managerBadge(id) {
222
+ const meta = LABELS[id] ?? LABELS.other;
223
+ return {
224
+ id,
225
+ label: meta.label,
226
+ badge: `[${meta.label}]`,
227
+ note: meta.note
228
+ };
229
+ }
230
+ function formatManagerBadgeLine(id, model) {
231
+ const b = managerBadge(id);
232
+ const modelPart = model ? ` \xB7 ${model}` : "";
233
+ return `${b.badge} ${b.note}${modelPart}`;
234
+ }
235
+ function defaultHasBinary(name) {
236
+ const res = spawnSync(name, ["--version"], { stdio: "ignore", encoding: "utf8" });
237
+ if (res.status === 0) return true;
238
+ const which = spawnSync(process.platform === "win32" ? "where" : "which", [name], {
239
+ stdio: "ignore",
240
+ encoding: "utf8"
241
+ });
242
+ return which.status === 0;
243
+ }
244
+ async function ensureManagerRuntime(opts) {
245
+ const manager = managerFromProviderId(opts.providerId);
246
+ const badge = managerBadge(manager);
247
+ const installed = [];
248
+ const pulled = [];
249
+ const messages = [];
250
+ const ensure = opts.ensurePackage ?? ensurePackage;
251
+ const hasBinary = opts.hasBinary ?? defaultHasBinary;
252
+ if (manager === "openrouter" || manager === "litellm" || manager === "openai" || manager === "together" || manager === "mock") {
253
+ return { ok: true, manager, badge, installed, pulled, messages };
254
+ }
255
+ if (manager === "lmstudio" || manager === "foundry-local") {
256
+ messages.push(
257
+ manager === "lmstudio" ? "LM Studio must already be running with a model loaded (we never install the app)" : "Foundry Local must already be running (we never install the app)"
258
+ );
259
+ return { ok: true, manager, badge, installed, pulled, messages };
260
+ }
261
+ const backend = manager === "vibgrate" ? "llama.cpp" : manager === "ollama" ? "ollama" : opts.providerId;
262
+ const deps = runtimeDepsForBackend(backend);
263
+ for (const dep of deps) {
264
+ if (dep.kind === "npm-runtime" && dep.spec) {
265
+ if (isPackageInstalled(dep.spec)) {
266
+ messages.push(`${dep.id} already installed`);
267
+ continue;
268
+ }
269
+ if (opts.offline) {
270
+ return {
271
+ ok: false,
272
+ manager,
273
+ badge,
274
+ installed,
275
+ pulled,
276
+ messages,
277
+ error: `${dep.spec} needed but offline/--local forbids install`
278
+ };
279
+ }
280
+ if (!opts.consent) {
281
+ return {
282
+ ok: false,
283
+ manager,
284
+ badge,
285
+ installed,
286
+ pulled,
287
+ messages,
288
+ error: `${dep.spec} needed \u2014 pass --yes or run \`vg models install\` once`
289
+ };
290
+ }
291
+ opts.onProgress?.(`installing ${dep.spec}`);
292
+ const ensureOpts = {
293
+ consent: true,
294
+ local: false,
295
+ interactive: false
296
+ };
297
+ const res = await ensure(dep.spec, ensureOpts);
298
+ if (!res.module) {
299
+ return {
300
+ ok: false,
301
+ manager,
302
+ badge,
303
+ installed,
304
+ pulled,
305
+ messages,
306
+ error: `couldn't install ${dep.spec}`
307
+ };
308
+ }
309
+ installed.push(dep.spec);
310
+ continue;
311
+ }
312
+ if (dep.kind === "native-binary" && dep.binary) {
313
+ if (!hasBinary(dep.binary)) {
314
+ return {
315
+ ok: false,
316
+ manager,
317
+ badge,
318
+ installed,
319
+ pulled,
320
+ messages,
321
+ error: dep.reason || `${dep.binary} is not on PATH \u2014 install it once, then re-run (vg never auto-installs third-party apps)`
322
+ };
323
+ }
324
+ messages.push(`${dep.binary} on PATH`);
325
+ }
326
+ }
327
+ if (manager === "ollama" && opts.model && opts.consent && !opts.offline) {
328
+ const list = spawnSync("ollama", ["list"], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
329
+ const have = list.status === 0 && (list.stdout ?? "").split("\n").slice(1).some((line) => {
330
+ const name = line.trim().split(/\s+/)[0]?.toLowerCase();
331
+ return name === opts.model.toLowerCase() || name?.startsWith(`${opts.model.toLowerCase()}:`);
332
+ });
333
+ if (!have) {
334
+ opts.onProgress?.(`pulling ${opts.model}`);
335
+ const pull = opts.ollamaPull ?? ((name) => spawnSync("ollama", ["pull", name], { stdio: "ignore" }).status ?? 1);
336
+ const status = pull(opts.model);
337
+ if (status !== 0) {
338
+ return {
339
+ ok: false,
340
+ manager,
341
+ badge,
342
+ installed,
343
+ pulled,
344
+ messages,
345
+ error: `ollama pull ${opts.model} failed (exit ${status})`
346
+ };
347
+ }
348
+ pulled.push(opts.model);
349
+ }
350
+ }
351
+ return { ok: true, manager, badge, installed, pulled, messages };
352
+ }
353
+
354
+ export { buildModelInstallPlan, ensureManagerRuntime, formatManagerBadgeLine, managerBadge, managerFromProviderId };
355
+ //# sourceMappingURL=chunk-YCJIIGLP.js.map
356
+ //# sourceMappingURL=chunk-YCJIIGLP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime/model-install-plan.ts","../src/runtime/model-manager.ts"],"names":[],"mappings":"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","file":"chunk-YCJIIGLP.js","sourcesContent":["/**\n * Model install plan — pure dependency closure for a provider + pack/weights.\n *\n * Used by `vg models install` / `pull` (and hosts that mirror them). Planning is\n * side-effect free; execution lives in `model-install.ts`.\n *\n * schemaVersion: model-install-plan/0\n */\n\nimport { isPackageInstalled } from '../code/ensure.js';\nimport type { PackWeightsRef } from './model-orchestrator.js';\nimport { isWeightCached, lookupCatalog } from './weight-store.js';\n\nexport const MODEL_INSTALL_PLAN_SCHEMA_VERSION = 'model-install-plan/0' as const;\n\nexport type RuntimeDepKind = 'npm-runtime' | 'native-binary' | 'weights';\n\n/** Dep/weight readiness: `manual` = user must supply path/app (we do not auto-fetch). */\nexport type DepStatus = 'satisfied' | 'missing' | 'unmanaged' | 'manual';\n\nexport interface ProviderRuntimeDep {\n id: string;\n kind: RuntimeDepKind;\n /** npm install spec, e.g. `node-llama-cpp@^3`. */\n spec?: string;\n /** PATH binary name for native-binary deps. */\n binary?: string;\n /** One-line human reason. */\n reason: string;\n /** When true, npm install may need scripts (surfaced in plan only). */\n requiresInstallScripts?: boolean;\n}\n\nexport interface PlannedDep extends ProviderRuntimeDep {\n status: DepStatus;\n}\n\nexport interface ModelInstallPlan {\n schemaVersion: typeof MODEL_INSTALL_PLAN_SCHEMA_VERSION;\n provider: string;\n backend: string;\n model: string;\n mode?: string;\n packId?: string;\n license?: string;\n promise?: string;\n fit?: string;\n runtimeDeps: PlannedDep[];\n weights: {\n channel: 'ollama' | 'local-path' | 'manual' | 'vibgrate';\n ref: string;\n status: DepStatus;\n /** First-party or pack download URL when channel is vibgrate. */\n downloadUrl?: string;\n };\n /** Ids already present (runtime + weights). */\n alreadySatisfied: string[];\n /** npm specs / binary ids we will install (never third-party apps). */\n willInstall: string[];\n /** Weight refs we will download via the backend channel. */\n willDownload: string[];\n /** Things the user must fix outside vg (e.g. install Ollama.app). */\n blocked: Array<{ id: string; reason: string }>;\n offlineBlocked: boolean;\n /** True when nothing remains to install/download and nothing is blocked. */\n ready: boolean;\n}\n\nexport interface BuildInstallPlanInput {\n backend: PackWeightsRef['backend'] | string;\n weightsRef: string;\n license?: string;\n mode?: string;\n packId?: string;\n promise?: string;\n fit?: string;\n /** Discovered local model names (Ollama / LM Studio / gguf). */\n installedNames?: string[];\n /** When true, network install/download is forbidden. */\n offline?: boolean;\n /** Injectable binary probe (defaults: which/where style via injected map). */\n hasBinary?: (name: string) => boolean;\n /** Injectable npm package probe. */\n isPackageInstalled?: (spec: string) => boolean;\n /** Optional local GGUF path (llama.cpp) — when set, weights are satisfied. */\n modelPath?: string;\n /** Pack/catalog HTTPS URL for first-party GGUF download. */\n downloadUrl?: string;\n /** Optional sha256 for first-party download. */\n sha256?: string;\n /** Injectable weight-cache probe (tests). */\n isWeightCached?: (ref: string) => boolean;\n}\n\n/** Runtime deps declared per backend (not third-party app installers). */\nexport function runtimeDepsForBackend(backend: string): ProviderRuntimeDep[] {\n const b = backend.toLowerCase();\n if (b === 'llama.cpp' || b === 'llama-cpp' || b === 'vibgrate') {\n return [\n {\n id: 'node-llama-cpp',\n kind: 'npm-runtime',\n spec: 'node-llama-cpp@^3',\n reason: 'in-process llama.cpp binding for the first-party / llama-cpp provider',\n },\n ];\n }\n if (b === 'ollama') {\n return [\n {\n id: 'ollama',\n kind: 'native-binary',\n binary: 'ollama',\n reason: 'Ollama on PATH (install from https://ollama.com — third-party apps are not auto-installed)',\n },\n ];\n }\n // LM Studio / Foundry / other: weights managed externally; no auto deps.\n return [];\n}\n\nexport function weightsChannelForBackend(\n backend: string,\n opts?: { downloadUrl?: string; weightsRef?: string },\n): ModelInstallPlan['weights']['channel'] {\n const b = backend.toLowerCase();\n if (b === 'ollama') return 'ollama';\n if (b === 'llama.cpp' || b === 'llama-cpp' || b === 'vibgrate') {\n // Prefer first-party store when we have a catalog/pack URL for this ref.\n if (opts?.downloadUrl || (opts?.weightsRef && lookupCatalog(opts.weightsRef))) return 'vibgrate';\n return 'local-path';\n }\n if (b === 'lm-studio' || b === 'lmstudio' || b === 'foundry-local') return 'manual';\n return 'manual';\n}\n\nfunction weightsInstalled(ref: string, installedNames: string[]): boolean {\n const want = ref.toLowerCase();\n return installedNames.some((n) => {\n const have = n.toLowerCase();\n return have === want || have.includes(want) || want.includes(have);\n });\n}\n\n/**\n * Build a side-effect-free install plan for a backend + weight ref.\n */\nexport function buildModelInstallPlan(input: BuildInstallPlanInput): ModelInstallPlan {\n const hasBinary = input.hasBinary ?? (() => false);\n const pkgInstalled = input.isPackageInstalled ?? isPackageInstalled;\n const installedNames = input.installedNames ?? [];\n const offline = !!input.offline;\n const backend = input.backend;\n const provider = providerLabel(backend);\n\n const runtimeDeps: PlannedDep[] = runtimeDepsForBackend(backend).map((dep) => {\n if (dep.kind === 'npm-runtime' && dep.spec) {\n return { ...dep, status: pkgInstalled(dep.spec) ? 'satisfied' : 'missing' };\n }\n if (dep.kind === 'native-binary' && dep.binary) {\n // Present → satisfied; absent → unmanaged (we never install third-party apps).\n return { ...dep, status: hasBinary(dep.binary) ? 'satisfied' : 'unmanaged' };\n }\n return { ...dep, status: 'unmanaged' as const };\n });\n\n const channel = weightsChannelForBackend(backend, {\n downloadUrl: input.downloadUrl,\n weightsRef: input.weightsRef,\n });\n const weightCached = (input.isWeightCached ?? isWeightCached)(input.weightsRef);\n const catalog = lookupCatalog(input.weightsRef);\n const downloadUrl = input.downloadUrl ?? catalog?.url;\n\n let weightsStatus: DepStatus = 'missing';\n if (channel === 'ollama') {\n weightsStatus = weightsInstalled(input.weightsRef, installedNames) ? 'satisfied' : 'missing';\n } else if (channel === 'vibgrate') {\n weightsStatus =\n weightCached || weightsInstalled(input.weightsRef, installedNames) || !!input.modelPath ? 'satisfied' : 'missing';\n } else if (channel === 'local-path') {\n // Satisfied only when caller reports the model (path) already discoverable.\n weightsStatus = weightsInstalled(input.weightsRef, installedNames) || !!input.modelPath || weightCached ? 'satisfied' : 'manual';\n } else {\n weightsStatus = weightsInstalled(input.weightsRef, installedNames) ? 'satisfied' : 'manual';\n }\n\n const alreadySatisfied: string[] = [];\n const willInstall: string[] = [];\n const willDownload: string[] = [];\n const blocked: Array<{ id: string; reason: string }> = [];\n\n for (const dep of runtimeDeps) {\n if (dep.status === 'satisfied') {\n alreadySatisfied.push(dep.id);\n continue;\n }\n if (dep.kind === 'npm-runtime' && dep.spec && dep.status === 'missing') {\n if (offline) {\n blocked.push({ id: dep.id, reason: `${dep.spec} needed but --local/offline forbids install` });\n } else {\n willInstall.push(dep.spec);\n }\n continue;\n }\n if (dep.kind === 'native-binary' && dep.status === 'unmanaged') {\n blocked.push({\n id: dep.id,\n reason: dep.reason,\n });\n }\n }\n\n if (weightsStatus === 'satisfied') {\n alreadySatisfied.push(`weights:${input.weightsRef}`);\n } else if (weightsStatus === 'missing' && (channel === 'ollama' || channel === 'vibgrate')) {\n if (offline) {\n blocked.push({ id: `weights:${input.weightsRef}`, reason: 'weights missing and --local/offline forbids download' });\n } else if (channel === 'ollama' && runtimeDeps.some((d) => d.id === 'ollama' && d.status === 'unmanaged')) {\n willDownload.push(input.weightsRef);\n } else if (channel === 'vibgrate' && !downloadUrl) {\n blocked.push({\n id: `weights:${input.weightsRef}`,\n reason: `no first-party download URL for ${input.weightsRef} — place a gguf in the weight store or pass --model-path`,\n });\n } else {\n willDownload.push(input.weightsRef);\n }\n } else if (weightsStatus === 'manual' || weightsStatus === 'missing') {\n blocked.push({\n id: `weights:${input.weightsRef}`,\n reason:\n channel === 'local-path'\n ? `point --model-path at a local gguf for ${input.weightsRef}, or run install when a first-party URL is catalogued`\n : `install or link weights for ${input.weightsRef} via the backend app`,\n });\n }\n\n // Under offline, do not claim we will download/install — those land in blocked.\n const effectiveWillInstall = offline ? [] : willInstall;\n const effectiveWillDownload = offline ? [] : willDownload;\n const offlineBlocked = offline && blocked.some((b) => /offline|forbids/i.test(b.reason));\n\n const allRuntimeOk = runtimeDeps.every((d) => d.status === 'satisfied');\n const fullyReady = allRuntimeOk && weightsStatus === 'satisfied' && blocked.length === 0;\n\n return {\n schemaVersion: MODEL_INSTALL_PLAN_SCHEMA_VERSION,\n provider,\n backend,\n model: input.weightsRef,\n mode: input.mode,\n packId: input.packId,\n license: input.license,\n promise: input.promise,\n fit: input.fit,\n runtimeDeps,\n weights: {\n channel,\n ref: input.weightsRef,\n status: weightsStatus,\n downloadUrl: channel === 'vibgrate' ? downloadUrl : undefined,\n },\n alreadySatisfied,\n willInstall: effectiveWillInstall,\n willDownload: effectiveWillDownload,\n blocked,\n offlineBlocked,\n ready: fullyReady,\n };\n}\n\nfunction providerLabel(backend: string): string {\n const b = backend.toLowerCase();\n if (b === 'llama.cpp' || b === 'llama-cpp') return 'llama-cpp';\n if (b === 'vibgrate') return 'vibgrate';\n if (b === 'lm-studio' || b === 'lmstudio') return 'lmstudio';\n if (b === 'foundry-local') return 'foundry-local';\n return b === 'ollama' ? 'ollama' : backend;\n}\n","/**\n * Model manager identity + runtime ensure.\n *\n * **Code Modes** always use the first-party **Vibgrate** manager (embedded\n * llama.cpp / vgd host-broker + weight store). Custom local/hosted backends\n * (Ollama, LM Studio, OpenRouter, …) are explicit user choices; when chosen we\n * silently install *our* installable runtime packages for that path (npm\n * bindings), never third-party desktop apps. The user sees a short badge for\n * which manager ran.\n */\n\nimport { spawnSync } from 'node:child_process';\nimport { ensurePackage, isPackageInstalled, type EnsureOptions } from '../code/ensure.js';\nimport { runtimeDepsForBackend } from './model-install-plan.js';\n\n/** Durable manager ids surfaced in badges and JSON. */\nexport type ModelManagerId =\n | 'vibgrate'\n | 'ollama'\n | 'lmstudio'\n | 'foundry-local'\n | 'openrouter'\n | 'litellm'\n | 'openai'\n | 'together'\n | 'mock'\n | 'other';\n\nexport interface ManagerBadge {\n id: ModelManagerId;\n /** Short product label, e.g. \"Vibgrate\". */\n label: string;\n /** Compact badge for CLI/UI, e.g. \"[Vibgrate]\". */\n badge: string;\n /** One-line after-run note. */\n note: string;\n}\n\nconst LABELS: Record<ModelManagerId, { label: string; note: string }> = {\n vibgrate: {\n label: 'Vibgrate',\n note: 'Code Mode · first-party model manager (embedded inference)',\n },\n ollama: {\n label: 'Ollama',\n note: 'Custom local · Ollama',\n },\n lmstudio: {\n label: 'LM Studio',\n note: 'Custom local · LM Studio',\n },\n 'foundry-local': {\n label: 'Foundry Local',\n note: 'Custom local · Foundry Local',\n },\n openrouter: {\n label: 'OpenRouter',\n note: 'Custom hosted · OpenRouter',\n },\n litellm: {\n label: 'LiteLLM',\n note: 'Custom hosted · LiteLLM',\n },\n openai: {\n label: 'OpenAI',\n note: 'Custom hosted · OpenAI',\n },\n together: {\n label: 'Together',\n note: 'Custom hosted · Together',\n },\n mock: {\n label: 'Mock',\n note: 'Scripted offline provider',\n },\n other: {\n label: 'Custom',\n note: 'Custom model backend',\n },\n};\n\n/** Map a provider id (`llama-cpp`, `ollama`, …) to a manager badge. */\nexport function managerFromProviderId(providerId: string | undefined | null): ModelManagerId {\n const id = (providerId ?? '').toLowerCase().trim();\n if (id === 'llama-cpp' || id === 'llama.cpp' || id === 'vibgrate' || id === 'vibgrate-store') return 'vibgrate';\n if (id === 'ollama') return 'ollama';\n if (id === 'lmstudio' || id === 'lm-studio') return 'lmstudio';\n if (id === 'foundry-local' || id === 'foundry') return 'foundry-local';\n if (id === 'openrouter') return 'openrouter';\n if (id === 'litellm') return 'litellm';\n if (id === 'openai') return 'openai';\n if (id === 'together') return 'together';\n if (id === 'mock' || id === 'scripted') return 'mock';\n return 'other';\n}\n\nexport function managerBadge(id: ModelManagerId): ManagerBadge {\n const meta = LABELS[id] ?? LABELS.other;\n return {\n id,\n label: meta.label,\n badge: `[${meta.label}]`,\n note: meta.note,\n };\n}\n\nexport function formatManagerBadgeLine(id: ModelManagerId, model?: string): string {\n const b = managerBadge(id);\n const modelPart = model ? ` · ${model}` : '';\n return `${b.badge} ${b.note}${modelPart}`;\n}\n\nexport interface EnsureManagerRuntimeOptions {\n /** Provider id that will run (llama-cpp, ollama, …). */\n providerId: string;\n /** Model id for weight pull when the backend supports it. */\n model?: string;\n /** `--local` / offline — no network install. */\n offline?: boolean;\n /**\n * Consent to install npm runtime packages (and ollama pull when binary is\n * present). True when the user chose a custom provider/model or passed --yes.\n */\n consent?: boolean;\n /** Injectable ensure (tests). */\n ensurePackage?: typeof ensurePackage;\n /** Injectable PATH binary probe. */\n hasBinary?: (name: string) => boolean;\n /** Injectable ollama pull. */\n ollamaPull?: (name: string) => number;\n onProgress?: (line: string) => void;\n}\n\nexport interface EnsureManagerRuntimeResult {\n ok: boolean;\n manager: ModelManagerId;\n badge: ManagerBadge;\n /** npm specs installed this call. */\n installed: string[];\n /** Weight refs pulled (e.g. ollama pull). */\n pulled: string[];\n /** Non-fatal notes (e.g. app already present). */\n messages: string[];\n error?: string;\n}\n\nfunction defaultHasBinary(name: string): boolean {\n const res = spawnSync(name, ['--version'], { stdio: 'ignore', encoding: 'utf8' });\n // Some CLIs use subcommands; try bare which-style.\n if (res.status === 0) return true;\n const which = spawnSync(process.platform === 'win32' ? 'where' : 'which', [name], {\n stdio: 'ignore',\n encoding: 'utf8',\n });\n return which.status === 0;\n}\n\n/**\n * Silently install *installable* runtime deps for the chosen manager.\n * Never installs third-party desktop apps (Ollama.app, LM Studio) — those\n * remain user-managed; we only install npm packages into the Vibgrate runtime\n * cache and pull weights when the backend binary is already on PATH.\n */\nexport async function ensureManagerRuntime(\n opts: EnsureManagerRuntimeOptions,\n): Promise<EnsureManagerRuntimeResult> {\n const manager = managerFromProviderId(opts.providerId);\n const badge = managerBadge(manager);\n const installed: string[] = [];\n const pulled: string[] = [];\n const messages: string[] = [];\n const ensure = opts.ensurePackage ?? ensurePackage;\n const hasBinary = opts.hasBinary ?? defaultHasBinary;\n\n // Hosted OpenAI-compatible backends: no local packages.\n if (\n manager === 'openrouter' ||\n manager === 'litellm' ||\n manager === 'openai' ||\n manager === 'together' ||\n manager === 'mock'\n ) {\n return { ok: true, manager, badge, installed, pulled, messages };\n }\n\n // LM Studio / Foundry: HTTP clients only — no auto app install (ADR-005).\n if (manager === 'lmstudio' || manager === 'foundry-local') {\n messages.push(\n manager === 'lmstudio'\n ? 'LM Studio must already be running with a model loaded (we never install the app)'\n : 'Foundry Local must already be running (we never install the app)',\n );\n return { ok: true, manager, badge, installed, pulled, messages };\n }\n\n const backend =\n manager === 'vibgrate' ? 'llama.cpp' : manager === 'ollama' ? 'ollama' : opts.providerId;\n const deps = runtimeDepsForBackend(backend);\n\n for (const dep of deps) {\n if (dep.kind === 'npm-runtime' && dep.spec) {\n if (isPackageInstalled(dep.spec)) {\n messages.push(`${dep.id} already installed`);\n continue;\n }\n if (opts.offline) {\n return {\n ok: false,\n manager,\n badge,\n installed,\n pulled,\n messages,\n error: `${dep.spec} needed but offline/--local forbids install`,\n };\n }\n if (!opts.consent) {\n return {\n ok: false,\n manager,\n badge,\n installed,\n pulled,\n messages,\n error: `${dep.spec} needed — pass --yes or run \\`vg models install\\` once`,\n };\n }\n opts.onProgress?.(`installing ${dep.spec}`);\n const ensureOpts: EnsureOptions = {\n consent: true,\n local: false,\n interactive: false,\n };\n const res = await ensure(dep.spec, ensureOpts);\n if (!res.module) {\n return {\n ok: false,\n manager,\n badge,\n installed,\n pulled,\n messages,\n error: `couldn't install ${dep.spec}`,\n };\n }\n installed.push(dep.spec);\n continue;\n }\n if (dep.kind === 'native-binary' && dep.binary) {\n if (!hasBinary(dep.binary)) {\n return {\n ok: false,\n manager,\n badge,\n installed,\n pulled,\n messages,\n error:\n dep.reason ||\n `${dep.binary} is not on PATH — install it once, then re-run (vg never auto-installs third-party apps)`,\n };\n }\n messages.push(`${dep.binary} on PATH`);\n }\n }\n\n // Optional: when user chose a custom Ollama model, pull weights if missing.\n if (manager === 'ollama' && opts.model && opts.consent && !opts.offline) {\n const list = spawnSync('ollama', ['list'], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] });\n const have =\n list.status === 0 &&\n (list.stdout ?? '')\n .split('\\n')\n .slice(1)\n .some((line) => {\n const name = line.trim().split(/\\s+/)[0]?.toLowerCase();\n return name === opts.model!.toLowerCase() || name?.startsWith(`${opts.model!.toLowerCase()}:`);\n });\n if (!have) {\n opts.onProgress?.(`pulling ${opts.model}`);\n const pull = opts.ollamaPull ?? ((name: string) => spawnSync('ollama', ['pull', name], { stdio: 'ignore' }).status ?? 1);\n const status = pull(opts.model);\n if (status !== 0) {\n return {\n ok: false,\n manager,\n badge,\n installed,\n pulled,\n messages,\n error: `ollama pull ${opts.model} failed (exit ${status})`,\n };\n }\n pulled.push(opts.model);\n }\n }\n\n return { ok: true, manager, badge, installed, pulled, messages };\n}\n"]}
@@ -1,9 +1,9 @@
1
- import { resolveVersion, resolveLib, loadCatalog, driftFor, localPackageDocs, readDoc, inventory, localApiSurface, edgeId, buildModuleResolver, resolve, applyStaticTestLinkage, nodeId } from './chunk-6JIKUDWM.js';
2
- import { loadConfig, computeUpgradeImpact, getChangelogSignals, gitHistoryAvailable, buildVersionTimelines, findPackageTimeline, severityRank, projectTypeToVulnEcosystem, VERSION } from './chunk-Y23HMSWU.js';
1
+ import { resolveVersion, resolveLib, loadCatalog, driftFor, localPackageDocs, readDoc, inventory, localApiSurface, edgeId, buildModuleResolver, resolve, applyStaticTestLinkage, nodeId } from './chunk-6AXHLQBV.js';
2
+ import { loadConfig, computeUpgradeImpact, getChangelogSignals, gitHistoryAvailable, buildVersionTimelines, findPackageTimeline, severityRank, projectTypeToVulnEcosystem, VERSION } from './chunk-T3AYRS7J.js';
3
3
  import { writeTextFile, pathExists, readJsonFile } from './chunk-CRAMOEBE.js';
4
4
  import { resolveOne, findNodes } from './chunk-J7LKEB2R.js';
5
- import { discoverModels } from './chunk-OOIG3RUM.js';
6
5
  import { impactOf, indexFor, withTimeout, getNodeEmbeddings, queryGraphSemantic, queryGraph, loadEmbedder, isModelReady, acquireLock, releaseLock } from './chunk-6UK6QPTR.js';
6
+ import { discoverModels } from './chunk-3SDV6ADQ.js';
7
7
  import { langById, grammarSetVersion, langForExtension, setGrammarsOverride, parseSource } from './chunk-ON25BX6T.js';
8
8
  import { redactSecrets } from './chunk-RXP66R2E.js';
9
9
  import { writeGraphIndex, SCHEMA_VERSION, loadGraph, ensureVibgrateGitignore, vibgrateDir, writeArtifacts } from './chunk-B3YUO3NW.js';
@@ -4189,6 +4189,12 @@ ${chunk2}`);
4189
4189
  }
4190
4190
 
4191
4191
  // src/engine/quality.ts
4192
+ var IDENT_RE = /^(?:[A-Za-z][a-z0-9]*[A-Z][A-Za-z0-9]*|[a-z][a-z0-9]*(?:_[a-z0-9]+)+|[a-z][a-z0-9]*(?:-[a-z0-9]+)+)$/;
4193
+ function identifierTerms(query) {
4194
+ if (!query) return [];
4195
+ const raw = [...new Set(query.split(/[^A-Za-z0-9_-]+/).filter((w) => w.length > 2))];
4196
+ return raw.filter((t) => IDENT_RE.test(t) || t.length >= 6 && /[A-Z]/.test(t) && /[a-z]/.test(t));
4197
+ }
4192
4198
  function assessDocQuality(content, opts = {}) {
4193
4199
  const minTokens = opts.minTokens ?? 60;
4194
4200
  const lc = content.toLowerCase();
@@ -4206,20 +4212,36 @@ function assessDocQuality(content, opts = {}) {
4206
4212
  else reasons.push("library name absent");
4207
4213
  }
4208
4214
  const qt = tokenizeQuery(opts.query);
4215
+ const idents = identifierTerms(opts.query);
4209
4216
  let onTopic = qt.length === 0;
4210
4217
  if (qt.length) {
4211
- const hits = qt.filter((t) => lc.includes(t)).length;
4212
- if (hits) {
4213
- score += Math.min(hits, 2);
4214
- onTopic = true;
4218
+ const missingIdents = idents.filter((id) => !lc.includes(id.toLowerCase()));
4219
+ if (missingIdents.length) {
4220
+ reasons.push(`API symbol(s) absent: ${missingIdents.join(", ")}`);
4221
+ onTopic = false;
4215
4222
  } else {
4216
- reasons.push("query terms absent");
4223
+ const hits = qt.filter((t) => lc.includes(t)).length;
4224
+ const need = Math.max(1, Math.floor(qt.length / 2) + 1);
4225
+ if (hits >= need) {
4226
+ score += Math.min(hits, 2);
4227
+ onTopic = true;
4228
+ } else {
4229
+ reasons.push(hits === 0 ? "query terms absent" : `query terms weak (${hits}/${qt.length})`);
4230
+ onTopic = false;
4231
+ }
4217
4232
  }
4218
4233
  }
4219
4234
  if (opts.symbols?.length) {
4220
4235
  if (opts.symbols.some((s) => s.length > 2 && lc.includes(s.toLowerCase()))) score += 1;
4221
4236
  else reasons.push("no API symbols present");
4222
4237
  }
4238
+ if (opts.readmeOnly && (idents.length > 0 || qt.length >= 2)) {
4239
+ onTopic = false;
4240
+ if (!reasons.includes("README-only source cannot answer a focused API query")) {
4241
+ reasons.push("README-only source cannot answer a focused API query");
4242
+ }
4243
+ score = Math.min(score, 4);
4244
+ }
4223
4245
  const sufficient = hasCode && tokens >= minTokens && onTopic;
4224
4246
  return { score, sufficient, reasons };
4225
4247
  }
@@ -4798,9 +4820,15 @@ var TOOLS = [
4798
4820
  {
4799
4821
  name: "get_facts",
4800
4822
  description: "Deterministic facts for a node (contract / invariant / characterization).",
4801
- inputSchema: obj({ name: { type: "string" } }, ["name"]),
4823
+ inputSchema: obj(
4824
+ {
4825
+ name: { type: "string" },
4826
+ pick: { type: "number", description: "nth candidate if ambiguous" }
4827
+ },
4828
+ ["name"]
4829
+ ),
4802
4830
  handler: (graph, args) => {
4803
- const { node, candidates } = resolveOne(graph, String(args.name ?? ""));
4831
+ const { node, candidates } = resolveOne(graph, String(args.name ?? ""), numOrU(args.pick));
4804
4832
  if (!node) return unresolved(candidates);
4805
4833
  if (!graph.facts) {
4806
4834
  return {
@@ -4815,9 +4843,15 @@ var TOOLS = [
4815
4843
  {
4816
4844
  name: "guide_node",
4817
4845
  description: "Cited standards/practices for a node (OWASP/CWE).",
4818
- inputSchema: obj({ name: { type: "string" } }, ["name"]),
4846
+ inputSchema: obj(
4847
+ {
4848
+ name: { type: "string" },
4849
+ pick: { type: "number", description: "nth candidate if ambiguous" }
4850
+ },
4851
+ ["name"]
4852
+ ),
4819
4853
  handler: (graph, args) => {
4820
- const { node, candidates } = resolveOne(graph, String(args.name ?? ""));
4854
+ const { node, candidates } = resolveOne(graph, String(args.name ?? ""), numOrU(args.pick));
4821
4855
  if (!node) return unresolved(candidates);
4822
4856
  const entries = new Map(FREE_PACK.entries.map((e) => [e.id, e]));
4823
4857
  return {
@@ -5011,13 +5045,24 @@ var TOOLS = [
5011
5045
  const verbosity = ["concise", "balanced", "exhaustive"].includes(String(args.verbosity)) ? String(args.verbosity) : query ? "concise" : "balanced";
5012
5046
  const budget = numOrU(args.max_tokens) ?? numOrU(args.tokens) ?? VERBOSITY_BUDGET[verbosity];
5013
5047
  const ver = resolveVersion(ctx.root, id);
5014
- const render = (readme, libName) => {
5015
- const apiSurface = localApiSurface(ctx.root, libName);
5016
- const sel = selectForBudget({ readme, query, apiSurface, budget });
5017
- const quality = assessDocQuality([readme, apiSurface].filter(Boolean).join("\n\n"), {
5048
+ const focusQuery = (() => {
5049
+ const q = query.trim();
5050
+ if (!q) return q;
5051
+ const bare = id.replace(/^@[^/]+\//, "").toLowerCase();
5052
+ const parts = q.split(/\s+/);
5053
+ if (parts.length > 1 && parts[0].toLowerCase().replace(/^@[^/]+\//, "") === bare) {
5054
+ return parts.slice(1).join(" ");
5055
+ }
5056
+ return q;
5057
+ })();
5058
+ const render = (readme, libName, readmeOnly) => {
5059
+ const apiSurface = localApiSurface(ctx.root, libName, focusQuery || void 0);
5060
+ const sel = selectForBudget({ readme, query: focusQuery || query, apiSurface, budget });
5061
+ const quality = assessDocQuality(sel.text, {
5018
5062
  name: libName,
5019
- query,
5020
- symbols: symbolsFromApi(apiSurface)
5063
+ query: focusQuery || query || void 0,
5064
+ symbols: symbolsFromApi(apiSurface),
5065
+ readmeOnly: readmeOnly === true && !apiSurface
5021
5066
  });
5022
5067
  return {
5023
5068
  content: sel.text,
@@ -5034,7 +5079,7 @@ var TOOLS = [
5034
5079
  let answer = null;
5035
5080
  let sufficient = false;
5036
5081
  if (entry) {
5037
- const r = render(readDoc(ctx.root, entry), entry.name);
5082
+ const r = render(readDoc(ctx.root, entry), entry.name, false);
5038
5083
  sufficient = r.metadata.quality.sufficient;
5039
5084
  answer = {
5040
5085
  targetId: entry.id,
@@ -5049,9 +5094,9 @@ var TOOLS = [
5049
5094
  metadata: r.metadata
5050
5095
  };
5051
5096
  } else {
5052
- const local = localPackageDocs(ctx.root, id);
5097
+ const local = localPackageDocs(ctx.root, id, { query: focusQuery || query || void 0 });
5053
5098
  if (local) {
5054
- const r = render(local.docs, id);
5099
+ const r = render(local.docs, id, local.readmeOnly);
5055
5100
  sufficient = r.metadata.quality.sufficient;
5056
5101
  answer = {
5057
5102
  targetId: id,
@@ -5644,5 +5689,5 @@ async function refreshIfStale(root, opts = {}) {
5644
5689
  }
5645
5690
 
5646
5691
  export { ASSISTANTS, CliError, ExitCode, FREE_PACK, NPX_INVOCATION, ResourceLimitError, SKIP_DIRS, SKIP_FILES, SMALL_REPO_FILES, TOOLS, UsageError, analyze, applyCoverage, assessDocQuality, assistantById, availableRegionIds, buildFacts, buildGraph, clearStoredCredentials, countTokens, coveringTests, createWorkspaceDsn, credentialsPath, dashHostForIngestHost, decodeScipIndex, detectAssistants, detectRunner, detectServeLaunch, discover, driftCount, dsnCommand, ensureGitignored, epistemicBreakdown, fetchHostedDocsCached, findGitRoot, gitignoreEntryForCredentials, groundGraph, hasDrift, homeCredentialsPath, hostedBase, ingestHostForRegionId, installAssistant, loadCoverage, loadSnapshot, parseDsn, pathDisconnect, probeFreshness, projectCredentialsPath, publishPrivateLibrary, pushCommand, readScanArtifact, readStoredCredentials, refreshIfStale, refreshInstalledInstructions, renderToolResult, resolveCliInvocation, resolveDsn, resolveIngestHost, resolveLimits, scipEdges, searchSymbols, selectForBudget, shortestPath, symbolsFromApi, testsToRun, uninstallAssistant, uploadScanArtifact, usageError, verifyDeterminism, warmEmbedderInBackground, writeNavigationConfig, writeSnapshot, writeStoredCredentials };
5647
- //# sourceMappingURL=chunk-MAY5HLDH.js.map
5648
- //# sourceMappingURL=chunk-MAY5HLDH.js.map
5692
+ //# sourceMappingURL=chunk-YKVH2PGF.js.map
5693
+ //# sourceMappingURL=chunk-YKVH2PGF.js.map