@telora/daemon 0.18.68 → 0.18.77

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 (71) hide show
  1. package/build-info.json +7 -3
  2. package/dist/completion/delivery-advancement-guard.d.ts +25 -0
  3. package/dist/completion/delivery-advancement-guard.d.ts.map +1 -0
  4. package/dist/completion/delivery-advancement-guard.js +54 -0
  5. package/dist/completion/delivery-advancement-guard.js.map +1 -0
  6. package/dist/completion/event-escalations.d.ts +17 -0
  7. package/dist/completion/event-escalations.d.ts.map +1 -1
  8. package/dist/completion/event-escalations.js +52 -0
  9. package/dist/completion/event-escalations.js.map +1 -1
  10. package/dist/completion/event.d.ts +4 -1
  11. package/dist/completion/event.d.ts.map +1 -1
  12. package/dist/completion/event.js +48 -2
  13. package/dist/completion/event.js.map +1 -1
  14. package/dist/completion/index.d.ts +1 -1
  15. package/dist/completion/index.d.ts.map +1 -1
  16. package/dist/completion/index.js +1 -1
  17. package/dist/completion/index.js.map +1 -1
  18. package/dist/completion/team-completion.d.ts.map +1 -1
  19. package/dist/completion/team-completion.js +6 -0
  20. package/dist/completion/team-completion.js.map +1 -1
  21. package/dist/directive/close-loop-stage.d.ts.map +1 -1
  22. package/dist/directive/close-loop-stage.js +4 -0
  23. package/dist/directive/close-loop-stage.js.map +1 -1
  24. package/dist/directive/directive-dispatch.d.ts +2 -2
  25. package/dist/directive/directive-dispatch.d.ts.map +1 -1
  26. package/dist/directive/directive-dispatch.js +7 -5
  27. package/dist/directive/directive-dispatch.js.map +1 -1
  28. package/dist/directive/directive-queue.d.ts +15 -0
  29. package/dist/directive/directive-queue.d.ts.map +1 -1
  30. package/dist/directive/directive-queue.js.map +1 -1
  31. package/dist/directive-executor.d.ts.map +1 -1
  32. package/dist/directive-executor.js +6 -1
  33. package/dist/directive-executor.js.map +1 -1
  34. package/dist/focus-executor.d.ts +53 -8
  35. package/dist/focus-executor.d.ts.map +1 -1
  36. package/dist/focus-executor.js +206 -59
  37. package/dist/focus-executor.js.map +1 -1
  38. package/dist/host-control/capability.d.ts.map +1 -1
  39. package/dist/host-control/capability.js +24 -7
  40. package/dist/host-control/capability.js.map +1 -1
  41. package/dist/host-control/catalog.d.ts +22 -0
  42. package/dist/host-control/catalog.d.ts.map +1 -1
  43. package/dist/host-control/catalog.js +60 -7
  44. package/dist/host-control/catalog.js.map +1 -1
  45. package/dist/host-control/index.d.ts +2 -0
  46. package/dist/host-control/index.d.ts.map +1 -1
  47. package/dist/host-control/index.js +1 -0
  48. package/dist/host-control/index.js.map +1 -1
  49. package/dist/host-control/load.d.ts +64 -4
  50. package/dist/host-control/load.d.ts.map +1 -1
  51. package/dist/host-control/load.js +79 -10
  52. package/dist/host-control/load.js.map +1 -1
  53. package/dist/host-control/sizing.d.ts +12 -0
  54. package/dist/host-control/sizing.d.ts.map +1 -1
  55. package/dist/host-control/sizing.js +17 -2
  56. package/dist/host-control/sizing.js.map +1 -1
  57. package/dist/host-control/swap-manager.d.ts +94 -0
  58. package/dist/host-control/swap-manager.d.ts.map +1 -0
  59. package/dist/host-control/swap-manager.js +156 -0
  60. package/dist/host-control/swap-manager.js.map +1 -0
  61. package/dist/index.js +3 -2
  62. package/dist/index.js.map +1 -1
  63. package/dist/model-resolution.d.ts +31 -0
  64. package/dist/model-resolution.d.ts.map +1 -0
  65. package/dist/model-resolution.js +33 -0
  66. package/dist/model-resolution.js.map +1 -0
  67. package/dist/prompt-sections/persona-sections.d.ts +1 -1
  68. package/dist/prompt-sections/persona-sections.d.ts.map +1 -1
  69. package/dist/prompt-sections/persona-sections.js +22 -1
  70. package/dist/prompt-sections/persona-sections.js.map +1 -1
  71. package/package.json +3 -3
@@ -9,8 +9,8 @@
9
9
  * falls back to the `/v1/models` floor. This guarantees a plain
10
10
  * OpenAI-compatible endpoint is never broken by the probe.
11
11
  */
