diff options
| author | Adam Malczewski <[email protected]> | 2026-06-02 20:05:48 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-06-02 20:05:48 +0900 |
| commit | 3307fec107fb8d1e7cb063bfdbfadf4b1d4f8c71 (patch) | |
| tree | 10fc7391ef0cfbbcd62d558991c54b4041b3dac9 /packages/api/src | |
| parent | b3aca3efe9e8cda79db6e2c7fa20482880ed16c3 (diff) | |
| download | dispatch-3307fec107fb8d1e7cb063bfdbfadf4b1d4f8c71.tar.gz dispatch-3307fec107fb8d1e7cb063bfdbfadf4b1d4f8c71.zip | |
fix(wake): resolve probe model dynamically from /v1/models by 'haiku' match
The wake probe was hardcoded to claude-3-5-haiku-20241022, which the
endpoint no longer serves (HTTP 404), exhausting the retry loop. Now the
probe fetches the live model list via fetchAnthropicModels (falling back
to ANTHROPIC_MODELS_FALLBACK if empty) and selects the current Haiku via
a new pure selectHaikuModel() helper (first case-insensitive 'haiku'
substring match; newest-first ordering). No-match surfaces a clear
per-account error instead of crashing.
Diffstat (limited to 'packages/api/src')
| -rw-r--r-- | packages/api/src/routes/models.ts | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/packages/api/src/routes/models.ts b/packages/api/src/routes/models.ts index 8f64bbb..eeb6029 100644 --- a/packages/api/src/routes/models.ts +++ b/packages/api/src/routes/models.ts @@ -20,6 +20,7 @@ import { refreshAccountCredentialsAsync, resolveApiKey, resolveContextLimit, + selectHaikuModel, setApiKey, validateAccountCredentials, } from "@dispatch/core"; @@ -568,13 +569,6 @@ modelsRoutes.post("/remove-key", async (c) => { // ─── Shared wake function ───────────────────────────────────── -/** - * Model used for the wake probe. A small/cheap model is enough — the only - * purpose is to register activity against the subscription so its rate-limit - * window keeps resetting on schedule. - */ -const WAKE_PROBE_MODEL = "claude-3-5-haiku-20241022"; - /** Max chars of upstream error body to keep in the surfaced message. */ const MAX_ERROR_BODY_CHARS = 200; @@ -631,6 +625,25 @@ async function wakeAllClaudeAccounts(): Promise< continue; } + // Resolve the probe model dynamically. A fixed model id (the old + // `claude-3-5-haiku-20241022`) eventually stops being served and + // the probe 404s, so pull the live list from `/v1/models` and pick + // the current Haiku. Fall back to the well-known list if the live + // fetch comes back empty (network blip, transient upstream error). + let availableModels = await fetchAnthropicModels(creds.accessToken); + if (availableModels.length === 0) { + availableModels = ANTHROPIC_MODELS_FALLBACK; + } + const probeModel = selectHaikuModel(availableModels); + if (!probeModel) { + results.push({ + label: acct.label, + ok: false, + error: "no 'haiku' model available from /v1/models", + }); + continue; + } + // Mirror a genuine Claude Code CLI request. These are OAuth // (Pro/Max) subscription accounts: Anthropic validates the // `system[]` array and rejects (401/403) any request whose system @@ -648,7 +661,7 @@ async function wakeAllClaudeAccounts(): Promise< "X-Claude-Code-Session-Id": randomUUID(), "x-client-request-id": randomUUID(), }, - body: JSON.stringify(buildWakeProbeBody(WAKE_PROBE_MODEL)), + body: JSON.stringify(buildWakeProbeBody(probeModel)), }); if (res.ok) { |
