fix(main): PTY_EXIT 补偿查询、SSH 飞行连接登记与双窗口守卫

- 新增 SESSION_STATE 查询通道(契约先行):PTY_EXIT 只广播一次不重放,
  绑定晚于退出的窗格订阅后补查一次退出状态,快速退出的 shell 不再留下
  永远空白、无死亡遮罩的窗格(退出码登记表上限 512 条 FIFO)
- openSession 在 connectSsh 返回前登记 pendingOpens(owner + onClient
  最早引用),killPtysByOwner/killAllPtys 可中止飞行中的握手,renderer
  崩溃后不再留下无主孤儿 SSH 会话
- whenReady 的 createWindow 加已有窗口守卫,堵住与 second-instance
  showOrCreate 的双窗口竞态
- killAllPtys 补 replayBuffers.clear(),与 killSession 拆卸清单对齐
- promptUser 注释 30s 改为实际 120s;pty.ts 顺带注入 zmodem 背压钩子
  (见下一提交)
This commit is contained in:
Bill committed 2026-10-09 11:30:51 +08:00
1 parent 0289dcbd1d
commit 81ac112dac
9 files changed
+223 -24

No files matched your search

+9 -1
View File
@@ -6,7 +6,8 @@ import type {
PtyDataEvent,
PtyExitEvent,
SessionOpenResult,
SessionSnapshot
SessionSnapshot,
SessionStateResult
} from './ipc'
import type { AppSettings } from './settings'
import type { ReleaseNote, UpdateState } from './ipc'
@@ -36,6 +37,13 @@ export interface AppApi {
openSession(opts: SessionOpenOptions): Promise<SessionOpenResult>
/** output a session produced before this renderer subscribed (capped ring buffer) */
getSessionReplay(id: string): Promise<string>
/**
* Compensating query for a missed PTY_EXIT: that broadcast fires exactly once
* and is never replayed, so a pane subscribing after its shell died would
* wait forever. `exited` (with `exitCode`) is the death state PTY_EXIT would
* have set.
*/
getSessionLiveState(id: string): Promise<SessionStateResult>
writePty(id: string, data: string): void
resizePty(id: string, cols: number, rows: number): void
killPty(id: string): void