12
- import { hostGet, hostRootFromBaseUrl, HOST_CONTROL_FETCH_TIMEOUT_MS } from './client.js';
13
- import { HOST_CONTROL_CATALOG_PATH, normalizeLocalCatalog } from './catalog.js';
12
+ import { hostGet, hostRootFromBaseUrl, HOST_CONTROL_FETCH_TIMEOUT_MS, HOST_CONTROL_ERROR_UNREACHABLE, HostControlError, } from './client.js';
13
+ import { HOST_CONTROL_CATALOG_PATH, normalizeLocalCatalog, cacheControllableCatalog, getCachedControllableCatalog, } from './catalog.js';
14
14
  /**
15
15
  * Pure decision: does a control-surface payload prove the host is controllable?
16
16
  * True only when the payload normalizes to at least one usable loadable-model
@@ -38,12 +38,29 @@ export async function detectHostCapability(baseUrl, apiKey) {
38
38
  apiKey,
39
39
  timeoutMs: HOST_CONTROL_FETCH_TIMEOUT_MS,
40
40
  });
41
- return { controllable: isControllableCatalogPayload(payload) };
41
+ const models = normalizeLocalCatalog(payload);
42
+ if (models.length > 0) {
43
+ // Positive read: cache it so a later transient probe failure retains
44
+ // controllability instead of flipping the host to unmanaged.
45
+ cacheControllableCatalog(root, { controllable: true, ids: models.map((m) => m.id), models });
46
+ return { controllable: true };
47
+ }
48
+ // 2xx but not a catalog: a DEFINITIVE not-controllable answer (plain
49
+ // OpenAI-compatible endpoint). Do not consult the cache.
50
+ return { controllable: false };
42
51
  }
43
- catch {
44
- // Fail-safe: any error => not controllable. Detail is intentionally swallowed
45
- // here (the catalog reader logs on its own fall-through); the probe must never
46
- // surface a probe-oracle or break the floor path.
52
+ catch (err) {
53
+ // A TRANSIENT failure (timeout / network unreachable) must not flip a
54
+ // known-controllable host to unmanaged -- that silently skips the swap when
55
+ // the host is busy cold-loading. Retain controllability from a fresh
56
+ // last-known catalog if we have one.
57
+ if (err instanceof HostControlError &&
58
+ err.dbMessage === HOST_CONTROL_ERROR_UNREACHABLE &&
59
+ getCachedControllableCatalog(root)) {
60
+ return { controllable: true };
61
+ }
62
+ // Otherwise fail-safe to not-controllable (a definitive status error, or no
63
+ // cache to lean on). The probe must never surface a probe-oracle.
47
64
  return { controllable: false };
48
65
  }
49
66
  }
@@ -1 +1 @@
1
- {"version":3,"file":"capability.js","sourceRoot":"","sources":["../../src/host-control/capability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,6BAA6B,EAAE,MAAM,aAAa,CAAC;AAC1F,OAAO,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAGhF;;;;;GAKG;AACH,MAAM,UAAU,4BAA4B,CAAC,OAAgB;IAC3D,OAAO,qBAAqB,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;AACnD,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,OAAe,EACf,MAAsB;IAEtB,MAAM,IAAI,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,UAAU,GAAG,GAAG,IAAI,GAAG,yBAAyB,EAAE,CAAC;IACzD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAU,UAAU,EAAE;YACjD,MAAM;YACN,SAAS,EAAE,6BAA6B;SACzC,CAAC,CAAC;QACH,OAAO,EAAE,YAAY,EAAE,4BAA4B,CAAC,OAAO,CAAC,EAAE,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,8EAA8E;QAC9E,+EAA+E;QAC/E,kDAAkD;QAClD,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;IACjC,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"capability.js","sourceRoot":"","sources":["../../src/host-control/capability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,OAAO,EACP,mBAAmB,EACnB,6BAA6B,EAC7B,8BAA8B,EAC9B,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,yBAAyB,EACzB,qBAAqB,EACrB,wBAAwB,EACxB,4BAA4B,GAC7B,MAAM,cAAc,CAAC;AAGtB;;;;;GAKG;AACH,MAAM,UAAU,4BAA4B,CAAC,OAAgB;IAC3D,OAAO,qBAAqB,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;AACnD,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,OAAe,EACf,MAAsB;IAEtB,MAAM,IAAI,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,UAAU,GAAG,GAAG,IAAI,GAAG,yBAAyB,EAAE,CAAC;IACzD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAU,UAAU,EAAE;YACjD,MAAM;YACN,SAAS,EAAE,6BAA6B;SACzC,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;QAC9C,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,qEAAqE;YACrE,6DAA6D;YAC7D,wBAAwB,CAAC,IAAI,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAC7F,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;QAChC,CAAC;QACD,qEAAqE;QACrE,yDAAyD;QACzD,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;IACjC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,sEAAsE;QACtE,4EAA4E;QAC5E,qEAAqE;QACrE,qCAAqC;QACrC,IACE,GAAG,YAAY,gBAAgB;YAC/B,GAAG,CAAC,SAAS,KAAK,8BAA8B;YAChD,4BAA4B,CAAC,IAAI,CAAC,EAClC,CAAC;YACD,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;QAChC,CAAC;QACD,4EAA4E;QAC5E,kEAAkE;QAClE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;IACjC,CAAC;AACH,CAAC"}
@@ -20,6 +20,28 @@
20
20
  import type { LoadableCatalog, LoadableModel } from './types.js';
21
21
  /** The control-surface path (under the host ROOT, not `/v1`) for the full catalog. */
22
22
  export declare const HOST_CONTROL_CATALOG_PATH = "/api/models/local";
23
+ /**
24
+ * TTL (ms) for the last-known-controllable catalog cache. A controllable host's
25
+ * catalog is stable over a pass; caching it means ONE slow/timed-out probe does
26
+ * not silently downgrade a managed host to the `/v1/models` floor (which would
27
+ * skip the swap and spawn against whatever is loaded). Bounded so a genuinely
28
+ * removed model / decommissioned host eventually re-probes. 5 minutes ~= 10
29
+ * focus-poll ticks.
30
+ */
31
+ export declare const HOST_CONTROL_CATALOG_CACHE_TTL_MS = 300000;
32
+ /**
33
+ * Return the fresh last-known controllable catalog for a host root, or null when
34
+ * absent or expired. `nowMs` is injectable for deterministic TTL tests.
35
+ */
36
+ export declare function getCachedControllableCatalog(root: string, nowMs?: number): LoadableCatalog | null;
37
+ /**
38
+ * Cache a CONTROLLABLE catalog for a host root. A non-controllable (floor)
39
+ * catalog is never cached -- only a positive control-surface read is worth
40
+ * retaining across a transient probe failure.
41
+ */
42
+ export declare function cacheControllableCatalog(root: string, catalog: LoadableCatalog, nowMs?: number): void;
43
+ /** Test-only: clear the per-host catalog cache between cases. */
44
+ export declare function __resetHostControlCatalogCache(): void;
23
45
  /**
24
46
  * Normalize a control-surface catalog payload into clean `LoadableModel`
25
47
  * entries. Pure + DEFENSIVE: tolerates a bare array or a wrapped container,
@@ -1 +1 @@
1
- {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/host-control/catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AASH,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEjE,sFAAsF;AACtF,eAAO,MAAM,yBAAyB,sBAAsB,CAAC;AAgD7D;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,aAAa,EAAE,CAkBvE;AAYD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GACrB,OAAO,CAAC,eAAe,CAAC,CAwB1B"}
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/host-control/catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAUH,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEjE,sFAAsF;AACtF,eAAO,MAAM,yBAAyB,sBAAsB,CAAC;AAE7D;;;;;;;GAOG;AACH,eAAO,MAAM,iCAAiC,SAAU,CAAC;AAUzD;;;GAGG;AACH,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,MAAM,EACZ,KAAK,GAAE,MAAmB,GACzB,eAAe,GAAG,IAAI,CAQxB;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,eAAe,EACxB,KAAK,GAAE,MAAmB,GACzB,IAAI,CAGN;AAED,iEAAiE;AACjE,wBAAgB,8BAA8B,IAAI,IAAI,CAErD;AAgDD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,aAAa,EAAE,CAkBvE;AAYD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GACrB,OAAO,CAAC,eAAe,CAAC,CAwC1B"}
@@ -18,9 +18,48 @@
18
18
  * live-shape reconciliation.
19
19
  */
20
20
  import { fetchModels } from '../discovery-poll.js';
21
- import { hostGet, hostRootFromBaseUrl, HOST_CONTROL_FETCH_TIMEOUT_MS, HostControlError, } from './client.js';
21
+ import { hostGet, hostRootFromBaseUrl, HOST_CONTROL_FETCH_TIMEOUT_MS, HOST_CONTROL_ERROR_UNREACHABLE, HostControlError, } from './client.js';
22
22
  /** The control-surface path (under the host ROOT, not `/v1`) for the full catalog. */
