Files
orca/src/main/native-chat/transcript-watch-contract.ts
T
Jinjing 42bff5e598 fix(native-chat): add reconciliation to catch missed transcript updates (#9701)
* fix(native-chat): add reconciliation to catch missed transcript updates

Periodic reconciliation catches file changes that fs.watch may miss on
remote filesystems. Event-driven drains use a bounded max-wait timer to
ensure responsiveness. Extracts timer logic into a scheduler module for
testability and maintainability.

* fix(native-chat): add reconciliation to catch missed transcript updates

Detects same-size file rewrites and native watcher failures by reconciling
transcript state even when fs.watch events don't fire. Extracts watcher
binding into a dedicated module that gracefully degrades to
reconciliation-only mode when native watch is unavailable. Adds test
coverage for watcher rebind failures, parent-directory replacements, and
unsubscribe races.

* Document transcript watcher reconciliation contract

Clarify that bind() is best-effort with reconciliation fallback,
invalidate() detaches from stale identities, and the caller's polling
loop owns transcript liveness. Supports resilience on remote filesystems.
2026-07-20 23:57:05 -07:00

39 lines
1.1 KiB
TypeScript

import type {
AgentType,
NativeChatMessage,
NativeChatTurnLifecycle
} from '../../shared/native-chat-types'
import type { ResolveSessionFileOptions } from './session-file-resolver'
export type SubscribeNativeChatTranscriptArgs = ResolveSessionFileOptions & {
agent: AgentType
sessionId: string
onAppend: (messages: NativeChatMessage[], lifecycle?: NativeChatTurnLifecycle) => void
onInitialSnapshot?: (
messages: NativeChatMessage[],
hasMore: boolean,
beforeOffset: number,
/** Set when the initial drain could not deliver a transcript. */
error?: string,
lifecycle?: NativeChatTurnLifecycle
) => void
onReplace?: (
messages: NativeChatMessage[],
hasMore: boolean,
beforeOffset: number,
lifecycle?: NativeChatTurnLifecycle
) => void
initialLimit?: number
filePath?: string
debounceMs?: number
/** Test-only override for the production resolve-poll backoff. */
resolvePollIntervalMs?: number
/** Test-only override for the host-side watcher reconciliation interval. */
reconciliationIntervalMs?: number
}
export type NativeChatTranscriptSubscription = {
unsubscribe: () => void
watching: boolean
}