import type { ModelProbeState } from "./model-selection" export const terminalAttr = "data-pty-id" export type TerminalProbeState = { connected: boolean connects: number rendered: string settled: number focusing: number } type TerminalProbeControl = { disconnect?: VoidFunction } export type E2EWindow = Window & { __opencode_e2e?: { model?: { enabled?: boolean current?: ModelProbeState } prompt?: { enabled?: boolean current?: import("./prompt").PromptProbeState } terminal?: { enabled?: boolean terminals?: Record controls?: Record } } } const seed = (): TerminalProbeState => ({ connected: false, connects: 0, rendered: "", settled: 0, focusing: 0, }) const root = () => { if (typeof window === "undefined") return const state = (window as E2EWindow).__opencode_e2e?.terminal if (!state?.enabled) return return state } const terms = () => { const state = root() if (!state) return state.terminals ??= {} return state.terminals } const controls = () => { const state = root() if (!state) return state.controls ??= {} return state.controls } export const terminalProbe = (id: string) => { const set = (next: Partial) => { const state = terms() if (!state) return state[id] = { ...(state[id] ?? seed()), ...next } } return { init() { set(seed()) }, connect() { const state = terms() if (!state) return const prev = state[id] ?? seed() state[id] = { ...prev, connected: true, connects: prev.connects + 1, } }, render(data: string) { const state = terms() if (!state) return const prev = state[id] ?? seed() state[id] = { ...prev, rendered: prev.rendered + data } }, settle() { const state = terms() if (!state) return const prev = state[id] ?? seed() state[id] = { ...prev, settled: prev.settled + 1 } }, focus(count: number) { set({ focusing: Math.max(0, count) }) }, step() { const state = terms() if (!state) return const prev = state[id] ?? seed() state[id] = { ...prev, focusing: Math.max(0, prev.focusing - 1) } }, control(next: Partial) { const state = controls() if (!state) return state[id] = { ...(state[id] ?? {}), ...next } }, drop() { const state = terms() if (state) delete state[id] const control = controls() if (control) delete control[id] }, } }