@otto-code/brain 0.8.7 → 0.8.9

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 (61) hide show
  1. package/dist/cli.js +2 -1
  2. package/dist/commands/bench.js +19 -5
  3. package/dist/commands/catalog.d.ts +3 -0
  4. package/dist/commands/catalog.js +2 -0
  5. package/dist/commands/pull.d.ts +1 -0
  6. package/dist/commands/pull.js +47 -14
  7. package/dist/commands/repo-download.d.ts +14 -0
  8. package/dist/commands/repo-download.js +29 -0
  9. package/dist/commands/runtime.d.ts +3 -0
  10. package/dist/commands/runtime.js +65 -18
  11. package/dist/commands/search.d.ts +3 -0
  12. package/dist/commands/search.js +38 -17
  13. package/dist/config/builtin-hosting-profiles.d.ts +8 -0
  14. package/dist/config/builtin-hosting-profiles.js +32 -0
  15. package/dist/config/hosting-profiles.d.ts +33 -0
  16. package/dist/config/hosting-profiles.js +71 -0
  17. package/dist/config/index.d.ts +1 -0
  18. package/dist/config/index.js +1 -0
  19. package/dist/config/paths.d.ts +2 -0
  20. package/dist/config/paths.js +1 -0
  21. package/dist/config/profile-edit.d.ts +5 -3
  22. package/dist/config/profile-edit.js +134 -14
  23. package/dist/config/profiles.js +66 -3
  24. package/dist/config/schema.d.ts +998 -0
  25. package/dist/config/schema.js +79 -0
  26. package/dist/config/store.js +28 -16
  27. package/dist/gguf.d.ts +1 -0
  28. package/dist/gguf.js +1 -0
  29. package/dist/models/download.d.ts +7 -0
  30. package/dist/models/download.js +165 -17
  31. package/dist/models/enrich.d.ts +6 -19
  32. package/dist/models/enrich.js +138 -4
  33. package/dist/models/hf.d.ts +14 -1
  34. package/dist/models/hf.js +239 -6
  35. package/dist/models/index.d.ts +2 -2
  36. package/dist/models/index.js +8 -5
  37. package/dist/models/manage.d.ts +4 -0
  38. package/dist/models/manage.js +34 -4
  39. package/dist/models/scan.js +8 -42
  40. package/dist/ops/calibrate.d.ts +4 -1
  41. package/dist/ops/calibrate.js +10 -7
  42. package/dist/ops/sweep.d.ts +3 -1
  43. package/dist/ops/sweep.js +3 -3
  44. package/dist/runtime/args.d.ts +2 -2
  45. package/dist/runtime/args.js +18 -1
  46. package/dist/runtime/index.d.ts +8 -1
  47. package/dist/runtime/index.js +11 -1
  48. package/dist/runtime/managed.d.ts +40 -0
  49. package/dist/runtime/managed.js +146 -7
  50. package/dist/service/host-api.d.ts +20 -3
  51. package/dist/service/host-api.js +313 -20
  52. package/dist/service/router.d.ts +18 -0
  53. package/dist/service/router.js +89 -4
  54. package/dist/service/serve.js +221 -22
  55. package/dist/service/supervisor.d.ts +32 -4
  56. package/dist/service/supervisor.js +30 -6
  57. package/dist/tui/app.js +1 -1
  58. package/dist/types.d.ts +24 -0
  59. package/dist/vram.d.ts +3 -0
  60. package/dist/vram.js +24 -6
  61. package/package.json +1 -1
package/dist/types.d.ts CHANGED
@@ -5,6 +5,8 @@
5
5
  */
