An unparseable request body was silently converted to null, merged over
defaults, and saved — wiping the admin's config while returning 200.
Throw SystemConfigError on JSON parse failure so the route returns 400
INVALID_REQUEST without touching the saved config file.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The collapse control now hangs off the top of the ResizableHandle so it
tracks the divider as the sidebar is resized, instead of sitting in the
header far from the boundary it controls. The header toggle remains for
the collapsed and mobile-overlay states. ResizableHandle now renders
passed children (previously shadowed by the withHandle element).
routeErrorResponse gains an optional actor; every route that resolves an
actor now passes it, so API failures survive the toast. Unauthenticated
failures and the error-logs route itself are never logged.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add errorReporter (errorToast = toast.error + fire-and-forget POST to
/api/error-logs) and wire it into the operational error toasts across
chat, threads, tasks, agents, models, files and clipboard. Pure form
validation hints stay on toast.error.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Three mechanisms, merged in ThreadList: a 10s heartbeat polling the new
?status=busy filter (out-of-band runs: scheduled tasks, other clients),
a module-level running store fed by useChat's own run lifecycle (zero
latency for this client's runs), and a spinner replacing the status dot
while either source marks the thread busy. The BFF list route now
validates and forwards the status filter, which also unbreaks the
previously ignored status dropdown.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The list route forwarded each thread's full values.messages to the
browser (~47MB for 20 threads), blocking the main thread on JSON.parse
and making the list appear suddenly after a long wait. The BFF now
derives title/description/pinned/needsUserInput server-side via the
shared conversationSummary module and never sends values or interrupts;
useThreads consumes the slim shape directly.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Matches the backend split: usage attribution no longer shares
EVOSCIENTIST_DEPLOYMENT_ID with workspace scope partitioning.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Every conversation-list load fanned out getByThread per visible thread;
legacy threads without a scope each logged a 404 warning and added a
round-trip. A thread whose metadata claims no workspace_scope_id can
never pass the scope assertion, so skip the probe and filter it directly.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds a GenerationParamSlider next to the reasoning-effort slider so a
per-thread temperature/top_p override can be set from the chat bar.
Unset sliders rest at the registry-catalog default in a muted style;
dragging commits an override, and clicking the value resets to the
default. Hidden below the sm breakpoint, and disabled while the
thread inherits the registry model.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>