23
23
  export const HOST_CONTROL_CATALOG_PATH = '/api/models/local';
24
+ /**
25
+ * TTL (ms) for the last-known-controllable catalog cache. A controllable host's
26
+ * catalog is stable over a pass; caching it means ONE slow/timed-out probe does
27
+ * not silently downgrade a managed host to the `/v1/models` floor (which would
28
+ * skip the swap and spawn against whatever is loaded). Bounded so a genuinely
29
+ * removed model / decommissioned host eventually re-probes. 5 minutes ~= 10
30
+ * focus-poll ticks.
31
+ */
32
+ export const HOST_CONTROL_CATALOG_CACHE_TTL_MS = 300_000;
33
+ /** Per-host (keyed by host root) last-known controllable catalog. */
34
+ const hostCatalogCache = new Map();
35
+ /**
36
+ * Return the fresh last-known controllable catalog for a host root, or null when
37
+ * absent or expired. `nowMs` is injectable for deterministic TTL tests.
38
+ */
39
+ export function getCachedControllableCatalog(root, nowMs = Date.now()) {
40
+ const entry = hostCatalogCache.get(root);
41
+ if (!entry)
42
+ return null;
43
+ if (nowMs - entry.cachedAtMs > HOST_CONTROL_CATALOG_CACHE_TTL_MS) {
44
+ hostCatalogCache.delete(root);
45
+ return null;
46
+ }
47
+ return entry.catalog;
48
+ }
49
+ /**
50
+ * Cache a CONTROLLABLE catalog for a host root. A non-controllable (floor)
51
+ * catalog is never cached -- only a positive control-surface read is worth
52
+ * retaining across a transient probe failure.
53
+ */
54
+ export function cacheControllableCatalog(root, catalog, nowMs = Date.now()) {
55
+ if (!catalog.controllable)
56
+ return;
57
+ hostCatalogCache.set(root, { catalog, cachedAtMs: nowMs });
58
+ }
59
+ /** Test-only: clear the per-host catalog cache between cases. */
60
+ export function __resetHostControlCatalogCache() {
61
+ hostCatalogCache.clear();
62
+ }
24
63
  /**
25
64
  * Candidate keys that may carry the array of catalog entries. The live host
26
65
  * (Unsloth Studio) returned a bare array under `/api/models/local`; other hosts
@@ -130,15 +169,29 @@ export async function readLoadableCatalog(baseUrl, apiKey) {
130
169
  });
131
170
  const models = normalizeLocalCatalog(payload);
132
171
  if (models.length > 0) {
133
- return { controllable: true, ids: models.map((m) => m.id), models };
172
+ const catalog = { controllable: true, ids: models.map((m) => m.id), models };
173
+ // Cache the positive read so a later transient probe failure can retain it.
174
+ cacheControllableCatalog(root, catalog);
175
+ return catalog;
134
176
  }
135
- // Well-formed but empty (or no usable ids): not a usable control catalog --
136
- // fall through to the floor so the picklist still offers the loaded model.
177
+ // Well-formed but empty (or no usable ids): a DEFINITIVE not-controllable
178
+ // answer (e.g. a plain OpenAI endpoint) -- fall through to the floor. Do NOT
179
+ // use a stale cache here: the host actively answered "no catalog".
137
180
  }
138
181
  catch (err) {
139
- // Fail-safe: any control-surface error means "not controllable here". Log the
140
- // rich detail daemon-side (address-free dbMessage available for categorizing)
141
- // and fall through to the floor. Never break a plain endpoint.
182
+ // A TRANSIENT failure (timeout / network unreachable) must not silently
183
+ // downgrade a known-controllable host to the floor -- that skips the swap
184
+ // exactly when the host is busy cold-loading. Retain the last-known
185
+ // controllable catalog if we have a fresh one.
186
+ if (err instanceof HostControlError && err.dbMessage === HOST_CONTROL_ERROR_UNREACHABLE) {
187
+ const cached = getCachedControllableCatalog(root);
188
+ if (cached) {
189
+ console.log(`[host-control] catalog probe failed transiently; using last-known controllable catalog for ${root}`);
190
+ return cached;
191
+ }
192
+ }
193
+ // No cache to fall back on (or a definitive non-2xx status error): log and
194
+ // fall through to the floor. Never break a plain endpoint.
142
195
  const detail = err instanceof HostControlError ? err.message : err.message;
143
196
  console.log(`[host-control] catalog read fell back to /v1/models floor: ${detail}`);
144
197
  }
@@ -1 +1 @@
1
- {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/host-control/catalog.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/host-control/catalog.ts"],"names":[],"mappings":"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"}
@@ -13,6 +13,8 @@ export { detectHostCapability, isControllableCatalogPayload } from './capability
13
13
  export { readLoadableCatalog, normalizeLocalCatalog, HOST_CONTROL_CATALOG_PATH, } from './catalog.js';
14
14
  export { loadModel, unloadModel, getStatus, resolveModelPath, decideSwap, ensureLoaded, normalizeStatus, DEFAULT_MAX_SEQ_LENGTH, HOST_CONTROL_LOAD_PATH, HOST_CONTROL_UNLOAD_PATH, HOST_CONTROL_STATUS_PATH, HOST_CONTROL_LOAD_READY_TIMEOUT_MS, HOST_CONTROL_LOAD_POLL_INTERVAL_MS, HOST_CONTROL_ERROR_LOAD_TIMEOUT, } from './load.js';
15
15
  export type { EnsureLoadedOptions } from './load.js';
16
+ export { observeHostSwap, claimResidentHost, releaseHostByFocus, hostSwapKey, __resetHostSwapManager, } from './swap-manager.js';
17
+ export type { HostSwapObservation, HostSwapPhase } from './swap-manager.js';
16
18
  export { getHardware, getKvCacheEstimate, normalizeHardware, normalizeKvCacheEstimate, computeSafeMaxSeqLength, resolveSafeLoadOptions, CODEX_TURN1_FLOOR, VRAM_SAFETY_MARGIN_MB, KV_CACHE_MB_PER_TOKEN, KV_QUANT_FOOTPRINT_FACTOR, KV_QUANT_CACHE_TYPE, MAX_SEQ_LENGTH_CEILING, HOST_CONTROL_HARDWARE_PATH, HOST_CONTROL_KV_CACHE_PATH, } from './sizing.js';
17
19
  export type { SafeLoadSizingHints } from './sizing.js';
18
20
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/host-control/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,YAAY,EACV,cAAc,EACd,eAAe,EACf,aAAa,EACb,UAAU,EACV,eAAe,EACf,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,qBAAqB,EACrB,eAAe,EACf,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,OAAO,EACP,QAAQ,EACR,mBAAmB,EACnB,gBAAgB,EAChB,6BAA6B,EAC7B,sBAAsB,EACtB,+BAA+B,EAC/B,yBAAyB,EACzB,8BAA8B,EAC9B,0BAA0B,GAC3B,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAE,oBAAoB,EAAE,4BAA4B,EAAE,MAAM,iBAAiB,CAAC;AAErF,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,yBAAyB,GAC1B,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,SAAS,EACT,WAAW,EACX,SAAS,EACT,gBAAgB,EAChB,UAAU,EACV,YAAY,EACZ,eAAe,EACf,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EACxB,wBAAwB,EACxB,kCAAkC,EAClC,kCAAkC,EAClC,+BAA+B,GAChC,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAErD,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,iBAAiB,EACjB,wBAAwB,EACxB,uBAAuB,EACvB,sBAAsB,EACtB,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,yBAAyB,EACzB,mBAAmB,EACnB,sBAAsB,EACtB,0BAA0B,EAC1B,0BAA0B,GAC3B,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/host-control/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,YAAY,EACV,cAAc,EACd,eAAe,EACf,aAAa,EACb,UAAU,EACV,eAAe,EACf,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,qBAAqB,EACrB,eAAe,EACf,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,OAAO,EACP,QAAQ,EACR,mBAAmB,EACnB,gBAAgB,EAChB,6BAA6B,EAC7B,sBAAsB,EACtB,+BAA+B,EAC/B,yBAAyB,EACzB,8BAA8B,EAC9B,0BAA0B,GAC3B,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAE,oBAAoB,EAAE,4BAA4B,EAAE,MAAM,iBAAiB,CAAC;AAErF,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,yBAAyB,GAC1B,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,SAAS,EACT,WAAW,EACX,SAAS,EACT,gBAAgB,EAChB,UAAU,EACV,YAAY,EACZ,eAAe,EACf,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EACxB,wBAAwB,EACxB,kCAAkC,EAClC,kCAAkC,EAClC,+BAA+B,GAChC,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAErD,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,WAAW,EACX,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAE5E,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,iBAAiB,EACjB,wBAAwB,EACxB,uBAAuB,EACvB,sBAAsB,EACtB,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,yBAAyB,EACzB,mBAAmB,EACnB,sBAAsB,EACtB,0BAA0B,EAC1B,0BAA0B,GAC3B,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC"}
@@ -10,5 +10,6 @@ export { hostGet, hostPost, hostRootFromBaseUrl, HostControlError, HOST_CONTROL_
10
10
  export { detectHostCapability, isControllableCatalogPayload } from './capability.js';
11
11
  export { readLoadableCatalog, normalizeLocalCatalog, HOST_CONTROL_CATALOG_PATH, } from './catalog.js';
12
12
  export { loadModel, unloadModel, getStatus, resolveModelPath, decideSwap, ensureLoaded, normalizeStatus, DEFAULT_MAX_SEQ_LENGTH, HOST_CONTROL_LOAD_PATH, HOST_CONTROL_UNLOAD_PATH, HOST_CONTROL_STATUS_PATH, HOST_CONTROL_LOAD_READY_TIMEOUT_MS, HOST_CONTROL_LOAD_POLL_INTERVAL_MS, HOST_CONTROL_ERROR_LOAD_TIMEOUT, } from './load.js';
13
+ export { observeHostSwap, claimResidentHost, releaseHostByFocus, hostSwapKey, __resetHostSwapManager, } from './swap-manager.js';
13
14
  export { getHardware, getKvCacheEstimate, normalizeHardware, normalizeKvCacheEstimate, computeSafeMaxSeqLength, resolveSafeLoadOptions, CODEX_TURN1_FLOOR, VRAM_SAFETY_MARGIN_MB, KV_CACHE_MB_PER_TOKEN, KV_QUANT_FOOTPRINT_FACTOR, KV_QUANT_CACHE_TYPE, MAX_SEQ_LENGTH_CEILING, HOST_CONTROL_HARDWARE_PATH, HOST_CONTROL_KV_CACHE_PATH, } from './sizing.js';
14
15
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/host-control/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAiBH,OAAO,EACL,OAAO,EACP,QAAQ,EACR,mBAAmB,EACnB,gBAAgB,EAChB,6BAA6B,EAC7B,sBAAsB,EACtB,+BAA+B,EAC/B,yBAAyB,EACzB,8BAA8B,EAC9B,0BAA0B,GAC3B,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,oBAAoB,EAAE,4BAA4B,EAAE,MAAM,iBAAiB,CAAC;AAErF,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,yBAAyB,GAC1B,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,SAAS,EACT,WAAW,EACX,SAAS,EACT,gBAAgB,EAChB,UAAU,EACV,YAAY,EACZ,eAAe,EACf,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EACxB,wBAAwB,EACxB,kCAAkC,EAClC,kCAAkC,EAClC,+BAA+B,GAChC,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,iBAAiB,EACjB,wBAAwB,EACxB,uBAAuB,EACvB,sBAAsB,EACtB,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,yBAAyB,EACzB,mBAAmB,EACnB,sBAAsB,EACtB,0BAA0B,EAC1B,0BAA0B,GAC3B,MAAM,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/host-control/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAiBH,OAAO,EACL,OAAO,EACP,QAAQ,EACR,mBAAmB,EACnB,gBAAgB,EAChB,6BAA6B,EAC7B,sBAAsB,EACtB,+BAA+B,EAC/B,yBAAyB,EACzB,8BAA8B,EAC9B,0BAA0B,GAC3B,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,oBAAoB,EAAE,4BAA4B,EAAE,MAAM,iBAAiB,CAAC;AAErF,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,yBAAyB,GAC1B,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,SAAS,EACT,WAAW,EACX,SAAS,EACT,gBAAgB,EAChB,UAAU,EACV,YAAY,EACZ,eAAe,EACf,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EACxB,wBAAwB,EACxB,kCAAkC,EAClC,kCAAkC,EAClC,+BAA+B,GAChC,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,WAAW,EACX,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,iBAAiB,EACjB,wBAAwB,EACxB,uBAAuB,EACvB,sBAAsB,EACtB,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,yBAAyB,EACzB,mBAAmB,EACnB,sBAAsB,EACtB,0BAA0B,EAC1B,0BAA0B,GAC3B,MAAM,aAAa,CAAC"}
@@ -43,6 +43,22 @@ export declare const DEFAULT_MAX_SEQ_LENGTH = 16384;
43
43
  * 12GB GPU has real latency; this is the bounded ceiling, not the expected wait.
44
44
  */
45
45
  export declare const HOST_CONTROL_LOAD_READY_TIMEOUT_MS = 180000;
46
+ /**
47
+ * Timeout (ms) for the model-MUTATION POSTs themselves -- both `POST /v1/load`
48
+ * AND `POST /v1/unload`. Some hosts block the response until the cold load (or
49
+ * the evict) completes (e.g. a 12B GGUF swap on a single GPU takes well over
50
+ * 5s); inheriting the generic 5s `HOST_CONTROL_FETCH_TIMEOUT_MS` would abort the
51
+ * POST before the `/v1/status` readiness poll is ever reached, so the swap is
52
+ * skipped and the daemon deadlocks in a spawn-retry loop. The evict_then_load
53
+ * path has the SAME failure mode on the unload POST, so both mutation POSTs use
54
+ * this budget. We size it to the readiness budget so a synchronously-loading
55
+ * host runs the operation to completion; the `/v1/status` poll -- NOT these
56
+ * POSTs -- remains the real ceiling. Operators may override via
57
+ * `TELORA_HOST_CONTROL_LOAD_TIMEOUT_MS` (declared in `@telora/daemon-core`'s
58
+ * env-config); the value is plumbed in by the caller (focus-executor) and this
59
+ * constant is the in-code default.
60
+ */
61
+ export declare const HOST_CONTROL_LOAD_POST_TIMEOUT_MS = 180000;
46
62
  /** Interval between `/v1/status` readiness polls while waiting for a load. */
