138 lines
3.4 KiB
TypeScript
138 lines
3.4 KiB
TypeScript
import type { TmuxConfig } from "../../config/schema"
|
|
import type { PaneAction, WindowState } from "./types"
|
|
import {
|
|
applyLayout,
|
|
spawnTmuxPane,
|
|
closeTmuxPane,
|
|
enforceMainPaneWidth,
|
|
replaceTmuxPane,
|
|
} from "../../shared/tmux"
|
|
import { getTmuxPath } from "../../tools/interactive-bash/tmux-path-resolver"
|
|
import { queryWindowState } from "./pane-state-querier"
|
|
import { log } from "../../shared"
|
|
import type {
|
|
ActionResult,
|
|
ActionExecutorDeps,
|
|
} from "./action-executor-core"
|
|
|
|
export type { ActionExecutorDeps, ActionResult } from "./action-executor-core"
|
|
|
|
export interface ExecuteActionsResult {
|
|
success: boolean
|
|
spawnedPaneId?: string
|
|
results: Array<{ action: PaneAction; result: ActionResult }>
|
|
}
|
|
|
|
export interface ExecuteContext {
|
|
config: TmuxConfig
|
|
serverUrl: string
|
|
windowState: WindowState
|
|
sourcePaneId?: string
|
|
}
|
|
|
|
async function enforceMainPane(
|
|
windowState: WindowState,
|
|
config: TmuxConfig,
|
|
): Promise<void> {
|
|
if (!windowState.mainPane) return
|
|
await enforceMainPaneWidth(windowState.mainPane.paneId, windowState.windowWidth, {
|
|
mainPaneSize: config.main_pane_size,
|
|
mainPaneMinWidth: config.main_pane_min_width,
|
|
agentPaneMinWidth: config.agent_pane_min_width,
|
|
})
|
|
}
|
|
|
|
async function enforceLayoutAndMainPane(ctx: ExecuteContext): Promise<void> {
|
|
const sourcePaneId = ctx.sourcePaneId
|
|
if (!sourcePaneId) {
|
|
await enforceMainPane(ctx.windowState, ctx.config)
|
|
return
|
|
}
|
|
|
|
const latestState = await queryWindowState(sourcePaneId)
|
|
if (!latestState?.mainPane) {
|
|
await enforceMainPane(ctx.windowState, ctx.config)
|
|
return
|
|
}
|
|
|
|
const tmux = await getTmuxPath()
|
|
if (tmux) {
|
|
await applyLayout(tmux, ctx.config.layout, ctx.config.main_pane_size)
|
|
}
|
|
|
|
await enforceMainPane(latestState, ctx.config)
|
|
}
|
|
|
|
export async function executeAction(
|
|
action: PaneAction,
|
|
ctx: ExecuteContext
|
|
): Promise<ActionResult> {
|
|
if (action.type === "close") {
|
|
const success = await closeTmuxPane(action.paneId)
|
|
if (success) {
|
|
await enforceLayoutAndMainPane(ctx)
|
|
}
|
|
return { success }
|
|
}
|
|
|
|
if (action.type === "replace") {
|
|
const result = await replaceTmuxPane(
|
|
action.paneId,
|
|
action.newSessionId,
|
|
action.description,
|
|
ctx.config,
|
|
ctx.serverUrl
|
|
)
|
|
if (result.success) {
|
|
await enforceLayoutAndMainPane(ctx)
|
|
}
|
|
return {
|
|
success: result.success,
|
|
paneId: result.paneId,
|
|
}
|
|
}
|
|
|
|
const result = await spawnTmuxPane(
|
|
action.sessionId,
|
|
action.description,
|
|
ctx.config,
|
|
ctx.serverUrl,
|
|
action.targetPaneId,
|
|
action.splitDirection
|
|
)
|
|
|
|
if (result.success) {
|
|
await enforceLayoutAndMainPane(ctx)
|
|
}
|
|
|
|
return {
|
|
success: result.success,
|
|
paneId: result.paneId,
|
|
}
|
|
}
|
|
|
|
export async function executeActions(
|
|
actions: PaneAction[],
|
|
ctx: ExecuteContext
|
|
): Promise<ExecuteActionsResult> {
|
|
const results: Array<{ action: PaneAction; result: ActionResult }> = []
|
|
let spawnedPaneId: string | undefined
|
|
|
|
for (const action of actions) {
|
|
log("[action-executor] executing", { type: action.type })
|
|
const result = await executeAction(action, ctx)
|
|
results.push({ action, result })
|
|
|
|
if (!result.success) {
|
|
log("[action-executor] action failed", { type: action.type, error: result.error })
|
|
return { success: false, results }
|
|
}
|
|
|
|
if ((action.type === "spawn" || action.type === "replace") && result.paneId) {
|
|
spawnedPaneId = result.paneId
|
|
}
|
|
}
|
|
|
|
return { success: true, spawnedPaneId, results }
|
|
}
|