Fix tmux Shift+Enter state reporting

This commit is contained in:
austinpower1258 2026-03-30 03:49:00 -07:00
parent 9ce4997ced
commit f4c99d34f3
5 changed files with 215 additions and 56 deletions

View file

@ -520,6 +520,42 @@ class TerminalController {
return trimmed
}
nonisolated static func normalizedReportedTTYName(_ raw: String?) -> String? {
guard let trimmed = raw?.trimmingCharacters(in: .whitespacesAndNewlines),
!trimmed.isEmpty,
trimmed != "not a tty" else {
return nil
}
let components = trimmed.split(separator: "/")
if let last = components.last, !last.isEmpty {
return String(last)
}
return trimmed
}
static func resolvePanelIdByTTY(_ ttyName: String?, in tab: Tab) -> UUID? {
guard let ttyName = normalizedReportedTTYName(ttyName) else {
return nil
}
if let focusedPanelId = tab.focusedPanelId,
normalizedReportedTTYName(tab.surfaceTTYNames[focusedPanelId]) == ttyName,
tab.panels[focusedPanelId] != nil {
return focusedPanelId
}
let matches = tab.surfaceTTYNames.compactMap { (panelId, candidateTTY) -> UUID? in
guard tab.panels[panelId] != nil,
normalizedReportedTTYName(candidateTTY) == ttyName else {
return nil
}
return panelId
}
guard matches.count == 1 else { return nil }
return matches[0]
}
nonisolated static func normalizedExportedScreenPath(_ raw: String?) -> String? {
guard let raw else { return nil }
let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines)
@ -11153,7 +11189,7 @@ class TerminalController {
report_tty <tty_name> [--tab=X] [--panel=Y] - Register TTY for batched port scanning
ports_kick [--tab=X] [--panel=Y] - Request batched port scan for panel
report_shell_state <prompt|running> [--tab=X] [--panel=Y] - Report whether the shell is idle at a prompt or running a command
report_tmux_state <inside|outside> [--tab=X] [--panel=Y] - Report whether the shell is currently inside tmux
report_tmux_state <inside|outside> [--tab=X] [--panel=Y] [--tty=Z] - Report whether the shell is currently inside tmux
report_pwd <path> [--tab=X] [--panel=Y] - Report current working directory
clear_ports [--tab=X] [--panel=Y] - Clear listening ports
sidebar_state [--tab=X] - Dump sidebar metadata
@ -15207,12 +15243,27 @@ class TerminalController {
private func reportTmuxState(_ args: String) -> String {
let parsed = parseOptions(args)
guard let rawState = parsed.positional.first, !rawState.isEmpty else {
return "ERROR: Missing tmux state — usage: report_tmux_state <inside|outside> [--tab=X] [--panel=Y]"
return "ERROR: Missing tmux state — usage: report_tmux_state <inside|outside> [--tab=X] [--panel=Y] [--tty=Z]"
}
guard let isInsideTmux = Self.parseReportedTmuxState(rawState) else {
return "ERROR: Invalid tmux state '\(rawState)' — expected inside or outside"
}
let panelArg = parsed.options["panel"] ?? parsed.options["surface"]
let fallbackPanelId: UUID?
if let panelArg {
if panelArg.isEmpty {
return "ERROR: Missing panel id — usage: report_tmux_state <inside|outside> [--tab=X] [--panel=Y] [--tty=Z]"
}
guard let parsedId = UUID(uuidString: panelArg) else {
return "ERROR: Invalid panel id '\(panelArg)'"
}
fallbackPanelId = parsedId
} else {
fallbackPanelId = nil
}
let reportedTTYName = Self.normalizedReportedTTYName(parsed.options["tty"])
if let scope = Self.explicitSocketScope(options: parsed.options) {
guard Self.socketFastPathState.shouldPublishTmuxState(
workspaceId: scope.workspaceId,
@ -15232,46 +15283,35 @@ class TerminalController {
return "OK"
}
guard let tabManager else { return "ERROR: TabManager not available" }
let tabResolution = resolveTabIdForSidebarMutation(reportArgs: args, options: parsed.options)
guard let targetTabId = tabResolution.tabId else {
return tabResolution.error ?? "ERROR: No tab selected"
}
var result = "OK"
DispatchQueue.main.sync {
guard let tab = resolveTabForReport(args) else {
result = parsed.options["tab"] != nil ? "ERROR: Tab not found" : "ERROR: No tab selected"
DispatchQueue.main.async { [weak self] in
guard let self,
let tab = self.tabForSidebarMutation(id: targetTabId) else {
return
}
let validSurfaceIds = Set(tab.panels.keys)
tab.pruneSurfaceMetadata(validSurfaceIds: validSurfaceIds)
let panelArg = parsed.options["panel"] ?? parsed.options["surface"]
let surfaceId: UUID
if let panelArg {
if panelArg.isEmpty {
result = "ERROR: Missing panel id — usage: report_tmux_state <inside|outside> [--tab=X] [--panel=Y]"
return
}
guard let parsedId = UUID(uuidString: panelArg) else {
result = "ERROR: Invalid panel id '\(panelArg)'"
return
}
surfaceId = parsedId
} else {
guard let focused = tab.focusedPanelId else {
result = "ERROR: Missing panel id (no focused surface)"
return
}
surfaceId = focused
}
guard validSurfaceIds.contains(surfaceId) else {
result = "ERROR: Panel not found '\(surfaceId.uuidString)'"
let surfaceId = fallbackPanelId
?? Self.resolvePanelIdByTTY(reportedTTYName, in: tab)
?? tab.focusedPanelId
guard let surfaceId, validSurfaceIds.contains(surfaceId) else { return }
guard Self.socketFastPathState.shouldPublishTmuxState(
workspaceId: tab.id,
panelId: surfaceId,
isInsideTmux: isInsideTmux
) else {
return
}
tabManager.updateSurfaceTmuxState(tabId: tab.id, surfaceId: surfaceId, isInsideTmux: isInsideTmux)
tab.updatePanelTmuxState(panelId: surfaceId, isInsideTmux: isInsideTmux)
}
return result
return "OK"
}
private func clearPorts(_ args: String) -> String {