mirror of
https://github.com/stablyai/orca.git
synced 2026-10-29 00:03:37 +00:00
* fix(mobile): keep the cached transcript visible while reconnecting A manual retry closes the client and opens a fresh one, so the chat session hook saw a new client under an unchanged identity, dropped its settled read, and handed out an empty list — the transcript collapsed to a full-screen spinner until the swapped client's snapshot landed. Hold the last settled list per identity (captured post-commit) and keep rendering it while the re-read is in flight. `transcriptLoading` still gates consumers that decide from an empty transcript, so the launch-draft seed is unaffected. The held list is keyed by a new `sourceIdentity` (host/workspace) in addition to agent/session/transcript, so it can never serve another source's messages. Refs STA-3333. * test(mobile): assert the whole reconnect window, not just its first frame The re-subscribe lands a commit after the first render of the swap, so a regression that cleared the held list there left frame 0 green and still blanked the transcript. Verified: clearing the cache in the subscribe cleanup now fails this test, where before only the view-toggle test caught it. * fix(mobile): don't derive a tappable ask card from the held transcript The cache this PR adds keeps the previous list rendered while a swapped client re-reads. useMobileNativeChatPrompts was the one consumer reading `messages` without honouring `transcriptLoading`, so an ask answered on the terminal resurrected as a live, tappable card during that window. Gating on `transcriptLoading` is exactly base behaviour: `setRead` only ever stores 'ready'/'error', so status==='loading' implied an empty list before this PR. The live `askFromStatus` path is untouched. * chore: keep merge formatting scoped
37 lines
1.1 KiB
TypeScript
37 lines
1.1 KiB
TypeScript
import type { NativeChatMessage } from './native-chat-types'
|
|
|
|
export const EMPTY_NATIVE_CHAT_TRANSCRIPT: NativeChatMessage[] = []
|
|
|
|
export function encodeNativeChatTranscriptIdentity(parts: readonly (string | null)[]): string {
|
|
return JSON.stringify(parts)
|
|
}
|
|
|
|
export type NativeChatTranscriptRetention = {
|
|
capture: (identity: string, messages: NativeChatMessage[]) => void
|
|
visible: (args: {
|
|
identity: string
|
|
messages: NativeChatMessage[]
|
|
settled: boolean
|
|
loading: boolean
|
|
}) => NativeChatMessage[]
|
|
}
|
|
|
|
/** Retains one settled transcript so a same-source rebind does not blank the conversation. */
|
|
export function createNativeChatTranscriptRetention(): NativeChatTranscriptRetention {
|
|
let captured: { identity: string; messages: NativeChatMessage[] } | null = null
|
|
|
|
return {
|
|
capture(identity, messages) {
|
|
captured = { identity, messages }
|
|
},
|
|
visible({ identity, messages, settled, loading }) {
|
|
if (settled) {
|
|
return messages
|
|
}
|
|
return loading && captured?.identity === identity
|
|
? captured.messages
|
|
: EMPTY_NATIVE_CHAT_TRANSCRIPT
|
|
}
|
|
}
|
|
}
|