llm-relay 0.58.0 → 0.59.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.d.ts CHANGED
@@ -260,11 +260,13 @@ export declare function renderCommand(invoke: {
260
260
  /**
261
261
  * `llm-relay lanes [--probe]` — what each cli lane's own tool says it serves.
262
262
  *
263
- * ⚠ `--probe` is the ONE place the relay runs a lane's command, and only as an explicit operator
264
- * action — same precedent as `pools --probe` sending real completions. The request path reads the
265
- * cached manifest and never spawns anything. Without `--probe` this just prints the cache.
263
+ * ⚠ `--probe` spawns lane commands as an explicit operator action same precedent as
264
+ * `pools --probe` sending real completions. The request path reads the cached manifest and never
265
+ * spawns anything; outside it the only OTHER spawn site is the relay's background lane cadence
266
+ * (owner decision 2026-08-29, docs/quota-reprobe-design-2026-08-29.md). Without `--probe` this
267
+ * just prints the cache.
266
268
  */
267
- export declare function runLanes(): void;
269
+ export declare function runLanes(): Promise<void>;
268
270
  /**
269
271
  * `llm-relay dispatch [lane]` — which lane to hand a delegated task to next.
270
272
  *
package/dist/cli.js CHANGED
@@ -12,9 +12,10 @@ import { offloadState, setOffload } from "./offload.js";
12
12
  import { buildCandidates } from "./candidates.js";
13
13
  import { CREDENTIAL_LABEL_PATTERN, makeCredentialId } from "./credential-id.js";
14
14
  import { providerCredentialSlots, slotAllowsModel } from "./credential-fleet.js";
15
- import { loadLaneManifest, verifyModel } from "./lane-manifest.js";
15
+ import { loadLaneManifest, rosterIsStale, verifyModel } from "./lane-manifest.js";
16
16
  import { probeLanes } from "./lane-probe.js";
17
- import { buildDispatch, normalizeCliCommand, specContextWindow, CONTEXT_TOKEN } from "./dispatch.js";
17
+ import { buildDispatch, normalizeCliCommand, restoreExhaustedRows, specContextWindow, CONTEXT_TOKEN } from "./dispatch.js";
18
+ import { loadExhaustedRows } from "./dispatch-exhaustion-persistence.js";
18
19
  import { detectHostRouting, parseHostRoutingState } from "./host-routing.js";
19
20
  import { contextWindowResolver, COST_CLASSES } from "./metadata.js";
20
21
  import { snapshotContextWindow } from "./tier-data.js";
@@ -1674,14 +1675,16 @@ export function renderCommand(invoke, shell = shellFor()) {
1674
1675
  /**
1675
1676
  * `llm-relay lanes [--probe]` — what each cli lane's own tool says it serves.
1676
1677
  *
1677
- * ⚠ `--probe` is the ONE place the relay runs a lane's command, and only as an explicit operator
1678
- * action — same precedent as `pools --probe` sending real completions. The request path reads the
1679
- * cached manifest and never spawns anything. Without `--probe` this just prints the cache.
1678
+ * ⚠ `--probe` spawns lane commands as an explicit operator action same precedent as
1679
+ * `pools --probe` sending real completions. The request path reads the cached manifest and never
1680
+ * spawns anything; outside it the only OTHER spawn site is the relay's background lane cadence
1681
+ * (owner decision 2026-08-29, docs/quota-reprobe-design-2026-08-29.md). Without `--probe` this
1682
+ * just prints the cache.
1680
1683
  */
1681
- export function runLanes() {
1684
+ export async function runLanes() {
1682
1685
  const cfg = loadOrExit();
1683
1686
  if (hasFlag("--probe")) {
1684
- for (const r of probeLanes(cfg)) {
1687
+ for (const r of await probeLanes(cfg)) {
1685
1688
  process.stdout.write(r.ok
1686
1689
  ? ` ✓ ${r.lane.padEnd(8)} ${String(r.modelCount).padStart(3)} models via \`${r.via}\`
1687
1690
  `
@@ -1697,8 +1700,11 @@ export function runLanes() {
1697
1700
  return;
1698
1701
  }
1699
1702
  for (const [lane, entry] of Object.entries(manifest.lanes)) {
1703
+ const stale = rosterIsStale(entry)
1704
+ ? " ⚠ STALE — no longer evidence for eviction; run `llm-relay lanes --probe`"
1705
+ : "";
1700
1706
  process.stdout.write(`
1701
- ${lane} — ${entry.models.length} models, probed ${entry.probedAt} via \`${entry.via}\`
1707
+ ${lane} — ${entry.models.length} models, probed ${entry.probedAt} via \`${entry.via}\`${stale}
1702
1708
  `);
1703
1709
  for (const m of entry.models) {
1704
1710
  const supports = m.supports
@@ -1722,7 +1728,7 @@ ${lane} — ${entry.models.length} models, probed ${entry.probedAt} via \`${entr
1722
1728
  const model = i >= 0 ? rung.args[i + 1] : undefined;
1723
1729
  if (!model)
1724
1730
  continue;
1725
- const v = verifyModel(manifest, rung.command, model);
1731
+ const v = verifyModel(manifest, rung.command, model, { args: rung.args });
1726
1732
  if (v.status === "not-servable" && !bad.includes(v.reason))
1727
1733
  bad.push(v.reason);
1728
1734
  }
@@ -1846,6 +1852,11 @@ export async function runDispatch(arg) {
1846
1852
  specContextWindow(l.spec, cfg, cachedContextWindow) !== null);
1847
1853
  const staleProxy = hostStale || windowStale;
1848
1854
  const live = staleProxy ? null : liveRaw;
1855
+ // The durable half of exhaustion state is readable cold since dispatch-exhaustion persistence
1856
+ // landed: restore still-future rows so the fallback ladder shows what the relay recorded.
1857
+ // In-memory-only rows on a running relay still need the live answer — this narrows the gap, it
1858
+ // does not close it. Read-only here: no listener is installed, so nothing writes back.
1859
+ restoreExhaustedRows(cfg, loadExhaustedRows());
1849
1860
  const view = normalizeDispatchCommands(live ??
1850
1861
  buildDispatch(cfg, {
1851
1862
  ...(task ? { task } : {}),
@@ -3285,14 +3296,10 @@ export function main() {
3285
3296
  return;
3286
3297
  }
3287
3298
  if (arg2 === "lanes") {
3288
- try {
3289
- runLanes();
3290
- }
3291
- catch (e) {
3292
- process.stderr.write(`llm-relay lanes: ${e.message}
3293
- `);
3299
+ runLanes().catch((e) => {
3300
+ process.stderr.write(`llm-relay lanes: ${e.message}\n`);
3294
3301
  process.exit(1);
3295
- }
3302
+ });
3296
3303
  return;
3297
3304
  }
3298
3305
  if (arg2 === "dispatch") {