6
6
  export interface ModelMetadata {
7
7
  arch?: string | null;
8
+ name?: string | null;
9
+ basename?: string | null;
8
10
  contextLength?: number | null;
9
11
  blockCount?: number | null;
10
12
  headCount?: number | null;
@@ -26,6 +28,22 @@ export interface ModelFeatures {
26
28
  imatrix: boolean;
27
29
  distilled: boolean;
28
30
  }
31
+ export type ModelComponentRole = "vision_projector" | "speculative_drafter";
32
+ /** A catalog-declared companion artifact resolved against local disk. */
33
+ export interface ModelComponent {
34
+ id: string;
35
+ label: string;
36
+ description: string;
37
+ role: ModelComponentRole;
38
+ path: string | null;
39
+ bytes: number;
40
+ required: boolean;
41
+ defaultDownload: boolean;
42
+ defaultLoad: boolean;
43
+ available: boolean;
44
+ unavailableReason?: string;
45
+ minRuntimeBuild?: number;
46
+ }
29
47
  /** A GGUF model discovered on disk (or resolvable from the download catalog). */
30
48
  export interface Model {
31
49
  id: string;
@@ -57,10 +75,16 @@ export interface Model {
57
75
  catalogId?: string;
58
76
  /** Back-reference: the hfRepo of the reconciled catalog entry, if matched. */
59
77
  catalogHfRepo?: string;
78
+ /** Hosting-profile family from the catalog or normalized GGUF metadata. */
79
+ family?: string;
80
+ /** Present only when this catalog entry declares a component manifest. */
81
+ components?: ModelComponent[];
60
82
  }
61
83
  /** A resolved llama.cpp runtime: an executable paired with its vendor DLL dir. */
62
84
  export interface Runtime {
63
85
  label: string;
86
+ /** Human-readable runtime identity, separate from the filesystem-safe label. */
87
+ displayName?: string;
64
88
  version: string;
65
89
  dir: string;
66
90
  exe: string;
package/dist/vram.d.ts CHANGED
@@ -21,6 +21,9 @@ export type BudgetSource = "measured" | "theoretical" | "unknown";
21
21
  export interface Budget {
22
22
  weightsBytes: number;
23
23
  mmprojBytes: number;
24
+ componentBytes: number;
25
+ drafterKvBytes: number;
26
+ imageProcessingBytes: number;
24
27
  kvBytes: number;
25
28
  overheadBytes: number;
26
29
  totalBytes: number;
package/dist/vram.js CHANGED
@@ -35,7 +35,17 @@ export function theoreticalKvBytesPerToken(metadata, cacheTypeK, cacheTypeV) {
35
35
  /** Compute a VRAM budget for a profile. */
36
36
  export function budget({ model, profile, calibration = null, totalVramBytes, reserveBytes = 1.5 * GIB, }) {
37
37
  const weights = model.sizeBytes;
38
- const mmproj = profile.vision && model.mmprojPath ? model.mmprojBytes : 0;
38
+ const enabled = new Set(profile.enabledComponents ?? []);
39
+ const components = model.components ?? [];
40
+ const projector = components.filter((component) => component.role === "vision_projector" && enabled.has(component.id) && component.available);
41
+ const drafters = components.filter((component) => component.role === "speculative_drafter" && enabled.has(component.id) && component.available);
42
+ const componentBytes = components.length
43
+ ? [...projector, ...drafters].reduce((total, component) => total + component.bytes, 0)
44
+ : profile.vision && model.mmprojPath
45
+ ? model.mmprojBytes
46
+ : 0;
47
+ const mmproj = projector.reduce((total, component) => total + component.bytes, 0) ||
48
+ (components.length ? 0 : componentBytes);
39
49
  const theoretical = theoreticalKvBytesPerToken(model.metadata, profile.cacheTypeK, profile.cacheTypeV);
40
50
  let kvBytesPerToken;
41
51
  let source;
@@ -52,14 +62,22 @@ export function budget({ model, profile, calibration = null, totalVramBytes, res
52
62
  source = "unknown";
53
63
  }
54
64
  const kv = kvBytesPerToken * profile.contextSize;
65
+ // The speculative decoder keeps its own KV cache. Until component-specific
66
+ // calibration exists, reserve the same conservative per-token cost.
67
+ const drafterKv = drafters.length * kv;
68
+ // Vision preprocessing needs transient GPU buffers in addition to weights.
69
+ const imageProcessing = projector.length * 256 * 1024 * 1024;
55
70
  // Compute buffers and the CUDA context; measured at ~0.6 GB for a 27B and
56
71
  // superseded by the calibrated value when available.
57
72
  const overhead = calibration && calibration.baseOverheadBytes > 0 ? calibration.baseOverheadBytes : 0.6 * GIB;
58
- const total = weights + mmproj + kv + overhead;
73
+ const total = weights + componentBytes + kv + drafterKv + imageProcessing + overhead;
59
74
  const usable = totalVramBytes - reserveBytes;
60
75
  return {
61
76
  weightsBytes: weights,
62
77
  mmprojBytes: mmproj,
78
+ componentBytes,
79
+ drafterKvBytes: drafterKv,
80
+ imageProcessingBytes: imageProcessing,
63
81
  kvBytes: kv,
64
82
  overheadBytes: overhead,
65
83
  totalBytes: total,
@@ -85,14 +103,14 @@ export function maxContextThatFits({ model, profile, calibration, totalVramBytes
85
103
  });
86
104
  if (probe.kvBytesPerToken <= 0)
87
105
  return null;
88
- const fixed = probe.weightsBytes + probe.mmprojBytes + probe.overheadBytes;
106
+ const fixed = probe.weightsBytes + probe.componentBytes + probe.imageProcessingBytes + probe.overheadBytes;
89
107
  const room = probe.usableBytes - fixed;
90
108
  if (room <= 0)
91
109
  return null;
92
110
  const tokens = Math.floor(room / probe.kvBytesPerToken);
93
- const capped = model.metadata?.contextLength
94
- ? Math.min(tokens, model.metadata.contextLength)
95
- : tokens;
111
+ const native = model.metadata?.contextLength;
112
+ const contextLimit = typeof native === "number" && native > 0 ? native * profile.contextMultiplier : tokens;
113
+ const capped = Math.min(tokens, contextLimit);
96
114
  return Math.max(0, Math.floor(capped / step) * step);
97
115
  }
98
116
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@otto-code/brain",
3
- "version": "0.8.7",
3
+ "version": "0.8.9",
4
4
  "description": "Otto Brain - self-contained host for local GGUF models, with measured VRAM budgeting and reasoning-budget control",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "bin": {