47
63
  export declare const HOST_CONTROL_LOAD_POLL_INTERVAL_MS = 2000;
48
64
  /** Address-free category for a load that never reached ready within the budget. */
@@ -62,11 +78,24 @@ export declare function normalizeStatus(payload: unknown): HostStatus;
62
78
  * Issue a model load (`POST /v1/load`). Maps camelCase app params to the host's
63
79
  * snake_case wire field names (`model_path`, `max_seq_length`, `cache_type_kv`,
64
80
  * `gpu_ids`) at THIS boundary only. `maxSeqLength` is a required INJECTED input
65
- * so D3 can pass a computed value. Throws `HostControlError` on any failure.
81
+ * so D3 can pass a computed value. `loadTimeoutMs` bounds the POST itself -- it
82
+ * MUST exceed a cold load on a host that blocks `/v1/load` until the load
83
+ * completes, so it defaults to `HOST_CONTROL_LOAD_POST_TIMEOUT_MS` (the
84
+ * readiness budget) rather than the generic 5s fetch timeout. Throws
85
+ * `HostControlError` on any failure.
66
86
  */
67
- export declare function loadModel(baseUrl: string, params: LoadModelParams, apiKey?: string | null): Promise<void>;
68
- /** Issue an unload (`POST /v1/unload`) -- evicts whatever is currently resident. */
69
- export declare function unloadModel(baseUrl: string, apiKey?: string | null): Promise<void>;
87
+ export declare function loadModel(baseUrl: string, params: LoadModelParams, apiKey?: string | null, loadTimeoutMs?: number): Promise<void>;
88
+ /**
89
+ * Issue an unload (`POST /v1/unload`) -- evicts whatever is currently resident.
90
+ * `unloadTimeoutMs` bounds the POST itself. A host that blocks `/v1/unload`
91
+ * until the eviction completes can take well over the generic 5s fetch timeout
92
+ * for a large model (a 12B GGUF evict), so this defaults to the same load-scoped
93
+ * `HOST_CONTROL_LOAD_POST_TIMEOUT_MS` as `loadModel` rather than the 5s default;
94
+ * otherwise the evict_then_load path aborts mid-evict and the daemon re-enters
95
+ * the same spawn-retry deadlock the load-scoped timeout exists to prevent.
96
+ * Throws `HostControlError` on any failure.
97
+ */
98
+ export declare function unloadModel(baseUrl: string, apiKey?: string | null, unloadTimeoutMs?: number): Promise<void>;
70
99
  /** Read current host status (`GET /v1/status`), normalized to a typed shape. */
71
100
  export declare function getStatus(baseUrl: string, apiKey?: string | null): Promise<HostStatus>;
72
101
  /**
@@ -77,6 +106,26 @@ export declare function getStatus(baseUrl: string, apiKey?: string | null): Prom
77
106
  * skips the swap.
78
107
  */
79
108
  export declare function resolveModelPath(baseUrl: string, modelId: string, apiKey?: string | null): Promise<string | null>;
109
+ /**
110
+ * Strip a single leading `<org>/` segment from a model id. Hosts disagree on id
111
+ * FORM: the registry / `/v1/models` catalog reports an org-prefixed id
112
+ * (`yuxinlu1/gemma-4-12B-agentic-...`) while `/v1/status` (and the Unsloth
113
+ * Studio UI) report the SAME loaded model unprefixed (`gemma-4-12B-agentic-...`).
114
+ * We strip exactly ONE leading segment up to and including the first `/`; an id
115
+ * with no `/` is returned unchanged. Pure + exported for unit testing.
116
+ */
117
+ export declare function stripModelOrgPrefix(id: string): string;
118
+ /**
119
+ * Compare two model ids tolerantly across the org-prefix discrepancy between a
120
+ * host's endpoints (see `stripModelOrgPrefix`). Matches when the ids are equal
121
+ * raw, OR when one equals the other with a single leading `<org>/` stripped
122
+ * (the incident shape: `/v1/status` reports `gemma-...` while the registry holds
123
+ * `yuxinlu1/gemma-...`). Deliberately NOT a both-sides-stripped compare, so two
124
+ * genuinely different org-prefixed models with the same basename
125
+ * (`orgA/model` vs `orgB/model`) do NOT false-positive as resident. Pure +
126
+ * exported for unit testing the resident-recognition boundary.
127
+ */
128
+ export declare function modelIdsMatch(a: string, b: string): boolean;
80
129
  /**
81
130
  * PURE swap decision over the current vs target resident model. Extracted from
82
131
  * `ensureLoaded` so the core single-GPU swap logic is unit-testable with NO HTTP:
@@ -89,6 +138,8 @@ export declare function resolveModelPath(baseUrl: string, modelId: string, apiKe
89
138
  * `current.ready` gates the noop (a resident-but-not-ready target still needs a
90
139
  * poll, but no reload -- treated as 'load' here so `ensureLoaded` re-issues +
91
140
  * polls; the host treats a load of the resident model as a fast no-op/confirm).
141
+ * Resident recognition uses `modelIdsMatch` so an org-prefix difference between
142
+ * the registry id (target) and the `/v1/status` id (current) still no-ops.
92
143
  */
