diff --git a/vision_runner.ts b/vision_runner.ts index fd06178..74e87fc 100644 --- a/vision_runner.ts +++ b/vision_runner.ts @@ -335,6 +335,22 @@ async function fetchModelId(api: string): Promise { } } +/** Wartet nach einem Server-Neustart (503/Verbindungsfehler), bis /health + * wieder OK meldet — Modell-Reload dauert 1-2 Minuten. */ +async function waitForHealthy(api: string, timeoutMs: number): Promise { + const healthUrl = api.replace(/\/v1\/?$/, "") + "/health"; + const deadline = Date.now() + timeoutMs; + while (Date.now() < deadline) { + try { + const r = await fetch(healthUrl, { signal: AbortSignal.timeout(5000) }); + if (r.ok) return; + } catch { + /* Server noch weg */ + } + await new Promise((res) => setTimeout(res, 5000)); + } +} + async function callVision(api: string, images: string[], timeoutMs: number): Promise { const content: Array> = [{ type: "text", text: USER_PROMPT }]; for (const img of images) { @@ -512,7 +528,15 @@ async function main(): Promise { break; } catch (e) { lastErr = e instanceof Error ? e.message : String(e); - if (attempt < RETRIES) await new Promise((res) => setTimeout(res, 5000 * attempt)); + if (attempt < RETRIES) { + if (/HTTP 50[23]|fetch failed|aborted|ECONNREFUSED|ECONNRESET/i.test(lastErr)) { + // Server crasht/lädt neu → auf /health warten (Modell-Reload dauert) + progress(`${tag} … Server neu am Laden, warte auf /health`); + await waitForHealthy(args.api, 300_000); + } else { + await new Promise((res) => setTimeout(res, 5000 * attempt)); + } + } } }