style(desktop): align stability changes with local conventions

This commit is contained in:
brooklyn!
2026-09-22 17:29:15 -05:00
parent a87310a343
commit 28aceb3451
4 changed files with 11 additions and 1 deletions

View File

@@ -712,6 +712,7 @@ export function placeCaretAtOffset(editor: HTMLElement, offset: number) {
* cloning the draft on every input flush makes ordinary typing needlessly costly. */
function removeComposerJunk(editor: HTMLElement, node: ChildNode) {
const selected = composerCollapsedSelectionContainer(editor)
const offset =
document.activeElement === editor && selected && node.contains(selected) ? caretOffsetInEditor(editor) : null

View File

@@ -14,8 +14,8 @@ import { $messages, setActiveSessionId, setMessages } from '@/store/session'
import { $sessionStates } from '@/store/session-states'
import { usePromptActions } from '../use-prompt-actions'
import { useSessionStateCache } from '../use-session-state-cache'
import { reconcileDurableHistory } from '../use-session-actions/utils'
import { useSessionStateCache } from '../use-session-state-cache'
import { useMessageStream } from './index'
@@ -109,12 +109,14 @@ function mount(rpc = requestGateway) {
it('binds a late submit acknowledgement to its exact optimistic prompt without reviving the turn', async () => {
const laterUser: ChatMessage = { id: 'later-user', role: 'user', parts: [{ type: 'text', text: 'Give the answer.' }] }
const h = mount(async <T,>(): Promise<T> => {
await h.send('message.start')
await h.send('message.delta', { text: ANSWER })
await h.send('message.complete', { text: ANSWER })
h.update(state => ({ ...state, messages: [...state.messages, laterUser], needsInput: true }))
await flush()
return { status: 'started', user_row_id: 71 } as T
})
@@ -139,6 +141,7 @@ it.each([true, false, undefined])(
const assistantId = h.state().streamId
const queued: ChatMessage = { id: `user-queued-${SID}`, role: 'user', parts: [{ type: 'text', text: 'Next' }] }
h.update(state => ({ ...state, messages: [...state.messages, queued] }))
const receipt =
complete === undefined
? undefined
@@ -168,6 +171,7 @@ it.each([true, false, undefined])(
['user', 'Next']
])
}
h.dispose()
}
)

View File

@@ -737,6 +737,7 @@ describe('preserveLocalPendingTurnMessages', () => {
const answer = msg('stored-answer', 'assistant', 'Completed.', { rowId: 30, timestamp: 5 })
const folded = { ...answer, rowId: 20, parts: [{ ...textPart('Completed.'), sourceRowId: 30 }] }
for (const next of [[answer], [msg('stored-followup', 'user', 'Follow-up request'), answer], [folded]]) {
expect(preserveLocalPendingTurnMessages(next, previous)).toEqual(next)
}

View File

@@ -58,6 +58,7 @@ import { reportBackendContract, reportInstallMethodWarning } from '@/store/updat
import type { SessionCreateResponse, SessionInfo, SessionResumeResult, SessionRuntimeInfo } from '@/types/hermes'
import type { ClientSessionState } from '../../../types'
import {
acknowledgedTranscriptBoundary,
conflictingTranscriptIdentity,
@@ -686,12 +687,14 @@ export function preserveLocalPendingTurnMessages(
}
crossedUserBoundary ||= message.role === 'user' || message.role === 'system'
// A second segment of the acknowledged turn can still be folded into its
// final row. A new prompt closes that ownership; identical later replies
// must not be consumed by the already-acknowledged prefix.
const candidates = (crossedUserBoundary ? remainingNext : acknowledgedTurn).filter(
candidate => !conflictingTranscriptIdentity(message, candidate)
)
const ordinal = previousRoleCounts.get(message.role) ?? 0
previousRoleCounts.set(message.role, ordinal + 1)
@@ -739,6 +742,7 @@ export function preserveLocalPendingTurnMessages(
}
const ordinalMatch = nextByRoleOrdinal.get(`${message.role}:${ordinal}`)
const authoritative =
ordinalMatch && !conflictingTranscriptIdentity(message, ordinalMatch) ? ordinalMatch : undefined