fix(review round 1): daemon PAT-header auth, job pruning, session-split batches, streaming tars, seed cleanup, ping/pong, byte caps, branch switch, slug --, ctx cancel, Init:true, pagination, latest/before events; web newest-window history + load-older, offline busy gate, staleness guards, memo store, auth probe, scroll key, focus-visible, draft restore, poll dedup; 106+181 tests, coverage 96.2%/95.1%+

This commit is contained in:
Raphael Westphal
2026-08-18 18:49:52 +02:00
parent 64e45e1a82
commit 6aac763563
25 changed files with 2564 additions and 959 deletions
+25 -1
View File
@@ -136,9 +136,20 @@ interface Props {
messages: ChatMessage[];
tools: Map<string, ToolState>;
busy: boolean;
/** an older page exists beyond the loaded window (B1) */
hasOlder: boolean;
loadingOlder: boolean;
onLoadOlder: () => void;
}
export default function ChatStream({ messages, tools, busy }: Props) {
export default function ChatStream({
messages,
tools,
busy,
hasOlder,
loadingOlder,
onLoadOlder,
}: Props) {
const scrollRef = useRef<HTMLDivElement | null>(null);
const pinnedRef = useRef<boolean>(true);
@@ -166,6 +177,19 @@ export default function ChatStream({ messages, tools, busy }: Props) {
return (
<div className="chat-scroll" ref={scrollRef} onScroll={onScroll}>
<div className="chat-inner">
{hasOlder && (
<div className="load-older">
<button
type="button"
className="btn-secondary"
aria-label="Load older messages"
disabled={loadingOlder}
onClick={onLoadOlder}
>
{loadingOlder ? "loading…" : "Load older"}
</button>
</div>
)}
{messages.map((m) => (
<Bubble key={m.key} msg={m} tools={tools} />
))}