@vibgrate/cli 2026.728.2 → 2026.728.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.
Files changed (40) hide show
  1. package/DOCS.md +3 -3
  2. package/dist/baseline-PPZJBYAJ.js +8 -0
  3. package/dist/{baseline-MRUM2P6H.js.map → baseline-PPZJBYAJ.js.map} +1 -1
  4. package/dist/{chunk-ZFTFCM7B.js → chunk-3BIRGSRS.js} +3 -3
  5. package/dist/{chunk-ZFTFCM7B.js.map → chunk-3BIRGSRS.js.map} +1 -1
  6. package/dist/{chunk-GQTWDKMJ.js → chunk-57QU36P6.js} +4 -4
  7. package/dist/{chunk-GQTWDKMJ.js.map → chunk-57QU36P6.js.map} +1 -1
  8. package/dist/{chunk-IWP7MYIA.js → chunk-6GRLZ4Z2.js} +7 -7
  9. package/dist/{chunk-IWP7MYIA.js.map → chunk-6GRLZ4Z2.js.map} +1 -1
  10. package/dist/{chunk-KKRSQQ3A.js → chunk-7AVYKZEM.js} +4 -4
  11. package/dist/{chunk-KKRSQQ3A.js.map → chunk-7AVYKZEM.js.map} +1 -1
  12. package/dist/{chunk-3SDV6ADQ.js → chunk-CQDUBAQY.js} +3 -3
  13. package/dist/{chunk-3SDV6ADQ.js.map → chunk-CQDUBAQY.js.map} +1 -1
  14. package/dist/{chunk-PVZBYZZR.js → chunk-NZELMYT4.js} +27 -6
  15. package/dist/chunk-NZELMYT4.js.map +1 -0
  16. package/dist/{chunk-GYSOQH5C.js → chunk-OV4KGXPD.js} +30 -4
  17. package/dist/chunk-OV4KGXPD.js.map +1 -0
  18. package/dist/{chunk-UIOBFLE6.js → chunk-SZSNPXSW.js} +3 -3
  19. package/dist/{chunk-UIOBFLE6.js.map → chunk-SZSNPXSW.js.map} +1 -1
  20. package/dist/{chunk-WY6DGTBP.js → chunk-VI4ITXHQ.js} +4 -4
  21. package/dist/{chunk-WY6DGTBP.js.map → chunk-VI4ITXHQ.js.map} +1 -1
  22. package/dist/{chunk-NTW5UEKT.js → chunk-VYGEOOLY.js} +3 -3
  23. package/dist/{chunk-NTW5UEKT.js.map → chunk-VYGEOOLY.js.map} +1 -1
  24. package/dist/cli.js +426 -134
  25. package/dist/cli.js.map +1 -1
  26. package/dist/index.d.ts +1 -1
  27. package/dist/index.js +5 -5
  28. package/dist/{interactive-36ZZ64WL.js → interactive-OCWQ326U.js} +10 -10
  29. package/dist/{interactive-36ZZ64WL.js.map → interactive-OCWQ326U.js.map} +1 -1
  30. package/dist/{model-manager-OEPY4I7W.js → model-manager-LB54VSV7.js} +4 -4
  31. package/dist/{model-manager-OEPY4I7W.js.map → model-manager-LB54VSV7.js.map} +1 -1
  32. package/dist/{model-orchestrator-4VSYP4J4.js → model-orchestrator-4M5FG6MN.js} +3 -3
  33. package/dist/{model-orchestrator-4VSYP4J4.js.map → model-orchestrator-4M5FG6MN.js.map} +1 -1
  34. package/dist/resolve-gguf-4AFRN4CP.js +9 -0
  35. package/dist/{resolve-gguf-Y6FH3CNB.js.map → resolve-gguf-4AFRN4CP.js.map} +1 -1
  36. package/package.json +1 -1
  37. package/dist/baseline-MRUM2P6H.js +0 -8
  38. package/dist/chunk-GYSOQH5C.js.map +0 -1
  39. package/dist/chunk-PVZBYZZR.js.map +0 -1
  40. package/dist/resolve-gguf-Y6FH3CNB.js +0 -9
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/runtime/resolve-gguf.ts"],"names":[],"mappings":"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","file":"chunk-KKRSQQ3A.js","sourcesContent":["/**\n * Resolve a GGUF path for embedded llama.cpp — best-in-breed default path.\n *\n * Order (first hit wins):\n * 1. Explicit path (exists on disk)\n * 2. VG_CODE_MODEL_PATH / env override\n * 3. First-party weight store (catalogued ref or basename)\n * 4. Discovered local fleet (gguf / lm-studio)\n *\n * Pure path resolution — never downloads (install is `vg models install`).\n */\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { discoverModels, type LocalModel } from '../engine/models.js';\nimport { isWeightCached, listCachedWeights, lookupCatalog, weightPathForRef } from './weight-store.js';\n\nexport interface ResolveGgufOptions {\n /** Explicit --model-path or absolute path. */\n modelPath?: string;\n /** Model id / weightsRef (e.g. qwen2.5-coder-3b-q4_k_m.gguf or qwen2.5-coder:3b). */\n modelRef?: string;\n env?: NodeJS.ProcessEnv;\n discover?: () => LocalModel[];\n}\n\nexport interface ResolveGgufResult {\n path: string;\n source: 'explicit' | 'env' | 'weight-store' | 'fleet' | 'catalog-path';\n ref?: string;\n}\n\n/**\n * Resolve an on-disk GGUF for local inference. Returns null when nothing is ready\n * (caller should fall back to Ollama or ask user to install).\n */\nexport function resolveGgufPath(opts: ResolveGgufOptions = {}): ResolveGgufResult | null {\n const env = opts.env ?? process.env;\n\n if (opts.modelPath && fs.existsSync(opts.modelPath) && fs.statSync(opts.modelPath).isFile()) {\n return { path: path.resolve(opts.modelPath), source: 'explicit', ref: opts.modelRef };\n }\n\n const envPath = env.VG_CODE_MODEL_PATH;\n if (envPath && fs.existsSync(envPath) && fs.statSync(envPath).isFile()) {\n return { path: path.resolve(envPath), source: 'env', ref: opts.modelRef };\n }\n\n const ref = opts.modelRef?.trim();\n if (ref) {\n // Direct weight-store hit.\n if (isWeightCached(ref, env)) {\n return { path: weightPathForRef(ref, env), source: 'weight-store', ref };\n }\n // Catalog basename may differ slightly from ollama-style refs.\n const catalog = lookupCatalog(ref);\n if (catalog && isWeightCached(catalog.ref, env)) {\n return { path: weightPathForRef(catalog.ref, env), source: 'weight-store', ref: catalog.ref };\n }\n // Ollama-style \"name:tag\" → try catalog aliases.\n const normalized = ref.includes(':')\n ? `${ref.replace(':', '-').replace(/\\//g, '-')}-q4_k_m.gguf`\n : ref.endsWith('.gguf')\n ? ref\n : `${ref}.gguf`;\n if (isWeightCached(normalized, env)) {\n return { path: weightPathForRef(normalized, env), source: 'weight-store', ref: normalized };\n }\n const cat2 = lookupCatalog(normalized);\n if (cat2 && isWeightCached(cat2.ref, env)) {\n return { path: weightPathForRef(cat2.ref, env), source: 'weight-store', ref: cat2.ref };\n }\n // Absolute path-looking ref\n if ((ref.startsWith('/') || /^[A-Za-z]:[\\\\/]/.test(ref)) && fs.existsSync(ref)) {\n return { path: path.resolve(ref), source: 'explicit', ref };\n }\n }\n\n // Any cached first-party weight (prefer matching ref substring).\n const cached = listCachedWeights(env);\n if (ref) {\n const hit = cached.find((w) => w.name.toLowerCase().includes(ref.toLowerCase().replace(/[:/]/g, '-')));\n if (hit) return { path: hit.path, source: 'weight-store', ref: hit.name };\n }\n\n // Fleet discovery: gguf / lm-studio paths.\n const fleet = (() => {\n try {\n return (opts.discover ?? discoverModels)();\n } catch {\n return [] as LocalModel[];\n }\n })();\n if (ref) {\n const want = ref.toLowerCase();\n const match = fleet.find(\n (m) =>\n (m.runtime === 'gguf' || m.runtime === 'lm-studio') &&\n (m.name.toLowerCase().includes(want) || m.path.toLowerCase().includes(want) || want.includes(m.name.toLowerCase())),\n );\n if (match && fs.existsSync(match.path)) {\n return { path: match.path, source: 'fleet', ref: match.name };\n }\n }\n const anyGguf = fleet.find((m) => (m.runtime === 'gguf' || m.runtime === 'lm-studio') && fs.existsSync(m.path));\n if (anyGguf) return { path: anyGguf.path, source: 'fleet', ref: anyGguf.name };\n\n // If only one weight in store, use it when no ref.\n if (!ref && cached.length === 1) {\n return { path: cached[0].path, source: 'weight-store', ref: cached[0].name };\n }\n\n return null;\n}\n\n/** Whether embedded llama.cpp is ready for this ref without a network install. */\nexport function embeddedLlamaReady(opts: ResolveGgufOptions = {}): boolean {\n return resolveGgufPath(opts) != null;\n}\n"]}
1
+ {"version":3,"sources":["../src/runtime/resolve-gguf.ts"],"names":[],"mappings":"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","file":"chunk-7AVYKZEM.js","sourcesContent":["/**\n * Resolve a GGUF path for embedded llama.cpp — best-in-breed default path.\n *\n * Order (first hit wins):\n * 1. Explicit path (exists on disk)\n * 2. VG_CODE_MODEL_PATH / env override\n * 3. First-party weight store (catalogued ref or basename)\n * 4. Discovered local fleet (gguf / lm-studio)\n *\n * Pure path resolution — never downloads (install is `vg models install`).\n */\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { discoverModels, type LocalModel } from '../engine/models.js';\nimport { isWeightCached, listCachedWeights, lookupCatalog, weightPathForRef } from './weight-store.js';\n\nexport interface ResolveGgufOptions {\n /** Explicit --model-path or absolute path. */\n modelPath?: string;\n /** Model id / weightsRef (e.g. qwen2.5-coder-3b-q4_k_m.gguf or qwen2.5-coder:3b). */\n modelRef?: string;\n env?: NodeJS.ProcessEnv;\n discover?: () => LocalModel[];\n}\n\nexport interface ResolveGgufResult {\n path: string;\n source: 'explicit' | 'env' | 'weight-store' | 'fleet' | 'catalog-path';\n ref?: string;\n}\n\n/**\n * Resolve an on-disk GGUF for local inference. Returns null when nothing is ready\n * (caller should fall back to Ollama or ask user to install).\n */\nexport function resolveGgufPath(opts: ResolveGgufOptions = {}): ResolveGgufResult | null {\n const env = opts.env ?? process.env;\n\n if (opts.modelPath && fs.existsSync(opts.modelPath) && fs.statSync(opts.modelPath).isFile()) {\n return { path: path.resolve(opts.modelPath), source: 'explicit', ref: opts.modelRef };\n }\n\n const envPath = env.VG_CODE_MODEL_PATH;\n if (envPath && fs.existsSync(envPath) && fs.statSync(envPath).isFile()) {\n return { path: path.resolve(envPath), source: 'env', ref: opts.modelRef };\n }\n\n const ref = opts.modelRef?.trim();\n if (ref) {\n // Direct weight-store hit.\n if (isWeightCached(ref, env)) {\n return { path: weightPathForRef(ref, env), source: 'weight-store', ref };\n }\n // Catalog basename may differ slightly from ollama-style refs.\n const catalog = lookupCatalog(ref);\n if (catalog && isWeightCached(catalog.ref, env)) {\n return { path: weightPathForRef(catalog.ref, env), source: 'weight-store', ref: catalog.ref };\n }\n // Ollama-style \"name:tag\" → try catalog aliases.\n const normalized = ref.includes(':')\n ? `${ref.replace(':', '-').replace(/\\//g, '-')}-q4_k_m.gguf`\n : ref.endsWith('.gguf')\n ? ref\n : `${ref}.gguf`;\n if (isWeightCached(normalized, env)) {\n return { path: weightPathForRef(normalized, env), source: 'weight-store', ref: normalized };\n }\n const cat2 = lookupCatalog(normalized);\n if (cat2 && isWeightCached(cat2.ref, env)) {\n return { path: weightPathForRef(cat2.ref, env), source: 'weight-store', ref: cat2.ref };\n }\n // Absolute path-looking ref\n if ((ref.startsWith('/') || /^[A-Za-z]:[\\\\/]/.test(ref)) && fs.existsSync(ref)) {\n return { path: path.resolve(ref), source: 'explicit', ref };\n }\n }\n\n // Any cached first-party weight (prefer matching ref substring).\n const cached = listCachedWeights(env);\n if (ref) {\n const hit = cached.find((w) => w.name.toLowerCase().includes(ref.toLowerCase().replace(/[:/]/g, '-')));\n if (hit) return { path: hit.path, source: 'weight-store', ref: hit.name };\n }\n\n // Fleet discovery: gguf / lm-studio paths.\n const fleet = (() => {\n try {\n return (opts.discover ?? discoverModels)();\n } catch {\n return [] as LocalModel[];\n }\n })();\n if (ref) {\n const want = ref.toLowerCase();\n const match = fleet.find(\n (m) =>\n (m.runtime === 'gguf' || m.runtime === 'lm-studio') &&\n (m.name.toLowerCase().includes(want) || m.path.toLowerCase().includes(want) || want.includes(m.name.toLowerCase())),\n );\n if (match && fs.existsSync(match.path)) {\n return { path: match.path, source: 'fleet', ref: match.name };\n }\n }\n const anyGguf = fleet.find((m) => (m.runtime === 'gguf' || m.runtime === 'lm-studio') && fs.existsSync(m.path));\n if (anyGguf) return { path: anyGguf.path, source: 'fleet', ref: anyGguf.name };\n\n // If only one weight in store, use it when no ref.\n if (!ref && cached.length === 1) {\n return { path: cached[0].path, source: 'weight-store', ref: cached[0].name };\n }\n\n return null;\n}\n\n/** Whether embedded llama.cpp is ready for this ref without a network install. */\nexport function embeddedLlamaReady(opts: ResolveGgufOptions = {}): boolean {\n return resolveGgufPath(opts) != null;\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { listCachedWeights } from './chunk-GYSOQH5C.js';
1
+ import { listCachedWeights } from './chunk-OV4KGXPD.js';
2
2
  import * as fs from 'fs';
3
3
  import * as os from 'os';
4
4
  import * as path from 'path';
@@ -74,5 +74,5 @@ function dedupe(models) {
74
74
  }
75
75
 
76
76
  export { discoverModels };
77
- //# sourceMappingURL=chunk-3SDV6ADQ.js.map
78
- //# sourceMappingURL=chunk-3SDV6ADQ.js.map
77
+ //# sourceMappingURL=chunk-CQDUBAQY.js.map
78
+ //# sourceMappingURL=chunk-CQDUBAQY.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/engine/models.ts"],"names":[],"mappings":"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","file":"chunk-3SDV6ADQ.js","sourcesContent":["import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { listCachedWeights } from '../runtime/weight-store.js';\n\n/**\n * Local-model discovery (VG-LOCAL-MODELS §9.2) — be a no-key *consumer* of the\n * developer's local model fleet. Fully offline and deterministic: inspect the\n * on-disk layouts of Ollama / LM Studio / llama.cpp / the Vibgrate weight store,\n * never the network. No runtime is built or launched.\n */\n\nexport interface LocalModel {\n runtime: 'ollama' | 'lm-studio' | 'gguf';\n name: string;\n path: string;\n}\n\nexport function discoverModels(home = os.homedir()): LocalModel[] {\n return [...ollama(home), ...lmStudio(home), ...looseGguf(home), ...vibgrateWeightStore()].sort(\n (a, b) => a.runtime.localeCompare(b.runtime) || a.name.localeCompare(b.name),\n );\n}\n\n/** First-party GGUF cache (runtime/weight-store.ts). */\nfunction vibgrateWeightStore(): LocalModel[] {\n return listCachedWeights().map((w) => ({ runtime: 'gguf' as const, name: w.name, path: w.path }));\n}\n\nfunction ollama(home: string): LocalModel[] {\n const base = path.join(home, '.ollama', 'models', 'manifests');\n const out: LocalModel[] = [];\n walk(base, 4, (file) => {\n // .../library/<model>/<tag>\n const rel = path.relative(base, file).split(path.sep);\n if (rel.length >= 2) {\n const tag = rel[rel.length - 1];\n const model = rel[rel.length - 2];\n out.push({ runtime: 'ollama', name: `${model}:${tag}`, path: file });\n }\n });\n return dedupe(out);\n}\n\nfunction lmStudio(home: string): LocalModel[] {\n const bases = [path.join(home, '.lmstudio', 'models'), path.join(home, '.cache', 'lm-studio', 'models')];\n const out: LocalModel[] = [];\n for (const base of bases) {\n walk(base, 5, (file) => {\n if (!file.endsWith('.gguf')) return;\n const rel = path.relative(base, file).replace(/\\\\/g, '/');\n out.push({ runtime: 'lm-studio', name: rel, path: file });\n });\n }\n return dedupe(out);\n}\n\nfunction looseGguf(home: string): LocalModel[] {\n const bases = [path.join(home, 'models'), path.join(home, '.cache', 'huggingface')];\n const out: LocalModel[] = [];\n for (const base of bases) {\n walk(base, 4, (file) => {\n if (!file.endsWith('.gguf')) return;\n out.push({ runtime: 'gguf', name: path.basename(file), path: file });\n });\n }\n return dedupe(out);\n}\n\nfunction walk(dir: string, depth: number, onFile: (file: string) => void): void {\n if (depth < 0) return;\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n for (const e of entries.sort((a, b) => a.name.localeCompare(b.name))) {\n const abs = path.join(dir, e.name);\n if (e.isDirectory()) walk(abs, depth - 1, onFile);\n else if (e.isFile()) onFile(abs);\n }\n}\n\nfunction dedupe(models: LocalModel[]): LocalModel[] {\n const seen = new Set<string>();\n const out: LocalModel[] = [];\n for (const m of models) {\n const key = `${m.runtime}:${m.name}`;\n if (seen.has(key)) continue;\n seen.add(key);\n out.push(m);\n }\n return out;\n}\n"]}
1
+ {"version":3,"sources":["../src/engine/models.ts"],"names":[],"mappings":"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","file":"chunk-CQDUBAQY.js","sourcesContent":["import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { listCachedWeights } from '../runtime/weight-store.js';\n\n/**\n * Local-model discovery (VG-LOCAL-MODELS §9.2) — be a no-key *consumer* of the\n * developer's local model fleet. Fully offline and deterministic: inspect the\n * on-disk layouts of Ollama / LM Studio / llama.cpp / the Vibgrate weight store,\n * never the network. No runtime is built or launched.\n */\n\nexport interface LocalModel {\n runtime: 'ollama' | 'lm-studio' | 'gguf';\n name: string;\n path: string;\n}\n\nexport function discoverModels(home = os.homedir()): LocalModel[] {\n return [...ollama(home), ...lmStudio(home), ...looseGguf(home), ...vibgrateWeightStore()].sort(\n (a, b) => a.runtime.localeCompare(b.runtime) || a.name.localeCompare(b.name),\n );\n}\n\n/** First-party GGUF cache (runtime/weight-store.ts). */\nfunction vibgrateWeightStore(): LocalModel[] {\n return listCachedWeights().map((w) => ({ runtime: 'gguf' as const, name: w.name, path: w.path }));\n}\n\nfunction ollama(home: string): LocalModel[] {\n const base = path.join(home, '.ollama', 'models', 'manifests');\n const out: LocalModel[] = [];\n walk(base, 4, (file) => {\n // .../library/<model>/<tag>\n const rel = path.relative(base, file).split(path.sep);\n if (rel.length >= 2) {\n const tag = rel[rel.length - 1];\n const model = rel[rel.length - 2];\n out.push({ runtime: 'ollama', name: `${model}:${tag}`, path: file });\n }\n });\n return dedupe(out);\n}\n\nfunction lmStudio(home: string): LocalModel[] {\n const bases = [path.join(home, '.lmstudio', 'models'), path.join(home, '.cache', 'lm-studio', 'models')];\n const out: LocalModel[] = [];\n for (const base of bases) {\n walk(base, 5, (file) => {\n if (!file.endsWith('.gguf')) return;\n const rel = path.relative(base, file).replace(/\\\\/g, '/');\n out.push({ runtime: 'lm-studio', name: rel, path: file });\n });\n }\n return dedupe(out);\n}\n\nfunction looseGguf(home: string): LocalModel[] {\n const bases = [path.join(home, 'models'), path.join(home, '.cache', 'huggingface')];\n const out: LocalModel[] = [];\n for (const base of bases) {\n walk(base, 4, (file) => {\n if (!file.endsWith('.gguf')) return;\n out.push({ runtime: 'gguf', name: path.basename(file), path: file });\n });\n }\n return dedupe(out);\n}\n\nfunction walk(dir: string, depth: number, onFile: (file: string) => void): void {\n if (depth < 0) return;\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n for (const e of entries.sort((a, b) => a.name.localeCompare(b.name))) {\n const abs = path.join(dir, e.name);\n if (e.isDirectory()) walk(abs, depth - 1, onFile);\n else if (e.isFile()) onFile(abs);\n }\n}\n\nfunction dedupe(models: LocalModel[]): LocalModel[] {\n const seen = new Set<string>();\n const out: LocalModel[] = [];\n for (const m of models) {\n const key = `${m.runtime}:${m.name}`;\n if (seen.has(key)) continue;\n seen.add(key);\n out.push(m);\n }\n return out;\n}\n"]}
@@ -209,6 +209,17 @@ function fitPack(input) {
209
209
  if (pack.mode === "forge" && ((input.repo?.fileCount ?? 0) > 1e4 || (input.repo?.graphNodeCount ?? 0) > 1e5) && label === "comfortable") {
210
210
  reasons.push("large repository \u2014 prefer moderated capsule + graph paging");
211
211
  }
212
+ const diskNeedBytes = Math.round(modelBytes + Math.max(GiB, modelBytes * 0.15));
213
+ if (typeof input.freeDiskBytes === "number" && Number.isFinite(input.freeDiskBytes)) {
214
+ if (input.freeDiskBytes < diskNeedBytes) {
215
+ if (label !== "will_not_fit") {
216
+ label = "will_not_fit";
217
+ }
218
+ reasons.push(
219
+ `needs ~${fmtGb(diskNeedBytes)} free disk for weights, only ~${fmtGb(input.freeDiskBytes)} free`
220
+ );
221
+ }
222
+ }
212
223
  let score = Math.max(0, Math.min(100, Math.round(ratio * 50)));
213
224
  if (label === "will_not_fit") score = Math.min(score, 20);
214
225
  if (label === "tight") score = Math.min(Math.max(score, 25), 45);
@@ -219,6 +230,8 @@ function fitPack(input) {
219
230
  score,
220
231
  needBytes,
221
232
  availableBytes,
233
+ diskNeedBytes,
234
+ freeDiskBytes: typeof input.freeDiskBytes === "number" ? input.freeDiskBytes : void 0,
222
235
  breakdown: {
223
236
  modelBytes,
224
237
  kvBytes,
@@ -261,9 +274,12 @@ function packToProfile(pack, underlying, fit) {
261
274
  inferenceIsolation: pack.contract.inferenceIsolation ?? "embedded"
262
275
  };
263
276
  }
264
- function tryWeights(pack, weights, system, repo, taskClass) {
277
+ function tryWeights(pack, weights, system, repo, taskClass, freeDiskBytes) {
265
278
  const trial = { ...pack, primary: weights };
266
- return { fit: fitPack({ system, pack: trial, repo}), underlying: weights };
279
+ return {
280
+ fit: fitPack({ system, pack: trial, repo, freeDiskBytes }),
281
+ underlying: weights
282
+ };
267
283
  }
268
284
  function resolveMode(opts) {
269
285
  const packs = opts.packs ?? QUALIFIED_PACKS;
@@ -290,14 +306,14 @@ function resolveMode(opts) {
290
306
  const candidates = [pack.primary, ...pack.fallback ?? []];
291
307
  let best = null;
292
308
  for (const w of candidates) {
293
- const trial = tryWeights(pack, w, opts.system, opts.repo, opts.taskClass);
309
+ const trial = tryWeights(pack, w, opts.system, opts.repo, opts.taskClass, opts.freeDiskBytes);
294
310
  if (!best || fitRank(trial.fit) > fitRank(best.fit)) best = trial;
295
311
  if (trial.fit.label === "flies" || trial.fit.label === "comfortable") {
296
312
  best = trial;
297
313
  break;
298
314
  }
299
315
  }
300
- const chosen = best ?? tryWeights(pack, pack.primary, opts.system, opts.repo, opts.taskClass);
316
+ const chosen = best ?? tryWeights(pack, pack.primary, opts.system, opts.repo, opts.taskClass, opts.freeDiskBytes);
301
317
  const profile = packToProfile(pack, chosen.underlying, chosen.fit);
302
318
  return {
303
319
  schemaVersion: MODEL_ORCHESTRATOR_SCHEMA_VERSION,
@@ -350,6 +366,7 @@ function recommendMode(system, repo, packs = QUALIFIED_PACKS) {
350
366
  function buildOrchestratorStatus(opts) {
351
367
  const packs = opts.packs ?? QUALIFIED_PACKS;
352
368
  const installed = new Set((opts.installedNames ?? []).map((n) => n.toLowerCase()));
369
+ const freeDiskBytes = opts.freeDiskBytes;
353
370
  const recommended = recommendMode(opts.system, opts.repo, packs);
354
371
  const pinFor = (mode) => {
355
372
  const fromMap = opts.pins?.[mode];
@@ -363,6 +380,7 @@ function buildOrchestratorStatus(opts) {
363
380
  autoFit: false,
364
381
  system: opts.system,
365
382
  repo: opts.repo,
383
+ freeDiskBytes,
366
384
  pin: pinFor(mode),
367
385
  packs
368
386
  });
@@ -379,6 +397,7 @@ function buildOrchestratorStatus(opts) {
379
397
  fitScore: resolved.fit.score,
380
398
  needBytes: resolved.fit.needBytes,
381
399
  availableBytes: resolved.fit.availableBytes,
400
+ diskNeedBytes: resolved.fit.diskNeedBytes,
382
401
  installed: installedHit,
383
402
  pinned: resolved.pinned
384
403
  };
@@ -387,6 +406,7 @@ function buildOrchestratorStatus(opts) {
387
406
  mode: recommended,
388
407
  autoFit: false,
389
408
  system: opts.system,
409
+ freeDiskBytes,
390
410
  repo: opts.repo,
391
411
  pin: pinFor(recommended),
392
412
  packs
@@ -402,6 +422,7 @@ function buildOrchestratorStatus(opts) {
402
422
  freeRamBytes: opts.system.freeRamBytes,
403
423
  ...typeof opts.system.vramTotalBytes === "number" ? { vramTotalBytes: opts.system.vramTotalBytes } : {},
404
424
  ...typeof opts.system.vramFreeBytes === "number" ? { vramFreeBytes: opts.system.vramFreeBytes } : {},
425
+ ...typeof freeDiskBytes === "number" ? { freeDiskBytes } : {},
405
426
  loaded: opts.system.loaded.map((l) => ({ name: l.name, bytes: l.bytes }))
406
427
  },
407
428
  memoryBreakdown: recResolved.fit.breakdown
@@ -484,5 +505,5 @@ function parseMode(raw) {
484
505
  }
485
506
 
486
507
  export { MODEL_ORCHESTRATOR_SCHEMA_VERSION, QUALIFIED_PACKS, activePin, buildOrchestratorStatus, fitPack, listModes, orchestratorStatePath, packById, packForMode, parseMode, pinPack, providerForBackend, readOrchestratorState, recommendMode, resolveMode, setDefaultMode, unpinPack, writeOrchestratorState };
487
- //# sourceMappingURL=chunk-PVZBYZZR.js.map
488
- //# sourceMappingURL=chunk-PVZBYZZR.js.map
508
+ //# sourceMappingURL=chunk-NZELMYT4.js.map
509
+ //# sourceMappingURL=chunk-NZELMYT4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime/model-orchestrator.ts"],"names":[],"mappings":"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","file":"chunk-NZELMYT4.js","sourcesContent":["/**\n * Vibgrate Model Orchestrator — Code Modes (Spark / Flow / Forge).\n *\n * Product stance (PRD): users and agents select outcome-oriented **Code Modes**,\n * never GGUF names by default. This module:\n * 1. Declares versioned **qualified packs** (contract + primary/fallback weights)\n * 2. Runs a **fit** algorithm (available memory now × reserves × repo signals)\n * 3. Resolves mode → pack → concrete model / backend\n * 4. Supports pin/unpin for reproducibility\n *\n * Pure resolve + fit helpers have no I/O. Registry pin state uses the global\n * Vibgrate data dir (never in-repo). Pull/ensure is a separate CLI concern that\n * calls into `vg models pull` after resolve.\n *\n * schemaVersion: model-orchestrator/0\n */\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { estimateModelBytes, type SystemMemory } from '../code/capability.js';\nimport {\n MODEL_EXECUTION_PROFILE_SCHEMA_VERSION,\n type ModelExecutionProfile,\n type ModelMode,\n type ToolCallingMode,\n type EditFormatPreference,\n} from './model-execution-profile.js';\nimport { vibgrateDataDir } from './paths.js';\n\nexport const MODEL_ORCHESTRATOR_SCHEMA_VERSION = 'model-orchestrator/0' as const;\n\n/** UX fit vocabulary (stricter than “weights fit”). */\nexport type FitLabel = 'flies' | 'comfortable' | 'tight' | 'will_not_fit';\n\nexport type TaskClass = 'spark_task' | 'flow_task' | 'forge_task' | 'explicit_mode';\n\nexport interface PackWeightsRef {\n /** Backend that can load these weights. */\n backend: 'ollama' | 'llama.cpp' | 'lm-studio' | 'foundry-local' | 'other';\n /** Concrete model id / slug (e.g. qwen2.5-coder:3b). */\n weightsRef: string;\n quant?: string;\n /** SPDX / short license note for first-download surface. */\n license?: string;\n /** Approx weights size in bytes (for fit when not discoverable). */\n weightsBytes?: number;\n /**\n * Optional HTTPS GGUF URL for the first-party weight store (must pass host\n * allowlist). When set, `vg models install` can download without Ollama.\n */\n downloadUrl?: string;\n /** Optional content hash for downloaded GGUF. */\n sha256?: string;\n}\n\nexport interface PackContract {\n toolCalling: ToolCallingMode;\n editFormat: EditFormatPreference;\n capsuleBudgetTokens: number;\n maxRepairRounds: number;\n maxParallelEdits: number;\n /** Minimum qualification score (0–1) this pack was gated on. */\n minEffectiveScore?: number;\n constrainedDecoding?: boolean;\n kvCacheStrategy?: ModelExecutionProfile['kvCacheStrategy'];\n securityTier?: ModelExecutionProfile['securityTier'];\n /**\n * Preferred inference path when available (ADR-005). Weights may still be\n * pulled via Ollama; embedded llama.cpp is preferred for sampler/grammar.\n */\n preferredInference?: 'ollama' | 'llama.cpp';\n /** Process isolation for preferredInference llama.cpp (default embedded). */\n inferenceIsolation?: ModelExecutionProfile['inferenceIsolation'];\n}\n\nexport interface QualifiedPack {\n /** e.g. flow@2026.07.1 */\n packId: string;\n mode: ModelMode;\n displayName: string;\n /** User-facing promise (one line). */\n promise: string;\n primary: PackWeightsRef;\n fallback?: PackWeightsRef[];\n contract: PackContract;\n resources: {\n minRamGb: number;\n minVramGb?: number;\n /** Estimated KV cache bytes per 1k context tokens. */\n estimatedKvPer1kContext?: number;\n };\n provenance?: {\n evalRunIds?: string[];\n notes?: string;\n };\n}\n\nexport interface RepoSignals {\n /** Approximate source file count (0 = unknown). */\n fileCount?: number;\n /** Graph node count when a map is warm (0 = unknown). */\n graphNodeCount?: number;\n /** Dominant languages (optional). */\n languages?: string[];\n}\n\nexport interface FitInput {\n system: SystemMemory;\n pack: QualifiedPack;\n repo?: RepoSignals;\n taskClass?: TaskClass;\n /**\n * Free space on the volume that holds model weights (weight store / Ollama).\n * When set, insufficient disk for the GGUF forces {@link FitLabel will_not_fit}.\n */\n freeDiskBytes?: number;\n /**\n * Static reserves (bytes) for IDE / OS / graph / tests.\n * Defaults applied when omitted.\n */\n reserves?: {\n ideBytes?: number;\n osBytes?: number;\n graphBytes?: number;\n testsBytes?: number;\n safetyMarginBytes?: number;\n };\n /** Context budget used to estimate KV (tokens). Defaults from pack contract. */\n contextBudgetTokens?: number;\n}\n\nexport interface FitResult {\n label: FitLabel;\n /** 0–100; higher is more headroom. */\n score: number;\n needBytes: number;\n availableBytes: number;\n /** Disk needed to store weights safely (weights + 15% + ≥1 GiB floor). */\n diskNeedBytes?: number;\n /** Free disk observed when fit was computed (if provided). */\n freeDiskBytes?: number;\n /** Breakdown for “memory pie” UX. */\n breakdown: {\n modelBytes: number;\n kvBytes: number;\n ideBytes: number;\n osBytes: number;\n graphBytes: number;\n testsBytes: number;\n freeAfterReservesBytes: number;\n };\n /** When tight: suggested reduced capsule budget. */\n reducedCapsuleBudgetTokens?: number;\n reasons: string[];\n}\n\nexport interface ResolvedMode {\n schemaVersion: typeof MODEL_ORCHESTRATOR_SCHEMA_VERSION;\n mode: ModelMode;\n pack: QualifiedPack;\n /** Concrete weights chosen (primary or fallback after fit). */\n underlying: PackWeightsRef;\n fit: FitResult;\n profile: ModelExecutionProfile;\n /** True when pack id was pinned by the user. */\n pinned: boolean;\n /** How the mode was chosen. */\n selection: 'explicit' | 'default' | 'auto_fit' | 'pinned';\n}\n\nexport interface OrchestratorStatus {\n schemaVersion: typeof MODEL_ORCHESTRATOR_SCHEMA_VERSION;\n defaultMode: ModelMode;\n pin?: { mode: ModelMode; packId: string } | null;\n modes: Array<{\n mode: ModelMode;\n packId: string;\n displayName: string;\n promise: string;\n underlyingModelId: string;\n backend: string;\n fit: FitLabel;\n fitScore: number;\n needBytes: number;\n availableBytes: number;\n /** Disk budget for storing this pack’s weights (when free disk was known). */\n diskNeedBytes?: number;\n installed: boolean;\n pinned: boolean;\n }>;\n recommended: ModelMode;\n system: {\n totalRamBytes: number;\n freeRamBytes: number;\n vramTotalBytes?: number;\n vramFreeBytes?: number;\n loaded: Array<{ name: string; bytes: number }>;\n /** Free bytes on the model-cache volume (when probed). */\n freeDiskBytes?: number;\n };\n memoryBreakdown?: FitResult['breakdown'];\n}\n\n// ── Curated packs (versioned; weights may change under the same mode contract) ─\n\n/** Pack channel — bump when contracts or weight refs change under stable mode names. */\nconst PACK_CHANNEL = '2026.07.4';\n\n/**\n * Current qualified packs — one primary per mode.\n *\n * Approach B default: Spark/Flow **primary** is first-party GGUF (llama.cpp)\n * for install + inference when fit allows. Ollama remains an explicit fallback\n * adapter, not the default path.\n */\nexport const QUALIFIED_PACKS: QualifiedPack[] = [\n {\n packId: `spark@${PACK_CHANNEL}`,\n mode: 'spark',\n displayName: 'Spark',\n promise: 'Fastest capable local coding — simple edits, minimal memory.',\n primary: {\n backend: 'llama.cpp',\n weightsRef: 'qwen2.5-coder-3b-q4_k_m.gguf',\n quant: 'q4_k_m',\n license: 'Apache-2.0',\n weightsBytes: estimateModelBytes('qwen2.5-coder:3b').bytes,\n },\n fallback: [\n {\n backend: 'ollama',\n weightsRef: 'qwen2.5-coder:3b',\n quant: 'q4_k_m',\n license: 'Apache-2.0',\n weightsBytes: estimateModelBytes('qwen2.5-coder:3b').bytes,\n },\n {\n backend: 'ollama',\n weightsRef: 'qwen2.5-coder:1.5b',\n quant: 'q4_k_m',\n license: 'Apache-2.0',\n weightsBytes: estimateModelBytes('qwen2.5-coder:1.5b').bytes,\n },\n ],\n contract: {\n toolCalling: 'grammar',\n editFormat: 'patch_ir_json',\n capsuleBudgetTokens: 2000,\n maxRepairRounds: 2,\n maxParallelEdits: 2,\n minEffectiveScore: 0.55,\n constrainedDecoding: true,\n preferredInference: 'llama.cpp',\n inferenceIsolation: 'embedded',\n kvCacheStrategy: 'stable_prefix',\n securityTier: 'L1',\n },\n resources: { minRamGb: 4, estimatedKvPer1kContext: 2 * 1024 * 1024 },\n provenance: {\n notes: 'Spark@2026.07.4 — Approach B: first-party GGUF + embedded vibgrate manager; Ollama pack fallback only',\n },\n },\n {\n packId: `flow@${PACK_CHANNEL}`,\n mode: 'flow',\n displayName: 'Flow',\n promise: 'Best everyday graph-guided coding for this machine.',\n primary: {\n backend: 'llama.cpp',\n weightsRef: 'qwen2.5-coder-7b-q4_k_m.gguf',\n quant: 'q4_k_m',\n license: 'Apache-2.0',\n weightsBytes: estimateModelBytes('qwen2.5-coder:7b').bytes,\n },\n fallback: [\n {\n backend: 'ollama',\n weightsRef: 'qwen2.5-coder:7b',\n quant: 'q4_k_m',\n license: 'Apache-2.0',\n weightsBytes: estimateModelBytes('qwen2.5-coder:7b').bytes,\n },\n {\n backend: 'ollama',\n weightsRef: 'qwen2.5-coder:3b',\n quant: 'q4_k_m',\n license: 'Apache-2.0',\n weightsBytes: estimateModelBytes('qwen2.5-coder:3b').bytes,\n },\n ],\n contract: {\n toolCalling: 'native',\n editFormat: 'auto',\n capsuleBudgetTokens: 3500,\n maxRepairRounds: 2,\n maxParallelEdits: 4,\n minEffectiveScore: 0.65,\n constrainedDecoding: false,\n preferredInference: 'llama.cpp',\n inferenceIsolation: 'embedded',\n kvCacheStrategy: 'stable_prefix',\n securityTier: 'L1',\n },\n resources: { minRamGb: 8, minVramGb: 6, estimatedKvPer1kContext: 4 * 1024 * 1024 },\n provenance: {\n notes: 'Flow@2026.07.4 — first-party GGUF primary; Ollama pack fallback only',\n },\n },\n {\n packId: `forge@${PACK_CHANNEL}`,\n mode: 'forge',\n displayName: 'Forge',\n promise: 'Strongest deep work that safely fits (migrations, multi-file).',\n primary: {\n backend: 'llama.cpp',\n weightsRef: 'qwen2.5-coder-14b-q4_k_m.gguf',\n quant: 'q4_k_m',\n license: 'Apache-2.0',\n weightsBytes: estimateModelBytes('qwen2.5-coder:14b').bytes,\n },\n fallback: [\n {\n backend: 'ollama',\n weightsRef: 'qwen2.5-coder:14b',\n quant: 'q4_k_m',\n license: 'Apache-2.0',\n weightsBytes: estimateModelBytes('qwen2.5-coder:14b').bytes,\n },\n {\n backend: 'ollama',\n weightsRef: 'qwen2.5-coder:7b',\n quant: 'q4_k_m',\n license: 'Apache-2.0',\n weightsBytes: estimateModelBytes('qwen2.5-coder:7b').bytes,\n },\n ],\n contract: {\n toolCalling: 'native',\n editFormat: 'patch_ir_json',\n capsuleBudgetTokens: 6000,\n maxRepairRounds: 3,\n maxParallelEdits: 6,\n minEffectiveScore: 0.7,\n constrainedDecoding: false,\n preferredInference: 'llama.cpp',\n inferenceIsolation: 'embedded',\n kvCacheStrategy: 'stable_prefix',\n securityTier: 'L1',\n },\n resources: { minRamGb: 16, minVramGb: 12, estimatedKvPer1kContext: 8 * 1024 * 1024 },\n provenance: {\n notes:\n 'Forge@2026.07.4 — first-party 14B GGUF + embedded vibgrate manager (same path as Spark/Flow); Ollama pack fallback only',\n },\n },\n];\n\nconst GiB = 1024 ** 3;\n\n/**\n * Static reserves applied on top of *available* RAM.\n *\n * Important: `freeRamBytes` is already residual after currently-running\n * processes (IDE, OS, browsers, …). Subtracting a full IDE/OS footprint again\n * double-counts and falsely zeros fit on healthy machines. Keep growth\n * headroom for graph/tests (often not yet resident) + safety, and a modest\n * fraction of IDE/OS for workspace growth under load.\n */\nconst DEFAULT_RESERVES = {\n ideBytes: 1.5 * GiB,\n osBytes: 2 * GiB,\n graphBytes: 0.5 * GiB,\n testsBytes: 0.25 * GiB,\n safetyMarginBytes: 1 * GiB,\n};\n\n/** Fraction of IDE+OS reserves kept as growth headroom on the free-RAM path. */\nconst IDE_OS_GROWTH_FRACTION = 0.25;\n\n// ── Pack lookup ───────────────────────────────────────────────────────────────\n\nexport function packForMode(mode: ModelMode, packs: QualifiedPack[] = QUALIFIED_PACKS): QualifiedPack | null {\n return packs.find((p) => p.mode === mode) ?? null;\n}\n\nexport function packById(packId: string, packs: QualifiedPack[] = QUALIFIED_PACKS): QualifiedPack | null {\n return packs.find((p) => p.packId === packId) ?? null;\n}\n\nexport function listModes(): ModelMode[] {\n return ['spark', 'flow', 'forge'];\n}\n\n// ── Fit algorithm ─────────────────────────────────────────────────────────────\n\n/**\n * Fit decision: available memory *now* after IDE/OS/graph/tests reserves and\n * safety margin — not only “weights fit in total RAM”.\n *\n * Target: < 100 ms once system snapshot is warm (pure arithmetic).\n */\nexport function fitPack(input: FitInput): FitResult {\n const r = { ...DEFAULT_RESERVES, ...input.reserves };\n const pack = input.pack;\n const weightsBytes =\n pack.primary.weightsBytes ??\n estimateModelBytes(pack.primary.weightsRef).bytes;\n const ctxTokens = input.contextBudgetTokens ?? pack.contract.capsuleBudgetTokens * 2;\n const kvPer1k = pack.resources.estimatedKvPer1kContext ?? 2 * 1024 * 1024;\n const kvBytes = Math.round((ctxTokens / 1000) * kvPer1k);\n const modelBytes = weightsBytes;\n const needBytes = modelBytes + kvBytes;\n\n const useVram =\n typeof input.system.vramTotalBytes === 'number' && input.system.vramTotalBytes > 0;\n const freeNow = useVram\n ? (input.system.vramFreeBytes ?? 0)\n : input.system.freeRamBytes;\n const loadedBytes = input.system.loaded.reduce((n, m) => n + m.bytes, 0);\n // Prefer free-after-unload for fit of *next* load when something is resident.\n const freePool = freeNow + loadedBytes;\n\n const graphBump =\n (input.repo?.graphNodeCount ?? 0) > 50_000\n ? 0.5 * GiB\n : (input.repo?.fileCount ?? 0) > 5_000\n ? 0.25 * GiB\n : 0;\n const graphBytes = r.graphBytes + graphBump;\n\n // On discrete VRAM, only model+KV compete for VRAM — host reserves stay on RAM.\n // On unified / CPU path: free/available RAM already excludes current IDE/OS\n // usage, so only charge growth (graph/tests/safety + modest IDE/OS headroom).\n const reserved = useVram\n ? r.safetyMarginBytes\n : graphBytes +\n r.testsBytes +\n r.safetyMarginBytes +\n IDE_OS_GROWTH_FRACTION * (r.ideBytes + r.osBytes);\n const freeAfterReserves = Math.max(0, freePool - reserved);\n\n const availableBytes = freeAfterReserves;\n const reasons: string[] = [];\n const headroom = availableBytes - needBytes;\n const ratio = needBytes > 0 ? availableBytes / needBytes : 0;\n\n let label: FitLabel;\n let reducedCapsuleBudgetTokens: number | undefined;\n\n if (availableBytes < needBytes * 0.85) {\n label = 'will_not_fit';\n reasons.push(\n `needs ~${fmtGb(needBytes)} but only ~${fmtGb(availableBytes)} is free after reserves`,\n );\n } else if (ratio < 1.1 || headroom < 0.5 * GiB) {\n label = 'tight';\n reducedCapsuleBudgetTokens = Math.max(\n 1200,\n Math.floor(pack.contract.capsuleBudgetTokens * 0.65),\n );\n reasons.push('tight fit — capsule budget will be reduced automatically');\n } else if (ratio >= 1.6 && headroom >= 2 * GiB) {\n label = 'flies';\n reasons.push('comfortable headroom for this mode');\n } else {\n label = 'comfortable';\n reasons.push('within policy for this machine');\n }\n\n // Large monorepo + forge → soft-downgrade score (does not force will_not_fit).\n if (\n pack.mode === 'forge' &&\n ((input.repo?.fileCount ?? 0) > 10_000 || (input.repo?.graphNodeCount ?? 0) > 100_000) &&\n label === 'comfortable'\n ) {\n reasons.push('large repository — prefer moderated capsule + graph paging');\n }\n\n // Disk: downloads need the full GGUF + headroom on the cache volume (not RAM).\n const diskNeedBytes = Math.round(modelBytes + Math.max(GiB, modelBytes * 0.15));\n if (typeof input.freeDiskBytes === 'number' && Number.isFinite(input.freeDiskBytes)) {\n if (input.freeDiskBytes < diskNeedBytes) {\n if (label !== 'will_not_fit') {\n label = 'will_not_fit';\n }\n reasons.push(\n `needs ~${fmtGb(diskNeedBytes)} free disk for weights, only ~${fmtGb(input.freeDiskBytes)} free`,\n );\n }\n }\n\n // Score: map ratio into 0–100 with floors for labels.\n let score = Math.max(0, Math.min(100, Math.round(ratio * 50)));\n if (label === 'will_not_fit') score = Math.min(score, 20);\n if (label === 'tight') score = Math.min(Math.max(score, 25), 45);\n if (label === 'comfortable') score = Math.min(Math.max(score, 50), 75);\n if (label === 'flies') score = Math.max(score, 80);\n\n return {\n label,\n score,\n needBytes,\n availableBytes,\n diskNeedBytes,\n freeDiskBytes: typeof input.freeDiskBytes === 'number' ? input.freeDiskBytes : undefined,\n breakdown: {\n modelBytes,\n kvBytes,\n // Report the charged growth headroom (not the full static IDE/OS footprint).\n ideBytes: useVram ? 0 : IDE_OS_GROWTH_FRACTION * r.ideBytes,\n osBytes: useVram ? 0 : IDE_OS_GROWTH_FRACTION * r.osBytes,\n graphBytes: useVram ? 0 : graphBytes,\n testsBytes: useVram ? 0 : r.testsBytes,\n freeAfterReservesBytes: freeAfterReserves,\n },\n reducedCapsuleBudgetTokens,\n reasons,\n };\n}\n\nfunction fmtGb(bytes: number): string {\n return `${(bytes / GiB).toFixed(1)} GiB`;\n}\n\n// ── Resolve mode → pack → underlying ──────────────────────────────────────────\n\nexport interface ResolveModeOptions {\n mode?: ModelMode;\n /** Prefer auto-fit when no mode set (default true for first-run wizard). */\n autoFit?: boolean;\n system: SystemMemory;\n repo?: RepoSignals;\n taskClass?: TaskClass;\n /** Free disk on the weight-store volume (bytes). */\n freeDiskBytes?: number;\n /** Installed model names (ollama/lmstudio) for installed: true. */\n installedNames?: string[];\n /** Pin map mode → packId. */\n pin?: { mode: ModelMode; packId: string } | null;\n packs?: QualifiedPack[];\n defaultMode?: ModelMode;\n}\n\nfunction packToProfile(pack: QualifiedPack, underlying: PackWeightsRef, fit: FitResult): ModelExecutionProfile {\n const budget =\n fit.label === 'tight' && fit.reducedCapsuleBudgetTokens\n ? fit.reducedCapsuleBudgetTokens\n : pack.contract.capsuleBudgetTokens;\n return {\n schemaVersion: MODEL_EXECUTION_PROFILE_SCHEMA_VERSION,\n id: underlying.weightsRef,\n displayName: `${pack.displayName} · ${underlying.weightsRef}`,\n mode: pack.mode,\n backend:\n underlying.backend === 'ollama'\n ? 'ollama'\n : underlying.backend === 'llama.cpp'\n ? 'llama.cpp'\n : underlying.backend === 'lm-studio'\n ? 'openai-compatible'\n : 'other',\n toolCalling: pack.contract.toolCalling,\n editFormat: pack.contract.editFormat,\n capsuleBudgetTokens: budget,\n maxParallelEdits: pack.contract.maxParallelEdits,\n maxRepairRounds: pack.contract.maxRepairRounds,\n temperature: 0,\n constrainedDecoding: pack.contract.constrainedDecoding ?? false,\n kvCacheStrategy: pack.contract.kvCacheStrategy,\n resources: {\n minRamGb: pack.resources.minRamGb,\n minVramGb: pack.resources.minVramGb,\n quant: underlying.quant,\n },\n securityTier: pack.contract.securityTier,\n inferenceIsolation: pack.contract.inferenceIsolation ?? 'embedded',\n };\n}\n\nfunction tryWeights(\n pack: QualifiedPack,\n weights: PackWeightsRef,\n system: SystemMemory,\n repo?: RepoSignals,\n taskClass?: TaskClass,\n freeDiskBytes?: number,\n): { fit: FitResult; underlying: PackWeightsRef } {\n const trial: QualifiedPack = { ...pack, primary: weights };\n return {\n fit: fitPack({ system, pack: trial, repo, taskClass, freeDiskBytes }),\n underlying: weights,\n };\n}\n\n/**\n * Resolve a Code Mode to a pack, concrete weights, fit label, and MEP.\n * Refuses primary load when fit is will_not_fit and tries fallbacks; if all\n * fail, returns the best effort with label will_not_fit (caller must not load).\n */\nexport function resolveMode(opts: ResolveModeOptions): ResolvedMode {\n const packs = opts.packs ?? QUALIFIED_PACKS;\n const defaultMode = opts.defaultMode ?? 'flow';\n let mode: ModelMode = opts.mode ?? defaultMode;\n let selection: ResolvedMode['selection'] = opts.mode ? 'explicit' : 'default';\n\n if (!opts.mode && opts.autoFit !== false) {\n mode = recommendMode(opts.system, opts.repo, packs);\n selection = 'auto_fit';\n }\n\n let pack = packForMode(mode, packs);\n if (!pack) {\n pack = packForMode('flow', packs)!;\n mode = 'flow';\n selection = 'default';\n }\n\n if (opts.pin && opts.pin.mode === mode) {\n const pinned = packById(opts.pin.packId, packs);\n if (pinned && pinned.mode === mode) {\n pack = pinned;\n selection = 'pinned';\n }\n }\n\n const candidates = [pack.primary, ...(pack.fallback ?? [])];\n let best: { fit: FitResult; underlying: PackWeightsRef } | null = null;\n\n for (const w of candidates) {\n const trial = tryWeights(pack, w, opts.system, opts.repo, opts.taskClass, opts.freeDiskBytes);\n if (!best || fitRank(trial.fit) > fitRank(best.fit)) best = trial;\n if (trial.fit.label === 'flies' || trial.fit.label === 'comfortable') {\n best = trial;\n break;\n }\n }\n\n const chosen =\n best ?? tryWeights(pack, pack.primary, opts.system, opts.repo, opts.taskClass, opts.freeDiskBytes);\n const profile = packToProfile(pack, chosen.underlying, chosen.fit);\n\n return {\n schemaVersion: MODEL_ORCHESTRATOR_SCHEMA_VERSION,\n mode,\n pack,\n underlying: chosen.underlying,\n fit: chosen.fit,\n profile,\n pinned: selection === 'pinned',\n selection,\n };\n}\n\nfunction fitRank(f: FitResult): number {\n const order: Record<FitLabel, number> = {\n flies: 4,\n comfortable: 3,\n tight: 2,\n will_not_fit: 1,\n };\n return order[f.label] * 1000 + f.score;\n}\n\n/**\n * Pick the strongest mode that still fits at least “comfortable” (or tight\n * for spark). Prefer Flow when both Flow and Forge are comfortable.\n */\nexport function recommendMode(\n system: SystemMemory,\n repo?: RepoSignals,\n packs: QualifiedPack[] = QUALIFIED_PACKS,\n): ModelMode {\n const order: ModelMode[] = ['forge', 'flow', 'spark'];\n let bestTight: ModelMode | null = null;\n for (const mode of order) {\n const pack = packForMode(mode, packs);\n if (!pack) continue;\n const resolved = resolveMode({\n mode,\n autoFit: false,\n system,\n repo,\n packs,\n });\n if (resolved.fit.label === 'flies' || resolved.fit.label === 'comfortable') {\n // Prefer Flow as daily default when Forge also fits, unless repo is tiny.\n if (mode === 'forge') {\n const flow = resolveMode({ mode: 'flow', autoFit: false, system, repo, packs });\n if (flow.fit.label === 'flies' || flow.fit.label === 'comfortable') {\n const files = repo?.fileCount ?? 0;\n if (files < 2000) return 'flow';\n }\n return 'forge';\n }\n return mode;\n }\n if (resolved.fit.label === 'tight' && !bestTight) bestTight = mode;\n }\n return bestTight ?? 'spark';\n}\n\n/** Build orchestrator status for `vg models status` / host UIs. */\nexport function buildOrchestratorStatus(opts: {\n system: SystemMemory;\n repo?: RepoSignals;\n installedNames?: string[];\n /** Free bytes on the weight-store volume (factored into fit). */\n freeDiskBytes?: number;\n /** Single pin (legacy) or full pin map. */\n pin?: { mode: ModelMode; packId: string } | null;\n pins?: Partial<Record<ModelMode, string>>;\n defaultMode?: ModelMode;\n packs?: QualifiedPack[];\n}): OrchestratorStatus {\n const packs = opts.packs ?? QUALIFIED_PACKS;\n const installed = new Set((opts.installedNames ?? []).map((n) => n.toLowerCase()));\n const freeDiskBytes = opts.freeDiskBytes;\n const recommended = recommendMode(opts.system, opts.repo, packs);\n const pinFor = (mode: ModelMode): { mode: ModelMode; packId: string } | null => {\n const fromMap = opts.pins?.[mode];\n if (fromMap) return { mode, packId: fromMap };\n if (opts.pin?.mode === mode) return opts.pin;\n return null;\n };\n const modes = listModes().map((mode) => {\n const resolved = resolveMode({\n mode,\n autoFit: false,\n system: opts.system,\n repo: opts.repo,\n freeDiskBytes,\n pin: pinFor(mode),\n packs,\n });\n const id = resolved.underlying.weightsRef.toLowerCase();\n const installedHit =\n installed.has(id) ||\n [...installed].some((n) => n.includes(id) || id.includes(n));\n return {\n mode,\n packId: resolved.pack.packId,\n displayName: resolved.pack.displayName,\n promise: resolved.pack.promise,\n underlyingModelId: resolved.underlying.weightsRef,\n backend: resolved.underlying.backend,\n fit: resolved.fit.label,\n fitScore: resolved.fit.score,\n needBytes: resolved.fit.needBytes,\n availableBytes: resolved.fit.availableBytes,\n diskNeedBytes: resolved.fit.diskNeedBytes,\n installed: installedHit,\n pinned: resolved.pinned,\n };\n });\n\n const recResolved = resolveMode({\n mode: recommended,\n autoFit: false,\n system: opts.system,\n freeDiskBytes,\n repo: opts.repo,\n pin: pinFor(recommended),\n packs,\n });\n\n return {\n schemaVersion: MODEL_ORCHESTRATOR_SCHEMA_VERSION,\n defaultMode: opts.defaultMode ?? 'flow',\n pin: pinFor(recommended),\n modes,\n recommended,\n system: {\n totalRamBytes: opts.system.totalRamBytes,\n freeRamBytes: opts.system.freeRamBytes,\n ...(typeof opts.system.vramTotalBytes === 'number'\n ? { vramTotalBytes: opts.system.vramTotalBytes }\n : {}),\n ...(typeof opts.system.vramFreeBytes === 'number'\n ? { vramFreeBytes: opts.system.vramFreeBytes }\n : {}),\n ...(typeof freeDiskBytes === 'number' ? { freeDiskBytes } : {}),\n loaded: opts.system.loaded.map((l) => ({ name: l.name, bytes: l.bytes })),\n },\n memoryBreakdown: recResolved.fit.breakdown,\n };\n}\n\n// ── Pin registry (global storage, not in-repo) ────────────────────────────────\n\nexport interface OrchestratorPinState {\n schemaVersion: 'model-orchestrator-pin/0';\n /** mode → packId */\n pins: Partial<Record<ModelMode, string>>;\n /** Workspace / global default mode preference. */\n defaultMode?: ModelMode;\n updatedAt: string;\n}\n\nexport function orchestratorStatePath(\n env: NodeJS.ProcessEnv = process.env,\n platform: NodeJS.Platform = process.platform,\n home?: string,\n): string {\n return path.join(vibgrateDataDir(env, platform, home), 'model-orchestrator', 'state.json');\n}\n\nexport function readOrchestratorState(\n env: NodeJS.ProcessEnv = process.env,\n platform: NodeJS.Platform = process.platform,\n home?: string,\n): OrchestratorPinState {\n const p = orchestratorStatePath(env, platform, home);\n try {\n const raw = JSON.parse(fs.readFileSync(p, 'utf8')) as Partial<OrchestratorPinState>;\n return {\n schemaVersion: 'model-orchestrator-pin/0',\n pins: raw.pins && typeof raw.pins === 'object' ? raw.pins : {},\n defaultMode:\n raw.defaultMode === 'spark' || raw.defaultMode === 'flow' || raw.defaultMode === 'forge'\n ? raw.defaultMode\n : undefined,\n updatedAt: typeof raw.updatedAt === 'string' ? raw.updatedAt : new Date(0).toISOString(),\n };\n } catch {\n return {\n schemaVersion: 'model-orchestrator-pin/0',\n pins: {},\n updatedAt: new Date(0).toISOString(),\n };\n }\n}\n\nexport function writeOrchestratorState(\n state: OrchestratorPinState,\n env: NodeJS.ProcessEnv = process.env,\n platform: NodeJS.Platform = process.platform,\n home?: string,\n): string {\n const p = orchestratorStatePath(env, platform, home);\n fs.mkdirSync(path.dirname(p), { recursive: true });\n const next: OrchestratorPinState = {\n ...state,\n schemaVersion: 'model-orchestrator-pin/0',\n updatedAt: new Date().toISOString(),\n };\n fs.writeFileSync(p, JSON.stringify(next, null, 2) + '\\n', 'utf8');\n return p;\n}\n\nexport function pinPack(\n mode: ModelMode,\n packId: string,\n env?: NodeJS.ProcessEnv,\n platform?: NodeJS.Platform,\n home?: string,\n): OrchestratorPinState {\n const state = readOrchestratorState(env, platform, home);\n if (!packById(packId)) {\n throw new Error(`unknown pack id: ${packId}`);\n }\n state.pins[mode] = packId;\n writeOrchestratorState(state, env, platform, home);\n return state;\n}\n\nexport function unpinPack(\n mode: ModelMode,\n env?: NodeJS.ProcessEnv,\n platform?: NodeJS.Platform,\n home?: string,\n): OrchestratorPinState {\n const state = readOrchestratorState(env, platform, home);\n delete state.pins[mode];\n writeOrchestratorState(state, env, platform, home);\n return state;\n}\n\nexport function setDefaultMode(\n mode: ModelMode,\n env?: NodeJS.ProcessEnv,\n platform?: NodeJS.Platform,\n home?: string,\n): OrchestratorPinState {\n const state = readOrchestratorState(env, platform, home);\n state.defaultMode = mode;\n writeOrchestratorState(state, env, platform, home);\n return state;\n}\n\n/** Active pin for a mode, if any. */\nexport function activePin(\n mode: ModelMode,\n state: OrchestratorPinState = readOrchestratorState(),\n): { mode: ModelMode; packId: string } | null {\n const packId = state.pins[mode];\n return packId ? { mode, packId } : null;\n}\n\n/** Map backend hint to vg code --provider id. */\nexport function providerForBackend(backend: PackWeightsRef['backend']): string {\n switch (backend) {\n case 'ollama':\n return 'ollama';\n case 'llama.cpp':\n return 'llama-cpp';\n case 'lm-studio':\n return 'lmstudio';\n default:\n return 'ollama';\n }\n}\n\n/** Parse mode from user string; null if invalid. */\nexport function parseMode(raw: string | undefined | null): ModelMode | null {\n if (!raw) return null;\n const m = raw.trim().toLowerCase();\n if (m === 'spark' || m === 'flow' || m === 'forge') return m;\n return null;\n}\n"]}
@@ -148,7 +148,16 @@ async function ensureWeightCached(ref, options = {}) {
148
148
  }
149
149
  function sha256File(file) {
150
150
  const h = createHash("sha256");
151
- h.update(fs.readFileSync(file));
151
+ const fd = fs.openSync(file, "r");
152
+ try {
153
+ const buf = Buffer.alloc(8 * 1024 * 1024);
154
+ let n;
155
+ while ((n = fs.readSync(fd, buf, 0, buf.length, null)) > 0) {
156
+ h.update(n === buf.length ? buf : buf.subarray(0, n));
157
+ }
158
+ } finally {
159
+ fs.closeSync(fd);
160
+ }
152
161
  return h.digest("hex");
153
162
  }
154
163
  function defaultFetchToFile(url, dest, onProgress) {
@@ -201,6 +210,23 @@ function defaultFetchToFile(url, dest, onProgress) {
201
210
  get(url, 0);
202
211
  });
203
212
  }
213
+ function freeBytesOnVolume(targetPath) {
214
+ let dir = targetPath;
215
+ for (let i = 0; i < 10; i++) {
216
+ try {
217
+ const st = fs.statfsSync?.(dir);
218
+ if (st) {
219
+ const free = Number(st.bavail) * Number(st.bsize);
220
+ if (Number.isFinite(free) && free >= 0) return free;
221
+ }
222
+ } catch {
223
+ }
224
+ const parent = path.dirname(dir);
225
+ if (parent === dir) break;
226
+ dir = parent;
227
+ }
228
+ return void 0;
229
+ }
204
230
  function listCachedWeights(env = process.env) {
205
231
  const dir = weightStoreDir(env);
206
232
  try {
@@ -210,6 +236,6 @@ function listCachedWeights(env = process.env) {
210
236
  }
211
237
  }
212
238
 
213
- export { catalogIntegrityReport, ensureWeightCached, isWeightCached, listCachedWeights, lookupCatalog, weightPathForRef, weightStoreDir };
214
- //# sourceMappingURL=chunk-GYSOQH5C.js.map
215
- //# sourceMappingURL=chunk-GYSOQH5C.js.map
239
+ export { catalogIntegrityReport, ensureWeightCached, freeBytesOnVolume, isWeightCached, listCachedWeights, lookupCatalog, weightPathForRef, weightStoreDir };
240
+ //# sourceMappingURL=chunk-OV4KGXPD.js.map
241
+ //# sourceMappingURL=chunk-OV4KGXPD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime/weight-store.ts"],"names":[],"mappings":";;;;;;;AAoBO,IAAM,8BAAA,uBAAqC,GAAA,CAAI;AAAA,EACpD,gBAAA;AAAA,EACA,OAAA;AAAA,EACA,wBAAA;AAAA,EACA,6BAAA;AAAA,EACA,kBAAA;AAAA,EACA,yBAAA;AAAA,EACA,+BAAA;AAAA,EACA;AACF,CAAC,CAAA;AAGM,SAAS,oBAAoB,QAAA,EAA2B;AAC7D,EAAA,MAAM,CAAA,GAAI,SAAS,WAAA,EAAY;AAC/B,EAAA,IAAI,8BAAA,CAA+B,GAAA,CAAI,CAAC,CAAA,EAAG,OAAO,IAAA;AAClD,EAAA,IAAI,CAAA,CAAE,QAAA,CAAS,iBAAiB,CAAA,EAAG,OAAO,IAAA;AAC1C,EAAA,IAAI,CAAA,CAAE,QAAA,CAAS,QAAQ,CAAA,EAAG,OAAO,IAAA;AACjC,EAAA,IAAI,CAAA,CAAE,QAAA,CAAS,YAAY,CAAA,EAAG,OAAO,IAAA;AACrC,EAAA,OAAO,KAAA;AACT;AA2BO,IAAM,0BAAA,GAAmD;AAAA,EAC9D;AAAA,IACE,GAAA,EAAK,8BAAA;AAAA,IACL,GAAA,EAAK,+GAAA;AAAA,IACL,OAAA,EAAS,YAAA;AAAA,IACT,WAAA,EAAa,WAAA;AAAA;AAAA,IAEb,MAAA,EAAQ,kEAAA;AAAA,IACR,KAAA,EAAO;AAAA,GACT;AAAA,EACA;AAAA,IACE,GAAA,EAAK,8BAAA;AAAA,IACL,GAAA,EAAK,+GAAA;AAAA,IACL,OAAA,EAAS,YAAA;AAAA,IACT,WAAA,EAAa,WAAA;AAAA,IACb,MAAA,EAAQ,kEAAA;AAAA,IACR,KAAA,EAAO;AAAA,GACT;AAAA,EACA;AAAA,IACE,GAAA,EAAK,+BAAA;AAAA,IACL,GAAA,EAAK,iHAAA;AAAA,IACL,OAAA,EAAS,YAAA;AAAA,IACT,WAAA,EAAa,WAAA;AAAA;AAAA,IAEb,MAAA,EAAQ,kEAAA;AAAA,IACR,KAAA,EAAO;AAAA;AAEX,CAAA;AAUO,SAAS,sBAAA,CACd,UAAgC,0BAAA,EACR;AACxB,EAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,MAAA,CAAO,CAAC,MAAM,CAAC,CAAA,CAAE,MAAA,EAAQ,IAAA,EAAM,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,GAAG,CAAA;AAC1E,EAAA,OAAO;AAAA,IACL,OAAO,OAAA,CAAQ,MAAA;AAAA,IACf,MAAA,EAAQ,OAAA,CAAQ,MAAA,GAAS,QAAA,CAAS,MAAA;AAAA,IAClC,QAAA;AAAA,IACA,QAAA,EAAU,SAAS,MAAA,KAAW;AAAA,GAChC;AACF;AAYO,SAAS,cAAA,CAAe,GAAA,GAAyB,OAAA,CAAQ,GAAA,EAAa;AAC3E,EAAA,OAAY,IAAA,CAAA,IAAA,CAAK,gBAAA,CAAiB,GAAG,CAAA,EAAG,SAAS,CAAA;AACnD;AAEO,SAAS,gBAAA,CAAiB,GAAA,EAAa,GAAA,GAAyB,OAAA,CAAQ,GAAA,EAAa;AAC1F,EAAA,MAAM,OAAY,IAAA,CAAA,QAAA,CAAS,GAAG,CAAA,CAAE,OAAA,CAAQ,qBAAqB,GAAG,CAAA;AAChE,EAAA,OAAY,IAAA,CAAA,IAAA,CAAK,cAAA,CAAe,GAAG,CAAA,EAAG,IAAI,CAAA;AAC5C;AAEO,SAAS,cAAA,CAAe,GAAA,EAAa,GAAA,GAAyB,OAAA,CAAQ,GAAA,EAAc;AACzF,EAAA,IAAI;AACF,IAAA,MAAM,CAAA,GAAI,gBAAA,CAAiB,GAAA,EAAK,GAAG,CAAA;AACnC,IAAA,OAAU,cAAW,CAAC,CAAA,IAAQ,EAAA,CAAA,QAAA,CAAS,CAAC,EAAE,IAAA,GAAO,CAAA;AAAA,EACnD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEO,SAAS,aAAA,CAAc,GAAA,EAAa,OAAA,GAAgC,0BAAA,EAAuD;AAChI,EAAA,MAAM,IAAA,GAAO,IAAI,WAAA,EAAY;AAC7B,EAAA,OACE,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,GAAA,CAAI,WAAA,EAAY,KAAM,IAAI,CAAA,IAChD,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,IAAA,CAAK,QAAA,CAAS,CAAA,CAAE,GAAA,CAAI,WAAA,EAAa,CAAA,IAAK,CAAA,CAAE,GAAA,CAAI,WAAA,EAAY,CAAE,QAAA,CAAS,IAAI,CAAC,CAAA,IAC5F,IAAA;AAEJ;AAEO,SAAS,mBAAmB,GAAA,EAAsB;AACvD,EAAA,IAAI;AACF,IAAA,MAAM,CAAA,GAAI,IAAI,GAAA,CAAI,GAAG,CAAA;AACrB,IAAA,IAAI,CAAA,CAAE,QAAA,KAAa,QAAA,EAAU,OAAO,KAAA;AACpC,IAAA,OAAO,mBAAA,CAAoB,EAAE,QAAQ,CAAA;AAAA,EACvC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAoBA,IAAM,QAAA,uBAAe,GAAA,EAA2C;AAMhE,eAAsB,kBAAA,CAAmB,GAAA,EAAa,OAAA,GAAiC,EAAC,EAAkC;AACxH,EAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,GAAA,IAAO,OAAA,CAAQ,GAAA;AACnC,EAAA,MAAM,IAAA,GAAO,gBAAA,CAAiB,GAAA,EAAK,GAAG,CAAA;AACtC,EAAA,IAAI,cAAA,CAAe,GAAA,EAAK,GAAG,CAAA,EAAG;AAC5B,IAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,IAAA,EAAM,IAAA,EAAM,WAAW,IAAA,EAAK;AAAA,EACjD;AAEA,EAAA,MAAM,QAAA,GAAW,QAAA,CAAS,GAAA,CAAI,IAAI,CAAA;AAClC,EAAA,IAAI,UAAU,OAAO,QAAA;AAErB,EAAA,MAAM,QAAQ,YAA2C;AAEvD,IAAA,IAAI,cAAA,CAAe,GAAA,EAAK,GAAG,CAAA,EAAG;AAC5B,MAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,IAAA,EAAM,IAAA,EAAM,WAAW,IAAA,EAAK;AAAA,IACjD;AAEA,IAAA,MAAM,KAAA,GAAQ,cAAc,GAAG,CAAA;AAC/B,IAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,GAAA,IAAO,KAAA,EAAO,GAAA;AAClC,IAAA,IAAI,CAAC,GAAA,EAAK;AACR,MAAA,OAAO,EAAE,IAAI,KAAA,EAAO,KAAA,EAAO,gDAAgD,GAAG,CAAA,mDAAA,EAAiD,IAAI,CAAA,CAAA,EAAG;AAAA,IACxI;AACA,IAAA,IAAI,CAAC,kBAAA,CAAmB,GAAG,CAAA,EAAG;AAC5B,MAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,KAAA,EAAO,CAAA,iCAAA,EAAoC,GAAG,CAAA,CAAA,EAAG;AAAA,IACvE;AAEA,IAAA,IAAI;AACF,MAAG,aAAe,IAAA,CAAA,OAAA,CAAQ,IAAI,GAAG,EAAE,SAAA,EAAW,MAAM,CAAA;AACpD,MAAA,MAAM,GAAA,GAAM,GAAG,IAAI,CAAA,SAAA,EAAY,QAAQ,GAAG,CAAA,CAAA,EAAI,IAAA,CAAK,GAAA,EAAK,CAAA,CAAA;AACxD,MAAA,MAAM,OAAA,GAAU,QAAQ,WAAA,IAAe,kBAAA;AACvC,MAAA,OAAA,CAAQ,UAAA,GAAa,CAAA,YAAA,EAAe,GAAG,CAAA,CAAE,CAAA;AACzC,MAAA,MAAM,OAAA,CAAQ,GAAA,EAAK,GAAA,EAAK,OAAA,CAAQ,UAAU,CAAA;AAC1C,MAAA,MAAM,GAAA,GAAA,CAAO,OAAA,CAAQ,cAAA,IAAkB,KAAA,EAAO,SAAS,IAAA,EAAK;AAC5D,MAAA,IAAI,GAAA,EAAK;AACP,QAAA,MAAM,MAAA,GAAS,WAAW,GAAG,CAAA;AAC7B,QAAA,IAAI,MAAA,KAAW,GAAA,CAAI,WAAA,EAAY,EAAG;AAChC,UAAA,IAAI;AACF,YAAG,cAAW,GAAG,CAAA;AAAA,UACnB,CAAA,CAAA,MAAQ;AAAA,UAER;AACA,UAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,KAAA,EAAO,CAAA,oBAAA,EAAuB,GAAG,CAAA,WAAA,EAAc,GAAG,CAAA,MAAA,EAAS,MAAM,CAAA,CAAA,CAAA,EAAI;AAAA,QAC3F;AAAA,MACF,CAAA,MAAA,IAAW,KAAA,IAAS,CAAC,KAAA,CAAM,MAAA,EAAQ;AACjC,QAAA,OAAA,CAAQ,UAAA,GAAa,CAAA,SAAA,EAAY,GAAG,CAAA,2DAAA,CAAwD,CAAA;AAAA,MAC9F;AAEA,MAAA,IAAI,cAAA,CAAe,GAAA,EAAK,GAAG,CAAA,EAAG;AAC5B,QAAA,IAAI;AACF,UAAG,cAAW,GAAG,CAAA;AAAA,QACnB,CAAA,CAAA,MAAQ;AAAA,QAER;AACA,QAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,IAAA,EAAM,IAAA,EAAM,WAAW,IAAA,EAAK;AAAA,MACjD;AACA,MAAG,EAAA,CAAA,UAAA,CAAW,KAAK,IAAI,CAAA;AACvB,MAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,IAAA,EAAM,IAAA,EAAM,WAAW,KAAA,EAAM;AAAA,IAClD,SAAS,CAAA,EAAG;AACV,MAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,KAAA,EAAO,CAAA,YAAa,QAAQ,CAAA,CAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAAA,EAAE;AAAA,IACxE,CAAA,SAAE;AACA,MAAA,QAAA,CAAS,OAAO,IAAI,CAAA;AAAA,IACtB;AAAA,EACF,CAAA,GAAG;AAEH,EAAA,QAAA,CAAS,GAAA,CAAI,MAAM,IAAI,CAAA;AACvB,EAAA,OAAO,IAAA;AACT;AAOA,SAAS,WAAW,IAAA,EAAsB;AACxC,EAAA,MAAM,CAAA,GAAI,WAAW,QAAQ,CAAA;AAC7B,EAAA,MAAM,EAAA,GAAQ,EAAA,CAAA,QAAA,CAAS,IAAA,EAAM,GAAG,CAAA;AAChC,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,KAAA,CAAM,CAAA,GAAI,OAAO,IAAI,CAAA;AACxC,IAAA,IAAI,CAAA;AACJ,IAAA,OAAA,CAAQ,CAAA,GAAO,YAAS,EAAA,EAAI,GAAA,EAAK,GAAG,GAAA,CAAI,MAAA,EAAQ,IAAI,CAAA,IAAK,CAAA,EAAG;AAC1D,MAAA,CAAA,CAAE,MAAA,CAAO,MAAM,GAAA,CAAI,MAAA,GAAS,MAAM,GAAA,CAAI,QAAA,CAAS,CAAA,EAAG,CAAC,CAAC,CAAA;AAAA,IACtD;AAAA,EACF,CAAA,SAAE;AACA,IAAG,aAAU,EAAE,CAAA;AAAA,EACjB;AACA,EAAA,OAAO,CAAA,CAAE,OAAO,KAAK,CAAA;AACvB;AAGO,SAAS,kBAAA,CAAmB,GAAA,EAAa,IAAA,EAAc,UAAA,EAAoD;AAChH,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,IAAA,MAAM,GAAA,GAAM,CAAC,CAAA,EAAW,SAAA,KAA4B;AAClD,MAAA,IAAI,YAAY,CAAA,EAAG;AACjB,QAAA,MAAA,CAAO,IAAI,KAAA,CAAM,oBAAoB,CAAC,CAAA;AACtC,QAAA;AAAA,MACF;AACA,MAAA,MAAM,GAAA,GAAM,CAAA,CAAE,UAAA,CAAW,QAAQ,IAAI,KAAA,GAAQ,IAAA;AAC7C,MAAA,MAAM,GAAA,GAAM,GAAA,CAAI,GAAA,CAAI,CAAA,EAAG,CAAC,GAAA,KAAQ;AAC9B,QAAA,MAAM,IAAA,GAAO,IAAI,UAAA,IAAc,CAAA;AAC/B,QAAA,IAAI,QAAQ,GAAA,IAAO,IAAA,GAAO,GAAA,IAAO,GAAA,CAAI,QAAQ,QAAA,EAAU;AACrD,UAAA,MAAM,OAAO,IAAI,GAAA,CAAI,IAAI,OAAA,CAAQ,QAAA,EAAU,CAAC,CAAA,CAAE,IAAA;AAE9C,UAAA,IAAI;AACF,YAAA,MAAM,OAAA,GAAU,IAAI,GAAA,CAAI,IAAI,CAAA;AAC5B,YAAA,IAAI,QAAQ,QAAA,KAAa,QAAA,IAAY,CAAC,mBAAA,CAAoB,OAAA,CAAQ,QAAQ,CAAA,EAAG;AAC3E,cAAA,MAAA,CAAO,IAAI,KAAA,CAAM,CAAA,+BAAA,EAAkC,QAAQ,QAAA,IAAY,IAAI,EAAE,CAAC,CAAA;AAC9E,cAAA;AAAA,YACF;AAAA,UACF,CAAA,CAAA,MAAQ;AACN,YAAA,MAAA,CAAO,IAAI,KAAA,CAAM,sBAAsB,CAAC,CAAA;AACxC,YAAA;AAAA,UACF;AACA,UAAA,GAAA,CAAI,MAAA,EAAO;AACX,UAAA,GAAA,CAAI,IAAA,EAAM,YAAY,CAAC,CAAA;AACvB,UAAA;AAAA,QACF;AACA,QAAA,IAAI,SAAS,GAAA,EAAK;AAChB,UAAA,MAAA,CAAO,IAAI,KAAA,CAAM,CAAA,KAAA,EAAQ,IAAI,mBAAmB,CAAC,CAAA;AACjD,UAAA,GAAA,CAAI,MAAA,EAAO;AACX,UAAA;AAAA,QACF;AACA,QAAA,MAAM,QAAQ,MAAA,CAAO,GAAA,CAAI,OAAA,CAAQ,gBAAgB,KAAK,CAAC,CAAA;AACvD,QAAA,IAAI,GAAA,GAAM,CAAA;AACV,QAAA,MAAM,GAAA,GAAS,qBAAkB,IAAI,CAAA;AACrC,QAAA,GAAA,CAAI,EAAA,CAAG,MAAA,EAAQ,CAAC,KAAA,KAAkB;AAChC,UAAA,GAAA,IAAO,KAAA,CAAM,MAAA;AACb,UAAA,IAAI,QAAQ,CAAA,IAAK,GAAA,IAAO,IAAI,IAAA,GAAO,IAAA,CAAA,GAAQ,MAAM,MAAA,EAAQ;AACvD,YAAA,UAAA,GAAa,GAAG,IAAA,CAAK,KAAA,CAAO,MAAM,GAAA,GAAO,KAAK,CAAC,CAAA,CAAA,CAAG,CAAA;AAAA,UACpD;AAAA,QACF,CAAC,CAAA;AACD,QAAA,GAAA,CAAI,KAAK,GAAG,CAAA;AACZ,QAAA,GAAA,CAAI,EAAA,CAAG,QAAA,EAAU,MAAM,OAAA,EAAS,CAAA;AAChC,QAAA,GAAA,CAAI,EAAA,CAAG,SAAS,MAAM,CAAA;AACtB,QAAA,GAAA,CAAI,EAAA,CAAG,SAAS,MAAM,CAAA;AAAA,MACxB,CAAC,CAAA;AACD,MAAA,GAAA,CAAI,EAAA,CAAG,SAAS,MAAM,CAAA;AAAA,IACxB,CAAA;AACA,IAAA,GAAA,CAAI,KAAK,CAAC,CAAA;AAAA,EACZ,CAAC,CAAA;AACH;AAMO,SAAS,kBAAkB,UAAA,EAAwC;AACxE,EAAA,IAAI,GAAA,GAAM,UAAA;AACV,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,EAAA,EAAI,CAAA,EAAA,EAAK;AAC3B,IAAA,IAAI;AACF,MAAA,MAAM,EAAA,GAIJ,gBAAa,GAAG,CAAA;AAClB,MAAA,IAAI,EAAA,EAAI;AACN,QAAA,MAAM,OAAO,MAAA,CAAO,EAAA,CAAG,MAAM,CAAA,GAAI,MAAA,CAAO,GAAG,KAAK,CAAA;AAChD,QAAA,IAAI,OAAO,QAAA,CAAS,IAAI,CAAA,IAAK,IAAA,IAAQ,GAAG,OAAO,IAAA;AAAA,MACjD;AAAA,IACF,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA,MAAM,MAAA,GAAc,aAAQ,GAAG,CAAA;AAC/B,IAAA,IAAI,WAAW,GAAA,EAAK;AACpB,IAAA,GAAA,GAAM,MAAA;AAAA,EACR;AACA,EAAA,OAAO,MAAA;AACT;AAGO,SAAS,iBAAA,CAAkB,GAAA,GAAyB,OAAA,CAAQ,GAAA,EAA4C;AAC7G,EAAA,MAAM,GAAA,GAAM,eAAe,GAAG,CAAA;AAC9B,EAAA,IAAI;AACF,IAAA,OACG,EAAA,CAAA,WAAA,CAAY,GAAG,CAAA,CACf,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,QAAA,CAAS,OAAO,CAAC,CAAA,CACjC,IAAA,GACA,GAAA,CAAI,CAAC,CAAA,MAAO,EAAE,IAAA,EAAM,CAAA,EAAG,MAAW,IAAA,CAAA,IAAA,CAAK,GAAA,EAAK,CAAC,CAAA,EAAE,CAAE,CAAA;AAAA,EACtD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAC;AAAA,EACV;AACF","file":"chunk-OV4KGXPD.js","sourcesContent":["/**\n * First-party weight store — content-addressed GGUF cache under the Vibgrate\n * cache root (never in-repo). Complements Ollama as a download channel so\n * embedded llama.cpp packs need not depend on a third-party app for weights.\n *\n * Only HTTPS URLs from an allowlist (or pack-declared URLs that pass the same\n * host allowlist) are fetched. No auto-download except via explicit\n * `vg models install` / executor consent.\n */\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport * as https from 'node:https';\nimport * as http from 'node:http';\nimport { createHash } from 'node:crypto';\nimport { vibgrateCacheDir } from './paths.js';\n\nexport const WEIGHT_STORE_SCHEMA = 'weight-store/0' as const;\n\n/** Hosts we will download weights from (no arbitrary open proxy). */\nexport const WEIGHT_DOWNLOAD_HOST_ALLOWLIST = new Set([\n 'huggingface.co',\n 'hf.co',\n 'cdn-lfs.huggingface.co',\n 'cdn-lfs-us-1.huggingface.co',\n 'us.aws.cdn.hf.co',\n 'cas-server.xethub.hf.co',\n 'objects.githubusercontent.com',\n 'github.com',\n]);\n\n/** Host suffixes allowed for HF LFS / Xet CDN redirects. */\nexport function isAllowedWeightHost(hostname: string): boolean {\n const h = hostname.toLowerCase();\n if (WEIGHT_DOWNLOAD_HOST_ALLOWLIST.has(h)) return true;\n if (h.endsWith('.huggingface.co')) return true;\n if (h.endsWith('.hf.co')) return true;\n if (h.endsWith('.cdn.hf.co')) return true;\n return false;\n}\n\nexport interface WeightCatalogEntry {\n /** Stable ref (matches pack weightsRef or basename). */\n ref: string;\n /** HTTPS URL to the GGUF (or redirected LFS object). */\n url: string;\n /** Optional expected size for progress UX. */\n bytes?: number;\n license?: string;\n /**\n * When set, download **must** match this sha256 or install fails (B6).\n * Leave unset only while pinning is pending — status reports unpinned.\n */\n sha256?: string;\n /** Pack channel this entry was verified against. */\n packChannel?: string;\n}\n\n/**\n * Curated first-party catalog — small, versioned with packs. Not a general hub.\n * URLs point at public Hugging Face GGUF artifacts for Qwen2.5-Coder.\n *\n * Integrity: sha256 pins are required for production installs once verified.\n * Entries without sha256 are marked unpinned in {@link catalogIntegrityReport}\n * and still download, but CI should fail if any pack primary lacks a pin.\n */\nexport const FIRST_PARTY_WEIGHT_CATALOG: WeightCatalogEntry[] = [\n {\n ref: 'qwen2.5-coder-3b-q4_k_m.gguf',\n url: 'https://huggingface.co/Qwen/Qwen2.5-Coder-3B-Instruct-GGUF/resolve/main/qwen2.5-coder-3b-instruct-q4_k_m.gguf',\n license: 'Apache-2.0',\n packChannel: '2026.07.3',\n // Git LFS oid = content sha256 (from HF API tree, 2026-07-27).\n sha256: '724fb256bec1ff062b2f65e4569e871ad2e95ab2a3989723d1769c54294730b7',\n bytes: 2_104_932_800,\n },\n {\n ref: 'qwen2.5-coder-7b-q4_k_m.gguf',\n url: 'https://huggingface.co/Qwen/Qwen2.5-Coder-7B-Instruct-GGUF/resolve/main/qwen2.5-coder-7b-instruct-q4_k_m.gguf',\n license: 'Apache-2.0',\n packChannel: '2026.07.3',\n sha256: '509287f78cb4d4cf6b3843734733b914b2c158e43e22a7f4bf5e963800894d3c',\n bytes: 4_683_073_536,\n },\n {\n ref: 'qwen2.5-coder-14b-q4_k_m.gguf',\n url: 'https://huggingface.co/Qwen/Qwen2.5-Coder-14B-Instruct-GGUF/resolve/main/qwen2.5-coder-14b-instruct-q4_k_m.gguf',\n license: 'Apache-2.0',\n packChannel: '2026.07.4',\n // Git LFS oid = content sha256 (from HF API tree, 2026-07-27).\n sha256: 'c1e659736d89ac1065fb495330fb824d94001974a4bfa78e7270e43476a8d940',\n bytes: 8_988_110_272,\n },\n];\n\nexport interface CatalogIntegrityReport {\n total: number;\n pinned: number;\n unpinned: string[];\n /** True when every entry has sha256. */\n complete: boolean;\n}\n\nexport function catalogIntegrityReport(\n catalog: WeightCatalogEntry[] = FIRST_PARTY_WEIGHT_CATALOG,\n): CatalogIntegrityReport {\n const unpinned = catalog.filter((e) => !e.sha256?.trim()).map((e) => e.ref);\n return {\n total: catalog.length,\n pinned: catalog.length - unpinned.length,\n unpinned,\n complete: unpinned.length === 0,\n };\n}\n\n/** Require sha256 on every catalog entry (CI gate for pack releases). */\nexport function assertCatalogPinned(catalog: WeightCatalogEntry[] = FIRST_PARTY_WEIGHT_CATALOG): void {\n const report = catalogIntegrityReport(catalog);\n if (!report.complete) {\n throw new Error(\n `weight catalog incomplete: ${report.unpinned.length}/${report.total} entries missing sha256: ${report.unpinned.join(', ')}`,\n );\n }\n}\n\nexport function weightStoreDir(env: NodeJS.ProcessEnv = process.env): string {\n return path.join(vibgrateCacheDir(env), 'weights');\n}\n\nexport function weightPathForRef(ref: string, env: NodeJS.ProcessEnv = process.env): string {\n const base = path.basename(ref).replace(/[^a-zA-Z0-9._+-]/g, '_');\n return path.join(weightStoreDir(env), base);\n}\n\nexport function isWeightCached(ref: string, env: NodeJS.ProcessEnv = process.env): boolean {\n try {\n const p = weightPathForRef(ref, env);\n return fs.existsSync(p) && fs.statSync(p).size > 0;\n } catch {\n return false;\n }\n}\n\nexport function lookupCatalog(ref: string, catalog: WeightCatalogEntry[] = FIRST_PARTY_WEIGHT_CATALOG): WeightCatalogEntry | null {\n const want = ref.toLowerCase();\n return (\n catalog.find((e) => e.ref.toLowerCase() === want) ??\n catalog.find((e) => want.includes(e.ref.toLowerCase()) || e.ref.toLowerCase().includes(want)) ??\n null\n );\n}\n\nexport function isAllowedWeightUrl(url: string): boolean {\n try {\n const u = new URL(url);\n if (u.protocol !== 'https:') return false;\n return isAllowedWeightHost(u.hostname);\n } catch {\n return false;\n }\n}\n\nexport interface DownloadWeightOptions {\n env?: NodeJS.ProcessEnv;\n /** Override catalog URL. */\n url?: string;\n expectedSha256?: string;\n onProgress?: (line: string) => void;\n /** Injectable fetch for tests. */\n fetchToFile?: (url: string, dest: string, onProgress?: (line: string) => void) => Promise<void>;\n}\n\nexport interface DownloadWeightResult {\n ok: boolean;\n path?: string;\n error?: string;\n fromCache?: boolean;\n}\n\n/** In-flight downloads: one network fetch per dest path (concurrent install-safe). */\nconst inflight = new Map<string, Promise<DownloadWeightResult>>();\n\n/**\n * Ensure weights for `ref` exist in the first-party store. Downloads when missing.\n * Concurrent callers for the same ref share a single download promise.\n */\nexport async function ensureWeightCached(ref: string, options: DownloadWeightOptions = {}): Promise<DownloadWeightResult> {\n const env = options.env ?? process.env;\n const dest = weightPathForRef(ref, env);\n if (isWeightCached(ref, env)) {\n return { ok: true, path: dest, fromCache: true };\n }\n\n const existing = inflight.get(dest);\n if (existing) return existing;\n\n const work = (async (): Promise<DownloadWeightResult> => {\n // Re-check after joining the queue.\n if (isWeightCached(ref, env)) {\n return { ok: true, path: dest, fromCache: true };\n }\n\n const entry = lookupCatalog(ref);\n const url = options.url ?? entry?.url;\n if (!url) {\n return { ok: false, error: `no first-party download URL for weights ref \"${ref}\" — set a pack downloadUrl or place a gguf at ${dest}` };\n }\n if (!isAllowedWeightUrl(url)) {\n return { ok: false, error: `weight URL host not allowlisted: ${url}` };\n }\n\n try {\n fs.mkdirSync(path.dirname(dest), { recursive: true });\n const tmp = `${dest}.partial.${process.pid}.${Date.now()}`;\n const fetchFn = options.fetchToFile ?? defaultFetchToFile;\n options.onProgress?.(`downloading ${ref}`);\n await fetchFn(url, tmp, options.onProgress);\n const sha = (options.expectedSha256 ?? entry?.sha256)?.trim();\n if (sha) {\n const actual = sha256File(tmp);\n if (actual !== sha.toLowerCase()) {\n try {\n fs.unlinkSync(tmp);\n } catch {\n /* ignore */\n }\n return { ok: false, error: `sha256 mismatch for ${ref} (expected ${sha}, got ${actual})` };\n }\n } else if (entry && !entry.sha256) {\n options.onProgress?.(`warning: ${ref} has no sha256 pin in catalog — integrity not verified`);\n }\n // Atomic publish: if another worker won the race, drop our partial.\n if (isWeightCached(ref, env)) {\n try {\n fs.unlinkSync(tmp);\n } catch {\n /* ignore */\n }\n return { ok: true, path: dest, fromCache: true };\n }\n fs.renameSync(tmp, dest);\n return { ok: true, path: dest, fromCache: false };\n } catch (e) {\n return { ok: false, error: e instanceof Error ? e.message : String(e) };\n } finally {\n inflight.delete(dest);\n }\n })();\n\n inflight.set(dest, work);\n return work;\n}\n\n/**\n * Stream a file through sha256. Never `readFileSync` whole weights — Node rejects\n * buffers larger than ~2 GiB (`File size (…) is greater than 2 GiB`), which broke\n * Flow/Forge installs even when the download completed.\n */\nfunction sha256File(file: string): string {\n const h = createHash('sha256');\n const fd = fs.openSync(file, 'r');\n try {\n const buf = Buffer.alloc(8 * 1024 * 1024);\n let n: number;\n while ((n = fs.readSync(fd, buf, 0, buf.length, null)) > 0) {\n h.update(n === buf.length ? buf : buf.subarray(0, n));\n }\n } finally {\n fs.closeSync(fd);\n }\n return h.digest('hex');\n}\n\n/** Minimal HTTPS GET with redirect follow (tests inject fetchToFile). */\nexport function defaultFetchToFile(url: string, dest: string, onProgress?: (line: string) => void): Promise<void> {\n return new Promise((resolve, reject) => {\n const get = (u: string, redirects: number): void => {\n if (redirects > 8) {\n reject(new Error('too many redirects'));\n return;\n }\n const lib = u.startsWith('https:') ? https : http;\n const req = lib.get(u, (res) => {\n const code = res.statusCode ?? 0;\n if (code >= 300 && code < 400 && res.headers.location) {\n const next = new URL(res.headers.location, u).href;\n // Redirects must stay on HTTPS + allowlisted hosts (incl. HF LFS/Xet CDNs).\n try {\n const nextUrl = new URL(next);\n if (nextUrl.protocol !== 'https:' || !isAllowedWeightHost(nextUrl.hostname)) {\n reject(new Error(`redirect host not allowlisted: ${nextUrl.hostname || next}`));\n return;\n }\n } catch {\n reject(new Error('invalid redirect URL'));\n return;\n }\n res.resume();\n get(next, redirects + 1);\n return;\n }\n if (code !== 200) {\n reject(new Error(`HTTP ${code} fetching weights`));\n res.resume();\n return;\n }\n const total = Number(res.headers['content-length'] || 0);\n let got = 0;\n const out = fs.createWriteStream(dest);\n res.on('data', (chunk: Buffer) => {\n got += chunk.length;\n if (total > 0 && got % (8 * 1024 * 1024) < chunk.length) {\n onProgress?.(`${Math.floor((100 * got) / total)}%`);\n }\n });\n res.pipe(out);\n out.on('finish', () => resolve());\n out.on('error', reject);\n res.on('error', reject);\n });\n req.on('error', reject);\n };\n get(url, 0);\n });\n}\n\n/**\n * Free bytes on the volume that holds `targetPath` (weight store / cache).\n * Best-effort via `statfsSync` (Node 18.15+); walks parents if path is missing.\n */\nexport function freeBytesOnVolume(targetPath: string): number | undefined {\n let dir = targetPath;\n for (let i = 0; i < 10; i++) {\n try {\n const st = (\n fs as typeof fs & {\n statfsSync?: (p: string) => { bavail: number | bigint; bsize: number | bigint };\n }\n ).statfsSync?.(dir);\n if (st) {\n const free = Number(st.bavail) * Number(st.bsize);\n if (Number.isFinite(free) && free >= 0) return free;\n }\n } catch {\n /* try parent */\n }\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return undefined;\n}\n\n/** List GGUF files already in the first-party store (for discovery). */\nexport function listCachedWeights(env: NodeJS.ProcessEnv = process.env): Array<{ name: string; path: string }> {\n const dir = weightStoreDir(env);\n try {\n return fs\n .readdirSync(dir)\n .filter((n) => n.endsWith('.gguf'))\n .sort()\n .map((n) => ({ name: n, path: path.join(dir, n) }));\n } catch {\n return [];\n }\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { isPackageInstalled, ensurePackage } from './chunk-OSD546W7.js';
2
- import { isWeightCached, lookupCatalog } from './chunk-GYSOQH5C.js';
2
+ import { isWeightCached, lookupCatalog } from './chunk-OV4KGXPD.js';
3
3
  import { spawnSync } from 'child_process';
4
4
 
5
5
  // src/runtime/model-install-plan.ts
@@ -352,5 +352,5 @@ async function ensureManagerRuntime(opts) {
352
352
  }
353
353
 
354
354
  export { buildModelInstallPlan, ensureManagerRuntime, formatManagerBadgeLine, managerBadge, managerFromProviderId };
355
- //# sourceMappingURL=chunk-UIOBFLE6.js.map
356
- //# sourceMappingURL=chunk-UIOBFLE6.js.map
355
+ //# sourceMappingURL=chunk-SZSNPXSW.js.map
356
+ //# sourceMappingURL=chunk-SZSNPXSW.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/runtime/model-install-plan.ts","../src/runtime/model-manager.ts"],"names":[],"mappings":"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","file":"chunk-UIOBFLE6.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
+ {"version":3,"sources":["../src/runtime/model-install-plan.ts","../src/runtime/model-manager.ts"],"names":[],"mappings":"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","file":"chunk-SZSNPXSW.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"]}