fix(tui): use SDK publish for acks and per-instance state tracking
- TUI ack events now use sdk.client.tui.publish() instead of Bus.publish() to properly route events from TUI process to backend worker thread - TerminalControl now uses Instance.state() for per-instance subscription tracking instead of global boolean, fixing multi-instance scenarios - Remove unused Bus import from app.tsxpull/14293/head
parent
44d0519137
commit
31e7749b43
|
|
@ -49,7 +49,6 @@ import { ToastProvider, useToast } from "./ui/toast"
|
|||
import { ExitProvider, useExit } from "./context/exit"
|
||||
import { Session as SessionApi } from "@/session"
|
||||
import { TuiEvent } from "./event"
|
||||
import { Bus } from "@/bus"
|
||||
import { KVProvider, useKV } from "./context/kv"
|
||||
import { Provider } from "@/provider/provider"
|
||||
import { ArgsProvider, useArgs, type Args } from "./context/args"
|
||||
|
|
@ -881,14 +880,24 @@ function App(props: { onSnapshot?: () => Promise<string[]> }) {
|
|||
sdk.event.on(TuiEvent.RendererSuspendRequest.type, async (evt) => {
|
||||
renderer.suspend()
|
||||
renderer.currentRenderBuffer.clear()
|
||||
await Bus.publish(TuiEvent.RendererSuspendAck, { token: evt.properties.token })
|
||||
await sdk.client.tui.publish({
|
||||
body: {
|
||||
type: TuiEvent.RendererSuspendAck.type,
|
||||
properties: { token: evt.properties.token },
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
sdk.event.on(TuiEvent.RendererResumeRequest.type, async (evt) => {
|
||||
renderer.currentRenderBuffer.clear()
|
||||
renderer.resume()
|
||||
renderer.requestRender()
|
||||
await Bus.publish(TuiEvent.RendererResumeAck, { token: evt.properties.token })
|
||||
await sdk.client.tui.publish({
|
||||
body: {
|
||||
type: TuiEvent.RendererResumeAck.type,
|
||||
properties: { token: evt.properties.token },
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Bus } from "@/bus"
|
||||
import { TuiEvent } from "@/cli/cmd/tui/event"
|
||||
import { Identifier } from "@/id/id"
|
||||
import { Instance } from "@/project/instance"
|
||||
import { Log } from "@/util/log"
|
||||
|
||||
const log = Log.create({ service: "terminal-control" })
|
||||
|
|
@ -23,7 +24,15 @@ export namespace TerminalControl {
|
|||
readonly timer: NodeJS.Timeout
|
||||
}
|
||||
|
||||
const pendingAcks = new Map<string, AckHandler>()
|
||||
interface State {
|
||||
pendingAcks: Map<string, AckHandler>
|
||||
subscriptionsInitialized: boolean
|
||||
}
|
||||
|
||||
const state = Instance.state(() => ({
|
||||
pendingAcks: new Map<string, AckHandler>(),
|
||||
subscriptionsInitialized: false,
|
||||
}))
|
||||
|
||||
function isTuiMode(): boolean {
|
||||
return process.env.OPENCODE_TUI === "1"
|
||||
|
|
@ -36,17 +45,17 @@ export namespace TerminalControl {
|
|||
function waitForAck(token: string, timeoutMs: number, operation: "suspend" | "resume"): Promise<void> {
|
||||
return new Promise<void>((resolve) => {
|
||||
const timer = setTimeout(() => {
|
||||
pendingAcks.delete(token)
|
||||
state().pendingAcks.delete(token)
|
||||
log.warn(`${operation}: timeout waiting for TUI ack`, { token, timeoutMs })
|
||||
resolve()
|
||||
}, timeoutMs)
|
||||
|
||||
pendingAcks.set(token, {
|
||||
state().pendingAcks.set(token, {
|
||||
token,
|
||||
timer,
|
||||
resolve: () => {
|
||||
clearTimeout(timer)
|
||||
pendingAcks.delete(token)
|
||||
state().pendingAcks.delete(token)
|
||||
log.debug(`${operation}: received ack`, { token })
|
||||
resolve()
|
||||
},
|
||||
|
|
@ -55,10 +64,10 @@ export namespace TerminalControl {
|
|||
}
|
||||
|
||||
function cleanupPendingAck(token: string): void {
|
||||
const handler = pendingAcks.get(token)
|
||||
const handler = state().pendingAcks.get(token)
|
||||
if (handler) {
|
||||
clearTimeout(handler.timer)
|
||||
pendingAcks.delete(token)
|
||||
state().pendingAcks.delete(token)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -101,14 +110,14 @@ export namespace TerminalControl {
|
|||
}
|
||||
|
||||
function handleAck(token: string): void {
|
||||
const handler = pendingAcks.get(token)
|
||||
const handler = state().pendingAcks.get(token)
|
||||
handler?.resolve()
|
||||
}
|
||||
|
||||
let subscriptionsInitialized = false
|
||||
function ensureSubscriptions(): void {
|
||||
if (subscriptionsInitialized) return
|
||||
subscriptionsInitialized = true
|
||||
const s = state()
|
||||
if (s.subscriptionsInitialized) return
|
||||
s.subscriptionsInitialized = true
|
||||
|
||||
Bus.subscribe(TuiEvent.RendererSuspendAck, (event) => {
|
||||
handleAck(event.properties.token)
|
||||
|
|
@ -118,6 +127,6 @@ export namespace TerminalControl {
|
|||
handleAck(event.properties.token)
|
||||
})
|
||||
|
||||
log.debug("Bus subscriptions initialized")
|
||||
log.debug("Bus subscriptions initialized", { directory: Instance.directory })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue