mirror of
https://github.com/stablyai/orca.git
synced 2026-09-24 00:02:24 +00:00
* perf(native-chat): suspend hidden transcript streams * fix(native-chat): keep assembly renders pure * fix(native-chat): keep a transient error from stranding a revealed chat - An error snapshot frame no longer latches frameArrived, so the in-flight read can still seed the pane instead of leaving it on the error surface. - Retained history is shown over a full-pane read error for the same source. - The paged read window survives a hide/reveal; only a source change resets it. Co-authored-by: Orca <help@stably.ai> * fix(mobile): match the trimmed native-chat retention signature The shared retention type no longer takes `loading`, so mobile's call was an excess-property error that broke the mobile typecheck job. Dropping it also lets mobile inherit the desktop behavior: a stream error or dropped client keeps the last transcript instead of swapping it for the error empty state. Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Orca <help@stably.ai>
42 lines
1.7 KiB
TypeScript
42 lines
1.7 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import type { NativeChatMessage } from './native-chat-types'
|
|
import {
|
|
createNativeChatTranscriptRetention,
|
|
encodeNativeChatTranscriptIdentity
|
|
} from './native-chat-transcript-retention'
|
|
|
|
function message(id: string): NativeChatMessage {
|
|
return { id, role: 'assistant', blocks: [], timestamp: 0, source: 'transcript' }
|
|
}
|
|
|
|
describe('native chat transcript retention', () => {
|
|
it('holds only the latest settled transcript for the same identity while unsettled', () => {
|
|
const retention = createNativeChatTranscriptRetention()
|
|
const first = [message('first')]
|
|
const second = [message('second')]
|
|
|
|
retention.capture('source-a', first)
|
|
expect(retention.visible({ identity: 'source-a', messages: [], settled: false })).toBe(first)
|
|
expect(retention.visible({ identity: 'source-b', messages: [], settled: false })).toEqual([])
|
|
|
|
retention.capture('source-b', second)
|
|
expect(retention.visible({ identity: 'source-a', messages: [], settled: false })).toEqual([])
|
|
expect(retention.visible({ identity: 'source-b', messages: [], settled: false })).toBe(second)
|
|
})
|
|
|
|
it('never substitutes retained history for a settled read', () => {
|
|
const retention = createNativeChatTranscriptRetention()
|
|
const retained = [message('retained')]
|
|
const fresh = [message('fresh')]
|
|
retention.capture('source', retained)
|
|
|
|
expect(retention.visible({ identity: 'source', messages: fresh, settled: true })).toBe(fresh)
|
|
})
|
|
|
|
it('encodes identity components without delimiter collisions', () => {
|
|
expect(encodeNativeChatTranscriptIdentity(['host\0workspace', 'session'])).not.toBe(
|
|
encodeNativeChatTranscriptIdentity(['host', 'workspace\0session'])
|
|
)
|
|
})
|
|
})
|