From 167431b786df857657b991f1c2faf1fded77d5e2 Mon Sep 17 00:00:00 2001 From: Lawrence Chen <54008264+lawrencecchen@users.noreply.github.com> Date: Fri, 20 Feb 2026 23:58:47 -0800 Subject: [PATCH] Avoid main-thread hops for explicit socket scope --- Sources/PortScanner.swift | 1 + Sources/TerminalController.swift | 33 +++++++++++++++++++ cmuxTests/CmuxWebViewKeyEquivalentTests.swift | 32 ++++++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/Sources/PortScanner.swift b/Sources/PortScanner.swift index fdaa7b39..9ed42027 100644 --- a/Sources/PortScanner.swift +++ b/Sources/PortScanner.swift @@ -49,6 +49,7 @@ final class PortScanner: @unchecked Sendable { func registerTTY(workspaceId: UUID, panelId: UUID, ttyName: String) { queue.async { [self] in let key = PanelKey(workspaceId: workspaceId, panelId: panelId) + guard ttyNames[key] != ttyName else { return } ttyNames[key] = ttyName } } diff --git a/Sources/TerminalController.swift b/Sources/TerminalController.swift index 4484656e..0d87e920 100644 --- a/Sources/TerminalController.swift +++ b/Sources/TerminalController.swift @@ -103,6 +103,20 @@ class TerminalController { return currentSorted != nextSorted } + nonisolated static func explicitSocketScope( + options: [String: String] + ) -> (workspaceId: UUID, panelId: UUID)? { + guard let tabRaw = options["tab"]?.trimmingCharacters(in: .whitespacesAndNewlines), + !tabRaw.isEmpty, + let panelRaw = (options["panel"] ?? options["surface"])?.trimmingCharacters(in: .whitespacesAndNewlines), + !panelRaw.isEmpty, + let workspaceId = UUID(uuidString: tabRaw), + let panelId = UUID(uuidString: panelRaw) else { + return nil + } + return (workspaceId, panelId) + } + /// Update which window's TabManager receives socket commands. /// This is used when the user switches between multiple terminal windows. func setActiveTabManager(_ tabManager: TabManager?) { @@ -10830,6 +10844,17 @@ class TerminalController { return "ERROR: Missing tty name — usage: report_tty [--tab=X] [--panel=Y]" } + // Shell integration always provides explicit UUID handles. + // Handle that common path off-main to avoid sync-hopping on every report. + if let scope = Self.explicitSocketScope(options: parsed.options) { + PortScanner.shared.registerTTY( + workspaceId: scope.workspaceId, + panelId: scope.panelId, + ttyName: ttyName + ) + return "OK" + } + var result = "OK" DispatchQueue.main.sync { guard let tab = resolveTabForReport(args) else { @@ -10872,6 +10897,14 @@ class TerminalController { private func portsKick(_ args: String) -> String { let parsed = parseOptions(args) + + // Shell integration always provides explicit UUID handles. + // Handle that common path off-main to keep prompt hooks from blocking UI work. + if let scope = Self.explicitSocketScope(options: parsed.options) { + PortScanner.shared.kick(workspaceId: scope.workspaceId, panelId: scope.panelId) + return "OK" + } + var result = "OK" DispatchQueue.main.sync { guard let tab = resolveTabForReport(args) else { diff --git a/cmuxTests/CmuxWebViewKeyEquivalentTests.swift b/cmuxTests/CmuxWebViewKeyEquivalentTests.swift index 977cfa5a..babd4d8d 100644 --- a/cmuxTests/CmuxWebViewKeyEquivalentTests.swift +++ b/cmuxTests/CmuxWebViewKeyEquivalentTests.swift @@ -3082,4 +3082,36 @@ final class TerminalControllerSidebarDedupeTests: XCTestCase { ) ) } + + func testExplicitSocketScopeParsesValidUUIDTabAndPanel() { + let workspaceId = UUID() + let panelId = UUID() + let scope = TerminalController.explicitSocketScope( + options: [ + "tab": workspaceId.uuidString, + "panel": panelId.uuidString + ] + ) + XCTAssertEqual(scope?.workspaceId, workspaceId) + XCTAssertEqual(scope?.panelId, panelId) + } + + func testExplicitSocketScopeAcceptsSurfaceAlias() { + let workspaceId = UUID() + let panelId = UUID() + let scope = TerminalController.explicitSocketScope( + options: [ + "tab": workspaceId.uuidString, + "surface": panelId.uuidString + ] + ) + XCTAssertEqual(scope?.workspaceId, workspaceId) + XCTAssertEqual(scope?.panelId, panelId) + } + + func testExplicitSocketScopeRejectsMissingOrInvalidValues() { + XCTAssertNil(TerminalController.explicitSocketScope(options: [:])) + XCTAssertNil(TerminalController.explicitSocketScope(options: ["tab": "workspace:1", "panel": UUID().uuidString])) + XCTAssertNil(TerminalController.explicitSocketScope(options: ["tab": UUID().uuidString, "panel": "surface:1"])) + } }