Root causes:
1. Duplicate .st-bme-notice__title and .st-bme-notice__message blocks (from
original code) were overriding the new transition-enabled versions,
stripping transitions and causing missing overflow:hidden on __message.
2. .st-bme-notice::after pseudo-element CSS was accidentally merged into
.st-bme-notice__message--marquee block during previous edit.
3. Compact layout .st-bme-notice__content had overflow:hidden with no
min-width constraint, causing the title to collapse to 'ST...'.
Fixes:
- Removed all duplicate CSS blocks; single canonical definitions with transitions
- Restored ::after pseudo-element as separate rule
- Added max-width:320px with overflow:hidden explicitly for compact content
- Added normal content max-width:360px with overflow:hidden
- Restored missing .st-bme-notice__actions base rule with transition
- Added .st-bme-notice__message overflow:hidden for max-height animation
Root cause: onStreamProgress callback fires 20-50x/sec during LLM streaming,
each calling setLastExtractionStatus with syncRuntime=true (default), which
triggers setRuntimeStatus -> refreshPanelLiveState() -> _refreshDashboard().
_refreshDashboard iterates all graph nodes (.filter x2) and performs heavy
DOM updates each time. When the panel is open, this blocks the main thread.
Fixes:
1. panel.js: Add requestAnimationFrame throttle to refreshLiveState() with
minimum 80ms gap between actual DOM refreshes. Rapid calls are collapsed
into a single animation frame, preventing main thread saturation.
2. extraction-controller.js: Change onStreamProgress to use syncRuntime=false
so streaming updates no longer trigger setRuntimeStatus (which would also
update the floating ball on each chunk).
3. recall-controller.js: Same fix for recall onStreamProgress which had
the identical syncRuntime=true issue.
Root cause analysis: extraction can appear stuck at '正在提取xx-xx楼层' indefinitely
when the LLM API connection goes half-open (server stops sending data but keeps the
TCP connection alive). The SSE stream reader.read() would block forever with no
per-chunk idle timeout.
Changes:
1. llm/llm.js: Add LLM_STREAM_IDLE_TIMEOUT_MS (90s default) to
parseDedicatedStreamingResponse. When no SSE data is received for 90 seconds,
the read loop aborts with a clear timeout error instead of hanging forever.
The idle timeout is configurable per-request (defaults to 30% of config timeout,
minimum 30s).
2. index.js: Add EXTRACTION_VECTOR_SYNC_TIMEOUT_MS (120s) timeout wrapper around
syncVectorState in handleExtractionSuccess. Vector sync now uses a combined
AbortSignal (extraction signal + timeout) so that either user abort or 120s
timeout will break out. Vector sync timeout is treated as non-fatal (doesn't
abort the entire extraction batch).
- Fix#2: _executeStatements fallback now batches transactions (150/batch)
and reorders upsert-before-delete to prevent data loss on payload overflow
- Fix#3: Read/write migratedToAuthority marker in chat_metadata to prevent
re-overwriting from legacy sources after Authority migration
- Fix#1: Add OPFS → Authority migration channel (exportOpfsSnapshotForChat,
maybeImportLegacyOpfsSnapshotToLocalStore) inserted before IndexedDB in
migration chain
- Fix#4: Mark runtimeVectorIndexState dirty with triviumRebuildRequired
and trigger submitAuthorityVectorRebuildJob after all three migration paths
- Fix#5: Dual-save safety snapshots to Authority blob; rollback can now
recover from blob when local IndexedDB snapshot is unavailable
- Fix#6: Add isEmptyCheck detail and console.warn for near-empty stores
to help diagnose residual vs real data in store-not-empty skips
- Fix#7: Add overflow warning logs and sessionStorage persistence for
Authority offline queue max-items/max-bytes exceeded events
Authority server expects params: SqlValue[] (positional array) but
ST-BME was sending params as a named map with :placeholders, causing
'invalid type: map, expected a sequence' deserialization errors.
Added convertNamedParamsToPositional() in AuthoritySqlHttpClient that
transforms :name placeholders to ? and extracts values in order before
sending to the server. This fixes the SQL probe failure that kept the
graph stuck in LOADING state.