fix(chat): keep the transcript steady at Turn end and when steering lands
Measured against 0.2.1-rc.4 and master with the frame-sampled motion matrix, the transcript moved back and forth at Turn end and around input landing. This keeps rc.4's landing behavior, master's steering layout, and fixes the reversals that remain. - Completion-time folding keeps the first visible surviving row still when work rows close at once, filling the gap with bottom space capped at half the scrollport, instead of letting the browser clamp the position. - After the Session stops running, the running status keeps its tail slot hidden and silent until the Turn's actions row replaces it, so the tail does not shrink and grow back. - A Turn's duration control takes its gap in one frame instead of sliding. - A fold batch that takes over following for a content change absorbs growth outside the batch before its first frame. - Steering lands at once under either fold timing: the running Turn keeps streaming above its echo, which a native animation would push down. - The running status no longer slides below a Step's first output, and the column no longer carries `data-chat-tail-pinned`; the steering entrance keeps its animation. - A queued prompt is accepted by its Inbox row as well as by its receipt, so the composer clears the draft in the frame the queue dock shows it. - A queued echo waits for the Inbox projection instead of retiring on the durable splice, so the queue dock does not empty for a frame.
This commit is contained in:
1 parent
6300195071
commit
ae07093132
21 files changed
+539
-366
No files matched your search
@@ -800,7 +800,10 @@ export class Session implements SessionFace {
|
||||
}
|
||||
}
|
||||
this.observeSubmissionInsertions(target, inserted, start, event.seq)
|
||||
for (const message of inserted) this.observeSubmissionMessage(message, false)
|
||||
// A queued echo waits for the inbox projection the queue dock renders, which can arrive after this
|
||||
// event; retiring it here would empty the dock for a frame. A claim in the same projection notification
|
||||
// still retires it through the durable user message.
|
||||
for (const message of inserted) this.observeSubmissionMessage(message, false, false)
|
||||
return
|
||||
}
|
||||
if (event.type === 'request/context' || event.type === 'turn/end') {
|
||||
@@ -818,21 +821,29 @@ export class Session implements SessionFace {
|
||||
const source = message.source
|
||||
if (source.kind !== 'user' || !('rpcId' in source)) continue
|
||||
const settlement = this.submissionSettlements.get(source.rpcId)
|
||||
if (settlement === undefined || settlement.placement === 'queued'
|
||||
|| settlement.retiring || (settlement.receipt?.seq ?? -1) > seq) continue
|
||||
if (settlement === undefined || settlement.retiring) continue
|
||||
// Either proof accepts a prompt; an Inbox row can reach the Client before the prompt receipt. A queued
|
||||
// prompt's row is the queue dock's own row, so its acceptance there lets the composer clear the draft in
|
||||
// the frame that shows the row; its retirement follows the Inbox projection, not a receipt position.
|
||||
if (settlement.placement === 'queued') {
|
||||
this.acceptPrompt(source.rpcId)
|
||||
continue
|
||||
}
|
||||
if ((settlement.receipt?.seq ?? -1) > seq) continue
|
||||
settlement.receipt = { target, seq, index: start + index, attachments: attachmentRefsIn(message.content) }
|
||||
// An Inbox row can reach the Client before the prompt receipt.
|
||||
this.acceptPrompt(source.rpcId)
|
||||
}
|
||||
}
|
||||
|
||||
private observeSubmissionMessage(message: UserMessage, admitted: boolean): void {
|
||||
private observeSubmissionMessage(message: UserMessage, admitted: boolean, retireQueued = true): void {
|
||||
const source = message.source
|
||||
if (source.kind !== 'user' || !('rpcId' in source)) return
|
||||
const settlement = this.submissionSettlements.get(source.rpcId)
|
||||
if (settlement === undefined || settlement.retiring) return
|
||||
if (!admitted) {
|
||||
if (settlement.placement === 'queued') this.scheduleObservedRetirement(source.rpcId, attachmentRefsIn(message.content))
|
||||
if (settlement.placement === 'queued' && retireQueued) {
|
||||
this.scheduleObservedRetirement(source.rpcId, attachmentRefsIn(message.content))
|
||||
}
|
||||
return
|
||||
}
|
||||
settlement.admitted = attachmentRefsIn(message.content)
|
||||
|
||||
Reference in new issue
Block a user