93
144
  export declare function decideSwap(input: {
94
145
  current: {
@@ -109,6 +160,15 @@ export interface EnsureLoadedOptions {
109
160
  readyTimeoutMs?: number;
110
161
  /** Override the ready-poll interval (ms). Defaults to the module constant. */
111
162
  pollIntervalMs?: number;
163
+ /**
164
+ * Override the timeout (ms) for the model-MUTATION POSTs -- both `POST /v1/load`
165
+ * AND the `POST /v1/unload` issued on the evict_then_load path. Defaults to
166
+ * `HOST_CONTROL_LOAD_POST_TIMEOUT_MS` so a synchronously-loading/evicting host
167
+ * is not cut at the generic 5s fetch timeout before readiness polling begins.
168
+ * A slow evict has the same 5s-abort failure mode as a slow load, so both
169
+ * mutation POSTs share this load-scoped budget.
170
+ */
171
+ loadTimeoutMs?: number;
112
172
  /**
113
173
  * Injectable sleep, so the timeout/poll path is fast + deterministic in tests.
114
174
  * Defaults to a real `setTimeout` wait.
@@ -1 +1 @@
1
- {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../src/host-control/load.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAc,YAAY,EAAE,MAAM,YAAY,CAAC;AAExF;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,UAAU,CAAC;AAC9C,eAAO,MAAM,wBAAwB,YAAY,CAAC;AAClD,eAAO,MAAM,wBAAwB,YAAY,CAAC;AAElD;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,QAAQ,CAAC;AAE5C;;;;GAIG;AACH,eAAO,MAAM,kCAAkC,SAAU,CAAC;AAE1D,8EAA8E;AAC9E,eAAO,MAAM,kCAAkC,OAAQ,CAAC;AAExD,mFAAmF;AACnF,eAAO,MAAM,+BAA+B,0CAA0C,CAAC;AAoCvF;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,UAAU,CA4B5D;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAC7B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,eAAe,EACvB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GACrB,OAAO,CAAC,IAAI,CAAC,CAQf;AAED,oFAAoF;AACpF,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAExF;AAED,gFAAgF;AAChF,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,CAG5F;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GACrB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAIxB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE;IAChC,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IACpD,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,YAAY,CAWf;AAED,+EAA+E;AAC/E,MAAM,WAAW,mBAAmB;IAClC,yEAAyE;IACzE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,4EAA4E;IAC5E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8EAA8E;IAC9E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,+EAA+E;IAC/E,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAMD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,IAAI,GAAE,mBAAwB,EAC9B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GACrB,OAAO,CAAC,IAAI,CAAC,CAqDf"}
1
+ {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../src/host-control/load.ts"],"names":[],"mappings":"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"}
@@ -44,6 +44,22 @@ export const DEFAULT_MAX_SEQ_LENGTH = 16384;
44
44
  * 12GB GPU has real latency; this is the bounded ceiling, not the expected wait.
45
45
  */
46
46
  export const HOST_CONTROL_LOAD_READY_TIMEOUT_MS = 180_000;
47
+ /**
48
+ * Timeout (ms) for the model-MUTATION POSTs themselves -- both `POST /v1/load`
49
+ * AND `POST /v1/unload`. Some hosts block the response until the cold load (or
50
+ * the evict) completes (e.g. a 12B GGUF swap on a single GPU takes well over
51
+ * 5s); inheriting the generic 5s `HOST_CONTROL_FETCH_TIMEOUT_MS` would abort the
52
+ * POST before the `/v1/status` readiness poll is ever reached, so the swap is
53
+ * skipped and the daemon deadlocks in a spawn-retry loop. The evict_then_load
54
+ * path has the SAME failure mode on the unload POST, so both mutation POSTs use
55
+ * this budget. We size it to the readiness budget so a synchronously-loading
56
+ * host runs the operation to completion; the `/v1/status` poll -- NOT these
57
+ * POSTs -- remains the real ceiling. Operators may override via
58
+ * `TELORA_HOST_CONTROL_LOAD_TIMEOUT_MS` (declared in `@telora/daemon-core`'s
59
+ * env-config); the value is plumbed in by the caller (focus-executor) and this
60
+ * constant is the in-code default.
61
+ */
62
+ export const HOST_CONTROL_LOAD_POST_TIMEOUT_MS = HOST_CONTROL_LOAD_READY_TIMEOUT_MS;
47
63
  /** Interval between `/v1/status` readiness polls while waiting for a load. */
48
64
  export const HOST_CONTROL_LOAD_POLL_INTERVAL_MS = 2_000;
49
65
  /** Address-free category for a load that never reached ready within the budget. */
@@ -119,9 +135,13 @@ export function normalizeStatus(payload) {
119
135
  * Issue a model load (`POST /v1/load`). Maps camelCase app params to the host's
120
136
  * snake_case wire field names (`model_path`, `max_seq_length`, `cache_type_kv`,
121
137
  * `gpu_ids`) at THIS boundary only. `maxSeqLength` is a required INJECTED input
122
- * so D3 can pass a computed value. Throws `HostControlError` on any failure.
138
+ * so D3 can pass a computed value. `loadTimeoutMs` bounds the POST itself -- it
139
+ * MUST exceed a cold load on a host that blocks `/v1/load` until the load
140
+ * completes, so it defaults to `HOST_CONTROL_LOAD_POST_TIMEOUT_MS` (the
141
+ * readiness budget) rather than the generic 5s fetch timeout. Throws
142
+ * `HostControlError` on any failure.
123
143
  */
124
- export async function loadModel(baseUrl, params, apiKey) {
144
+ export async function loadModel(baseUrl, params, apiKey, loadTimeoutMs = HOST_CONTROL_LOAD_POST_TIMEOUT_MS) {
125
145
  const body = {
126
146
  model_path: params.modelPath,
127
147
  max_seq_length: params.maxSeqLength,
@@ -130,11 +150,26 @@ export async function loadModel(baseUrl, params, apiKey) {
130
150
  body.cache_type_kv = params.cacheTypeKv;
131
151
  if (params.gpuIds !== undefined)
132
152
  body.gpu_ids = params.gpuIds;
133
- await hostPost(controlUrl(baseUrl, HOST_CONTROL_LOAD_PATH), body, { apiKey });
153
+ await hostPost(controlUrl(baseUrl, HOST_CONTROL_LOAD_PATH), body, {
154
+ apiKey,
155
+ timeoutMs: loadTimeoutMs,
156
+ });
134
157
  }
135
- /** Issue an unload (`POST /v1/unload`) -- evicts whatever is currently resident. */
136
- export async function unloadModel(baseUrl, apiKey) {
137
- await hostPost(controlUrl(baseUrl, HOST_CONTROL_UNLOAD_PATH), {}, { apiKey });
158
+ /**
159
+ * Issue an unload (`POST /v1/unload`) -- evicts whatever is currently resident.
160
+ * `unloadTimeoutMs` bounds the POST itself. A host that blocks `/v1/unload`
161
+ * until the eviction completes can take well over the generic 5s fetch timeout
162
+ * for a large model (a 12B GGUF evict), so this defaults to the same load-scoped
163
+ * `HOST_CONTROL_LOAD_POST_TIMEOUT_MS` as `loadModel` rather than the 5s default;
164
+ * otherwise the evict_then_load path aborts mid-evict and the daemon re-enters
165
+ * the same spawn-retry deadlock the load-scoped timeout exists to prevent.
166
+ * Throws `HostControlError` on any failure.
167
+ */
168
+ export async function unloadModel(baseUrl, apiKey, unloadTimeoutMs = HOST_CONTROL_LOAD_POST_TIMEOUT_MS) {
169
+ await hostPost(controlUrl(baseUrl, HOST_CONTROL_UNLOAD_PATH), {}, {
170
+ apiKey,
171
+ timeoutMs: unloadTimeoutMs,
172
+ });
138
173
  }
139
174
  /** Read current host status (`GET /v1/status`), normalized to a typed shape. */
140
175
  export async function getStatus(baseUrl, apiKey) {
@@ -153,6 +188,31 @@ export async function resolveModelPath(baseUrl, modelId, apiKey) {
153
188
  const match = catalog.models.find((m) => m.id === modelId);
154
189
  return match?.modelPath ?? null;
155
190
  }
191
+ /**
192
+ * Strip a single leading `<org>/` segment from a model id. Hosts disagree on id
193
+ * FORM: the registry / `/v1/models` catalog reports an org-prefixed id
194
+ * (`yuxinlu1/gemma-4-12B-agentic-...`) while `/v1/status` (and the Unsloth
195
+ * Studio UI) report the SAME loaded model unprefixed (`gemma-4-12B-agentic-...`).
196
+ * We strip exactly ONE leading segment up to and including the first `/`; an id
197
+ * with no `/` is returned unchanged. Pure + exported for unit testing.
198
+ */
199
+ export function stripModelOrgPrefix(id) {
200
+ const slash = id.indexOf('/');
201
+ return slash === -1 ? id : id.slice(slash + 1);
202
+ }
203
+ /**
204
+ * Compare two model ids tolerantly across the org-prefix discrepancy between a
205
+ * host's endpoints (see `stripModelOrgPrefix`). Matches when the ids are equal
206
+ * raw, OR when one equals the other with a single leading `<org>/` stripped
207
+ * (the incident shape: `/v1/status` reports `gemma-...` while the registry holds
208
+ * `yuxinlu1/gemma-...`). Deliberately NOT a both-sides-stripped compare, so two
209
+ * genuinely different org-prefixed models with the same basename
210
+ * (`orgA/model` vs `orgB/model`) do NOT false-positive as resident. Pure +
211
+ * exported for unit testing the resident-recognition boundary.
212
+ */
213
+ export function modelIdsMatch(a, b) {
214
+ return a === b || stripModelOrgPrefix(a) === b || a === stripModelOrgPrefix(b);
215
+ }
156
216
  /**
157
217
  * PURE swap decision over the current vs target resident model. Extracted from
158
218
  * `ensureLoaded` so the core single-GPU swap logic is unit-testable with NO HTTP:
@@ -165,11 +225,13 @@ export async function resolveModelPath(baseUrl, modelId, apiKey) {
165
225
  * `current.ready` gates the noop (a resident-but-not-ready target still needs a
166
226
  * poll, but no reload -- treated as 'load' here so `ensureLoaded` re-issues +
167
227
  * polls; the host treats a load of the resident model as a fast no-op/confirm).
228
+ * Resident recognition uses `modelIdsMatch` so an org-prefix difference between
229
+ * the registry id (target) and the `/v1/status` id (current) still no-ops.
168
230
  */
169
231
  export function decideSwap(input) {
170
232
  const { current, target } = input;
171
233
  let action;
172
- if (current.modelId === target) {
234
+ if (current.modelId !== null && modelIdsMatch(current.modelId, target)) {
173
235
  action = current.ready ? 'noop' : 'load';
174
236
  }
175
237
  else if (current.modelId !== null) {
@@ -202,6 +264,7 @@ export async function ensureLoaded(baseUrl, modelId, opts = {}, apiKey) {
202
264
  const maxSeqLength = opts.maxSeqLength ?? DEFAULT_MAX_SEQ_LENGTH;
203
265
  const readyTimeoutMs = opts.readyTimeoutMs ?? HOST_CONTROL_LOAD_READY_TIMEOUT_MS;
204
266
  const pollIntervalMs = opts.pollIntervalMs ?? HOST_CONTROL_LOAD_POLL_INTERVAL_MS;
267
+ const loadTimeoutMs = opts.loadTimeoutMs ?? HOST_CONTROL_LOAD_POST_TIMEOUT_MS;
205
268
  const sleep = opts.sleep ?? defaultSleep;
206
269
  const now = opts.now ?? Date.now;
207
270
  const status = await getStatus(baseUrl, apiKey);
@@ -212,7 +275,9 @@ export async function ensureLoaded(baseUrl, modelId, opts = {}, apiKey) {
212
275
  if (decision.action === 'noop')
213
276
  return;
214
277
  if (decision.action === 'evict_then_load') {
215
- await unloadModel(baseUrl, apiKey);
278
+ // Same load-scoped budget as the load POST: a slow evict on a synchronously-
279
+ // evicting host must not be cut at the generic 5s fetch timeout.
280
+ await unloadModel(baseUrl, apiKey, loadTimeoutMs);
216
281
  }
217
282
  const modelPath = await resolveModelPath(baseUrl, modelId, apiKey);
218
283
  if (!modelPath) {
@@ -225,13 +290,17 @@ export async function ensureLoaded(baseUrl, modelId, opts = {}, apiKey) {
225
290
  maxSeqLength,
226
291
  ...(opts.cacheTypeKv !== undefined ? { cacheTypeKv: opts.cacheTypeKv } : {}),
227
292
  ...(opts.gpuIds !== undefined ? { gpuIds: opts.gpuIds } : {}),
228
- }, apiKey);
293
+ }, apiKey, loadTimeoutMs);
229
294
  // Poll for readiness up to the bounded budget. A cold load has real latency.
230
295
  const deadline = now() + readyTimeoutMs;
231
296
  for (;;) {
232
297
  const polled = await getStatus(baseUrl, apiKey);
233
- if (polled.loadedModelId === modelId && polled.ready)
298
+ // Org-prefix-tolerant match: `/v1/status` may report the loaded id unprefixed
299
+ // while `modelId` (the registry id) carries the `<org>/` prefix -- an exact
300
+ // compare here would never resolve and the poll would always time out.
301
+ if (polled.loadedModelId !== null && modelIdsMatch(polled.loadedModelId, modelId) && polled.ready) {
234
302
  return;
303
+ }
235
304
  if (now() >= deadline) {
236
305
  throw new HostControlError(`Model "${modelId}" did not reach ready within ${readyTimeoutMs}ms`, HOST_CONTROL_ERROR_LOAD_TIMEOUT);
237
306
  }
@@ -1 +1 @@
1
- {"version":3,"file":"load.js","sourceRoot":"","sources":["../../src/host-control/load.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"load.js","sourceRoot":"","sources":["../../src/host-control/load.ts"],"names":[],"mappings":"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"}
@@ -25,6 +25,18 @@
25
25
  * "no sizing data" and falls back to the fixed floor default, never breaking a
26
26
  * swap that previously worked.
27
27
  */
28
+ /**
29
+ * Timeout (ms) for the sizing reads (`/api/system/hardware`,
30
+ * `/api/models/kv-cache-estimate`). These inherited the generic 5s
31
+ * `HOST_CONTROL_FETCH_TIMEOUT_MS`, but a host that is BUSY cold-loading a model
32
+ * (exactly when a swap sizes the next load) can take longer than 5s to answer a
33
+ * hardware query -- so the read timed out and `resolveSafeLoadOptions` fell back
34
+ * to the fixed 16384 default, reporting sizing "unavailable" on a host that
35
+ * actually exposes it. A tolerant budget removes that false fallback. The read
36
+ * is still best-effort: a genuine miss (endpoint absent / unsupported) returns
37
+ * fast (4xx) and degrades safely to the fixed default.
38
+ */
39
+ export declare const HOST_CONTROL_SIZING_TIMEOUT_MS = 15000;
28
40
  import type { HostHardware, KvCacheEstimate, KvCacheEstimateParams, SafeMaxSeqInput, SafeMaxSeqResult } from './types.js';
29
41
  /**
30
42
  * The control-surface path (under the host ROOT, not `/v1`) for GPU hardware
@@ -1 +1 @@
1
- {"version":3,"file":"sizing.d.ts","sourceRoot":"","sources":["../../src/host-control/sizing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,qBAAqB,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE1H;;;GAGG;AACH,eAAO,MAAM,0BAA0B,yBAAyB,CAAC;AAEjE;;;GAGG;AACH,eAAO,MAAM,0BAA0B,kCAAkC,CAAC;AAE1E;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAEtC;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAEzC;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,qBAAqB,OAAO,CAAC;AAE1C;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAE7C;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,SAAS,CAAC;AAE1C;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,SAAS,CAAC;AA0F7C;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,CAUhE;AASD;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,eAAe,CAmB1E;AAID;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC,CAIhG;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,qBAAqB,EAC7B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GACrB,OAAO,CAAC,eAAe,CAAC,CAY1B;AAmCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,eAAe,GAAG,gBAAgB,CAsEhF;AAID;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,mEAAmE;IACnE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,KAAK,GAAE,mBAAwB,EAC/B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GACrB,OAAO,CAAC;IACT,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,UAAU,GAAG,UAAU,CAAC;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC,CAyDD"}
1
+ {"version":3,"file":"sizing.d.ts","sourceRoot":"","sources":["../../src/host-control/sizing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAKH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,8BAA8B,QAAS,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,qBAAqB,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE1H;;;GAGG;AACH,eAAO,MAAM,0BAA0B,yBAAyB,CAAC;AAEjE;;;GAGG;AACH,eAAO,MAAM,0BAA0B,kCAAkC,CAAC;AAE1E;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAEtC;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAEzC;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,qBAAqB,OAAO,CAAC;AAE1C;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAE7C;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,SAAS,CAAC;AAE1C;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,SAAS,CAAC;AA0F7C;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,CAUhE;AASD;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,eAAe,CAmB1E;AAID;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC,CAOhG;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,qBAAqB,EAC7B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GACrB,OAAO,CAAC,eAAe,CAAC,CAY1B;AAmCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,eAAe,GAAG,gBAAgB,CAsEhF;AAID;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,mEAAmE;IACnE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,KAAK,GAAE,mBAAwB,EAC/B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GACrB,OAAO,CAAC;IACT,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,UAAU,GAAG,UAAU,CAAC;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC,CAyDD"}
@@ -27,6 +27,18 @@
27
27
  */
28
28
  import { hostGet, hostRootFromBaseUrl } from './client.js';
29
29
  import { DEFAULT_MAX_SEQ_LENGTH } from './load.js';
30
+ /**
31
+ * Timeout (ms) for the sizing reads (`/api/system/hardware`,
32
+ * `/api/models/kv-cache-estimate`). These inherited the generic 5s
33
+ * `HOST_CONTROL_FETCH_TIMEOUT_MS`, but a host that is BUSY cold-loading a model
34
+ * (exactly when a swap sizes the next load) can take longer than 5s to answer a
35
+ * hardware query -- so the read timed out and `resolveSafeLoadOptions` fell back
36
+ * to the fixed 16384 default, reporting sizing "unavailable" on a host that
37
+ * actually exposes it. A tolerant budget removes that false fallback. The read
38
+ * is still best-effort: a genuine miss (endpoint absent / unsupported) returns
39
+ * fast (4xx) and degrades safely to the fixed default.
40
+ */
41
+ export const HOST_CONTROL_SIZING_TIMEOUT_MS = 15_000;
30
42
  /**
31
43
  * The control-surface path (under the host ROOT, not `/v1`) for GPU hardware
32
44
  * info: GPU name + total/used VRAM. Reconcile field names per the runbook.
@@ -237,7 +249,10 @@ export function normalizeKvCacheEstimate(payload) {
237
249
  */
238
250
  export async function getHardware(baseUrl, apiKey) {
239
251
  const root = hostRootFromBaseUrl(baseUrl);
240
- const payload = await hostGet(`${root}${HOST_CONTROL_HARDWARE_PATH}`, { apiKey });
252
+ const payload = await hostGet(`${root}${HOST_CONTROL_HARDWARE_PATH}`, {
253
+ apiKey,
254
+ timeoutMs: HOST_CONTROL_SIZING_TIMEOUT_MS,
255
+ });
241
256
  return normalizeHardware(payload);
242
257
  }
243
258
  /**
@@ -261,7 +276,7 @@ export async function getKvCacheEstimate(baseUrl, params, apiKey) {
261
276
  qs.set('model_path', params.modelPath);
262
277
  if (params.cacheTypeKv)
263
278
  qs.set('cache_type_kv', params.cacheTypeKv);
264
- const payload = await hostGet(`${root}${HOST_CONTROL_KV_CACHE_PATH}?${qs.toString()}`, { apiKey });
279
+ const payload = await hostGet(`${root}${HOST_CONTROL_KV_CACHE_PATH}?${qs.toString()}`, { apiKey, timeoutMs: HOST_CONTROL_SIZING_TIMEOUT_MS });
265
280
  return normalizeKvCacheEstimate(payload);
266
281
  }
267
282
  // ── The pure heart: computeSafeMaxSeqLength ──────────────────────────────────