Commit Graph
3 Commits
Author SHA1 Message Date
e3b9c98977 fix(ui): return untruncated errors exactly as received
Follow-up to discussion_r3831361300 on #1058.

Both non-truncated return paths handed back the trimmed working copy, so
an error like "  request timed out\n" came back altered even though
nothing had been omitted. That contradicted the stated intent that short
errors pass through untouched, and left `display` differing from `full`
for no reason.

`display` is now byte-identical to `full` whenever `truncated` is false —
the trimmed copy is only used for measuring against the budget and for
building the shortened head. Documented on the field.

Verified across padded short errors, clean short errors, empty and
whitespace-only input, and either side of the threshold: display === full
on every untruncated case, and `full` matches the input exactly in all of
them.

One visible consequence: with whitespace-pre-wrap on the description, an
error carrying leading or trailing newlines now renders with that blank
space. Trivial for the messages this sees in practice, and the
alternative was silently editing the text.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-10-04 00:00:15 +00:00
96c6f9cad9 fix(ui): preserve the original error text and handle clipboard failures
Two CodeRabbit findings on #1058.

condenseError trimmed the input before storing it in `full`, which is
documented as the untouched original and is what the Copy action hands
over. The trim now applies only to the working copy used for measuring
and cutting, so `full` is byte-for-byte what the server sent while
`display` and `omitted` still ignore surrounding blank space.

The Copy handler called navigator.clipboard.writeText with no guard.
Outside a secure context the property access itself throws, and
writeText rejects when permission is denied; neither was handled, so a
click could become an unhandled rejection with no sign that nothing was
copied. Both paths are now caught and reported, pointing at Settings ->
Logs as the fallback.

Not taken: aligning MIN_TO_CONDENSE with the 400-char budget. The gap is
deliberate -- cutting a 450-char error to 400 saves 50 characters in a
description that already scrolls, and no Copy action is needed there
because `display` holds the whole message. Documented in place.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-10-04 00:00:15 +00:00
9ba2b33069 fix(ui): make long error toasts readable and copyable
A failed generation put the server's error straight into a toast. The
transformers "Unrecognized model" error is ~4.8KB, of which the first
sentence carries the meaning and the remaining 4.7KB is an alphabetical
list of every architecture it knows. In a 420px toast with
overflow-hidden and no scroll, that clipped the text at both ends and
pushed the close button off-screen: unreadable and undismissable.

- ToastDescription is capped at 40vh and scrolls, wraps on whitespace
  and breaks long unspaced tokens so a path cannot widen the toast.
- The toast aligns to the start rather than centring, so the title
  stays visible next to a tall description.
- condenseError() keeps the head of an oversized error, cutting at the
  first newline or the last sentence end inside a 400-char budget, and
  reports how many characters it dropped. Short errors pass through
  untouched.
- When it does truncate, the toast offers a Copy action for the full
  text and points at Settings -> Logs.

Verified against the real 4795-char error: 4795 -> 400 chars keeping
both meaningful sentences.

The hook moves to .tsx to render ToastAction, matching useAutoUpdater.tsx
which is a .tsx hook for the same reason. createElement was tried first
but this repo's ToastActionElement type is the older shadcn definition
(ReactElement<typeof ToastAction>) which only accepts JSX-constructed
elements.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-10-04 00:00:15 +00:00