diff --git a/src/components/AsciiSpinner.svelte b/src/components/AsciiSpinner.svelte index 81cc7197..10884a1e 100644 --- a/src/components/AsciiSpinner.svelte +++ b/src/components/AsciiSpinner.svelte @@ -1,7 +1,9 @@ + Retrying... + {:else} + Retry + {/if} {#if retryError[row.threadId]} @@ -384,6 +396,9 @@ cursor: progress; opacity: 0.7; } + .wiki-skipped-retry-spinner { + margin-right: 0.4rem; + } .wiki-skipped-retry-error { color: var(--danger, #b91c1c); font-size: 0.85rem; diff --git a/src/lib/ui/ascii-spinner.ts b/src/lib/ui/ascii-spinner.ts index a01f4178..49330c27 100644 --- a/src/lib/ui/ascii-spinner.ts +++ b/src/lib/ui/ascii-spinner.ts @@ -1,9 +1,10 @@ /** - * Frame data for the text spinner that marks an in-flight row in the - * wiki librarian-run strip (`src/components/AsciiSpinner.svelte`, - * rendered by `src/screens/Wiki.svelte`). The sequence and the wrap - * arithmetic live here so they can be tested without mounting a - * component or running timers. + * Frame data for the text spinner that marks an in-flight wiki-agent + * surface (`src/components/AsciiSpinner.svelte`, rendered by the + * librarian-run strip in `src/screens/Wiki.svelte` and the Skipped + * panel's Retrying button in `WikiSkippedPanel.svelte`). The sequence + * and the wrap arithmetic live here so they can be tested without + * mounting a component or running timers. * * The memory strip does NOT use this - it runs `SleepSpinner.svelte`, * whose frames are CSS keyframes rather than data, because its passes diff --git a/supabase/functions/_shared/venice.ts b/supabase/functions/_shared/venice.ts index fb4cc01d..2d0cca69 100644 --- a/supabase/functions/_shared/venice.ts +++ b/supabase/functions/_shared/venice.ts @@ -340,16 +340,22 @@ async function veniceCompleteOnce(opts: VeniceCompleteOptions): Promise if (!res.ok) { const errBody = await res.text().catch(() => ''); + // 600, not the 200 the other endpoints use: completions errors are + // the ones that land verbatim in user-facing surfaces (the Wiki + // Skipped panel stores this message as the per-thread skip reason), + // and Venice's context-length 400 body runs past 200 chars - the + // old cap cut it mid-sentence ("...for a total of at least 1638"). + // 600 covers every observed completions error body whole. if (res.status === 429) { throw new VeniceError( - `Venice chat/completions 429: ${errBody.slice(0, 200)}`, + `Venice chat/completions 429: ${errBody.slice(0, 600)}`, 'rate_limit', 429, parseVeniceRetryAfterMs(res.headers) ); } throw new VeniceError( - `Venice chat/completions ${res.status}: ${errBody.slice(0, 200)}`, + `Venice chat/completions ${res.status}: ${errBody.slice(0, 600)}`, 'http', res.status ); diff --git a/supabase/schema.sql b/supabase/schema.sql index 3859fe2b..b1228308 100644 --- a/supabase/schema.sql +++ b/supabase/schema.sql @@ -9642,11 +9642,12 @@ begin wiki_claim_expires_at = null, wiki_failure_count = 0, wiki_last_skip_at = now(), - -- Truncate at 500 chars to keep the row reasonable when the - -- error body is a large HTTP response. The UI shows enough - -- to identify the failure mode (Venice's classifier message - -- is short); a longer body would just bloat the row store. - wiki_last_skip_reason = nullif(left(coalesce(p_reason, ''), 500), ''), + -- Truncate at 1000 chars to keep the row reasonable when + -- the error body is a large HTTP response. Sized above the + -- edge client's 600-char completions error-body cap plus + -- its message prefix, so the Skipped panel shows the whole + -- captured error rather than clipping it a second time. + wiki_last_skip_reason = nullif(left(coalesce(p_reason, ''), 1000), ''), -- If the agent gave up with a content-classifier reason, -- we know the in-agent primary -> fallback retry already -- ran (the wiki agent always tries the fallback for that @@ -10721,7 +10722,10 @@ begin wiki_record_claim_expires_at = null, wiki_record_failure_count = 0, wiki_record_last_skip_at = now(), - wiki_record_last_skip_reason = nullif(left(coalesce(p_reason, ''), 500), '') + -- 1000 mirrors the wiki agent's skip-reason cap: above the + -- edge client's 600-char completions error-body slice plus + -- prefix, so the stored reason is never clipped twice. + wiki_record_last_skip_reason = nullif(left(coalesce(p_reason, ''), 1000), '') where id = p_thread_id; return 'skipped'; end if;