The server streams continuous empty partial keep-alive frames; the
per-chunk status patch blindly downgraded to the unlabeled "generating"
phase, wiping "Thinking…"/server statusText moments after it appeared
(pre-existing blind clear, exposed by chunk cadence). The streaming
patch is now guarded: no-op patches keep the previous status object,
keep-alive chunks never downgrade a labeled state, and startedAt
carries over so the elapsed ticker never resets. Live-verified; pinned
by a lifecycle test that fails against the old behavior.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
useCanvasDraft merges the preview hook + TTADialog's replacement-tag
trio into one owner; the canvas tag is now the local message.id (server
messageId is metadata-only). Shared trailing-flush throttle fixes the
frozen-canvas-on-stall bug (M1); intermediate preview elements are
filtered from local persistence and swept on dialog open (N3).
Capture rule unified: NEVER via updateScene, IMMEDIATELY via
syncActionResult. All pinned invariants re-asserted in the rewritten
tests.
Per tta_rewrite_final.md §2.4/§6 row 5; details in the progress log.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Step 3 (§2.1): ChatMessage becomes a three-kind union with a
discriminated AssistantStatus (streaming/done/stopped/error); the
14-optional-field bag, dead lifecycleStatus/parseError, and warningType
fake-assistant bubbles are gone. Rate-limit warnings are system
messages; server ids are metadata; truncation surfaces as
status.warning.
Step 4 (§2.5): conversations persist flat per-chat (loadChats/saveChat/
deleteChat adapter), the messages<->turns round-trip is deleted, brand
new chats buffer until `started` (kills the history-row id-swap +
chatIdRef), assistant messages persist only at terminal status, hydrate
merges by id+updatedAt. Terminal error bubbles persist; warnings do
not. Dev IndexedDB needs a one-time wipe (legacy "all" blob ignored).
Per tta_rewrite_final.md §6 rows 3-4; details in the progress log.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Reads the trailing [DONE] sentinel + EOF (detached, 2s-bounded) so the
response body completes instead of being abandoned mid-stream, letting
the keep-alive connection be reused. Note: this does NOT remove the
net::ERR_ABORTED annotation DevTools attaches to these requests —
verified via A/B that Chrome logs it for cross-origin SSE fetches even
when the body is fully read; that annotation is a reporting quirk, not
an actual abort.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New useGenerationSlot (ownership-checked slot) + runGeneration in
TTADialog: the sole entry point for send/retry, reserving the slot
before any chat mutation (Enter while streaming is a no-op that keeps
the composer draft) with one shared catch. Retry targets the turn's
last successful attempt via new persisted lastCompletedMessageId
(fixes the always-400 error-retry against the server's
current_message_id lookup); chat switch / active-chat delete now
auto-stop the stream first (commit draft, mark bubble interrupted)
instead of orphaning it. generateResponse's finally is now
ownership-checked so a canceled predecessor can't clobber its
successor's controller/throttle state; isSendingChat is derived from
the slot.
Per tta_rewrite_final.md §2.3/§6 step 2.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Success now requires a `done` frame: EOF or [DONE] without one returns
STREAM_INTERRUPTED (1002) instead of a fabricated empty success, keeping
streamed partials on the message. On-error canvas policy switches from
wipe to commit-like-Stop (bubble/thumbnail/canvas agree), error-retry
queues the failed generation for replacement, and errored bubbles with
partial skeletons render their preview + "To canvas" (salvage UI).
Also: partial.isComplete forwarded, done.finishReason carried
(length/content_filter → truncated status line), truncate response
validated as { ok, chatId, updatedAt? } (M4), dead [ai-server] filter
and changed-chatId re-onStarted branch deleted, N5 spinner hole closed.
sse.ts gains an opt-in onDoneSentinel (TTD untouched).
Per tta_rewrite_final.md §2.2/§6 step 1 (design from tta_c2.md).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Per tta_rewrite_final.md §6 step 0: fix getViewportCenter via
viewportCoordsToSceneCoords (+3 centering tests), delete dead helpers /
path constants / composer uncontrolled mode / 12 dead i18n keys, unexport
consumer-less atoms, merge the two scroll effects, inline
tta-chat-empty.svg as a data URI (was a root-absolute URL). Also fixes
the pre-existing typecheck break from 3a7c9fbad (syncActionResult mock
missing captureUpdate).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(packages/excalidraw): add `props.interaction` and `props.ui`
* fix: prevent browser zoom when interaction disabled
* changelog
* clean up interactive state on disable and consolidate `viewMode` and interaction state updates
* render UI rendered to `children` even if editor-exported
* support `allowed.navigation` and `allowed.embeds/interactiveContent`
* change naming `allowed` -> `enabled`
* changelog: add PR links
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* clear flowchart sessions via consolidated `app.flowchart` after master merge
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor getters -> methods
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Closes#8518. Fixes the issue when adding a new child to a flowchart node that already has children (after the first creation session was committed), the new child could land on top of, or misaligned with, an existing sibling.
---------
Signed-off-by: Mark Tolmacs <mark@lazycat.hu>
Co-authored-by: Mark Tolmacs <mark@lazycat.hu>