style(desktop): align stability changes with local conventions
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user