← Về thư mục
📄 / / profiles / r-and-d / raw_evidence / OpenAI4S / frontend / src / features / messages / README.md

frontend/src/features/messages

中文说明

F-10 message stream. Framed history paint (40 rows per rAF + one fragment), dual-node streaming markdown (sealed prefix + live tail), tool output textNode.appendData(delta), follow-scroll coalesced on rAF. 1MB live-output cap is F-08 appendLiveOutput; this lane only turns it into a delta. Window names (openConversation, fetch*Messages, down) are assigned here, not left as F-05 stubs.

Files

File Responsibility
cardState.ts The live activity card's state: a new Cell card shows a progress glyph (not the success check) and records its producing_cell_id; notebook_cell_finished (forwarded by the Notebook's handler) marks that card failed (x glyph, error bar, "Failed · N lines"), succeeded or stopped; turnDone settles any card still running to a neutral "ended". The generated "Running analysis · cell N" title becomes "Analysis · cell N" once the cell ends; a cell's own title stays. Feature-local copy.
copy.ts Source-owned bilingual history-recovery text; generated locale extracts stay unchanged.
components.tsx MessageList (#messages / #jump-pill), accessible history status/retry outside the message host, and StreamingPre.
cut.ts Incremental _mdStableCut / mdStableCut (app.js:5378-5402).
cut.test.ts Incremental scan matches the original from-scratch cut; fence / 120-char tail.
delta.ts liveOutputDelta, bindStreamingPre (appendData), toolMetaLabel.
delta.test.ts 1MB truncation idempotent; newlines counted on the increment only.
dom.ts $ / el / #messages / ensureMessageDom.
fetch.ts fetchRecentMessages / fetchOlderMessages / fetchAllMessages (6926-6961).
handlers.ts text_reset / text_chunk WS handlers.
handlers.test.ts mine / stale-turn guards; idempotent register.
identity.ts Candidate identity + storedCandidateOwnsChunk at the feed boundary.
index.ts Public exports; installMessages assigns window names via isReady.
install.test.ts Contract names are real (isReady), not F-05 stubs.
list.ts renderStored, insertMessageByTime, framed batch paint. A plan-mode user row renders as the user's own text and a plan execution seed as a plan marker (planPrompt.ts).
list.test.ts 640 rows → 16 frames of 40; insert-by-time skips #msgs-earlier.
messages.css .md-sealed / .md-tail { display: contents }; the stopped-turn marker and stopped card (muted glyph, neutral bar); running and ended cards (neutral glyph and bar, the running glyph spins unless reduced motion is preferred) and failed cards (error glyph colour and bar); the reopened plan-seed line shares the stopped marker's style.
open.ts openConversation / recoverConversation: generation-scoped read results, GET-only retries, confirmed-history retention and atomic framed paint. The per-session reset keys on openedFrameId (the frame whose state is on screen), not only on currentId, so a new session published before it is opened, or opened after Home, starts with an empty Notebook.
open.test.ts Generation-scoped history failures, GET-only recovery, REST/WS races and retained older pages; a new session's Notebook holds only its own cells (adopted from an open session, after Home, with a late read of the previous session).
planPrompt.ts Plan-mode rows reopened as what the user wrote: planModeRequestText cuts the plan-mode prompt (workbench, legacy app.js, revision seed) from a stored user row, mirroring openai4s/server/plans.py; planSeed / planSeedMarker render an approval or resume seed as one muted "Plan approved: …" line (feature-local copy). Stored rows are unchanged.
raf.ts Shared requestAnimationFrame / setTimeout fallback.
scroll.ts down / updateJumpPill on one rAF; throttled scroll listener.
stopped.ts The stopped-turn marker: a text_chunk or stored row carrying cancelled renders as one marker (feature-local copy), the still-running activity card is marked stopped through cardState.ts (stop glyph, and the generated "Running analysis · cell N" title becomes "Analysis · cell N"; a card whose own outcome already arrived keeps it), and a cancelled terminal whose chunk was missed gets the same marker.
stopped.test.ts Live marker instead of prose, stopped card (glyph, generated title replaced, the cell's own title kept) vs. a card that finished first, terminal fallback without duplicates, reopen via both stored renderers, malformed metadata stays prose. The card outcome through the real notebook_cell_finished handler: a cell that raised ends failed (no check, no running title), success keeps the check, an interrupted cell is stopped once, only the named cell's card is repainted, and a card with no outcome does not outlive its turn as running. Stored plan-mode rows through both renderers: the prompt's bubble is the task (en/zh), a revision's is the change request, an approval seed is a plan marker, ordinary text is untouched.
stream.ts feed / flushRender / scheduleRender / startStream / sealText.