Skip to content

Commit 8ebc933

Browse files
committed
fix(tmux-subagent): enable 2D grid layout with divider-aware calculations
- Account for tmux pane dividers (1 char) in all size calculations - Reduce MIN_PANE_WIDTH from 53 to 52 to fit 2 columns in standard terminals - Fix enforceMainPaneWidth to use (windowWidth - divider) / 2 - Add virtual mainPane handling for close-spawn eviction loop - Add comprehensive decision-engine tests (23 test cases)
1 parent a67a35a commit 8ebc933

File tree

8 files changed

+787
-194
lines changed

8 files changed

+787
-194
lines changed

src/features/tmux-subagent/action-executor.ts

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { TmuxConfig } from "../../config/schema"
2-
import type { PaneAction } from "./types"
3-
import { spawnTmuxPane, closeTmuxPane } from "../../shared/tmux"
2+
import type { PaneAction, WindowState } from "./types"
3+
import { spawnTmuxPane, closeTmuxPane, enforceMainPaneWidth } from "../../shared/tmux"
44
import { log } from "../../shared"
55

66
export interface ActionResult {
@@ -15,24 +15,42 @@ export interface ExecuteActionsResult {
1515
results: Array<{ action: PaneAction; result: ActionResult }>
1616
}
1717

18+
export interface ExecuteContext {
19+
config: TmuxConfig
20+
serverUrl: string
21+
windowState: WindowState
22+
}
23+
24+
async function enforceMainPane(windowState: WindowState): Promise<void> {
25+
if (!windowState.mainPane) return
26+
await enforceMainPaneWidth(windowState.mainPane.paneId, windowState.windowWidth)
27+
}
28+
1829
export async function executeAction(
1930
action: PaneAction,
20-
config: TmuxConfig,
21-
serverUrl: string
31+
ctx: ExecuteContext
2232
): Promise<ActionResult> {
2333
if (action.type === "close") {
2434
const success = await closeTmuxPane(action.paneId)
35+
if (success) {
36+
await enforceMainPane(ctx.windowState)
37+
}
2538
return { success }
2639
}
2740

2841
const result = await spawnTmuxPane(
2942
action.sessionId,
3043
action.description,
31-
config,
32-
serverUrl,
33-
action.targetPaneId
44+
ctx.config,
45+
ctx.serverUrl,
46+
action.targetPaneId,
47+
action.splitDirection
3448
)
3549

50+
if (result.success) {
51+
await enforceMainPane(ctx.windowState)
52+
}
53+
3654
return {
3755
success: result.success,
3856
paneId: result.paneId,
@@ -41,15 +59,14 @@ export async function executeAction(
4159

4260
export async function executeActions(
4361
actions: PaneAction[],
44-
config: TmuxConfig,
45-
serverUrl: string
62+
ctx: ExecuteContext
4663
): Promise<ExecuteActionsResult> {
4764
const results: Array<{ action: PaneAction; result: ActionResult }> = []
4865
let spawnedPaneId: string | undefined
4966

5067
for (const action of actions) {
5168
log("[action-executor] executing", { type: action.type })
52-
const result = await executeAction(action, config, serverUrl)
69+
const result = await executeAction(action, ctx)
5370
results.push({ action, result })
5471

5572
if (!result.success) {

0 commit comments

Comments
 (0)