vde-layout
Version:
Terminal multiplexer layout management tool for VDE (Vibe Coding Development Environment)
1 lines • 323 kB
Source Map (JSON)
{"version":3,"file":"index.mjs","names":["yaml","parseCommand","toCommandString","parseCommand","toCommandString","SINGLE_QUOTE","SHELL_SINGLE_QUOTE_ESCAPE","findNewPaneId","resolveSplitOrientationFromStep","input","output","selectPreset","defaultSelectPreset","defaultCompilePreset","defaultCompilePresetFromValue","defaultCreateLayoutPlan","defaultEmitPlan"],"sources":["../src/utils/errors.ts","../src/models/schema.ts","../src/config/validator.ts","../src/config/loader.ts","../src/layout/preset.ts","../src/cli/package-version.ts","../src/core/errors.ts","../src/core/compile.ts","../src/core/planner.ts","../src/core/emitter.ts","../src/cli/error-handling.ts","../src/utils/logger.ts","../src/cli/runtime-and-list.ts","../src/backends/pane-tracking.ts","../src/executor/real-executor.ts","../src/executor/dry-run-executor.ts","../src/executor/mock-executor.ts","../src/backends/tmux/executor.ts","../src/utils/async.ts","../src/utils/pane-map.ts","../src/executor/split-step.ts","../src/utils/template-tokens.ts","../src/executor/terminal-command-preparation.ts","../src/executor/plan-runner-helpers.ts","../src/executor/sidebar-detection.ts","../src/executor/plan-runner.ts","../src/executor/step-target.ts","../src/executor/unsupported-step-kind.ts","../src/backends/tmux/backend.ts","../src/backends/wezterm/list-parser.ts","../src/backends/wezterm/cli.ts","../src/backends/wezterm/dry-run.ts","../src/backends/wezterm/layout-resolution.ts","../src/backends/wezterm/pane-map.ts","../src/backends/wezterm/step-execution.ts","../src/backends/wezterm/backend.ts","../src/executor/backend-factory.ts","../src/executor/backend-resolver.ts","../src/cli/after-apply-hook.ts","../src/cli/command-helpers.ts","../src/cli/user-prompt.ts","../src/cli/window-mode.ts","../src/cli/preset-execution.ts","../src/cli/select-args.ts","../src/cli/preset-selector.ts","../src/cli/index.ts","../src/index.ts"],"sourcesContent":["export type VDELayoutError = Error & {\n readonly code: string\n readonly details: Readonly<Record<string, unknown>>\n}\n\nexport const ErrorCodes = {\n CONFIG_NOT_FOUND: \"CONFIG_NOT_FOUND\",\n CONFIG_PARSE_ERROR: \"CONFIG_PARSE_ERROR\",\n CONFIG_PERMISSION_ERROR: \"CONFIG_PERMISSION_ERROR\",\n INVALID_PRESET: \"INVALID_PRESET\",\n PRESET_NOT_FOUND: \"PRESET_NOT_FOUND\",\n INVALID_LAYOUT: \"INVALID_LAYOUT\",\n INVALID_PANE: \"INVALID_PANE\",\n INVALID_PLAN: \"INVALID_PLAN\",\n MISSING_TARGET: \"MISSING_TARGET\",\n TMUX_NOT_RUNNING: \"TMUX_NOT_RUNNING\",\n TMUX_COMMAND_FAILED: \"TMUX_COMMAND_FAILED\",\n NOT_IN_TMUX_SESSION: \"NOT_IN_TMUX_SESSION\",\n TMUX_NOT_FOUND: \"TMUX_NOT_FOUND\",\n TMUX_NOT_INSTALLED: \"TMUX_NOT_INSTALLED\",\n UNSUPPORTED_TMUX_VERSION: \"UNSUPPORTED_TMUX_VERSION\",\n BACKEND_NOT_FOUND: \"BACKEND_NOT_FOUND\",\n TERMINAL_COMMAND_FAILED: \"TERMINAL_COMMAND_FAILED\",\n TEMPLATE_TOKEN_ERROR: \"TEMPLATE_TOKEN_ERROR\",\n WEZTERM_NOT_FOUND: \"WEZTERM_NOT_FOUND\",\n UNSUPPORTED_WEZTERM_VERSION: \"UNSUPPORTED_WEZTERM_VERSION\",\n USER_CANCELLED: \"USER_CANCELLED\",\n SPLIT_SIZE_RESOLUTION_FAILED: \"SPLIT_SIZE_RESOLUTION_FAILED\",\n} as const\n\nconst createBaseError = (\n name: string,\n message: string,\n code: string,\n details: Readonly<Record<string, unknown>> = {},\n): VDELayoutError => {\n const error = new Error(message) as VDELayoutError\n error.name = name\n ;(error as { code: string }).code = code\n ;(error as { details: Readonly<Record<string, unknown>> }).details = details\n return error\n}\n\nexport const createConfigError = (\n message: string,\n code: string,\n details: Readonly<Record<string, unknown>> = {},\n): VDELayoutError => {\n return createBaseError(\"ConfigError\", message, code, details)\n}\n\nexport const createValidationError = (\n message: string,\n code: string,\n details: Readonly<Record<string, unknown>> = {},\n): VDELayoutError => {\n return createBaseError(\"ValidationError\", message, code, details)\n}\n\nexport const createTmuxError = (\n message: string,\n code: string,\n details: Readonly<Record<string, unknown>> = {},\n): VDELayoutError => {\n return createBaseError(\"TmuxError\", message, code, details)\n}\n\nexport const createEnvironmentError = (\n message: string,\n code: string,\n details: Readonly<Record<string, unknown>> = {},\n): VDELayoutError => {\n return createBaseError(\"EnvironmentError\", message, code, details)\n}\n\nexport const isVDELayoutError = (error: unknown): error is VDELayoutError => {\n if (typeof error !== \"object\" || error === null) {\n return false\n }\n\n if (!(\"code\" in error)) {\n return false\n }\n\n const { code } = error as { code?: unknown }\n if (typeof code !== \"string\") {\n return false\n }\n\n if (!(\"details\" in error)) {\n return false\n }\n\n return true\n}\n\nconst formatters: Record<string, (error: VDELayoutError) => string> = {\n [ErrorCodes.CONFIG_NOT_FOUND]: (error) => {\n const searchPaths = error.details.searchPaths\n if (!Array.isArray(searchPaths)) {\n return \"\"\n }\n\n const lines = [\"\", \"Searched in the following locations:\"]\n searchPaths.forEach((location) => lines.push(` - ${location}`))\n lines.push(\"\", \"To create a configuration file, run:\")\n lines.push(\" mkdir -p ~/.config/vde\")\n lines.push(' echo \"presets: {}\" > ~/.config/vde/layout.yml')\n return lines.join(\"\\n\")\n },\n [ErrorCodes.NOT_IN_TMUX_SESSION]: () => {\n return \"\\nThis command must be run inside a tmux session.\\nStart tmux first with: tmux\\n\"\n },\n [ErrorCodes.TMUX_NOT_INSTALLED]: () => {\n return (\n \"\\ntmux is required but not installed.\\n\" +\n \"Install tmux using your package manager:\\n\" +\n \" - macOS: brew install tmux\\n\" +\n \" - Ubuntu/Debian: sudo apt-get install tmux\\n\" +\n \" - Fedora: sudo dnf install tmux\\n\"\n )\n },\n [ErrorCodes.UNSUPPORTED_TMUX_VERSION]: (error) => {\n const requiredVersion = error.details.requiredVersion\n if (typeof requiredVersion !== \"string\") {\n return \"\"\n }\n return `\\nRequired tmux version: ${requiredVersion} or higher\\n`\n },\n [ErrorCodes.BACKEND_NOT_FOUND]: (error) => {\n const backend = typeof error.details.backend === \"string\" ? error.details.backend : \"terminal backend\"\n const binary = typeof error.details.binary === \"string\" ? error.details.binary : backend\n const suggestion =\n backend === \"wezterm\"\n ? [\n \"\",\n `${backend} is required but not installed.`,\n \"Install wezterm using your package manager:\",\n \" - macOS: brew install --cask wezterm\",\n \" - Ubuntu/Debian: sudo apt-get install wezterm\",\n \" - Fedora: sudo dnf install wezterm\",\n ].join(\"\\n\")\n : \"\"\n return `\\nMissing binary: ${binary}${suggestion}`\n },\n [ErrorCodes.WEZTERM_NOT_FOUND]: () => {\n return (\n \"\\nwezterm command was not found.\\n\" +\n \"Install wezterm using your package manager:\\n\" +\n \" - macOS: brew install --cask wezterm\\n\" +\n \" - Ubuntu/Debian: sudo apt-get install wezterm\\n\" +\n \" - Fedora: sudo dnf install wezterm\\n\"\n )\n },\n [ErrorCodes.UNSUPPORTED_WEZTERM_VERSION]: (error) => {\n const requiredVersion = typeof error.details.requiredVersion === \"string\" ? error.details.requiredVersion : \"\"\n const detected = typeof error.details.detectedVersion === \"string\" ? error.details.detectedVersion : \"\"\n const lines = [\"\", \"Unsupported wezterm version detected.\"]\n if (detected) {\n lines.push(`Detected version: ${detected}`)\n }\n if (requiredVersion) {\n lines.push(`Required version: ${requiredVersion} or higher`)\n }\n return lines.join(\"\\n\")\n },\n [ErrorCodes.SPLIT_SIZE_RESOLUTION_FAILED]: (error) => {\n const paneId = typeof error.details.paneId === \"string\" ? error.details.paneId : \"\"\n const paneCells = typeof error.details.paneCells === \"number\" ? String(error.details.paneCells) : \"\"\n const detected = typeof error.details.detectedVersion === \"string\" ? error.details.detectedVersion : \"\"\n const required = typeof error.details.requiredVersion === \"string\" ? error.details.requiredVersion : \"\"\n const lines = [\"\", \"Unable to resolve split size from pane dimensions.\"]\n if (paneId) {\n lines.push(`Pane ID: ${paneId}`)\n }\n if (paneCells) {\n lines.push(`Pane cells: ${paneCells}`)\n }\n if (detected) {\n lines.push(`Detected version: ${detected}`)\n }\n if (required) {\n lines.push(`Required version: ${required}`)\n }\n return lines.join(\"\\n\")\n },\n}\n\nexport const formatError = (error: Error): string => {\n if (!isVDELayoutError(error)) {\n return `${error.name}: ${error.message}`\n }\n\n let message = `Error: ${error.message}`\n\n const formatter = formatters[error.code]\n if (formatter) {\n message += `\\n${formatter(error)}`\n }\n\n const commandDetail = error.details.command\n if (commandDetail !== undefined) {\n message += `\\nCommand: ${JSON.stringify(commandDetail)}`\n }\n\n const stderrDetail = error.details.stderr\n if (stderrDetail !== undefined) {\n message += `\\nstderr: ${String(stderrDetail)}`\n }\n\n const presetDetail = error.details.preset\n if (presetDetail !== undefined) {\n message += `\\npreset: ${String(presetDetail)}`\n }\n\n const nestedErrors = error.details.errors\n if (Array.isArray(nestedErrors) && nestedErrors.length > 0) {\n message += \"\\nValidation errors:\\n\"\n nestedErrors.forEach((item) => {\n message += ` - ${String(item)}\\n`\n })\n }\n\n return message\n}\n","import { z } from \"zod\"\n\nexport const WindowModeSchema = z.enum([\"new-window\", \"current-window\"])\nconst TerminalBackendSchema = z.enum([\"tmux\", \"wezterm\"])\nexport const SELECT_UI_MODES = [\"auto\", \"fzf\"] as const\nexport const SELECT_SURFACE_MODES = [\"auto\", \"inline\", \"tmux-popup\"] as const\nexport const SelectUiModeSchema = z.enum(SELECT_UI_MODES)\nexport const SelectSurfaceModeSchema = z.enum(SELECT_SURFACE_MODES)\n\nconst SelectorFzfSchema = z\n .object({\n extraArgs: z.array(z.string().min(1)).optional(),\n })\n .strict()\n\nconst HooksSchema = z\n .object({\n afterApply: z.string().min(1).optional(),\n })\n .strict()\n\nconst SelectorDefaultsSchema = z\n .object({\n ui: SelectUiModeSchema.optional(),\n surface: SelectSurfaceModeSchema.optional(),\n tmuxPopupOpts: z.string().min(1).optional(),\n fzf: SelectorFzfSchema.optional(),\n })\n .strict()\n\nconst RatioValueSchema = z.union([\n z.number().positive(),\n z.string().regex(/^[1-9][0-9]*c$/, {\n message: 'ratio value must be a positive number or \"<positive-integer>c\"',\n }),\n])\n\nconst hasNumericWeight = (ratio: ReadonlyArray<number | string>): boolean => {\n return ratio.some((value) => typeof value === \"number\")\n}\n\nexport const LayoutIssueParamCodes = {\n RATIO_LENGTH_MISMATCH: \"RATIO_LENGTH_MISMATCH\",\n RATIO_WEIGHT_MISSING: \"RATIO_WEIGHT_MISSING\",\n} as const\n\n// Terminal pane schema\nconst TerminalPaneSchema = z\n .object({\n name: z.string().min(1),\n command: z.string().optional(),\n cwd: z.string().optional(),\n env: z.record(z.string()).optional(),\n delay: z.number().int().positive().optional(),\n title: z.string().optional(),\n focus: z.boolean().optional(),\n ephemeral: z.boolean().optional(),\n closeOnError: z.boolean().optional(),\n })\n .strict()\n\n// Split container schema (recursive)\nconst SplitPaneSchema: z.ZodType<unknown> = z.lazy(() =>\n z\n .object({\n type: z.enum([\"horizontal\", \"vertical\"]),\n ratio: z.array(RatioValueSchema).min(1),\n panes: z.array(PaneSchema).min(1),\n })\n .strict()\n .refine((data) => data.ratio.length === data.panes.length, {\n message: \"Number of elements in ratio array does not match number of elements in panes array\",\n params: { code: LayoutIssueParamCodes.RATIO_LENGTH_MISMATCH },\n })\n .refine((data) => hasNumericWeight(data.ratio), {\n message: \"ratio must include at least one numeric weight\",\n params: { code: LayoutIssueParamCodes.RATIO_WEIGHT_MISSING },\n }),\n)\n\n// Recursive Pane schema definition\nexport const PaneSchema: z.ZodType<unknown> = z.lazy(() => z.union([SplitPaneSchema, TerminalPaneSchema]))\n\n// Layout schema definition\nexport const LayoutSchema = z\n .object({\n type: z.enum([\"horizontal\", \"vertical\"]),\n ratio: z.array(RatioValueSchema).min(1),\n panes: z.array(PaneSchema).min(1),\n })\n .refine((data) => data.ratio.length === data.panes.length, {\n message: \"Number of elements in ratio array does not match number of elements in panes array\",\n params: { code: LayoutIssueParamCodes.RATIO_LENGTH_MISMATCH },\n })\n .refine((data) => hasNumericWeight(data.ratio), {\n message: \"ratio must include at least one numeric weight\",\n params: { code: LayoutIssueParamCodes.RATIO_WEIGHT_MISSING },\n })\n\n// Preset schema definition\nexport const PresetSchema = z.object({\n name: z.string().min(1),\n description: z.string().optional(),\n layout: LayoutSchema.optional(),\n command: z.string().optional(),\n windowMode: WindowModeSchema.optional(),\n backend: TerminalBackendSchema.optional(),\n hooks: HooksSchema.optional(),\n})\n\n// Config schema definition\nexport const ConfigSchema = z.object({\n defaults: z\n .object({\n windowMode: WindowModeSchema.optional(),\n selector: SelectorDefaultsSchema.optional(),\n })\n .optional(),\n presets: z.record(PresetSchema),\n})\n\n// Validation result type\ntype ValidationResult<T> = {\n success: boolean\n data?: T\n error?: string\n}\n\n// Helper function to format Zod errors consistently\nconst formatValidationError = (error: z.ZodError): string => {\n const messages = error.errors.map((e) => {\n const path = e.path.join(\".\")\n const message = e.message\n\n // Customize error message for panes array element count check\n if (path === \"layout.panes\" && message.includes(\"at least 2 element\")) {\n return `${path}: panes array must have at least 2 elements`\n }\n\n return `${path}: ${message}`\n })\n\n return messages.join(\"\\n\")\n}\n\n// Config validation\nexport const validateConfig = (data: unknown): ValidationResult<z.infer<typeof ConfigSchema>> => {\n try {\n const parsed = ConfigSchema.parse(data)\n return { success: true, data: parsed }\n } catch (error) {\n if (error instanceof z.ZodError) {\n return { success: false, error: formatValidationError(error) }\n }\n return { success: false, error: String(error) }\n }\n}\n\n// Preset validation\nexport const validatePreset = (data: unknown): ValidationResult<z.infer<typeof PresetSchema>> => {\n try {\n const parsed = PresetSchema.parse(data)\n return { success: true, data: parsed }\n } catch (error) {\n if (error instanceof z.ZodError) {\n return { success: false, error: formatValidationError(error) }\n }\n return { success: false, error: String(error) }\n }\n}\n\n// Pane validation\nexport const validatePane = (data: unknown): ValidationResult<z.infer<typeof PaneSchema>> => {\n try {\n const parsed = PaneSchema.parse(data)\n return { success: true, data: parsed }\n } catch (error) {\n if (error instanceof z.ZodError) {\n return { success: false, error: formatValidationError(error) }\n }\n return { success: false, error: String(error) }\n }\n}\n","import * as YAML from \"yaml\"\nimport { z } from \"zod\"\nimport { ConfigSchema } from \"../models/schema\"\nimport type { Config } from \"../models/types\"\nimport { createValidationError, ErrorCodes, isVDELayoutError } from \"../utils/errors\"\n\n/**\n * Parse YAML text into an object\n * @param yamlText - YAML text to parse\n * @returns Parsed object\n * @throws {ValidationError} When YAML parsing fails\n */\nconst parseYAML = (yamlText: string): unknown => {\n // Input validation\n if (!yamlText || typeof yamlText !== \"string\") {\n throw createValidationError(\"YAML text not provided\", ErrorCodes.CONFIG_PARSE_ERROR, {\n received: typeof yamlText,\n })\n }\n\n try {\n return YAML.parse(yamlText)\n } catch (error) {\n throw createValidationError(\"Failed to parse YAML\", ErrorCodes.CONFIG_PARSE_ERROR, {\n parseError: error instanceof Error ? error.message : String(error),\n yamlSnippet: yamlText.substring(0, 200),\n })\n }\n}\n\n/**\n * Validate basic configuration structure\n * @param parsed - Parsed YAML object\n * @throws {ValidationError} When structure is invalid\n */\nconst validateConfigStructure = (parsed: unknown): void => {\n // Check for empty YAML\n if (parsed === null || parsed === undefined || typeof parsed !== \"object\") {\n throw createValidationError(\"YAML is empty or invalid format\", ErrorCodes.CONFIG_PARSE_ERROR, {\n parsed: parsed,\n })\n }\n\n // Check for presets field existence\n const parsedObj = parsed as Record<string, unknown>\n if (!(\"presets\" in parsedObj) || parsedObj.presets === undefined || parsedObj.presets === null) {\n throw createValidationError(\"presets field is required\", ErrorCodes.INVALID_PRESET, {\n availableFields: Object.keys(parsedObj),\n })\n }\n\n // Check for empty presets\n const presetsObj = parsedObj.presets\n if (typeof presetsObj !== \"object\" || presetsObj === null || Object.keys(presetsObj).length === 0) {\n throw createValidationError(\"At least one preset is required\", ErrorCodes.INVALID_PRESET, {\n presets: presetsObj,\n })\n }\n}\n\n/**\n * Format Zod validation errors into user-friendly messages\n * @param error - Zod validation error\n * @returns Formatted error issues\n */\nconst formatZodErrors = (error: z.ZodError): Array<{ path: string; message: string; code: string }> => {\n return error.issues.map((issue) => {\n const path = issue.path.join(\".\")\n let message = issue.message\n\n // Custom error messages\n if (issue.code === \"invalid_type\") {\n if (issue.path.includes(\"command\") && issue.expected === \"string\") {\n message = \"command field must be a string\"\n } else if (issue.path.includes(\"workingDirectory\") && issue.expected === \"string\") {\n message = \"workingDirectory field must be a string\"\n } else if (issue.received === \"number\" && issue.expected === \"string\") {\n message = `${path} must be a string`\n } else if (issue.received === \"array\" && issue.expected === \"string\") {\n message = `${path} must be a string`\n }\n } else if (issue.code === \"invalid_union\") {\n // Detailed error messages for union types\n const unionIssue = issue as z.ZodIssue & { unionErrors?: z.ZodError[] }\n if (unionIssue.unionErrors !== undefined) {\n // When command is missing in terminal pane\n const terminalError = unionIssue.unionErrors.find(\n (e) => e.issues?.some((i) => i.path.includes(\"command\") && i.code === \"invalid_type\") === true,\n )\n if (terminalError !== undefined) {\n message = \"command field is required\"\n } else {\n // When panes is missing in split pane\n const splitError = unionIssue.unionErrors.find(\n (e) => e.issues?.some((i) => i.path.includes(\"panes\") && i.code === \"invalid_type\") === true,\n )\n if (splitError !== undefined) {\n message = \"panes field is required\"\n } else {\n message = 'Pane type must be \"terminal\" or \"split\"'\n }\n }\n } else {\n message = 'Pane type must be \"terminal\" or \"split\"'\n }\n } else if (issue.code === \"invalid_literal\") {\n if (issue.path.includes(\"direction\")) {\n message = 'direction must be \"horizontal\" or \"vertical\"'\n }\n } else if (issue.message.includes(\"required\")) {\n // Use the message as is\n message = issue.message\n } else if (issue.code === \"custom\" && issue.message.includes(\"ratio array\")) {\n message = issue.message\n } else if (issue.code === \"too_small\" && issue.message.includes(\"Array must contain at least\")) {\n // Minimum array elements error\n if (path.includes(\"panes\")) {\n message = \"panes array must contain at least 2 elements\"\n } else if (path.includes(\"ratio\")) {\n message = \"ratio array must contain at least 2 elements\"\n } else {\n message = issue.message\n }\n }\n\n return {\n path,\n message,\n code: issue.code,\n }\n })\n}\n\n/**\n * Validates YAML text and converts it to a type-safe Config object\n * @param yamlText - YAML text to validate\n * @returns Validated Config object\n * @throws {ValidationError} When YAML is invalid\n */\nexport const validateYAML = (yamlText: string): Config => {\n // Parse YAML\n const parsed = parseYAML(yamlText)\n\n // Validate basic structure\n validateConfigStructure(parsed)\n\n // Ratio sum validation removed - unnecessary due to automatic normalization\n\n // Validation with Zod schema\n try {\n const validated = ConfigSchema.parse(parsed)\n return validated\n } catch (error) {\n if (error instanceof z.ZodError) {\n const issues = formatZodErrors(error)\n\n // Use the first error message as the primary message\n const primaryMessage = issues.length > 0 && issues[0] ? issues[0].message : \"Configuration validation failed\"\n\n throw createValidationError(primaryMessage, ErrorCodes.CONFIG_PARSE_ERROR, {\n issues,\n rawErrors: error.issues,\n })\n }\n\n if (isVDELayoutError(error) && error.name === \"ValidationError\") {\n throw error\n }\n\n // Other errors\n throw createValidationError(\"Unexpected validation error occurred\", ErrorCodes.CONFIG_PARSE_ERROR, {\n error: error instanceof Error ? error.message : String(error),\n })\n }\n}\n","import fs from \"fs-extra\"\nimport path from \"path\"\nimport os from \"os\"\nimport * as yaml from \"yaml\"\nimport type { Config } from \"../models/types\"\nimport { createConfigError, ErrorCodes } from \"../utils/errors\"\nimport { validateYAML } from \"./validator\"\n\nexport type ConfigLoaderOptions = {\n readonly configPaths?: string[]\n readonly onWarning?: (message: string) => void\n}\n\nexport type ConfigLoader = {\n readonly loadYAML: () => Promise<string>\n readonly loadConfig: () => Promise<Config>\n readonly findConfigFile: () => Promise<string | null>\n readonly getSearchPaths: () => string[]\n}\n\ntype SearchPathGroup = readonly string[]\ntype SelectorDefaults = NonNullable<NonNullable<Config[\"defaults\"]>[\"selector\"]>\n\nexport const createConfigLoader = (options: ConfigLoaderOptions = {}): ConfigLoader => {\n const explicitConfigPaths = options.configPaths\n const emitWarning: (message: string) => void = options.onWarning ?? ((message: string): void => console.warn(message))\n\n const computeCachedSearchPaths = (): string[] => {\n if (explicitConfigPaths && explicitConfigPaths.length > 0) {\n return [...explicitConfigPaths]\n }\n\n const candidates: string[] = []\n const projectCandidate = findProjectConfigCandidate()\n if (projectCandidate !== null) {\n candidates.push(projectCandidate)\n }\n\n const defaultSearchPathGroups = buildDefaultSearchPathGroups()\n candidates.push(...flattenSearchPathGroups(defaultSearchPathGroups))\n\n return [...new Set(candidates)]\n }\n\n const loadConfig = async (): Promise<Config> => {\n if (explicitConfigPaths && explicitConfigPaths.length > 0) {\n const filePath = await findFirstExisting(explicitConfigPaths)\n if (filePath === null) {\n throw createConfigError(\"Configuration file not found\", ErrorCodes.CONFIG_NOT_FOUND, {\n searchPaths: explicitConfigPaths,\n })\n }\n\n const content = await safeReadFile(filePath)\n return validateYAML(content)\n }\n\n const searchPaths = computeCachedSearchPaths()\n const defaultSearchPathGroups = buildDefaultSearchPathGroups()\n const globalPaths = await resolveFirstExistingPaths(defaultSearchPathGroups)\n const projectPath = findProjectConfigCandidate()\n const projectConfigExists = projectPath !== null ? await fs.pathExists(projectPath) : false\n\n if (globalPaths.length === 0 && !projectConfigExists) {\n throw createConfigError(\"Configuration file not found\", ErrorCodes.CONFIG_NOT_FOUND, {\n searchPaths,\n })\n }\n\n let mergedConfig: Config = { presets: {} }\n\n for (const globalPath of globalPaths) {\n const content = await safeReadFile(globalPath)\n const config = validateYAML(content)\n mergedConfig = mergeConfigs(mergedConfig, config, emitWarning)\n }\n\n if (projectPath !== null && projectConfigExists) {\n const content = await safeReadFile(projectPath)\n const config = validateYAML(content)\n mergedConfig = mergeConfigs(mergedConfig, config, emitWarning)\n }\n\n return mergedConfig\n }\n\n return {\n loadYAML: async (): Promise<string> => {\n const config = await loadConfig()\n return yaml.stringify(config)\n },\n loadConfig,\n findConfigFile: async (): Promise<string | null> => {\n const searchPaths =\n explicitConfigPaths && explicitConfigPaths.length > 0 ? [...explicitConfigPaths] : computeCachedSearchPaths()\n\n for (const searchPath of searchPaths) {\n if (await fs.pathExists(searchPath)) {\n return searchPath\n }\n }\n return null\n },\n getSearchPaths: (): string[] => computeCachedSearchPaths(),\n }\n}\n\nconst buildDefaultSearchPathGroups = (): ReadonlyArray<SearchPathGroup> => {\n const pathGroups: string[][] = []\n\n const vdeConfigPath = process.env.VDE_CONFIG_PATH\n if (vdeConfigPath !== undefined) {\n pathGroups.push([path.join(vdeConfigPath, \"layout.yml\")])\n }\n\n const homeDir = process.env.HOME ?? os.homedir()\n const xdgConfigHome = process.env.XDG_CONFIG_HOME ?? path.join(homeDir, \".config\")\n pathGroups.push([\n path.join(xdgConfigHome, \"vde\", \"layout\", \"config.yml\"),\n path.join(xdgConfigHome, \"vde\", \"layout.yml\"),\n ])\n\n return pathGroups.map((group): SearchPathGroup => [...new Set(group)])\n}\n\nconst flattenSearchPathGroups = (pathGroups: ReadonlyArray<SearchPathGroup>): string[] => {\n const paths: string[] = []\n for (const group of pathGroups) {\n paths.push(...group)\n }\n return [...new Set(paths)]\n}\n\nconst resolveFirstExistingPaths = async (pathGroups: ReadonlyArray<SearchPathGroup>): Promise<string[]> => {\n const existingPaths = await Promise.all(pathGroups.map(async (group) => findFirstExisting(group)))\n const seenPaths = new Set<string>()\n const resolvedPaths: string[] = []\n\n for (const existingPath of existingPaths) {\n if (existingPath !== null && !seenPaths.has(existingPath)) {\n seenPaths.add(existingPath)\n resolvedPaths.push(existingPath)\n }\n }\n\n return resolvedPaths\n}\n\nconst findProjectConfigCandidate = (): string | null => {\n let currentDir = process.cwd()\n const { root } = path.parse(currentDir)\n\n while (true) {\n const candidates = [\n path.join(currentDir, \".vde\", \"layout\", \"config.yml\"),\n path.join(currentDir, \".vde\", \"layout.yml\"),\n ]\n\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) {\n return candidate\n }\n }\n\n if (currentDir === root) {\n break\n }\n\n const parent = path.dirname(currentDir)\n if (parent === currentDir) {\n break\n }\n\n currentDir = parent\n }\n\n return null\n}\n\nconst findFirstExisting = async (paths: ReadonlyArray<string>): Promise<string | null> => {\n for (const candidate of paths) {\n if (await fs.pathExists(candidate)) {\n return candidate\n }\n }\n return null\n}\n\nconst safeReadFile = async (filePath: string): Promise<string> => {\n try {\n return await fs.readFile(filePath, \"utf8\")\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error)\n throw createConfigError(`Failed to read configuration file`, ErrorCodes.CONFIG_PERMISSION_ERROR, {\n filePath,\n error: errorMessage,\n })\n }\n}\n\nconst mergeConfigs = (base: Config, override: Config, emitWarning: (message: string) => void): Config => {\n const mergedPresets: Config[\"presets\"] = { ...base.presets }\n\n for (const [presetKey, overridePreset] of Object.entries(override.presets)) {\n const basePreset = base.presets[presetKey]\n if (\n basePreset !== undefined &&\n basePreset.windowMode !== undefined &&\n overridePreset.windowMode !== undefined &&\n basePreset.windowMode !== overridePreset.windowMode\n ) {\n emitWarning(\n `[vde-layout] Preset \"${presetKey}\" windowMode conflict: \"${basePreset.windowMode}\" overridden by \"${overridePreset.windowMode}\"`,\n )\n }\n mergedPresets[presetKey] = overridePreset\n }\n\n const baseDefaults = base.defaults\n const overrideDefaults = override.defaults\n\n if (\n baseDefaults?.windowMode !== undefined &&\n overrideDefaults?.windowMode !== undefined &&\n baseDefaults.windowMode !== overrideDefaults.windowMode\n ) {\n emitWarning(\n `[vde-layout] defaults.windowMode conflict: \"${baseDefaults.windowMode}\" overridden by \"${overrideDefaults.windowMode}\"`,\n )\n }\n\n const mergedSelectorDefaults = mergeSelectorDefaults({\n baseSelector: baseDefaults?.selector,\n overrideSelector: overrideDefaults?.selector,\n emitWarning,\n })\n\n const mergedDefaults =\n baseDefaults !== undefined || overrideDefaults !== undefined\n ? {\n ...(baseDefaults ?? {}),\n ...(overrideDefaults ?? {}),\n ...(mergedSelectorDefaults !== undefined ? { selector: mergedSelectorDefaults } : {}),\n }\n : undefined\n\n return mergedDefaults === undefined\n ? {\n presets: mergedPresets,\n }\n : {\n defaults: mergedDefaults,\n presets: mergedPresets,\n }\n}\n\nconst mergeSelectorDefaults = ({\n baseSelector,\n overrideSelector,\n emitWarning,\n}: {\n readonly baseSelector: SelectorDefaults | undefined\n readonly overrideSelector: SelectorDefaults | undefined\n readonly emitWarning: (message: string) => void\n}): SelectorDefaults | undefined => {\n if (baseSelector === undefined && overrideSelector === undefined) {\n return undefined\n }\n\n if (baseSelector?.ui !== undefined && overrideSelector?.ui !== undefined && baseSelector.ui !== overrideSelector.ui) {\n emitWarning(\n `[vde-layout] defaults.selector.ui conflict: \"${baseSelector.ui}\" overridden by \"${overrideSelector.ui}\"`,\n )\n }\n\n if (\n baseSelector?.surface !== undefined &&\n overrideSelector?.surface !== undefined &&\n baseSelector.surface !== overrideSelector.surface\n ) {\n emitWarning(\n `[vde-layout] defaults.selector.surface conflict: \"${baseSelector.surface}\" overridden by \"${overrideSelector.surface}\"`,\n )\n }\n\n if (\n baseSelector?.tmuxPopupOpts !== undefined &&\n overrideSelector?.tmuxPopupOpts !== undefined &&\n baseSelector.tmuxPopupOpts !== overrideSelector.tmuxPopupOpts\n ) {\n emitWarning(\n `[vde-layout] defaults.selector.tmuxPopupOpts conflict: \"${baseSelector.tmuxPopupOpts}\" overridden by \"${overrideSelector.tmuxPopupOpts}\"`,\n )\n }\n\n const baseExtraArgs = baseSelector?.fzf?.extraArgs\n const overrideExtraArgs = overrideSelector?.fzf?.extraArgs\n if (\n Array.isArray(baseExtraArgs) &&\n Array.isArray(overrideExtraArgs) &&\n JSON.stringify(baseExtraArgs) !== JSON.stringify(overrideExtraArgs)\n ) {\n emitWarning(`[vde-layout] defaults.selector.fzf.extraArgs conflict: global value overridden by project value`)\n }\n\n const mergedFzf =\n baseSelector?.fzf !== undefined || overrideSelector?.fzf !== undefined\n ? {\n ...(baseSelector?.fzf ?? {}),\n ...(overrideSelector?.fzf ?? {}),\n }\n : undefined\n\n return {\n ...(baseSelector ?? {}),\n ...(overrideSelector ?? {}),\n ...(mergedFzf !== undefined ? { fzf: mergedFzf } : {}),\n }\n}\n","import { createConfigLoader, type ConfigLoaderOptions } from \"../config/loader\"\nimport { createConfigError, ErrorCodes } from \"../utils/errors\"\nimport type { Config, Preset, PresetInfo } from \"../models/types\"\nimport type { PresetManager } from \"../contracts\"\n\ntype PresetState = {\n setConfigPath: (filePath: string) => void\n loadConfig: () => Promise<void>\n getPreset: (name: string) => Preset\n listPresets: () => PresetInfo[]\n getDefaultPreset: () => Preset\n getDefaults: () => Config[\"defaults\"] | undefined\n}\n\nconst createState = (options: ConfigLoaderOptions = {}): PresetState => {\n let loaderOptions: ConfigLoaderOptions = options\n let cachedConfig: Config | null = null\n\n const setConfigPath = (filePath: string): void => {\n loaderOptions = { configPaths: [filePath] }\n cachedConfig = null\n }\n\n const loadConfig = async (): Promise<void> => {\n const loader = createConfigLoader(loaderOptions)\n cachedConfig = await loader.loadConfig()\n }\n\n const ensureConfig = (): Config => {\n if (cachedConfig === null) {\n throw createConfigError(\"Configuration not loaded\", ErrorCodes.CONFIG_NOT_FOUND)\n }\n return cachedConfig\n }\n\n const getPreset = (name: string): Preset => {\n const config = ensureConfig()\n const preset = config.presets[name]\n if (preset === undefined) {\n throw createConfigError(`Preset \"${name}\" not found`, ErrorCodes.PRESET_NOT_FOUND, {\n availablePresets: Object.keys(config.presets),\n })\n }\n return preset\n }\n\n const listPresets = (): PresetInfo[] => {\n if (cachedConfig === null) {\n return []\n }\n\n return Object.entries(cachedConfig.presets).map(([key, preset]) => ({\n key,\n name: preset.name,\n description: preset.description,\n }))\n }\n\n const getDefaultPreset = (): Preset => {\n const config = ensureConfig()\n\n if (config.presets.default !== undefined) {\n return config.presets.default\n }\n\n const firstKey = Object.keys(config.presets)[0]\n if (typeof firstKey !== \"string\" || firstKey.length === 0) {\n throw createConfigError(\"No presets defined\", ErrorCodes.PRESET_NOT_FOUND)\n }\n\n return config.presets[firstKey]!\n }\n\n const getDefaults = (): Config[\"defaults\"] | undefined => {\n const config = ensureConfig()\n return config.defaults\n }\n\n return {\n setConfigPath,\n loadConfig,\n getPreset,\n listPresets,\n getDefaultPreset,\n getDefaults,\n }\n}\n\nexport const createPresetManager = (options: ConfigLoaderOptions = {}): PresetManager => {\n const state = createState(options)\n return {\n setConfigPath: state.setConfigPath,\n loadConfig: state.loadConfig,\n getPreset: state.getPreset,\n listPresets: state.listPresets,\n getDefaultPreset: state.getDefaultPreset,\n getDefaults: state.getDefaults,\n }\n}\n","type PackageJsonModule = {\n readonly version: string\n}\n\ntype ModuleLoadError = Error & {\n readonly code?: string\n}\n\nconst CANDIDATE_PATHS = [\"../package.json\", \"../../package.json\"] as const\n\nconst isModuleNotFoundError = (error: unknown): error is ModuleLoadError => {\n return error instanceof Error && (error as ModuleLoadError).code === \"MODULE_NOT_FOUND\"\n}\n\nexport const loadPackageVersion = (requireFn: NodeJS.Require): string => {\n let lastNotFound: ModuleLoadError | undefined\n\n for (const path of CANDIDATE_PATHS) {\n try {\n return (requireFn(path) as PackageJsonModule).version\n } catch (error) {\n if (isModuleNotFoundError(error)) {\n lastNotFound = error\n continue\n }\n\n throw error\n }\n }\n\n throw lastNotFound ?? new Error(`Unable to resolve package version from candidates: ${CANDIDATE_PATHS.join(\", \")}`)\n}\n","type CoreErrorKind = \"compile\" | \"plan\" | \"emit\" | \"execution\"\n\nexport type CoreError = {\n readonly kind: CoreErrorKind\n readonly code: string\n readonly message: string\n readonly source?: string\n readonly path?: string\n readonly details?: Readonly<Record<string, unknown>>\n}\n\nexport const createCoreError = (\n kind: CoreErrorKind,\n error: {\n readonly code: string\n readonly message: string\n readonly source?: string\n readonly path?: string\n readonly details?: Readonly<Record<string, unknown>>\n },\n): CoreError => ({\n kind,\n code: error.code,\n message: error.message,\n source: error.source,\n path: error.path,\n details: error.details,\n})\n\nexport const isCoreError = (value: unknown): value is CoreError => {\n if (typeof value !== \"object\" || value === null) {\n return false\n }\n const candidate = value as Partial<CoreError>\n return (\n (candidate.kind === \"compile\" ||\n candidate.kind === \"plan\" ||\n candidate.kind === \"emit\" ||\n candidate.kind === \"execution\") &&\n typeof candidate.code === \"string\" &&\n typeof candidate.message === \"string\"\n )\n}\n","import { parse } from \"yaml\"\nimport { z } from \"zod\"\nimport { LayoutIssueParamCodes, LayoutSchema } from \"../models/schema\"\nimport { createCoreError, type CoreError } from \"./errors\"\n\nexport type CompilePresetInput = {\n readonly document: string\n readonly source: string\n}\n\nexport type CompilePresetFromValueInput = {\n readonly value: unknown\n readonly source: string\n}\n\nexport type CompiledTerminalPane = {\n readonly kind: \"terminal\"\n readonly name: string\n readonly command?: string\n readonly cwd?: string\n readonly env?: Readonly<Record<string, string>>\n readonly delay?: number\n readonly title?: string\n readonly focus?: boolean\n readonly ephemeral?: boolean\n readonly closeOnError?: boolean\n readonly options?: Readonly<Record<string, unknown>>\n}\n\nexport type CompiledRatioEntry =\n | { readonly kind: \"weight\"; readonly weight: number }\n | { readonly kind: \"fixed-cells\"; readonly cells: number }\n\nexport type CompiledSplitPane = {\n readonly kind: \"split\"\n readonly orientation: \"horizontal\" | \"vertical\"\n readonly ratio: ReadonlyArray<CompiledRatioEntry>\n readonly panes: ReadonlyArray<CompiledLayoutNode>\n}\n\nexport type CompiledLayoutNode = CompiledTerminalPane | CompiledSplitPane\n\ntype CompiledPresetMetadata = {\n readonly source: string\n}\n\nexport type CompiledPresetHooks = {\n readonly afterApply?: string\n}\n\nexport type CompiledPreset = {\n readonly name: string\n readonly version: string\n readonly command?: string\n readonly layout?: CompiledLayoutNode\n readonly hooks?: CompiledPresetHooks\n readonly metadata: CompiledPresetMetadata\n}\n\nexport type CompilePresetSuccess = {\n readonly preset: CompiledPreset\n}\n\nexport const compilePreset = ({ document, source }: CompilePresetInput): CompilePresetSuccess => {\n let parsed: unknown\n try {\n parsed = parse(document)\n } catch (error) {\n throw compileError(\"PRESET_PARSE_ERROR\", {\n source,\n message: `Failed to parse YAML: ${(error as Error).message}`,\n details: {\n reason: error instanceof Error ? error.message : String(error),\n },\n })\n }\n\n return compilePresetValue({ value: parsed, source })\n}\n\nexport const compilePresetFromValue = ({ value, source }: CompilePresetFromValueInput): CompilePresetSuccess => {\n return compilePresetValue({ value, source })\n}\n\nconst FIXED_RATIO_PATTERN = /^([1-9][0-9]*)c$/\n\nconst compilePresetValue = ({ value, source }: CompilePresetFromValueInput): CompilePresetSuccess => {\n const parsed = value\n\n if (!isRecord(parsed)) {\n throw compileError(\"PRESET_INVALID_DOCUMENT\", {\n source,\n message: \"Preset definition is not an object\",\n path: \"preset\",\n })\n }\n\n const name = typeof parsed.name === \"string\" && parsed.name.trim().length > 0 ? parsed.name : \"Unnamed preset\"\n const validatedLayout = validateLayoutDefinition(parsed.layout, {\n source,\n path: \"preset.layout\",\n })\n\n const layout = parseLayoutNode(validatedLayout, {\n source,\n path: \"preset.layout\",\n })\n\n return {\n preset: {\n name,\n version: \"legacy\",\n command: typeof parsed.command === \"string\" ? parsed.command : undefined,\n layout: layout ?? undefined,\n hooks: parseHooks(parsed.hooks),\n metadata: { source },\n },\n }\n}\n\nconst parseHooks = (hooks: unknown): CompiledPresetHooks | undefined => {\n if (!isRecord(hooks)) {\n return undefined\n }\n\n const afterApply = typeof hooks.afterApply === \"string\" && hooks.afterApply.length > 0 ? hooks.afterApply : undefined\n\n return afterApply === undefined ? undefined : { afterApply }\n}\n\nconst validateLayoutDefinition = (\n layout: unknown,\n context: { readonly source: string; readonly path: string },\n): unknown => {\n if (layout === undefined || layout === null) {\n return layout\n }\n\n if (!isRecord(layout) || !looksSplitLikeNode(layout)) {\n return layout\n }\n\n const normalizedLayout = sanitizeLayoutForSchemaValidation(layout)\n const validated = LayoutSchema.safeParse(normalizedLayout)\n if (validated.success) {\n return layout\n }\n\n const issue = validated.error.issues[0]\n if (!issue) {\n throw compileError(\"LAYOUT_INVALID_NODE\", {\n source: context.source,\n message: \"Layout node is invalid\",\n path: context.path,\n details: { layout },\n })\n }\n\n throw convertLayoutIssueToCompileError({\n issue,\n source: context.source,\n basePath: context.path,\n layout,\n })\n}\n\nconst parseLayoutNode = (\n node: unknown,\n context: { readonly source: string; readonly path: string },\n): CompiledLayoutNode | null => {\n if (node === undefined || node === null) {\n return null\n }\n\n if (!isRecord(node)) {\n throw compileError(\"LAYOUT_INVALID_NODE\", {\n source: context.source,\n message: \"Layout node is invalid\",\n path: context.path,\n details: { node },\n })\n }\n\n if (\"type\" in node || \"ratio\" in node || \"panes\" in node) {\n return parseSplitPane(node, context)\n }\n\n if (typeof node.name === \"string\") {\n return parseTerminalPane(node)\n }\n\n throw compileError(\"LAYOUT_INVALID_NODE\", {\n source: context.source,\n message: \"Layout node is invalid\",\n path: context.path,\n details: { node },\n })\n}\n\nconst parseSplitPane = (\n node: Record<string, unknown>,\n context: { readonly source: string; readonly path: string },\n): CompiledSplitPane => {\n const orientation = node.type\n const panesInput = node.panes\n const ratioInput = node.ratio\n if (\n (orientation !== \"horizontal\" && orientation !== \"vertical\") ||\n !Array.isArray(panesInput) ||\n !Array.isArray(ratioInput)\n ) {\n throw compileError(\"LAYOUT_INVALID_NODE\", {\n source: context.source,\n message: \"Layout node is invalid\",\n path: context.path,\n details: { node },\n })\n }\n\n const panes = panesInput.map((child, index) =>\n parseLayoutNode(child, {\n source: context.source,\n path: `${context.path}.panes[${index}]`,\n }),\n )\n const ratio = ratioInput.map(\n (value, index): CompiledRatioEntry =>\n parseRatioEntry(value, {\n source: context.source,\n path: `${context.path}.ratio[${index}]`,\n }),\n )\n\n if (!ratio.some((entry) => entry.kind === \"weight\")) {\n throw compileError(\"RATIO_WEIGHT_MISSING\", {\n source: context.source,\n message: \"ratio must include at least one numeric weight\",\n path: `${context.path}.ratio`,\n details: { ratio: ratioInput },\n })\n }\n\n return {\n kind: \"split\",\n orientation,\n ratio,\n panes: panes.filter((pane): pane is CompiledLayoutNode => pane !== null),\n }\n}\n\nconst parseRatioEntry = (\n value: unknown,\n context: { readonly source: string; readonly path: string },\n): CompiledRatioEntry => {\n if (typeof value === \"number\" && Number.isFinite(value) && value > 0) {\n return {\n kind: \"weight\",\n weight: value,\n }\n }\n\n if (typeof value === \"string\") {\n const match = value.match(FIXED_RATIO_PATTERN)\n if (match?.[1] !== undefined) {\n const parsed = Number(match[1])\n if (Number.isInteger(parsed) && parsed > 0) {\n return {\n kind: \"fixed-cells\",\n cells: parsed,\n }\n }\n }\n }\n\n throw compileError(\"RATIO_INVALID_VALUE\", {\n source: context.source,\n message: 'ratio value must be a positive number or \"<positive-integer>c\"',\n path: context.path,\n details: { value },\n })\n}\n\nconst parseTerminalPane = (node: Record<string, unknown>): CompiledTerminalPane => {\n const name = typeof node.name === \"string\" ? node.name : \"\"\n const command = typeof node.command === \"string\" ? node.command : undefined\n const cwd = typeof node.cwd === \"string\" ? node.cwd : undefined\n const delay = typeof node.delay === \"number\" && Number.isFinite(node.delay) && node.delay > 0 ? node.delay : undefined\n const title = typeof node.title === \"string\" && node.title.length > 0 ? node.title : undefined\n const focus = node.focus === true ? true : undefined\n const ephemeral = node.ephemeral === true ? true : undefined\n const closeOnError = node.closeOnError === true ? true : undefined\n const env = normalizeEnv(node.env)\n\n const knownKeys = new Set([\n \"name\",\n \"command\",\n \"cwd\",\n \"env\",\n \"focus\",\n \"ephemeral\",\n \"closeOnError\",\n \"options\",\n \"title\",\n \"delay\",\n ])\n const options = collectOptions(node, knownKeys)\n\n return {\n kind: \"terminal\",\n name,\n command,\n cwd,\n env,\n delay,\n title,\n focus,\n ephemeral,\n closeOnError,\n options,\n }\n}\n\nconst normalizeEnv = (env: unknown): Readonly<Record<string, string>> | undefined => {\n if (!isRecord(env)) {\n return undefined\n }\n\n const entries = Object.entries(env).reduce<Record<string, string>>((accumulator, [key, value]) => {\n if (typeof value === \"string\") {\n accumulator[key] = value\n }\n return accumulator\n }, {})\n\n return Object.keys(entries).length > 0 ? entries : undefined\n}\n\nconst collectOptions = (\n node: Record<string, unknown>,\n excludedKeys: ReadonlySet<string>,\n): Readonly<Record<string, unknown>> | undefined => {\n const optionsEntries = Object.entries(node).filter(([key]) => !excludedKeys.has(key))\n if (optionsEntries.length === 0) {\n return undefined\n }\n\n return optionsEntries.reduce<Record<string, unknown>>((accumulator, [key, value]) => {\n accumulator[key] = value\n return accumulator\n }, {})\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> => {\n return typeof value === \"object\" && value !== null\n}\n\nconst looksSplitLikeNode = (value: Record<string, unknown>): boolean => {\n return \"type\" in value || \"ratio\" in value || \"panes\" in value\n}\n\nconst sanitizeLayoutForSchemaValidation = (node: unknown): unknown => {\n if (!isRecord(node)) {\n return node\n }\n\n if (looksSplitLikeNode(node)) {\n const panes = Array.isArray(node.panes)\n ? node.panes.map((child) => sanitizeLayoutForSchemaValidation(child))\n : node.panes\n return {\n type: node.type,\n ratio: node.ratio,\n panes,\n }\n }\n\n return {\n name: node.name,\n command: node.command,\n cwd: node.cwd,\n env: normalizeEnv(node.env),\n delay: node.delay,\n title: node.title,\n focus: node.focus,\n ephemeral: node.ephemeral,\n closeOnError: node.closeOnError,\n }\n}\n\nconst convertLayoutIssueToCompileError = ({\n issue,\n source,\n basePath,\n layout,\n}: {\n readonly issue: z.ZodIssue\n readonly source: string\n readonly basePath: string\n readonly layout: unknown\n}): CoreError => {\n const issueParamCode = getIssueParamCode(issue)\n\n if (isMissingArrayIssue(issue, \"panes\")) {\n return compileError(\"LAYOUT_PANES_MISSING\", {\n source,\n message: \"panes array is missing or empty\",\n path: `${basePath}.panes`,\n })\n }\n\n if (isMissingArrayIssue(issue, \"ratio\")) {\n return compileError(\"LAYOUT_RATIO_MISSING\", {\n source,\n message: \"ratio array is missing or empty\",\n path: `${basePath}.ratio`,\n })\n }\n\n if (issue.path.includes(\"type\")) {\n return compileError(\"LAYOUT_INVALID_ORIENTATION\", {\n source,\n message: \"layout.type must be horizontal or vertical\",\n path: `${basePath}.type`,\n details: {\n type: getValueAtPath(layout, issue.path),\n },\n })\n }\n\n if (\n issueParamCode === LayoutIssueParamCodes.RATIO_LENGTH_MISMATCH ||\n issue.message.includes(\"Number of elements in ratio array does not match number of elements in panes array\")\n ) {\n return compileError(\"LAYOUT_RATIO_MISMATCH\", {\n source,\n message: \"ratio and panes arrays must have the same length\",\n path: basePath,\n details: getRatioLengthDetails(layout),\n })\n }\n\n if (\n issueParamCode === LayoutIssueParamCodes.RATIO_WEIGHT_MISSING ||\n issue.message.includes(\"ratio must include at least one numeric weight\")\n ) {\n const ratio = isRecord(layout) ? layout.ratio : undefined\n return compileError(\"RATIO_WEIGHT_MISSING\", {\n source,\n message: \"ratio must include at least one numeric weight\",\n path: `${basePath}.ratio`,\n details: {\n ratio,\n },\n })\n }\n\n if (issue.path.includes(\"ratio\")) {\n return compileError(\"RATIO_INVALID_VALUE\", {\n source,\n message: 'ratio value must be a positive number or \"<positive-integer>c\"',\n path: formatPath(basePath, issue.path),\n details: {\n value: getValueAtPath(layout, issue.path),\n },\n })\n }\n\n return compileError(\"LAYOUT_INVALID_NODE\", {\n source,\n message: \"Layout node is invalid\",\n path: formatPath(basePath, issue.path),\n details: {\n issue: issue.message,\n node: getValueAtPath(layout, issue.path),\n },\n })\n}\n\nconst isMissingArrayIssue = (issue: z.ZodIssue, field: \"panes\" | \"ratio\"): boolean => {\n if (issue.path.length !== 1 || issue.path[0] !== field) {\n return false\n }\n\n return issue.code === \"invalid_type\" || (issue.code === \"too_small\" && issue.type === \"array\")\n}\n\nconst getIssueParamCode = (issue: z.ZodIssue): string | undefined => {\n if (issue.code !== z.ZodIssueCode.custom) {\n return undefined\n }\n const customIssue = issue as z.ZodCustomIssue\n const code = customIssue.params?.code\n return typeof code === \"string\" ? code : undefined\n}\n\nconst getRatioLengthDetails = (layout: unknown): Readonly<Record<string, unknown>> | undefined => {\n if (!isRecord(layout)) {\n return undefined\n }\n\n const ratio = layout.ratio\n const panes = layout.panes\n if (!Array.isArray(ratio) || !Array.isArray(panes)) {\n return undefined\n }\n\n return {\n ratioLength: ratio.length,\n panesLength: panes.length,\n }\n}\n\nconst formatPath = (basePath: string, path: ReadonlyArray<string | number>): string => {\n if (path.length === 0) {\n return basePath\n }\n\n return path.reduce<string>((accumulator, segment) => {\n if (typeof segment === \"number\") {\n return `${accumulator}[${segment}]`\n }\n return `${accumulator}.${segment}`\n }, basePath)\n}\n\nconst getValueAtPath = (value: unknown, path: ReadonlyArray<string | number>): unknown => {\n let current: unknown = value\n\n for (const segment of path) {\n if (typeof segment === \"number\") {\n if (!Array.isArray(current)) {\n return undefined\n }\n current = current[segment]\n continue\n }\n\n if (!isRecord(current)) {\n return undefined\n }\n current = current[segment]\n }\n\n return current\n}\n\nconst compileError = (\n code: string,\n error: {\n readonly source?: string\n readonly message: string\n readonly path?: string\n readonly details?: Readonly<Record<string, unknown>>\n },\n): CoreError => {\n return createCoreError(\"compile\", {\n code,\n message: error.message,\n source: error.source,\n path: error.path,\n details: error.details,\n })\n}\n","import type {\n CompiledLayoutNode,\n CompiledPreset,\n CompiledRatioEntry,\n CompiledSplitPane,\n CompiledTerminalPane,\n} from \"./compile\"\nimport { createCoreError, type CoreError } from \"./errors\"\n\ntype CreateLayoutPlanInput = {\n readonly preset: CompiledPreset\n}\n\ntype PlanTerminal = {\n readonly kind: \"terminal\"\n readonly id: string\n readonly name: string\n readonly command?: string\n readonly cwd?: string\n readonly env?: Readonly<Record<string, string>>\n readonly delay?: number\n readonly title?: string\n readonly focus: boolean\n readonly ephemeral?: boolean\n readonly closeOnError?: boolean\n readonly options?: Readonly<Record<string, unknown>>\n}\n\ntype PlanSplit = {\n readonly kind: \"split\"\n readonly id: string\n readonly orientation: \"horizontal\" | \"vertical\"\n readonly ratio: ReadonlyArray<CompiledRatioEntry>\n readonly panes: ReadonlyArray<PlanNode>\n}\n\nexport type PlanNode = PlanTerminal | PlanSplit\n\nexport type LayoutPlan = {\n readonly root: PlanNode\n readonly focusPaneId: string\n}\n\nexport type CreateLayoutPlanSuccess = {\n readonly plan: LayoutPlan\n}\n\nexport const createLayoutPlan = ({ preset }: CreateLayoutPlanInput): CreateLayoutPlanSuccess => {\n if (!preset.layout) {\n const terminal = createTerminalNode({\n id: \"root\",\n terminal: {\n kind: \"terminal\",\n name: preset.name,\n command: preset.command,\n },\n focusOverride: true,\n })\n\n return {\n plan: {\n root: terminal,\n focusPaneId: terminal.id,\n },\n }\n }\n\n const { node, focusPaneIds, terminalPaneIds } = buildLayoutNode(preset.layout, {\n parentId: \"root\",\n path: \"preset.layout\",\n source: preset.metadata.source,\n })\n\n if (focusPaneIds.length > 1) {\n throw planError(\"FOCUS_CONFLICT\", {\n message: \"Multiple panes specify focus=true\",\n path: \"preset.layout\",\n source: preset.metadata.source,\n details: { focusPaneIds },\n })\n }\n\n if (terminalPaneIds.length === 0) {\n throw planError(\"NO_TERMINAL_PANES\", {\n message: \"No terminal panes are defined\",\n path: \"preset.layout\",\n source: preset.metadata.source,\n })\n }\n\n const focusPaneId = focusPaneIds[0] ?? terminalPaneIds[0]!\n const root = ensureFocus(node, focusPaneId)\n\n return {\n plan: {\n root,\n focusPaneId,\n },\n }\n}\n\ntype BuildResult = {\n readonly node: PlanNode\n readonly focusPaneIds: ReadonlyArray<string>\n readonly terminalPaneIds: ReadonlyArray<string>\n}\n\nconst buildLayoutNode = (\n node: CompiledLayoutNode,\n context: { readonly parentId: string; readonly path: string; readonly source: string },\n): BuildResult => {\n if (node.kind === \"split\") {\n return buildSplitNode(node, context)\n }\n\n return {\n node: createTerminalNode({ id: context.parentId, terminal: node }),\n focusPaneIds: node.focus === true ? [context.parentId] : [],\n terminalPaneIds: [context.parentId],\n }\n}\n\nconst buildSplitNode = (\n node: CompiledSplitPane,\n context: { readonly parentId: string; readonly path: string; readonly source: string },\n): BuildResult => {\n const ratio = validateRatioEntries(node.ratio, context)\n\n const panes: PlanNode[] = []\n const focusPaneIds: string[] = []\n const terminalPaneIds: string[] = []\n\n for (let index = 0; index < node.panes.length; index += 1) {\n const childId = `${context.parentId}.${index}`\n const childContext = {\n parentId: childId,\n path: `${context.path}.panes[${index}]`,\n source: context.source,\n }\n\n const childResult = buildLayoutNode(node.panes[index]!, childContext)\n panes.push(childResult.node)\n focusPaneIds.push(...childResult.focusPaneIds)\n terminalPaneIds.push(...childResult.terminalPaneIds)\n }\n\n return {\n node: {\n kind: \"split\",\n id: context.parentId,\n orientation: node.orientation,\n ratio,\n panes,\n },\n focusPaneIds,\n terminalPaneIds,\n }\n}\n\nconst createTerminalNode = ({\n id,\n terminal,\n focusOverride,\n}: {\n readonly id: string\n readonly terminal: CompiledTerminalPane\n readonly focusOverride?: boolean\n}): PlanTerminal => {\n return {\n kind: \"terminal\",\n id,\n name: terminal.name,\n command: terminal.command,\n cwd: terminal.cwd,\n env: terminal.env,\n delay: terminal.delay,\n title: terminal.title,\n options: terminal.options,\n focus: focusOverride === true ? true : terminal.focus === true,\n ephemeral: terminal.ephemeral,\n closeOnError: terminal.closeOnError,\n }\n}\n\nconst ensureFocus = (node: PlanNode, focusPaneId: string): PlanNode => {\n if (node.kind === \"terminal\") {\n return {\n ...node,\n focus: node.id === focusPaneId,\n }\n }\n\n return {\n ...node,\n panes: node.panes.map((pane) => ensureFocus(pane, focusPaneId)),\n }\n}\n\nconst validateRatioEntries = (\n ratio: ReadonlyArray<CompiledRatioEntry>,\n context: { readonly path: string; readonly source: string },\n): ReadonlyArray<CompiledRatioEntry> => {\n let hasWeight = false\n\n for (let index = 0; index < ratio.length; index += 1) {\n const value = ratio[index]\n if (value?.kind === \"weight\") {\n if (!Number.isFinite(value.weight) || value.weight <= 0) {\n throw planError(\"RATIO_INVALID_VALUE\", {\n message: 'ratio value must be a positive number or \"<positive-integer>c\"',\n path: `${context.path}.ratio[${index}]`,\n source: context.source,\n details: { value },\n })\n }\n hasWeight = true\n continue\n }\n\n if (value?.kind === \"fixed-cells\") {\n if (!Number.isInteger(value.cells) || value.cells <= 0) {\n throw planError(\"RATIO_INVALID_VALUE\", {\n message: 'ratio value must be a positive number or \"<positive-integer>c\"',\n path: `${context.path}.ratio[${index}]`,\n source: context.source,\n details: { value },\n })\n }\n continue\n }\n\n throw planError(\"RATIO_INVALID_VALUE\", {\n message: \"ratio entry is invalid\",\n path: `${context.path}.ratio[${index}]`,\n source: context.source,\n details: { value },\n })\n }\n\n if (!hasWeight) {\n throw planError(\"RATIO_WEIGHT_MISSING\", {\n message: \"ratio must include at least one numeric weight\",\n path: `${context.path}.ratio`,\n source: context.source,\n details: { ratio },\n })\n }\n\n return ratio\n}\n\nconst planError = (\n code: string,\n error: {\n readonly message: string\n readonly source?: string\n readonly path?: string\n readonly details?: Readonly<Record<string, unknown>>\n },\n): CoreError => {\n return createCoreError(\"plan\", {\n code,\n message: error.message,\n source: error.source,\n path: error.path,\n details: error.details,\n })\n}\n","import { createHash } from \"crypto\"\nimport type { LayoutPlan, PlanNode } from \"./planner\"\nimport type { CompiledRatioEntry } from \"./compile\"\n\ntype EmitPlanInput = {\n readonly plan: LayoutPlan\n}\n\ntype CommandStepKind = \"split\" | \"focus\"\n\nexport type SplitSizing =\n | { readonly mode: \"percent\"; readonly percentage: number }\n | {\n readonly mode: \"dynamic-cells\"\n readonly target: CompiledRatioEntry\n readonly remainingFixedCells: number\n readonly remainingWeight: number\n readonly remainingWeightPaneCount: number\n }\n\nexport type CommandStep = {\n readonly id: string\n readonly kind: CommandStepKind\n readonly command?: ReadonlyArray<string>\n readonly summary: string\n readonly targetPaneId?: string\n readonly createdPaneId?: string\n readonly orientation?: \"horizontal\" | \"vertical\"\n readonly percentage?: number\n readonly splitSizing?: SplitSizing\n}\n\nexport type EmittedTerminal = {\n readonly virtualPaneId: string\n readonly command?: string\n readonly cwd?: string\n readonly env?: Readonly<Record<string, string>>\n readonly delay?: number\n readonly title?: string\n readonly focus: boolean\n readonly name: string\n readonly ephemeral?: boolean\n readonly closeOnError?: boolean\n}\n\ntype PlanEmissionSummary = {\n readonly stepsCount: number\n readonly focusPaneId: string\n readonly initialPaneId: string\n}\n\nexport type PlanEmission = {\n readonly steps: ReadonlyArray<CommandStep>\n readonly summary: PlanEmissionSummary\n readonly terminals: ReadonlyArray<EmittedTerminal>\n readonly hash: string\n}\n\ntype SplitNode = Extract<PlanNode, { kind: \"split\" }>\n\nexport const emitPlan = ({ plan }: EmitPlanInput): PlanEmission => {\n const steps: CommandStep[] = []\n collectSplitSteps(plan.root, steps)\n\n steps.push({\n id: `${plan.focusPaneId}:focus`,\n kind: \"focus\",\n summary: `select pane ${plan.focusPaneId}`,\n targetPaneId: plan.focusPaneId,\n })\n\n const hash = createPlanHash(plan, steps)\n const initialPaneId = determineInitialPaneId(plan.root)\n const terminals = collectTerminals(plan.root)\n\n return {\n steps,\n summary: {\n stepsCount: steps.length,\n focusPaneId: plan.focusPaneId,\n initialPaneId,\n },\n terminals,\n hash,\n }\n}\n\nconst collectSplitSteps = (node: PlanNode, steps: CommandStep[]): void => {\n if (node.kind === \"terminal\") {\n return\n }\n\n appendSplitSteps(node, steps)\n node.panes.forEach((pane) => collectSplitSteps(pane, steps))\n}\n\nconst appendSplitSteps = (node: SplitNode, steps: CommandStep[]): void => {\n const directionFlag = node.orientation === \"horizontal\" ? \"-h\" : \"-v\"\n const hasFixedCells = node.ratio.some((entry) => entry.kind === \"fixed-cells\")\n\n for (let index = 1; index < node.panes.length; index += 1) {\n const targetPaneId = node.panes[index - 1]?.id ?? node.id\n const createdPaneId = node.panes[index]?.id\n\n const splitSizing = hasFixedCells\n ? buildDynamicSplitSizing(node.ratio, index)\n : buildPercentSplitSizing(node.ratio, index)\n\n const percentage = splitSizing.mode === \"percent\" ? splitSizing.percentage : undefined\n\n steps.push({\n id: `${node.id}:split:${index}`,\n kind: \"split\",\n summary: `split ${targetPaneId} (${directionFlag})`,\n targetPaneId,\n createdPaneId,\n orientation: node.orientation,\n percentage,\n splitSizing,\n })\n }\n}\n\nconst buildPercentSplitSizing = (ratio: ReadonlyArray<CompiledRatioEntry>, index: number): SplitSizing => {\n const remainingIncludingTarget = ratio\n .slice(index - 1)\n .reduce((sum, entry) => sum + (entry.kind === \"weight\" ? entry.weight : 0), 0)\n const remainingAfterTarget = ratio\n .slice(index)\n .reduce((sum, entry) => sum + (entry.kind === \"weight\" ? entry.weight : 0), 0)\n\n const desiredPercentage = remainingIncludingTarget <= 0 ? 0 : (remainingAfterTarget / remainingIncludingTarget) * 100\n\n return {\n mode: \"percent\",\n percentage: clampPercent(desiredPercentage),\n }\n}\n\nconst buildDynamicSplitSizing = (ratio: ReadonlyArray<CompiledRatioEntry>, index: number): SplitSizing => {\n const target = ratio[index - 1]!\n const remaining = ratio.slice(index)\n\n const remainingFixedCells = remaining.reduce((sum, entry) => {\n return entry.kind === \"fixed-cells\" ? sum + entry.cells : sum\n }, 0)\n const remainingWeight = remaining.reduce((sum, entry) => {\n return entry.kind === \"weight\" ? sum + entry.weight : sum\n }, 0)\n const remainingWeightPaneCount = remaining.reduce((count, entry) => {\n return entry.kind === \"weight\" ? count + 1 : count\n }, 0)\n\n return {\n mode: \"dynamic-cells\",\n target,\n remainingFixedCells,\n remainingWeight,\n remainingWeightPaneCount,\n }\n}\n\nconst clampPercent = (value: number): number => {\n return Math.min(99, Math.max(1, Math.round(value)))\n}\n\nconst collectTerminals = (node: PlanNode): EmittedTerminal[] => {\n if (node.kind === \"terminal\") {\n return [\n {\n virtualPaneId: node.id,\n command: node.command,\n cwd: node.cwd,\n env: node.env,\n delay: node.delay,\n title: node.title,\n focus: node.focus,\n name: node.name,\n ephemeral: node.ephemeral,\n closeOnError: node.closeOnError,\n },\n ]\n }\n\n return node.panes.flatMap((pane) => collectTerminals(pane))\n}\n\nconst determineInitialPaneId = (node: PlanNode): string => {\n if (node.kind === \"terminal\") {\n return node.id\n }\n\n let current: PlanNode = node\n while (current.kind === \"split\") {\n current = current.panes[0]!\n }\n return current.id\n}\n\nconst createPlanHash = (plan: LayoutPlan, steps: ReadonlyArray<CommandStep>): string => {\n const digest = createHash(\"sha256\")\n const normalized = {\n focusPaneId: plan.focusPaneId,\n root: plan.root,\n steps,\n }\n digest.update(JSON.stringify(normalized))\n return digest.digest(\"hex\")\n}\n","import { isCoreError, type CoreError } from \"../core/index\"\nimport type { Logger } from \"../utils/logger\"\n\ntype CliErrorHandlers = {\n handleCoreError: (error: CoreError) => number\n handleError: (error: unknown) => number\n handlePipelineFailure: (error: unknown) => number\n}\n\nexport const createCliErrorHandlers = ({ getLogger }: { getLogger: () => Logger }): CliErrorHandlers => {\n const handleCoreError = (error: CoreError): number => {\n const header = [`[${error.kind}]`, `[${error.code}]`]\n if (typeof error.path === \"string\" && error.path.length > 0) {\n header.push(`[${error.path}]`)\n }\n\n const lines = [`${header.join(\" \")} ${error.message}`.trim()]\n\n if (typeof error.source === \"string\" && error.source.length > 0) {\n lines.push(`source: ${error.source}`)\n }\n\n const commandDetail = error.details?.command\n if (Array.isArray(commandDetail)) {\n const parts = commandDetail.filter((segment): segment is string => typeof segment === \"string\")\n if (parts.length > 0) {\n lines.push(`command: ${parts.join(\" \")}`)\n }\n } else if (typeof commandDetail === \"string\" && commandDetail.length > 0) {\n lines.push(`command: ${commandDetail}`)\n }\n\n const stderrDetail = error.details?.stderr\n if (typeof stderrDetail === \"string\" && stderrDetail.length > 0) {\n lines.push(`stderr: ${stderrDetail}`)\n } else if (stderrDetail !== undefined) {\n lines.push(`stderr: ${String(stderrDetail)}`)\n }\n\n getLogger().error(lines.join(\"\\n\"))\n return 1\n }\n\n const handleError = (error: unknown): number => {\n if (error instanceof Error) {\n getLogger().error(error.message, error)\n } else {\n getLogger().error(\"An unexpected error occurred\")\n }\n\n return 1\n }\n\n const handlePipelineFailure = (error: unknown): number => {\n if (isCoreError(error)) {\n return handleCoreError(error)\n }\n return handleError(error)\n }\n\n return {\n handleCoreError,\n handleError,\n handlePipelineFailure,\n }\n}\n","import chalk from \"chalk\"\n\nexport enum LogLevel {\n ERROR = 0,\n WARN = 1,\n INFO = 2,\n DEBUG = 3,\n}\n\ntype LoggerOptions = {\n readonly level?: LogLevel\n readonly prefix?: string\n}\n\nexport type Logger = {\n readonly level: LogLevel\n readonly prefix: string\n error: (message: string, error?: Error) => void\n warn: (message: string) => void\n info: (message: string) => void\n debug: (message: string) => void\n success: (message: string) => void\n createChild: (suffix: string) => Logger\n}\n\nconst resolveDefaultLogLevel = (): LogLevel => {\n if (process.env.VDE_DEBUG === \"true\") {\n return LogLevel.DEBUG\n }\n if (process.env.VDE_VERBOSE === \"true\") {\n return LogLevel.INFO\n }\n return LogLevel.WARN\n}\n\nconst formatMessage = (prefix: string, message: string): string => {\n return prefix ? `${prefix} ${message}` : message\n}\n\nexport const createLogger = (options: LoggerOptions = {}): Logger => {\n const level = options.level ?? resolveDefaultLogLevel()\n const prefix = options.prefix ?? \"\"\n\n const build = (nextPrefix: string, nextLevel: LogLevel): Logger => {\n const resolvedPrefix = nextPrefix\n\n return {\n level: nextLevel,\n prefix: resolvedPrefix,\n error(message: string, error?: Error): void {\n if (nextLevel >= LogLevel.ERROR) {\n console.error(chalk.red(formatMessage(resolvedPrefix, `Error: ${message}`)))\n if (error && process.env.VDE_DEBUG === \"true\") {\n console.error(chalk.gray(error.stack))\n }\n }\n },\n warn(message: string): void {\n if (nextLevel >= LogLevel.WARN) {\n console.warn(chalk.yellow(formatMessage(resolvedPrefix, message)))\n }\n },\n info(message: string): void {\n if (nextLevel >= LogLevel.INFO) {\n console.log(formatMessage(resolvedPrefix, message))\n }\n },\n debug(message: string): void {\n if (nextLevel >= LogLevel.DEBUG) {\n console.log(chalk.gray(formatMessage(resolvedPrefix, `[DEBUG] ${message}`)))\n }\n },\n success(message: string): void {\n console.log(chalk.green(formatMessage(resolvedPrefix, message)))\n },\n createChild(suffix: string): Logger {\n const childPrefix = resolvedPrefix ? `${resolvedPrefix} ${suffix}` : suffix\n return build(childPrefix, nextLevel)\n },\n }\n }\n\n return build(prefix, level)\n}\n","import chalk from \"chalk\"\n\nimport type { PresetInfo } from \"../models/types\"\nimport type { PresetManager } from \"../contracts\"\nimport { LogLevel, type Logger } from \"../utils/logger\"\n\ntype RuntimeOptions = {\n readonly verbose?: boolean\n readonly config?: string\n}\n\nexport const applyRuntimeOptions = ({\n runtimeOptions,\n createLogger,\n presetManager,\n}: {\n readonly runtimeOptions: RuntimeOptions\n readonly createLogger: (options?: { level?: LogLevel }) => Logger\n readonly presetManager: PresetManager\n}): Logger => {\n const logger =\n runtimeOptions.verbose === true\n ? createLogger({\n level: LogLevel.INFO,\n })\n : createLogger()\n\n if (\n typeof runtimeOptions.config === \"string\" &&\n runtimeOptions.config.length > 0 &&\n typeof presetManager.setConfigPath === \"function\"\n ) {\n presetManager.setConfigPath(runtimeOptions.config)\n }\n\n return logger\n}\n\nexport const listPresets = async ({\n presetManager,\n logger,\n onError,\n output = (line: string): void => console.log(line),\n}: {\n readonly presetManager: PresetManager\n readonly logger: Logger\n readonly onError: (error: unknown) => number\n readonly output?: (line: string) => void\n}): Promise<number> => {\n try {\n await presetManager.loadConfig()\n const presets = presetManager.listPresets()\n\n if (presets.length === 0) {\n logger.warn(\"No presets defined\")\n return 0\n }\n\n output(chalk.bold(\"Available presets:\\n\"))\n\n const maxKeyLength = Math.max(...presets.map((preset) => preset.key.length))\n presets.forEach((preset: PresetInfo) => {\n const paddedKey = preset.key.padEnd(maxKeyLength + 2)\n const description = preset.description ?? \"\"\n output(` ${chalk.cyan(paddedKey)} ${description}`)\n })\n\n return 0\n } catch (error) {\n return onError(error)\n }\n}\n","export type PaneDimensions = {\n readonly cols: number\n readonly rows: number\n}\n\nexport const updatePaneSizes = ({\n paneSizes,\n targetPaneId,\n createdPaneId,\n orientation,\n targetCells,\n createdCells,\n}: {\n readonly paneSizes: Map<string, PaneDimensions>\n readonly targetPaneId: string\n readonly createdPaneId: string\n readonly orientation: \"horizontal\" | \"vertical\"\n readonly targetCells: number\n readonly createdCells: number\n}): void => {\n const base = paneSizes.get(targetPaneId)\n if (base === undefined) {\n return\n }\n\n if (orientation === \"horizontal\") {\n paneSizes.set(targetPaneId, { cols: targetCells, rows: base.rows })\n paneSizes.set(createdPaneId, { cols: createdCells, rows: base.rows })\n return\n }\n\n paneSizes.set(targetPaneId, { cols: base.cols, rows: targetCells })\n paneSizes.set(createdPaneId, { cols: base.cols, rows: createdCells })\n}\n","import { execa } from \"execa\"\nimport { createTmuxError, ErrorCodes } from \"../utils/errors\"\nimport type { CommandExecutor } from \"../contracts\"\nimport { createLogger, LogLevel } from \"../utils/logger\"\n\ntype RealExecutorOptions = {\n readonly verbose?: boolean\n}\n\nconst parseCommand = (commandOrArgs: string | string[]): string[] => {\n return typeof commandOrArgs === \"string\"\n ? commandOrArgs\n .split(\" \")\n .filter((segment) => segment.length > 0)\n .slice(1)\n : commandOrArgs\n}\n\nconst toCommandString = (args: string[]): string => {\n return [\"tmux\", ...args].join(\" \")\n}\n\nexport const createRealExecutor = (options: RealExecutorOptions = {}): CommandExecutor => {\n const verbose = options.verbose ?? false\n const logger = createLogger({\n level: verbose ? LogLevel.INFO : LogLevel.WARN,\n prefix: \"[tmux]\",\n })\n\n const execute = async (commandOrArgs: string | string[]): Promise<string> => {\n const args = parseCommand(commandOrArgs)\n const commandString = toCommandString(args)\n\n logger.info(`Executing: ${commandString}`)\n\n try {\n const result = await execa(\"tmux\", args)\n return result.stdout\n } catch (error) {\n const execaError = error as { exitCode?: number; stderr?: string; message: string }\n\n throw createTmuxError(\"Failed to execute tmux command\", ErrorCodes.TMUX_COMMAND_FAILED, {\n command: commandString,\n exitCode: execaError.exitCode,\n stderr: execaError.stderr,\n })\n }\n }\n\n return {\n execute,\n async executeMany(commandsList: string[][]): Promise<void> {\n for (const args of commandsList) {\n await execute(args)\n }\n },\n isDryRun(): boolean {\n return false\n },\n logCommand(command: string): void {\n logger.info(`Executing: ${command}`)\n },\n }\n}\n","import type { CommandExecutor } from \"../contracts\"\nimport { createLogger, LogLevel } from \"../utils/logger\"\n\ntype DryRunExecutorOptions = {\n readonly verbose?: boolean\n}\n\nconst parseCommand = (commandOrArgs: string | string[]): string[] => {\n return typeof commandOrArgs === \"string\"\n ? commandOrArgs\n .split(\" \")\n .filter((segment) => segment.length > 0)\n .slice(1)\n : commandOrArgs\n}\n\nconst toCommandString = (args: string[]): string => {\n return [\"tmux\", ...args].join(\" \")\n}\n\nexport const createDryRunExecutor = (options: DryRunExecutorOptions = {}): CommandExecutor => {\n const verbose = options.verbose ?? false\n const logger = createLogger({\n level: verbose ? LogLevel.INFO : LogLevel.WARN,\n prefix: \"[tmux] [DRY RUN]\",\n })\n\n const execute = async (commandOrArgs: string | string[]): Promise<string> => {\n const args = parseCommand(commandOrArgs)\n const commandString = toCommandString(args)\n logger.info(`Would execute: ${commandString}`)\n return \"\"\n }\n\n return {\n execute,\n async executeMany(commandsList: string[][]): Promise<void> {\n for (const args of commandsList) {\n await execute(args)\n }\n },\n isDryRun(): boolean {\n return true\n },\n logCommand(command: string): void {\n logger.info(`Would execute: ${command}`)\n },\n }\n}\n","import type { CommandExecutor } from \"../contracts\"\nimport type { TmuxExecutorContract } from \"../contracts\"\nimport { createEnvironmentError, ErrorCodes } from \"../utils/errors\"\n\nexport type MockExecutor = CommandExecutor &\n TmuxExecutorContract & {\n readonly getExecutedCommands: () => string[][]\n readonly clearExecutedCommands: () => void\n readonly setMockPaneIds: (paneIds: string[]) => void\n readonly getPaneIds: () => string[]\n readonly setMockProtectedPaneIds: (paneIds: string[]) => void\n }\n\nconst parseCommand = (commandOrArgs: string | string[]): string[] => {\n return typeof commandOrArgs === \"string\"\n ? commandOrArgs\n .split(\" \")\n .filter((segment) => segment.length > 0)\n .slice(1)\n : commandOrArgs\n}\n\nconst isInTmuxSession = (): boolean => {\n return Boolean(process.env.TMUX)\n}\n\nconst toCommandString = (args: string[]): string => {\n return [\"tmux\", ...args].join(\" \")\n}\n\nexport const createMockExecutor = (): MockExecutor => {\n let mockPaneCounter = 0\n let mockPaneIds: string[] = [\"%0\"]\n let mockProtectedPaneIds: string[] = []\n let executedCommands: string[][] = []\n\n const execute = async (commandOrArgs: string | string[]): Promise<string> => {\n const args = parseCommand(commandOrArgs)\n executedCommands.push(args)\n\n if (args[0] === \"new-window\") {\n mockPaneCounter = 0\n mockPaneIds = [\"%0\"]\n return \"%0\"\n }\n\n if (args.includes(\"display-message\")) {\n const parts: string[] = []\n if (args.includes(\"#{pane_id}\")) {\n parts.push(mockPaneIds[0] ?? \"%0\")\n }\n if (args.includes(\"#{pane_width}\")) {\n parts.push(\"200\")\n }\n if (args.includes(\"#{pane_height}\")) {\n parts.push(\"60\")\n }\n if (parts.length > 0) {\n return parts.join(\" \")\n }\n }\n\n // The two list-panes formats below are matched by exact string equality on the\n // -F argument, so at most one of these branches ever applies to a given call.\n if (args.includes(\"list-panes\") && args.includes(\"#{pane_id}\\t#{@vde_sidebar}\")) {\n const protectedPaneIds = new Set(mockProtectedPaneIds)\n return mockPaneIds.map((paneId) => `${paneId}\\t${protectedPaneIds.has(paneId) ? \"1\" : \"\"}`).join(\"\\n\")\n }\n\n if (args.includes(\"list-panes\") && args.includes(\"#{pane_id}\")) {\n return mockPaneIds.join(\"\\n\")\n }\n\n if (args[0] === \"kill-pane\" && args.includes(\"-a\")) {\n // NOTE: Real tmux's `kill-pane -a -t <target>` kills every other pane in the\n // window, including sidebar panes. This mock deliberately diverges by keeping\n // mockProtectedPaneIds alive so tests can simulate protection, but production\n // code must not rely on `kill-pane -a` alone to spare the sidebar: it has to\n // compute the kill target set explicitly via classifyWindowPanes and kill\n // non-sidebar panes individually (see plan.md Step 1-4).\n const targetIndex = args.indexOf(\"-t\")\n const targetPane =\n (targetIndex >= 0 && targetIndex + 1 < args.length ? args[targetIndex + 1] : mockPaneIds[0]) ?? \"%0\"\n const survivingPaneIds = mockPaneIds.filter(\n (paneId) => paneId === targetPane || mockProtectedPaneIds.includes(paneId),\n )\n mockPaneIds = survivingPaneIds.includes(targetPane) ? survivingPaneIds : [targetPane, ...survivingPaneIds]\n const parsedCounter = Number(targetPane.replace(\"%\", \"\"))\n if (!Number.isNaN(parsedCounter)) {\n mockPaneCounter = parsedCounter\n }\n return \"\"\n }\n\n if (args[0] === \"kill-pane\") {\n // Individual `kill-pane -t <target>` (no `-a`): only the named pane is\n // removed, matching real tmux. Production code relies on this to close\n // non-sidebar panes one at a time (see plan.md Step 1-4).\n const targetIndex = args.indexOf(\"-t\")\n const targetPane = targetIndex >= 0 && targetIndex + 1 < args.length ? args[targetIndex + 1] : undefined\n if (typeof targetPane === \"string\") {\n mockPaneIds = mockPaneIds.filter((paneId) => paneId !== targetPane)\n }\n return \"\"\n }\n\n if (args.includes(\"split-window\")) {\n mockPaneCounter += 1\n const newPaneId = `%${mockPaneCounter}`\n mockPaneIds = [...mockPaneIds, newPaneId]\n\n // `-P -F \"#{pane_id}\"` asks tmux to print the newly created pane id, matching\n // real tmux's split-window behavior (see splitPaneBesideSidebar).\n if (args.includes(\"-P\") && args.includes(\"#{pane_id}\")) {\n return newPaneId\n }\n }\n\n return \"\"\n }\n\n return {\n execute,\n async executeMany(commandsList: string[][]): Promise<void> {\n for (const args of commandsList) {\n await execute(args)\n }\n },\n isDryRun(): boolean {\n return true\n },\n logCommand(): void {\n // noop\n },\n getExecutedCommands(): string[][] {\n return executedCommands\n },\n clearExecutedCommands(): void {\n executedCommands = []\n },\n setMockPaneIds(paneIds: string[]): void {\n mockPaneIds = [...paneIds]\n },\n getPaneIds(): string[] {\n return mockPaneIds\n },\n setMockProtectedPaneIds(paneIds: string[]): void {\n mockProtectedPaneIds = [...paneIds]\n },\n isInTmuxSession,\n async verifyTmuxEnvironment(): Promise<void> {\n if (!isInTmuxSession()) {\n throw createEnvironmentError(\"Must be run inside a tmux session\", ErrorCodes.NOT_IN_TMUX_SESSION, {\n hint: \"Please start a tmux session and try again\",\n })\n }\n },\n getCommandString: toCommandString,\n async getCurrentSessionName(): Promise<string> {\n return \"mock-session\"\n },\n }\n}\n","import { execa } from \"execa\"\nimport { createEnvironmentError, ErrorCodes } from \"../../utils/errors\"\nimport type { TmuxExecutorContract } from \"../../contracts\"\nimport type { CommandExecutor } from \"../../contracts\"\nimport { createRealExecutor, createDryRunExecutor, createMockExecutor } from \"../../executor/index\"\n\ntype TmuxExecutorOptions = {\n readonly verbose?: boolean\n readonly dryRun?: boolean\n readonly executor?: CommandExecutor\n}\n\nexport type TmuxExecutor = TmuxExecutorContract & {\n readonly getExecutor: () => CommandExecutor\n}\n\nexport const createTmuxExecutor = (options: TmuxExecutorOptions = {}): TmuxExecutor => {\n const executor = resolveExecutor(options)\n\n const isInTmuxSession = (): boolean => {\n return Boolean(process.env.TMUX)\n }\n\n const verifyTmuxEnvironment = async (): Promise<void> => {\n if (!isInTmuxSession()) {\n throw createEnvironmentError(\"Must be run inside a tmux session\", ErrorCodes.NOT_IN_TMUX_SESSION, {\n hint: \"Please start a tmux session and try again\",\n })\n }\n\n if (executor.isDryRun()) {\n return\n }\n\n try {\n await execa(\"tmux\", [\"-V\"])\n } catch (_error) {\n throw createEnvironmentError(\"tmux is not installed\", ErrorCodes.TMUX_NOT_FOUND, {\n hint: \"Please install tmux\",\n })\n }\n }\n\n const execute = async (commandOrArgs: string | string[]): Promise<string> => {\n return executor.execute(commandOrArgs)\n }\n\n const executeMany = async (commandsList: string[][]): Promise<void> => {\n for (const command of commandsList) {\n await execute(command)\n }\n }\n\n const getCommandString = (args: string[]): string => {\n return [\"tmux\", ...args].join(\" \")\n }\n\n const getCurrentSessionName = async (): Promise<string> => {\n return execute([\"display-message\", \"-p\", \"#{session_name}\"])\n }\n\n return {\n verifyTmuxEnvironment,\n execute,\n executeMany,\n isInTmuxSession,\n getCurrentSessionName,\n getCommandString,\n getExecutor: () => executor,\n }\n}\n\nconst resolveExecutor = (options: TmuxExecutorOptions): CommandExecutor => {\n if (options.executor) {\n return options.executor\n }\n\n if (options.dryRun === true) {\n return createDryRunExecutor({ verbose: options.verbose })\n }\n\n if (isTestEnvironment()) {\n return createMockExecutor()\n }\n\n return createRealExecutor({ verbose: options.verbose })\n}\n\nconst isTestEnvironment = (): boolean => {\n return process.env.VDE_TEST_MODE === \"true\" || process.env.NODE_ENV === \"test\" || process.env.VITEST === \"true\"\n}\n","export const waitForDelay = (ms: number): Promise<void> => {\n return new Promise<void>((resolve) => {\n setTimeout(resolve, ms)\n })\n}\n","export const resolvePaneMapping = (paneMap: Map<string, string>, virtualId: string): string | undefined => {\n const direct = paneMap.get(virtualId)\n if (typeof direct === \"string\" && direct.length > 0) {\n return direct\n }\n\n let ancestor = virtualId\n while (ancestor.includes(\".\")) {\n ancestor = ancestor.slice(0, ancestor.lastIndexOf(\".\"))\n const candidate = paneMap.get(ancestor)\n if (typeof candidate === \"string\" && candidate.length > 0) {\n paneMap.set(virtualId, candidate)\n return candidate\n }\n }\n\n for (const [key, value] of paneMap.entries()) {\n if (key.startsWith(`${virtualId}.`)) {\n if (typeof value === \"string\" && value.length > 0) {\n paneMap.set(virtualId, value)\n return value\n }\n }\n }\n\n return undefined\n}\n","import type { CommandStep, SplitSizing } from \"../core/emitter\"\nimport { createCoreError } from \"../core/errors\"\nimport { ErrorCodes } from \"../utils/errors\"\n\ntype SplitOrientation = \"horizontal\" | \"vertical\"\ntype SplitCommandStep = CommandStep & { readonly kind: \"split\" }\n\nexport type SplitSizeResolutionContext = {\n readonly paneCells?: number\n readonly paneId?: string\n readonly requiredVersion?: string\n readonly detectedVersion?: string\n readonly rawPaneRecord?: Readonly<Record<string, unknown>>\n}\n\nexport type ResolvedSplitSize =\n | {\n readonly mode: \"percent\"\n readonly percentage: string\n }\n | {\n readonly mode: \"cells\"\n readonly cells: string\n readonly targetCells: number\n readonly createdCells: number\n }\n\nconst asSplitStep = (step: CommandStep, field: \"orientation\" | \"percentage\" | \"sizing\"): SplitCommandStep => {\n if (step.kind !== \"split\") {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.INVALID_PLAN,\n message: `Non-split step cannot resolve split ${field}`,\n path: step.id,\n details: { kind: step.kind },\n })\n }\n return step as SplitCommandStep\n}\n\nexport const resolveSplitOrientation = (step: CommandStep): SplitOrientation => {\n const splitStep = asSplitStep(step, \"orientation\")\n\n if (splitStep.orientation === \"horizontal\" || splitStep.orientation === \"vertical\") {\n return splitStep.orientation\n }\n\n throw createCoreError(\"execution\", {\n code: ErrorCodes.INVALID_PLAN,\n message: \"Split step missing orientation metadata\",\n path: splitStep.id,\n details: { orientation: splitStep.orientation },\n })\n}\n\nconst resolveLegacySplitSizing = (step: SplitCommandStep): SplitSizing | undefined => {\n if (typeof step.percentage === \"number\" && Number.isFinite(step.percentage)) {\n return {\n mode: \"percent\",\n percentage: step.percentage,\n }\n }\n return undefined\n}\n\nconst resolveSplitSizingMetadata = (step: SplitCommandStep): SplitSizing | undefined => {\n if (step.splitSizing !== undefined) {\n return step.splitSizing\n }\n return resolveLegacySplitSizing(step)\n}\n\nexport const resolveSplitSize = (step: CommandStep, context: SplitSizeResolutionContext = {}): ResolvedSplitSize => {\n const splitStep = asSplitStep(step, \"sizing\")\n const splitSizing = resolveSplitSizingMetadata(splitStep)\n\n if (splitSizing === undefined) {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.INVALID_PLAN,\n message: \"Split step missing sizing metadata\",\n path: splitStep.id,\n details: {\n splitSizing: splitStep.splitSizing,\n percentage: splitStep.percentage,\n },\n })\n }\n\n if (splitSizing.mode === \"percent\") {\n if (Number.isFinite(splitSizing.percentage)) {\n return {\n mode: \"percent\",\n percentage: String(clampSplitPercentage(splitSizing.percentage)),\n }\n }\n\n throw createCoreError(\"execution\", {\n code: ErrorCodes.INVALID_PLAN,\n message: \"Split step missing percentage metadata\",\n path: splitStep.id,\n details: { percentage: splitSizing.percentage },\n })\n }\n\n const dynamic = splitSizing\n const resolvedPaneCells = context.paneCells\n if (typeof resolvedPaneCells !== \"number\" || !Number.isInteger(resolvedPaneCells) || resolvedPaneCells <= 0) {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.SPLIT_SIZE_RESOLUTION_FAILED,\n message: \"Pane size is unavailable for dynamic split sizing\",\n path: splitStep.id,\n details: buildDynamicResolutionDetails(splitStep, dynamic, context),\n })\n }\n\n const { remainingFixedCells, remainingWeight, remainingWeightPaneCount, target } = dynamic\n if (\n !Number.isInteger(remainingFixedCells) ||\n remainingFixedCells < 0 ||\n !Number.isFinite(remainingWeight) ||\n remainingWeight < 0 ||\n !Number.isInteger(remainingWeightPaneCount) ||\n remainingWeightPaneCount < 0\n ) {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.INVALID_PLAN,\n message: \"Split step has invalid dynamic sizing metadata\",\n path: splitStep.id,\n details: buildDynamicResolutionDetails(splitStep, dynamic, context),\n })\n }\n\n const minTargetCells = target.kind === \"fixed-cells\" ? target.cells : 1\n // Together with minTargetCells, minCreatedCells reserves remainingFixedCells + remainingWeightPaneCount.\n const minCreatedCells = remainingFixedCells + remainingWeightPaneCount\n\n if (\n !Number.isInteger(minTargetCells) ||\n minTargetCells <= 0 ||\n !Number.isInteger(minCreatedCells) ||\n minCreatedCells < 0\n ) {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.INVALID_PLAN,\n message: \"Split step has invalid minimum-cell constraints\",\n path: splitStep.id,\n details: buildDynamicResolutionDetails(splitStep, dynamic, context),\n })\n }\n\n if (resolvedPaneCells < minTargetCells + minCreatedCells) {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.SPLIT_SIZE_RESOLUTION_FAILED,\n message: \"Pane is too small for requested fixed and weighted splits\",\n path: splitStep.id,\n details: buildDynamicResolutionDetails(splitStep, dynamic, context),\n })\n }\n\n let targetCells: number\n if (target.kind === \"fixed-cells\") {\n targetCells = target.cells\n } else {\n if (!Number.isFinite(target.weight) || target.weight <= 0) {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.INVALID_PLAN,\n message: \"Split step has invalid weight metadata\",\n path: splitStep.id,\n details: buildDynamicResolutionDetails(splitStep, dynamic, context),\n })\n }\n\n const availableForWeights = resolvedPaneCells - remainingFixedCells\n const weightTotal = target.weight + remainingWeight\n if (!Number.isFinite(weightTotal) || weightTotal <= 0) {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.INVALID_PLAN,\n message: \"Split step has invalid dynamic weight totals\",\n path: splitStep.id,\n details: buildDynamicResolutionDetails(splitStep, dynamic, context),\n })\n }\n\n const rawTarget = Math.round((availableForWeights * target.weight) / weightTotal)\n const maxTargetCells = resolvedPaneCells - minCreatedCells\n targetCells = clamp(rawTarget, minTargetCells, maxTargetCells)\n }\n\n const createdCells = resolvedPaneCells - targetCells\n\n if (targetCells < minTargetCells || createdCells < minCreatedCells || targetCells <= 0 || createdCells <= 0) {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.SPLIT_SIZE_RESOLUTION_FAILED,\n message: \"Unable to resolve split size without violating pane minimums\",\n path: splitStep.id,\n details: buildDynamicResolutionDetails(splitStep, dynamic, context, {\n targetCells,\n createdCells,\n }),\n })\n }\n\n return {\n mode: \"cells\",\n cells: String(createdCells),\n targetCells,\n createdCells,\n }\n}\n\nexport const resolveSplitPercentage = (step: CommandStep): string => {\n const splitStep = asSplitStep(step, \"percentage\")\n const splitSizing = resolveSplitSizingMetadata(splitStep)\n if (splitSizing?.mode === \"dynamic-cells\") {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.INVALID_PLAN,\n message: \"Split step uses dynamic sizing and has no percentage value\",\n path: splitStep.id,\n details: { splitSizing: splitStep.splitSizing },\n })\n }\n\n const resolved = resolveSplitSize(step)\n if (resolved.mode === \"percent\") {\n return resolved.percentage\n }\n\n throw createCoreError(\"execution\", {\n code: ErrorCodes.INVALID_PLAN,\n message: \"Split step uses dynamic sizing and has no percentage value\",\n path: splitStep.id,\n details: { splitSizing: splitStep.splitSizing },\n })\n}\n\nconst clampSplitPercentage = (value: number): number => {\n return Math.min(99, Math.max(1, Math.round(value)))\n}\n\nconst clamp = (value: number, min: number, max: number): number => {\n return Math.min(max, Math.max(min, value))\n}\n\nconst buildDynamicResolutionDetails = (\n splitStep: SplitCommandStep,\n splitSizing: Extract<SplitSizing, { mode: \"dynamic-cells\" }>,\n context: SplitSizeResolutionContext,\n extra: Readonly<Record<string, unknown>> = {},\n): Readonly<Record<string, unknown>> => {\n return {\n stepId: splitStep.id,\n paneId: context.paneId,\n paneCells: context.paneCells,\n targetSpec: splitSizing.target,\n remainingFixedCells: splitSizing.remainingFixedCells,\n remainingWeight: splitSizing.remainingWeight,\n remainingWeightPaneCount: splitSizing.remainingWeightPaneCount,\n requiredVersion: context.requiredVersion,\n detectedVersion: context.detectedVersion,\n rawPaneRecord: context.rawPaneRecord,\n ...extra,\n }\n}\n","import type { EmittedTerminal } from \"../core/emitter\"\n\n/**\n * Template token types supported in pane commands:\n * - {{pane_id:<name>}} - resolves to a specific pane's ID by name\n * - {{this_pane}} - references the current pane receiving the command\n * - {{focus_pane}} - references the intended focus pane\n * - {{window_id}} - references the real window ID the layout was applied into\n * (e.g. tmux's `@5`). Only resolved by callers that supply `windowId`\n * (currently hooks.afterApply); callers that omit it - e.g. pane\n * `command:` preparation - get a TemplateTokenError if the token is used,\n * the same as an unresolved {{pane_id:<name>}}.\n */\n\ntype ReplaceTemplateTokensInput = {\n readonly command: string\n readonly currentPaneRealId: string\n readonly focusPaneRealId: string\n readonly nameToRealIdMap: ReadonlyMap<string, string>\n readonly windowId?: string\n}\n\nexport type TemplateTokenError = Error & {\n readonly tokenType: string\n readonly availablePanes?: ReadonlyArray<string>\n}\n\ntype TemplateTokenErrorConstructor = {\n new (message: string, tokenType: string, availablePanes?: ReadonlyArray<string>): TemplateTokenError\n (message: string, tokenType: string, availablePanes?: ReadonlyArray<string>): TemplateTokenError\n readonly prototype: TemplateTokenError\n}\n\nconst TemplateTokenErrorImpl = function TemplateTokenError(\n message: string,\n tokenType: string,\n availablePanes?: ReadonlyArray<string>,\n): TemplateTokenError {\n type MutableTemplateTokenError = Error & { tokenType: string; availablePanes?: ReadonlyArray<string> }\n const error = new Error(message) as MutableTemplateTokenError\n Object.setPrototypeOf(error, TemplateTokenErrorImpl.prototype)\n error.name = \"TemplateTokenError\"\n error.tokenType = tokenType\n error.availablePanes = availablePanes\n return error as TemplateTokenError\n}\n\nTemplateTokenErrorImpl.prototype = Object.create(Error.prototype)\nTemplateTokenErrorImpl.prototype.constructor = TemplateTokenErrorImpl\n\nexport const TemplateTokenError = TemplateTokenErrorImpl as TemplateTokenErrorConstructor\n\n/**\n * Replaces template tokens in a command string with actual pane IDs.\n *\n * Uses a single-pass regex replacement to avoid nested token issues.\n * All tokens are replaced in a single pass, preventing already-replaced\n * values from being re-processed.\n *\n * @param input - Object containing the command and pane ID mappings\n * @returns The command string with all template tokens replaced\n * @throws TemplateTokenError if a referenced pane name is not found in the mapping,\n * or if {{window_id}} is used but no `windowId` was supplied\n */\nexport const replaceTemplateTokens = ({\n command,\n currentPaneRealId,\n focusPaneRealId,\n nameToRealIdMap,\n windowId,\n}: ReplaceTemplateTokensInput): string => {\n // Single-pass regex that matches all token types\n // This prevents nested token issues by replacing everything in one pass\n const tokenPattern = /\\{\\{(this_pane|focus_pane|window_id|pane_id:([^}]+))\\}\\}/g\n\n return command.replace(tokenPattern, (match, tokenContent: string, paneName?: string) => {\n if (tokenContent === \"this_pane\") {\n return currentPaneRealId\n }\n\n if (tokenContent === \"focus_pane\") {\n return focusPaneRealId\n }\n\n if (tokenContent === \"window_id\") {\n if (windowId === undefined) {\n throw new TemplateTokenError(\n \"Window ID is not available. {{window_id}} can only be resolved in hooks.afterApply.\",\n \"window_id\",\n )\n }\n return windowId\n }\n\n // Must be pane_id:<name> token\n if (tokenContent.startsWith(\"pane_id:\") && paneName !== undefined) {\n const trimmedName = paneName.trim()\n const paneId = nameToRealIdMap.get(trimmedName)\n\n if (paneId === undefined) {\n throw new TemplateTokenError(\n `Pane name \"${trimmedName}\" not found. Available panes: ${Array.from(nameToRealIdMap.keys()).join(\", \")}`,\n \"pane_id\",\n Array.from(nameToRealIdMap.keys()),\n )\n }\n\n return paneId\n }\n\n // Fallback: return original match if token is malformed\n return match\n })\n}\n\n/**\n * Builds a mapping from pane names to real pane IDs.\n *\n * **Duplicate Name Handling:**\n * If multiple panes share the same name, the last one in the terminals\n * array wins. This follows the iteration order of the layout tree.\n * It's recommended to use unique names for panes to avoid ambiguity\n * in template token references.\n *\n * **Virtual to Real ID Resolution:**\n * Only panes with successfully resolved real IDs (present in paneMap)\n * are included in the resulting map. This ensures that template tokens\n * only reference panes that have been properly created.\n *\n * @param terminals - Array of emitted terminals from the layout plan\n * @param paneMap - Map from virtual pane IDs to real pane IDs (backend-specific)\n * @returns A map from pane names to real pane IDs\n */\nexport const buildNameToRealIdMap = (\n terminals: ReadonlyArray<EmittedTerminal>,\n paneMap: ReadonlyMap<string, string>,\n): Map<string, string> => {\n const nameToRealIdMap = new Map<string, string>()\n\n for (const terminal of terminals) {\n const realId = paneMap.get(terminal.virtualPaneId)\n if (realId !== undefined) {\n nameToRealIdMap.set(terminal.name, realId)\n }\n }\n\n return nameToRealIdMap\n}\n","import type { EmittedTerminal } from \"../core/emitter\"\nimport { buildNameToRealIdMap, replaceTemplateTokens, TemplateTokenError } from \"../utils/template-tokens\"\n\ntype TemplateTokenErrorContext = {\n readonly terminal: EmittedTerminal\n readonly error: TemplateTokenError\n}\n\ntype PrepareTerminalCommandsInput = {\n readonly terminals: ReadonlyArray<EmittedTerminal>\n readonly focusPaneVirtualId: string\n readonly resolveRealPaneId: (virtualPaneId: string) => string\n readonly onTemplateTokenError: (context: TemplateTokenErrorContext) => never\n}\n\ntype PreparedTerminalCommand = {\n readonly terminal: EmittedTerminal\n readonly realPaneId: string\n readonly cwdCommand?: string\n readonly envCommands: ReadonlyArray<{\n readonly key: string\n readonly command: string\n }>\n readonly title?: string\n readonly command?: {\n readonly text: string\n readonly delayMs: number\n }\n}\n\ntype PreparedTerminalCommands = {\n readonly focusPaneRealId: string\n readonly commands: ReadonlyArray<PreparedTerminalCommand>\n}\n\nconst SINGLE_QUOTE = \"'\"\nconst SHELL_SINGLE_QUOTE_ESCAPE = `'\"'\"'`\nconst ENV_KEY_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/\n\nconst shellQuoteLiteral = (value: string): string => {\n return `'${value.split(SINGLE_QUOTE).join(SHELL_SINGLE_QUOTE_ESCAPE)}'`\n}\n\nconst assertValidEnvKey = (key: string): void => {\n if (!ENV_KEY_PATTERN.test(key)) {\n throw new Error(`Invalid environment variable name: ${key}`)\n }\n}\n\nconst normalizeDelay = (delay: unknown): number => {\n return typeof delay === \"number\" && Number.isFinite(delay) && delay > 0 ? delay : 0\n}\n\nconst applyEphemeralSuffix = (command: string, terminal: EmittedTerminal): string => {\n if (terminal.ephemeral !== true) {\n return command\n }\n\n return terminal.closeOnError === true ? `${command}; exit` : `${command}; [ $? -eq 0 ] && exit`\n}\n\nexport const prepareTerminalCommands = ({\n terminals,\n focusPaneVirtualId,\n resolveRealPaneId,\n onTemplateTokenError,\n}: PrepareTerminalCommandsInput): PreparedTerminalCommands => {\n const paneMap = new Map<string, string>()\n for (const terminal of terminals) {\n paneMap.set(terminal.virtualPaneId, resolveRealPaneId(terminal.virtualPaneId))\n }\n\n const focusPaneRealId = paneMap.get(focusPaneVirtualId) ?? resolveRealPaneId(focusPaneVirtualId)\n const nameToRealIdMap = buildNameToRealIdMap(terminals, paneMap)\n\n const commands: PreparedTerminalCommand[] = terminals.map((terminal) => {\n const realPaneId = paneMap.get(terminal.virtualPaneId)\n if (realPaneId === undefined) {\n throw new Error(`Unknown pane: ${terminal.virtualPaneId}`)\n }\n\n const cwdCommand =\n typeof terminal.cwd === \"string\" && terminal.cwd.length > 0\n ? `cd -- ${shellQuoteLiteral(terminal.cwd)}`\n : undefined\n\n const envCommands =\n terminal.env === undefined\n ? []\n : Object.entries(terminal.env).map(([key, value]) => {\n assertValidEnvKey(key)\n return {\n key,\n command: `export ${key}=${shellQuoteLiteral(String(value))}`,\n }\n })\n\n const title = typeof terminal.title === \"string\" && terminal.title.length > 0 ? terminal.title : undefined\n\n let command:\n | {\n readonly text: string\n readonly delayMs: number\n }\n | undefined\n\n if (typeof terminal.command === \"string\" && terminal.command.length > 0) {\n try {\n const commandUsesFocusToken = terminal.command.includes(\"{{focus_pane}}\")\n const replaced = replaceTemplateTokens({\n command: terminal.command,\n currentPaneRealId: realPaneId,\n focusPaneRealId: commandUsesFocusToken ? focusPaneRealId : \"\",\n nameToRealIdMap,\n })\n\n command = {\n text: applyEphemeralSuffix(replaced, terminal),\n delayMs: normalizeDelay(terminal.delay),\n }\n } catch (error) {\n if (error instanceof TemplateTokenError) {\n return onTemplateTokenError({ terminal, error })\n }\n throw error\n }\n }\n\n return {\n terminal,\n realPaneId,\n cwdCommand,\n envCommands,\n title,\n command,\n }\n })\n\n return {\n focusPaneRealId,\n commands,\n }\n}\n","import type { CommandStep, EmittedTerminal } from \"../core/emitter\"\nimport { createCoreError } from \"../core/errors\"\nimport type { CommandExecutor } from \"../contracts\"\nimport { waitForDelay } from \"../utils/async\"\nimport { ErrorCodes } from \"../utils/errors\"\nimport { resolvePaneMapping } from \"../utils/pane-map\"\nimport { resolveSplitOrientation, resolveSplitSize } from \"./split-step\"\nimport { prepareTerminalCommands } from \"./terminal-command-preparation\"\n\nexport const executeSplitStep = async ({\n step,\n executor,\n paneMap,\n detectedVersion,\n}: {\n readonly step: CommandStep\n readonly executor: CommandExecutor\n readonly paneMap: Map<string, string>\n readonly detectedVersion?: string\n}): Promise<void> => {\n const targetVirtualId = ensureNonEmpty(step.targetPaneId, () =>\n raiseExecutionError(ErrorCodes.MISSING_TARGET, {\n message: \"Split step missing target pane metadata\",\n path: step.id,\n }),\n )\n\n const targetRealId = ensureNonEmpty(resolvePaneId(paneMap, targetVirtualId), () =>\n raiseExecutionError(ErrorCodes.INVALID_PANE, {\n message: `Unknown target pane: ${targetVirtualId}`,\n path: step.id,\n }),\n )\n\n const panesBefore = await listPaneIds(executor, step)\n const splitCommand = await buildSplitCommand({\n step,\n targetRealId,\n executor,\n detectedVersion,\n })\n await executeCommand(executor, splitCommand, {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: `Failed to execute split step ${step.id}`,\n path: step.id,\n details: { command: splitCommand },\n })\n\n const panesAfter = await listPaneIds(executor, step)\n const newPaneId = ensureNonEmpty(findNewPaneId(panesBefore, panesAfter), () =>\n raiseExecutionError(ErrorCodes.INVALID_PANE, {\n message: \"Unable to determine newly created pane\",\n path: step.id,\n }),\n )\n\n const createdVirtualId = step.createdPaneId\n if (typeof createdVirtualId === \"string\" && createdVirtualId.length > 0) {\n registerPane(paneMap, createdVirtualId, newPaneId)\n }\n}\n\nexport const executeFocusStep = async ({\n step,\n executor,\n paneMap,\n}: {\n readonly step: CommandStep\n readonly executor: CommandExecutor\n readonly paneMap: Map<string, string>\n}): Promise<void> => {\n const targetVirtualId = ensureNonEmpty(step.targetPaneId, () =>\n raiseExecutionError(ErrorCodes.MISSING_TARGET, {\n message: \"Focus step missing target pane metadata\",\n path: step.id,\n }),\n )\n\n const targetRealId = ensureNonEmpty(resolvePaneId(paneMap, targetVirtualId), () =>\n raiseExecutionError(ErrorCodes.INVALID_PANE, {\n message: `Unknown focus pane: ${targetVirtualId}`,\n path: step.id,\n }),\n )\n\n const command = buildFocusCommand(targetRealId)\n await executeCommand(executor, command, {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: `Failed to execute focus step ${step.id}`,\n path: step.id,\n details: { command },\n })\n}\n\nexport const executeTerminalCommands = async ({\n terminals,\n executor,\n paneMap,\n focusPaneVirtualId,\n}: {\n readonly terminals: ReadonlyArray<EmittedTerminal>\n readonly executor: CommandExecutor\n readonly paneMap: Map<string, string>\n readonly focusPaneVirtualId: string\n}): Promise<void> => {\n if (!paneMap.has(focusPaneVirtualId)) {\n raiseExecutionError(ErrorCodes.INVALID_PANE, {\n message: `Unknown focus pane: ${focusPaneVirtualId}`,\n path: focusPaneVirtualId,\n })\n }\n ensureNonEmpty(resolvePaneId(paneMap, focusPaneVirtualId), () =>\n raiseExecutionError(ErrorCodes.INVALID_PANE, {\n message: `Unknown focus pane: ${focusPaneVirtualId}`,\n path: focusPaneVirtualId,\n }),\n )\n\n const resolveRealPaneId = (virtualPaneId: string): string => {\n return ensureNonEmpty(resolvePaneId(paneMap, virtualPaneId), () =>\n raiseExecutionError(ErrorCodes.INVALID_PANE, {\n message: `Unknown terminal pane: ${virtualPaneId}`,\n path: virtualPaneId,\n }),\n )\n }\n\n const prepared = prepareTerminalCommands({\n terminals,\n focusPaneVirtualId,\n resolveRealPaneId,\n onTemplateTokenError: ({ terminal, error }): never => {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.TEMPLATE_TOKEN_ERROR,\n message: `Template token resolution failed for pane ${terminal.virtualPaneId}: ${error.message}`,\n path: terminal.virtualPaneId,\n details: {\n command: terminal.command,\n tokenType: error.tokenType,\n availablePanes: error.availablePanes,\n },\n })\n },\n })\n\n for (const commandSet of prepared.commands) {\n const { terminal, realPaneId } = commandSet\n\n if (typeof commandSet.cwdCommand === \"string\") {\n await executeCommand(executor, [\"send-keys\", \"-t\", realPaneId, commandSet.cwdCommand, \"Enter\"], {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: `Failed to change directory for pane ${terminal.virtualPaneId}`,\n path: terminal.virtualPaneId,\n details: { cwd: terminal.cwd },\n })\n }\n\n for (const envEntry of commandSet.envCommands) {\n await executeCommand(executor, [\"send-keys\", \"-t\", realPaneId, envEntry.command, \"Enter\"], {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: `Failed to set environment variable ${envEntry.key}`,\n path: terminal.virtualPaneId,\n })\n }\n\n if (typeof commandSet.title === \"string\") {\n await executeCommand(executor, [\"select-pane\", \"-t\", realPaneId, \"-T\", commandSet.title], {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: `Failed to set pane title for pane ${terminal.virtualPaneId}`,\n path: terminal.virtualPaneId,\n details: { title: commandSet.title },\n })\n }\n\n if (commandSet.command !== undefined) {\n if (commandSet.command.delayMs > 0) {\n await waitForDelay(commandSet.command.delayMs)\n }\n\n await executeCommand(executor, [\"send-keys\", \"-t\", realPaneId, commandSet.command.text, \"Enter\"], {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: `Failed to execute command for pane ${terminal.virtualPaneId}`,\n path: terminal.virtualPaneId,\n details: { command: terminal.command },\n })\n }\n }\n}\n\nexport const executeCommand = async (\n executor: CommandExecutor,\n command: string[],\n context: {\n readonly code: string\n readonly message: string\n readonly path: string\n readonly details?: Record<string, unknown>\n },\n): Promise<string> => {\n try {\n return await executor.execute([...command])\n } catch (error) {\n if (error instanceof Error && \"code\" in error && \"message\" in error) {\n const candidate = error as { code?: string; message?: string; details?: Record<string, unknown> }\n throw createCoreError(\"execution\", {\n code: typeof candidate.code === \"string\" ? candidate.code : context.code,\n message: candidate.message ?? context.message,\n path: context.path,\n details: candidate.details ?? context.details,\n })\n }\n\n throw createCoreError(\"execution\", {\n code: context.code,\n message: context.message,\n path: context.path,\n details: context.details,\n })\n }\n}\n\nexport const resolveCurrentPaneId = async ({\n executor,\n contextPath,\n isDryRun,\n}: {\n executor: CommandExecutor\n contextPath: string\n isDryRun: boolean\n}): Promise<string> => {\n const envPaneId = process.env.TMUX_PANE\n if (typeof envPaneId === \"string\" && envPaneId.trim().length > 0) {\n return normalizePaneId(envPaneId)\n }\n\n if (isDryRun) {\n return \"%0\"\n }\n\n const output = await executeCommand(executor, [\"display-message\", \"-p\", \"#{pane_id}\"], {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: \"Failed to resolve current tmux pane\",\n path: contextPath,\n })\n\n const paneId = output.trim()\n if (paneId.length === 0) {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.NOT_IN_TMUX_SESSION,\n message: \"Unable to determine current tmux pane\",\n path: contextPath,\n })\n }\n\n return normalizePaneId(paneId)\n}\n\nexport const listWindowPaneIds = async (executor: CommandExecutor, contextPath: string): Promise<string[]> => {\n const output = await executeCommand(executor, [\"list-panes\", \"-F\", \"#{pane_id}\"], {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: \"Failed to list tmux panes\",\n path: contextPath,\n })\n\n return output\n .split(\"\\n\")\n .map((pane) => pane.trim())\n .filter((pane) => pane.length > 0)\n}\n\nconst listPaneIds = async (executor: CommandExecutor, step: CommandStep): Promise<string[]> => {\n return listWindowPaneIds(executor, step.id)\n}\n\nconst findNewPaneId = (before: string[], after: string[]): string | undefined => {\n const beforeSet = new Set(before)\n return after.find((id) => !beforeSet.has(id))\n}\n\nconst buildSplitCommand = async ({\n step,\n targetRealId,\n executor,\n detectedVersion,\n}: {\n readonly step: CommandStep\n readonly targetRealId: string\n readonly executor: CommandExecutor\n readonly detectedVersion?: string\n}): Promise<string[]> => {\n const orientation = resolveSplitOrientation(step)\n const directionFlag = orientation === \"horizontal\" ? \"-h\" : \"-v\"\n if (isDynamicSplit(step)) {\n const paneCells = await resolveTmuxPaneCells({\n executor,\n step,\n targetRealId,\n orientation,\n detectedVersion,\n })\n const splitSize = resolveSplitSize(step, {\n paneCells,\n paneId: targetRealId,\n detectedVersion,\n rawPaneRecord: {\n backend: \"tmux\",\n paneId: targetRealId,\n sourceFormat: \"tmux-format\",\n },\n })\n if (splitSize.mode === \"cells\") {\n return [\"split-window\", directionFlag, \"-t\", targetRealId, \"-l\", splitSize.cells]\n }\n return raiseExecutionError(ErrorCodes.INVALID_PLAN, {\n message: \"Dynamic split resolved to a non-cell sizing mode\",\n path: step.id,\n details: { splitSize },\n })\n }\n\n const splitSize = resolveSplitSize(step, {\n paneId: targetRealId,\n detectedVersion,\n })\n if (splitSize.mode === \"percent\") {\n return [\"split-window\", directionFlag, \"-t\", targetRealId, \"-p\", splitSize.percentage]\n }\n return raiseExecutionError(ErrorCodes.INVALID_PLAN, {\n message: \"Percent split resolved to a non-percent sizing mode\",\n path: step.id,\n details: { splitSize },\n })\n}\n\nconst buildFocusCommand = (targetRealId: string): string[] => {\n return [\"select-pane\", \"-t\", targetRealId]\n}\n\nexport const normalizePaneId = (raw: string): string => {\n const trimmed = raw.trim()\n return trimmed.length === 0 ? \"%0\" : trimmed\n}\n\nexport const registerPane = (paneMap: Map<string, string>, virtualId: string, realId: string): void => {\n paneMap.set(virtualId, realId)\n}\n\nexport const resolvePaneId = (paneMap: Map<string, string>, virtualId: string): string | undefined => {\n return resolvePaneMapping(paneMap, virtualId)\n}\n\nconst resolveTmuxPaneCells = async ({\n executor,\n step,\n targetRealId,\n orientation,\n detectedVersion,\n}: {\n readonly executor: CommandExecutor\n readonly step: CommandStep\n readonly targetRealId: string\n readonly orientation: \"horizontal\" | \"vertical\"\n readonly detectedVersion?: string\n}): Promise<number> => {\n const format = orientation === \"horizontal\" ? \"#{pane_width}\" : \"#{pane_height}\"\n const output = await executeCommand(executor, [\"display-message\", \"-p\", \"-t\", targetRealId, format], {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: \"Failed to resolve tmux pane size\",\n path: step.id,\n details: { command: [\"display-message\", \"-p\", \"-t\", targetRealId, format] },\n })\n const value = Number.parseInt(output.trim(), 10)\n if (!Number.isInteger(value) || value <= 0) {\n raiseExecutionError(ErrorCodes.SPLIT_SIZE_RESOLUTION_FAILED, {\n message: \"Unable to parse tmux pane size\",\n path: step.id,\n details: {\n paneId: targetRealId,\n orientation,\n output,\n detectedVersion,\n },\n })\n }\n return value\n}\n\nconst isDynamicSplit = (step: CommandStep): boolean => {\n return step.kind === \"split\" && step.splitSizing?.mode === \"dynamic-cells\"\n}\n\nconst ensureNonEmpty = <T extends string>(value: T | undefined, buildError: () => never): T => {\n if (value === undefined || value.length === 0) {\n return buildError()\n }\n return value\n}\n\nexport const raiseExecutionError = (\n code: string,\n error: {\n readonly message: string\n readonly path: string\n readonly details?: Record<string, unknown>\n },\n): never => {\n throw createCoreError(\"execution\", {\n code,\n message: error.message,\n path: error.path,\n details: error.details,\n })\n}\n","// Sidebar pane detection.\n//\n// vde-tmux-sidebar marks its own pane by setting the tmux pane user option\n// `@vde_sidebar` to `1`. Verified against real tmux 3.7b that a single\n// `list-panes -F \"#{pane_id}\\t#{@vde_sidebar}\"` query expands both the pane\n// id and the pane user option value in one call: panes with the option set\n// return `1`, panes without it return an empty string. No per-pane\n// `show-options -pqv -t <pane> @vde_sidebar` fallback is needed.\nimport type { CommandExecutor } from \"../contracts\"\nimport { executeCommand } from \"./plan-runner-helpers\"\nimport { ErrorCodes } from \"../utils/errors\"\n\nexport const SIDEBAR_LIST_PANES_FORMAT = \"#{pane_id}\\t#{@vde_sidebar}\"\n\nexport type ClassifyWindowPanesResult = {\n readonly sidebarPanes: string[]\n readonly normalPanes: string[]\n}\n\nexport const classifyWindowPanes = async (\n executor: CommandExecutor,\n contextPath: string,\n targetPaneId?: string,\n): Promise<ClassifyWindowPanesResult> => {\n // `-t <pane-id>` scopes `list-panes` to the window that pane belongs to (tmux\n // resolves a pane id target to its containing window), so passing the current\n // pane id here guarantees the classification covers that pane's window even in\n // multi-window/multi-session setups where the \"active\" window might differ.\n const command =\n typeof targetPaneId === \"string\" && targetPaneId.length > 0\n ? [\"list-panes\", \"-t\", targetPaneId, \"-F\", SIDEBAR_LIST_PANES_FORMAT]\n : [\"list-panes\", \"-F\", SIDEBAR_LIST_PANES_FORMAT]\n\n const output = await executeCommand(executor, command, {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: \"Failed to list tmux panes for sidebar detection\",\n path: contextPath,\n })\n\n const sidebarPanes: string[] = []\n const normalPanes: string[] = []\n\n for (const line of output.split(\"\\n\")) {\n const [paneId, sidebarFlag] = line.split(\"\\t\")\n if (typeof paneId !== \"string\" || paneId.trim().length === 0) {\n continue\n }\n\n if (sidebarFlag?.trim() === \"1\") {\n sidebarPanes.push(paneId.trim())\n } else {\n normalPanes.push(paneId.trim())\n }\n }\n\n return { sidebarPanes, normalPanes }\n}\n","import type { PlanEmission } from \"../core/emitter\"\nimport type { ConfirmPaneClosure } from \"../contracts\"\nimport type { CommandExecutor } from \"../contracts\"\nimport { ErrorCodes } from \"../utils/errors\"\nimport type { WindowMode } from \"../models/types\"\nimport { classifyWindowPanes } from \"./sidebar-detection\"\nimport {\n executeCommand,\n executeFocusStep,\n executeSplitStep,\n executeTerminalCommands,\n normalizePaneId,\n raiseExecutionError,\n registerPane,\n resolveCurrentPaneId,\n resolvePaneId,\n} from \"./plan-runner-helpers\"\n\ntype ExecutePlanInput = {\n readonly emission: PlanEmission\n readonly executor: CommandExecutor\n readonly windowName?: string\n readonly windowMode: WindowMode\n readonly onConfirmKill?: ConfirmPaneClosure\n readonly detectedVersion?: string\n}\n\ntype ExecutePlanSuccess = {\n readonly executedSteps: number\n readonly paneMap: ReadonlyMap<string, string>\n}\n\nexport const executePlan = async ({\n emission,\n executor,\n windowName,\n windowMode,\n onConfirmKill,\n detectedVersion,\n}: ExecutePlanInput): Promise<ExecutePlanSuccess> => {\n const initialVirtualPaneId = emission.summary.initialPaneId\n if (typeof initialVirtualPaneId !== \"string\" || initialVirtualPaneId.length === 0) {\n raiseExecutionError(ErrorCodes.INVALID_PLAN, {\n message: \"Plan emission is missing initial pane metadata\",\n path: \"plan.initialPaneId\",\n })\n }\n\n const paneMap = new Map<string, string>()\n\n const isDryRun = executor.isDryRun()\n\n let initialPaneId: string\n\n if (windowMode === \"current-window\") {\n const currentPaneId = await resolveCurrentPaneId({\n executor,\n contextPath: initialVirtualPaneId,\n isDryRun,\n })\n\n // Target the classification at the current pane's own window (via `-t\n // currentPaneId`) rather than tmux's \"active\" window, so multi-window/multi-session\n // setups always classify the window this invocation is actually running in.\n const { sidebarPanes, normalPanes } = await classifyWindowPanes(executor, initialVirtualPaneId, currentPaneId)\n const sidebarPaneIds = new Set(sidebarPanes)\n\n let originPaneId: string\n if (sidebarPaneIds.has(currentPaneId)) {\n // The resolved \"current pane\" is the protected sidebar pane itself. Rebuild the\n // layout starting from the first non-sidebar pane instead, splitting a fresh one\n // beside the sidebar when the window has no other panes to build on.\n const [firstNormalPane] = normalPanes\n originPaneId =\n firstNormalPane !== undefined\n ? firstNormalPane\n : await splitPaneBesideSidebar({\n executor,\n sidebarPaneId: currentPaneId,\n contextPath: initialVirtualPaneId,\n })\n } else {\n originPaneId = currentPaneId\n }\n\n const panesToClose = normalPanes.filter((paneId) => paneId !== originPaneId)\n\n if (panesToClose.length > 0) {\n let confirmed = true\n if (onConfirmKill !== undefined) {\n confirmed = await onConfirmKill({ panesToClose, dryRun: isDryRun })\n }\n\n if (confirmed !== true) {\n raiseExecutionError(ErrorCodes.USER_CANCELLED, {\n message: \"Aborted layout application for current window\",\n path: initialVirtualPaneId,\n details: { panes: panesToClose },\n })\n }\n\n // `kill-pane -a` would also kill protected sidebar panes in real tmux, so close\n // each non-sidebar pane individually instead of relying on the bulk flag.\n for (const paneId of panesToClose) {\n await executeCommand(executor, [\"kill-pane\", \"-t\", paneId], {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: \"Failed to close existing panes\",\n path: initialVirtualPaneId,\n details: { command: [\"kill-pane\", \"-t\", paneId] },\n })\n }\n }\n\n initialPaneId = normalizePaneId(originPaneId)\n } else {\n const newWindowCommand: string[] = [\"new-window\", \"-P\", \"-F\", \"#{pane_id}\"]\n if (typeof windowName === \"string\" && windowName.trim().length > 0) {\n newWindowCommand.push(\"-n\", windowName.trim())\n }\n\n const createdPane = await executeCommand(executor, newWindowCommand, {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: \"Failed to create tmux window\",\n path: initialVirtualPaneId,\n })\n initialPaneId = normalizePaneId(createdPane)\n }\n\n registerPane(paneMap, initialVirtualPaneId, initialPaneId)\n\n let executedSteps = 0\n\n for (const step of emission.steps) {\n if (step.kind === \"split\") {\n await executeSplitStep({ step, executor, paneMap, detectedVersion })\n executedSteps += 1\n } else if (step.kind === \"focus\") {\n await executeFocusStep({ step, executor, paneMap })\n executedSteps += 1\n } else {\n raiseExecutionError(ErrorCodes.INVALID_PLAN, {\n message: `Unsupported step kind in emission: ${String((step as { kind?: unknown }).kind)}`,\n path: step.id,\n })\n }\n }\n\n await executeTerminalCommands({\n terminals: emission.terminals,\n executor,\n paneMap,\n focusPaneVirtualId: emission.summary.focusPaneId,\n })\n\n const finalRealFocus = resolvePaneId(paneMap, emission.summary.focusPaneId)\n if (typeof finalRealFocus === \"string\" && finalRealFocus.length > 0) {\n await executeCommand(executor, [\"select-pane\", \"-t\", finalRealFocus], {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: \"Failed to restore focus\",\n path: emission.summary.focusPaneId,\n })\n }\n\n return { executedSteps, paneMap }\n}\n\n/**\n * Splits a fresh pane beside the sidebar so it can be used as the layout's origin\n * pane. Only reached when the current window contains nothing but sidebar panes\n * (no normal pane to reuse). The split direction is fixed to a horizontal split\n * away from the sidebar (i.e. the new pane appears on the opposite side).\n *\n * Uses `-P -F \"#{pane_id}\"` to have tmux report the newly created pane id directly\n * in the split-window output, rather than diffing a follow-up `list-panes` call\n * against the pre-split pane set (which was fragile under concurrent pane changes).\n */\nconst splitPaneBesideSidebar = async ({\n executor,\n sidebarPaneId,\n contextPath,\n}: {\n readonly executor: CommandExecutor\n readonly sidebarPaneId: string\n readonly contextPath: string\n}): Promise<string> => {\n const command = [\"split-window\", \"-h\", \"-P\", \"-F\", \"#{pane_id}\", \"-t\", sidebarPaneId]\n const output = await executeCommand(executor, command, {\n code: ErrorCodes.TMUX_COMMAND_FAILED,\n message: \"Failed to split a pane beside the sidebar\",\n path: contextPath,\n details: { command },\n })\n\n const newPaneId = output.trim()\n if (newPaneId.length === 0) {\n return raiseExecutionError(ErrorCodes.INVALID_PANE, {\n message: \"Unable to determine the pane created beside the sidebar\",\n path: contextPath,\n })\n }\n\n return newPaneId\n}\n","import type { CommandStep } from \"../core/emitter\"\nimport { createCoreError } from \"../core/errors\"\nimport { ErrorCodes } from \"../utils/errors\"\n\nconst getStepLabel = (step: CommandStep): string => {\n if (step.kind === \"split\") {\n return \"Split\"\n }\n if (step.kind === \"focus\") {\n return \"Focus\"\n }\n return \"Step\"\n}\n\nexport const resolveRequiredStepTargetPaneId = (step: CommandStep): string => {\n if (typeof step.targetPaneId === \"string\" && step.targetPaneId.length > 0) {\n return step.targetPaneId\n }\n\n throw createCoreError(\"execution\", {\n code: ErrorCodes.MISSING_TARGET,\n message: `${getStepLabel(step)} step missing target pane metadata`,\n path: step.id,\n })\n}\n","import { createCoreError } from \"../core/errors\"\nimport type { CoreError } from \"../core/errors\"\nimport { ErrorCodes } from \"../utils/errors\"\n\ntype UnsupportedStep = {\n readonly id: string\n readonly kind?: unknown\n}\n\nexport const createUnsupportedStepKindError = (step: UnsupportedStep): CoreError => {\n return createCoreError(\"execution\", {\n code: ErrorCodes.INVALID_PLAN,\n message: `Unsupported step kind in emission: ${String(step.kind)}`,\n path: step.id,\n })\n}\n","import { execFileSync } from \"node:child_process\"\nimport { type PaneDimensions, updatePaneSizes } from \"../pane-tracking\"\nimport { createTmuxExecutor, type TmuxExecutor } from \"./executor\"\nimport type { CommandStep, PlanEmission } from \"../../core/emitter\"\nimport { isCoreError } from \"../../core/errors\"\nimport { executePlan } from \"../../executor/plan-runner\"\nimport { SIDEBAR_LIST_PANES_FORMAT } from \"../../executor/sidebar-detection\"\nimport { resolveSplitOrientation as resolveSplitOrientationFromStep, resolveSplitSize } from \"../../executor/split-step\"\nimport { resolveRequiredStepTargetPaneId } from \"../../executor/step-target\"\nimport { createUnsupportedStepKindError } from \"../../executor/unsupported-step-kind\"\nimport { buildNameToRealIdMap } from \"../../utils/template-tokens\"\nimport type {\n ApplyPlanParameters,\n ApplyPlanResult,\n DryRunStep,\n TerminalBackend,\n TmuxTerminalBackendContext,\n} from \"../../executor/terminal-backend\"\nimport { ErrorCodes } from \"../../utils/errors\"\n\nconst TMUX_VERSION_REGEX = /^tmux\\s+(.+)$/\n\nexport const createTmuxBackend = (context: TmuxTerminalBackendContext): TerminalBackend => {\n const tmuxExecutor = createTmuxExecutor({\n executor: context.executor,\n verbose: context.verbose,\n dryRun: context.dryRun,\n })\n\n let detectedVersion: string | undefined\n\n const buildDryRunSteps = (emission: PlanEmission): DryRunStep[] => {\n const paneSizes = new Map<string, PaneDimensions>()\n const initialPane = emission.summary.initialPaneId\n const initialPaneSize = resolveInitialTmuxPaneSize()\n if (initialPaneSize !== undefined) {\n paneSizes.set(initialPane, initialPaneSize)\n }\n\n return emission.steps.map((step) => ({\n backend: \"tmux\" as const,\n summary: step.summary,\n command: tmuxExecutor.getCommandString(\n buildTmuxCommand({\n step,\n paneSizes,\n detectedVersion,\n }),\n ),\n }))\n }\n\n const verifyEnvironment = async (): Promise<void> => {\n if (context.dryRun) {\n return\n }\n await tmuxExecutor.verifyTmuxEnvironment()\n detectedVersion = await detectTmuxVersion(tmuxExecutor)\n }\n\n const applyPlan = async ({ emission, windowMode, windowName }: ApplyPlanParameters): Promise<ApplyPlanResult> => {\n const executionResult = await executePlan({\n emission,\n executor: tmuxExecutor.getExecutor(),\n windowMode,\n windowName,\n onConfirmKill: context.prompt,\n detectedVersion,\n })\n\n // The plan runner tracks a virtual-pane-id -> real-pane-id map internally; expose\n // it (resolved) here so callers such as hooks.afterApply can address panes by\n // name/focus without knowing tmux's virtual ids. Tests may stub executePlan\n // without a paneMap, so fall back to an empty one rather than throwing.\n const paneMap = executionResult.paneMap ?? new Map<string, string>()\n const focusPaneId = paneMap.get(emission.summary.focusPaneId)\n\n return {\n executedSteps: executionResult.executedSteps,\n focusPaneId,\n paneNameToRealId: buildNameToRealIdMap(emission.terminals, paneMap),\n windowId: await resolveTmuxWindowId({ tmuxExecutor, focusPaneId }),\n }\n }\n\n return {\n verifyEnvironment,\n applyPlan,\n getDryRunSteps: buildDryRunSteps,\n }\n}\n\n// Resolves the real tmux window id (e.g. \"@5\") the layout was applied into, so\n// callers such as hooks.afterApply can pass it to external tools via {{window_id}}.\n// tmux's `-t` does not expand formats, so this literal must be resolved here rather\n// than left for the consuming command to figure out. Issued once, after the plan has\n// finished applying; any failure (e.g. the pane has since gone away) is swallowed so\n// it never affects the outcome of applyPlan itself.\nconst resolveTmuxWindowId = async ({\n tmuxExecutor,\n focusPaneId,\n}: {\n readonly tmuxExecutor: TmuxExecutor\n readonly focusPaneId: string | undefined\n}): Promise<string | undefined> => {\n if (focusPaneId === undefined) {\n return undefined\n }\n\n try {\n const output = await tmuxExecutor.execute([\"display-message\", \"-p\", \"-t\", focusPaneId, \"#{window_id}\"])\n const trimmed = output.trim()\n return trimmed.length > 0 ? trimmed : undefined\n } catch {\n return undefined\n }\n}\n\nconst buildTmuxCommand = ({\n step,\n paneSizes,\n detectedVersion,\n}: {\n readonly step: CommandStep\n readonly paneSizes: Map<string, PaneDimensions>\n readonly detectedVersion?: string\n}): string[] => {\n if (step.kind === \"split\") {\n const target = resolveRequiredStepTargetPaneId(step)\n const orientation = resolveSplitOrientationFromStep(step)\n const direction = orientation === \"horizontal\" ? \"-h\" : \"-v\"\n\n if (step.splitSizing?.mode === \"dynamic-cells\") {\n const paneSize = paneSizes.get(target)\n if (paneSize !== undefined) {\n const paneCells = orientation === \"horizontal\" ? paneSize.cols : paneSize.rows\n\n try {\n const splitSize = resolveSplitSize(step, {\n paneCells,\n paneId: target,\n detectedVersion,\n rawPaneRecord: {\n backend: \"tmux\",\n paneId: target,\n sourceFormat: \"tmux-format\",\n size: {\n cols: paneSize.cols,\n rows: paneSize.rows,\n },\n },\n })\n\n if (splitSize.mode === \"cells\") {\n if (typeof step.createdPaneId === \"string\" && step.createdPaneId.length > 0) {\n updatePaneSizes({\n paneSizes,\n targetPaneId: target,\n createdPaneId: step.createdPaneId,\n orientation,\n targetCells: splitSize.targetCells,\n createdCells: splitSize.createdCells,\n })\n }\n return [\"split-window\", direction, \"-t\", target, \"-l\", splitSize.cells]\n }\n } catch (error) {\n if (isCoreError(error) && error.code === ErrorCodes.SPLIT_SIZE_RESOLUTION_FAILED) {\n // dry-run intentionally falls back to a placeholder when pane size cannot be resolved\n } else {\n throw error\n }\n }\n }\n\n return [\"split-window\", direction, \"-t\", target, \"-l\", \"<dynamic>\"]\n }\n\n const splitSize = resolveSplitSize(step, {\n paneId: target,\n detectedVersion,\n })\n if (splitSize.mode !== \"percent\") {\n throw createUnsupportedStepKindError(step)\n }\n return [\"split-window\", direction, \"-t\", target, \"-p\", splitSize.percentage]\n }\n\n if (step.kind === \"focus\") {\n const target = resolveRequiredStepTargetPaneId(step)\n return [\"select-pane\", \"-t\", target]\n }\n\n throw createUnsupportedStepKindError(step)\n}\n\nconst detectTmuxVersion = async (tmuxExecutor: ReturnType<typeof createTmuxExecutor>): Promise<string | undefined> => {\n try {\n const raw = await tmuxExecutor.execute([\"-V\"])\n const match = raw.trim().match(TMUX_VERSION_REGEX)\n return match?.[1]?.trim()\n } catch {\n return undefined\n }\n}\n\n// This is windowMode-independent: it only reads process.env.TMUX_PANE/TMUX and is\n// invoked purely to seed dry-run size estimates, regardless of whether the plan will\n// eventually be applied in \"current-window\" or \"new-window\" mode. The sidebar\n// correction below therefore applies unconditionally whenever the process happens to\n// be running with its current pane inside a real tmux sidebar, not just when\n// windowMode is \"current-window\".\nconst resolveInitialTmuxPaneSize = (): PaneDimensions | undefined => {\n const tmuxPane = process.env.TMUX_PANE\n const tmuxSession = process.env.TMUX\n if (\n typeof tmuxSession !== \"string\" ||\n tmuxSession.length === 0 ||\n typeof tmuxPane !== \"string\" ||\n tmuxPane.length === 0\n ) {\n return undefined\n }\n\n const currentPane = queryTmuxCurrentPaneSizeAndSidebarFlag(tmuxPane)\n if (currentPane === undefined) {\n return undefined\n }\n\n if (!currentPane.isSidebar) {\n return { cols: currentPane.cols, rows: currentPane.rows }\n }\n\n // The current pane is the protected sidebar. Dry-run sizing must reflect the\n // pane the layout will actually be built from (see plan-runner's split-origin\n // resolution, which applies the same correction when windowMode is\n // \"current-window\"), not the sidebar itself. A real split is never performed\n // here: when the window has no other pane yet, sizing is simply left unresolved.\n const originPaneId = resolveDryRunOriginPaneId(tmuxPane)\n if (originPaneId === undefined) {\n return undefined\n }\n\n return queryTmuxPaneSize(originPaneId)\n}\n\nconst queryTmuxCurrentPaneSizeAndSidebarFlag = (\n paneId: string,\n): { cols: number; rows: number; isSidebar: boolean } | undefined => {\n try {\n const output = execFileSync(\n \"tmux\",\n [\"display-message\", \"-p\", \"-t\", paneId, \"#{pane_width} #{pane_height} #{@vde_sidebar}\"],\n {\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n },\n ).trim()\n const [colsRaw = \"\", rowsRaw = \"\", sidebarFlag = \"\"] = output.split(/\\s+/, 3)\n\n const cols = Number.parseInt(colsRaw, 10)\n const rows = Number.parseInt(rowsRaw, 10)\n if (!Number.isInteger(cols) || cols <= 0 || !Number.isInteger(rows) || rows <= 0) {\n return undefined\n }\n return { cols, rows, isSidebar: sidebarFlag === \"1\" }\n } catch {\n return undefined\n }\n}\n\n// `-t targetPaneId` scopes `list-panes` to the window that pane belongs to, so the\n// caller's current pane id must be passed through here too (see the module-level\n// comment above on why this correction is windowMode-independent): without it,\n// this would list tmux's \"active\" window instead of the one this process is\n// actually running in, which can differ in multi-window/multi-session setups.\nconst resolveDryRunOriginPaneId = (targetPaneId: string): string | undefined => {\n try {\n const output = execFileSync(\"tmux\", [\"list-panes\", \"-t\", targetPaneId, \"-F\", SIDEBAR_LIST_PANES_FORMAT], {\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n })\n\n for (const line of output.split(\"\\n\")) {\n const [paneId, sidebarFlag] = line.split(\"\\t\")\n if (typeof paneId === \"string\" && paneId.trim().length > 0 && sidebarFlag?.trim() !== \"1\") {\n return paneId.trim()\n }\n }\n return undefined\n } catch {\n return undefined\n }\n}\n\nconst queryTmuxPaneSize = (paneId: string): PaneDimensions | undefined => {\n try {\n const sizeOutput = execFileSync(\"tmux\", [\"display-message\", \"-p\", \"-t\", paneId, \"#{pane_width} #{pane_height}\"], {\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }).trim()\n const [colsRaw = \"\", rowsRaw = \"\"] = sizeOutput.split(/\\s+/, 2)\n\n const cols = Number.parseInt(colsRaw, 10)\n const rows = Number.parseInt(rowsRaw, 10)\n if (!Number.isInteger(cols) || cols <= 0 || !Number.isInteger(rows) || rows <= 0) {\n return undefined\n }\n return { cols, rows }\n } catch {\n return undefined\n }\n}\n","export type WeztermPaneSize = {\n readonly cols?: number\n readonly rows?: number\n}\n\nexport type WeztermRawPaneRecord = {\n readonly backend: \"wezterm\"\n readonly windowId?: string\n readonly tabId?: string\n readonly paneId: string\n readonly isActive?: boolean\n readonly size?: WeztermPaneSize\n readonly sourceFormat: \"wezterm-array\" | \"wezterm-object\" | \"unknown\"\n}\n\nexport type WeztermListPane = {\n readonly paneId: string\n readonly isActive: boolean\n readonly size?: WeztermPaneSize\n readonly rawPaneRecord: WeztermRawPaneRecord\n}\n\ntype WeztermListTab = {\n readonly tabId: string\n readonly isActive: boolean\n readonly panes: ReadonlyArray<WeztermListPane>\n}\n\nexport type WeztermListWindow = {\n readonly windowId: string\n readonly isActive: boolean\n readonly workspace?: string\n readonly tabs: ReadonlyArray<WeztermListTab>\n}\n\nexport type WeztermListResult = {\n readonly windows: ReadonlyArray<WeztermListWindow>\n}\n\ntype RawListSize = {\n readonly cols?: unknown\n readonly rows?: unknown\n}\n\ntype RawListPane = {\n readonly pane_id?: number | string\n readonly is_active?: unknown\n readonly size?: RawListSize\n}\n\ntype RawListTab = {\n readonly tab_id?: number | string\n readonly is_active?: unknown\n readonly panes?: RawListPane[]\n}\n\ntype RawListWindow = {\n readonly window_id?: number | string\n readonly is_active?: unknown\n readonly workspace?: unknown\n readonly tabs?: RawListTab[]\n}\n\ntype RawListEntry = {\n readonly window_id?: number | string\n readonly tab_id?: number | string\n readonly pane_id?: number | string\n readonly workspace?: unknown\n readonly is_active?: unknown\n readonly size?: RawListSize\n}\n\ntype RawListResult = {\n readonly windows?: RawListWindow[]\n}\n\nconst toIdString = (value: unknown): string | undefined => {\n if (typeof value === \"string\") {\n return value\n }\n if (typeof value === \"number\") {\n return value.toString()\n }\n return undefined\n}\n\nconst isNonEmptyString = (value: string | undefined): value is string => {\n return typeof value === \"string\" && value.length > 0\n}\n\nconst toWorkspaceString = (value: unknown): string | undefined => {\n if (typeof value === \"string\" && value.length > 0) {\n return value\n }\n return undefined\n}\n\nconst toPositiveInteger = (value: unknown): number | undefined => {\n if (typeof value !== \"number\" || !Number.isInteger(value) || value <= 0) {\n return undefined\n }\n return value\n}\n\nconst toPaneSize = (value: unknown): WeztermPaneSize | undefined => {\n if (typeof value !== \"object\" || value === null) {\n return undefined\n }\n const raw = value as RawListSize\n const cols = toPositiveInteger(raw.cols)\n const rows = toPositiveInteger(raw.rows)\n if (cols === undefined && rows === undefined) {\n return undefined\n }\n return {\n cols,\n rows,\n }\n}\n\ntype MutableTabRecord = {\n tabId: string\n isActive: boolean\n panes: WeztermListPane[]\n}\n\ntype MutableWindowRecord = {\n windowId: string\n isActive: boolean\n workspace?: string\n tabs: Map<string, MutableTabRecord>\n}\n\ntype NormalizedArrayEntry = {\n windowId: string\n tabId: string\n paneId: string\n workspace?: string\n isActive: boolean\n size?: WeztermPaneSize\n}\n\nconst toImmutablePanes = (panes: ReadonlyArray<WeztermListPane>): WeztermListPane[] => {\n return panes.map(\n (pane): WeztermListPane => ({\n paneId: pane.paneId,\n isActive: pane.isActive,\n ...(pane.size !== undefined ? { size: pane.size } : {}),\n rawPaneRecord: pane.rawPaneRecord,\n }),\n )\n}\n\nconst toImmutableTabs = (tabs: ReadonlyMap<string, MutableTabRecord>): WeztermListTab[] => {\n return Array.from(tabs.values()).map(\n (tabRecord): WeztermListTab => ({\n tabId: tabRecord.tabId,\n isActive: tabRecord.isActive,\n panes: toImmutablePanes(tabRecord.panes),\n }),\n )\n}\n\nconst toImmutableWindows = (windows: ReadonlyMap<string, MutableWindowRecord>): WeztermListWindow[] => {\n return Array.from(windows.values()).map(\n (windowRecord): WeztermListWindow => ({\n windowId: windowRecord.windowId,\n isActive: windowRecord.isActive,\n workspace: windowRecord.workspace,\n tabs: toImmutableTabs(windowRecord.tabs),\n }),\n )\n}\n\nconst normalizeArrayEntry = (entry: unknown): NormalizedArrayEntry | undefined => {\n if (typeof entry !== \"object\" || entry === null) {\n return undefined\n }\n const listEntry = entry as RawListEntry\n const windowIdRaw = toIdString(listEntry.window_id)\n const paneIdRaw = toIdString(listEntry.pane_id)\n const tabIdRaw = toIdString(listEntry.tab_id) ?? windowIdRaw\n if (!isNonEmptyString(windowIdRaw) || !isNonEmptyString(tabIdRaw) || !isNonEmptyString(paneIdRaw)) {\n return undefined\n }\n return {\n windowId: windowIdRaw,\n tabId: tabIdRaw,\n paneId: paneIdRaw,\n workspace: toWorkspaceString(listEntry.workspace),\n isActive: listEntry.is_active === true,\n size: toPaneSize(listEntry.size),\n }\n}\n\nconst getOrCreateWindowRecord = (\n windows: Map<string, MutableWindowRecord>,\n entry: NormalizedArrayEntry,\n): MutableWindowRecord => {\n const existingWindow = windows.get(entry.windowId)\n if (existingWindow) {\n if (entry.workspace !== undefined && existingWindow.workspace === undefined) {\n existingWindow.workspace = entry.workspace\n }\n return existingWindow\n }\n const createdWindow: MutableWindowRecord = {\n windowId: entry.windowId,\n isActive: false,\n workspace: entry.workspace,\n tabs: new Map(),\n }\n windows.set(entry.windowId, createdWindow)\n return createdWindow\n}\n\nconst getOrCreateTabRecord = (windowRecord: MutableWindowRecord, tabId: string): MutableTabRecord => {\n const existingTab = windowRecord.tabs.get(tabId)\n if (existingTab) {\n return existingTab\n }\n const createdTab: MutableTabRecord = {\n tabId,\n isActive: false,\n panes: [],\n }\n windowRecord.tabs.set(tabId, createdTab)\n return createdTab\n}\n\nconst createArrayRawPaneRecord = (entry: NormalizedArrayEntry): WeztermRawPaneRecord => {\n return {\n backend: \"wezterm\",\n windowId: entry.windowId,\n tabId: entry.tabId,\n paneId: entry.paneId,\n isActive: entry.isActive,\n size: entry.size,\n sourceFormat: \"wezterm-array\",\n }\n}\n\nconst createObjectRawPaneRecord = ({\n rawPane,\n context,\n paneId,\n size,\n}: {\n readonly rawPane: RawListPane\n readonly context: { readonly windowId: string; readonly tabId: string }\n readonly paneId: string\n readonly size?: WeztermPaneSize\n}): WeztermRawPaneRecord => {\n return {\n backend: \"wezterm\",\n windowId: context.windowId,\n tabId: context.tabId,\n paneId,\n isActive: rawPane.is_active === true,\n size,\n sourceFormat: \"wezterm-object\",\n }\n}\n\nconst parseArrayResponse = (parsed: unknown): WeztermListResult | undefined => {\n if (!Array.isArray(parsed)) {\n return undefined\n }\n\n const windowMap = new Map<string, MutableWindowRecord>()\n for (const entry of parsed) {\n const normalizedEntry = normalizeArrayEntry(entry)\n if (!normalizedEntry) {\n continue\n }\n\n const windowRecord = getOrCreateWindowRecord(windowMap, normalizedEntry)\n const tabRecord = getOrCreateTabRecord(windowRecord, normalizedEntry.tabId)\n\n windowRecord.isActive ||= normalizedEntry.isActive\n tabRecord.isActive ||= normalizedEntry.isActive\n tabRecord.panes.push({\n paneId: normalizedEntry.paneId,\n isActive: normalizedEntry.isActive,\n ...(normalizedEntry.size !== undefined ? { size: normalizedEntry.size } : {}),\n rawPaneRecord: createArrayRawPaneRecord(normalizedEntry),\n })\n }\n\n return { windows: toImmutableWindows(windowMap) }\n}\n\nconst parseObjectPane = (\n pane: unknown,\n context: { readonly windowId: string; readonly tabId: string },\n): WeztermListPane | undefined => {\n if (typeof pane !== \"object\" || pane === null) {\n return undefined\n }\n const rawPane = pane as RawListPane\n const paneIdRaw = toIdString(rawPane.pane_id)\n if (!isNonEmptyString(paneIdRaw)) {\n return undefined\n }\n\n const size = toPaneSize(rawPane.size)\n return {\n paneId: paneIdRaw,\n isActive: rawPane.is_active === true,\n ...(size !== undefined ? { size } : {}),\n rawPaneRecord: createObjectRawPaneRecord({\n rawPane,\n context,\n paneId: paneIdRaw,\n size,\n }),\n }\n}\n\nconst parseObjectTab = (tab: unknown, context: { readonly windowId: string }): WeztermListTab | undefined => {\n if (typeof tab !== \"object\" || tab === null) {\n return undefined\n }\n const rawTab = tab as RawListTab\n const tabIdRaw = toIdString(rawTab.tab_id)\n if (!isNonEmptyString(tabIdRaw)) {\n return undefined\n }\n\n const paneRecords = Array.isArray(rawTab.panes) ? rawTab.panes : []\n const panes: WeztermListPane[] = []\n for (const pane of paneRecords) {\n const mappedPane = parseObjectPane(pane, {\n windowId: context.windowId,\n tabId: tabIdRaw,\n })\n if (mappedPane) {\n panes.push(mappedPane)\n }\n }\n\n return {\n tabId: tabIdRaw,\n isActive: rawTab.is_active === true,\n panes,\n }\n}\n\nconst parseObjectWindow = (window: unknown): WeztermListWindow | undefined => {\n if (typeof window !== \"object\" || window === null) {\n return undefined\n }\n const rawWindow = window as RawListWindow\n const windowIdRaw = toIdString(rawWindow.window_id)\n if (!isNonEmptyString(windowIdRaw)) {\n return undefined\n }\n\n const tabs: WeztermListTab[] = []\n const rawTabs = Array.isArray(rawWindow.tabs) ? rawWindow.tabs : []\n for (const tab of rawTabs) {\n const mappedTab = parseObjectTab(tab, { windowId: windowIdRaw })\n if (mappedTab) {\n tabs.push(mappedTab)\n }\n }\n\n return {\n windowId: windowIdRaw,\n isActive: rawWindow.is_active === true,\n workspace: toWorkspaceString(rawWindow.workspace),\n tabs,\n }\n}\n\nconst parseObjectResponse = (parsed: unknown): WeztermListResult | undefined => {\n if (typeof parsed !== \"object\" || parsed === null) {\n return undefined\n }\n\n const candidate = parsed as Partial<RawListResult>\n const rawWindows = Array.isArray(candidate.windows) ? candidate.windows : []\n const windows: WeztermListWindow[] = []\n for (const window of rawWindows) {\n const mappedWindow = parseObjectWindow(window)\n if (mappedWindow) {\n windows.push(mappedWindow)\n }\n }\n return { windows }\n}\n\nexport const parseWeztermListResult = (stdout: string): WeztermListResult | undefined => {\n try {\n const parsed: unknown = JSON.parse(stdout)\n return parseArrayResponse(parsed) ?? parseObjectResponse(parsed)\n } catch {\n return undefined\n }\n}\n","import { execa } from \"execa\"\nimport { createEnvironmentError, ErrorCodes } from \"../../utils/errors\"\nimport { createCoreError } from \"../../core/errors\"\nimport { parseWeztermListResult, type WeztermListResult } from \"./list-parser\"\n\nexport type { WeztermListResult } from \"./list-parser\"\n\nconst WEZTERM_BINARY = \"wezterm\"\nexport const WEZTERM_MINIMUM_VERSION = \"20220624-141144-bd1b7c5d\"\nconst VERSION_REGEX = /(\\d{8})-(\\d{6})-([0-9a-fA-F]+)/i\n\ntype ExecaLikeError = Error & {\n readonly exitCode?: number\n readonly code?: string\n readonly stderr?: string\n readonly stdout?: string\n}\n\nexport const verifyWeztermAvailability = async (): Promise<{ version: string }> => {\n let stdout: string\n try {\n const result = await execa(WEZTERM_BINARY, [\"--version\"])\n stdout = result.stdout\n } catch (error) {\n const execaError = error as ExecaLikeError\n if (execaError.code === \"ENOENT\") {\n throw createEnvironmentError(\"wezterm is not installed\", ErrorCodes.BACKEND_NOT_FOUND, {\n backend: \"wezterm\",\n binary: WEZTERM_BINARY,\n })\n }\n throw createEnvironmentError(\"Failed to execute wezterm --version\", ErrorCodes.WEZTERM_NOT_FOUND, {\n backend: \"wezterm\",\n binary: WEZTERM_BINARY,\n stderr: execaError.stderr,\n })\n }\n\n const detectedVersion = extractVersion(stdout)\n if (detectedVersion === undefined) {\n throw createEnvironmentError(\"Unable to determine wezterm version\", ErrorCodes.UNSUPPORTED_WEZTERM_VERSION, {\n requiredVersion: WEZTERM_MINIMUM_VERSION,\n detectedVersion: stdout.trim(),\n })\n }\n\n if (!isVersionSupported(detectedVersion, WEZTERM_MINIMUM_VERSION)) {\n throw createEnvironmentError(\"Unsupported wezterm version\", ErrorCodes.UNSUPPORTED_WEZTERM_VERSION, {\n requiredVersion: WEZTERM_MINIMUM_VERSION,\n detectedVersion,\n })\n }\n\n return { version: detectedVersion }\n}\n\nexport type RunWeztermErrorContext = {\n readonly message: string\n readonly path?: string\n readonly details?: Readonly<Record<string, unknown>>\n}\n\nexport const runWeztermCli = async (args: string[], errorContext: RunWeztermErrorContext): Promise<string> => {\n try {\n const result = await execa(WEZTERM_BINARY, [\"cli\", ...args])\n return result.stdout\n } catch (error) {\n const execaError = error as ExecaLikeError\n throw createCoreError(\"execution\", {\n code: ErrorCodes.TERMINAL_COMMAND_FAILED,\n message: errorContext.message,\n path: errorContext.path,\n details: {\n command: [WEZTERM_BINARY, \"cli\", ...args],\n stderr: execaError.stderr,\n exitCode: execaError.exitCode,\n backend: \"wezterm\",\n ...(errorContext.details ?? {}),\n },\n })\n }\n}\n\nexport const listWeztermWindows = async (): Promise<WeztermListResult> => {\n const stdout = await runWeztermCli([\"list\", \"--format\", \"json\"], { message: \"Failed to list wezterm panes\" })\n const result = parseWeztermListResult(stdout)\n if (result === undefined) {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.TERMINAL_COMMAND_FAILED,\n message: \"Invalid wezterm list output\",\n details: { stdout },\n })\n }\n return result\n}\n\nexport const killWeztermPane = async (paneId: string): Promise<void> => {\n await runWeztermCli([\"kill-pane\", \"--pane-id\", paneId], {\n message: `Failed to kill wezterm pane ${paneId}`,\n path: paneId,\n })\n}\n\nconst extractVersion = (raw: string): string | undefined => {\n const match = raw.match(VERSION_REGEX)\n if (!match) {\n return undefined\n }\n const date = match[1]\n const time = match[2]\n const commit = match[3]\n if (date === undefined || time === undefined || commit === undefined) {\n return undefined\n }\n return `${date}-${time}-${commit.toLowerCase()}`\n}\n\nconst isVersionSupported = (detected: string, minimum: string): boolean => {\n const parse = (version: string): { build: number; commit: string } | undefined => {\n const match = version.match(VERSION_REGEX)\n if (!match) {\n return undefined\n }\n const date = match[1]\n const time = match[2]\n const commit = match[3]\n if (date === undefined || time === undefined || commit === undefined) {\n return undefined\n }\n const build = Number(`${date}${time}`)\n if (Number.isNaN(build)) {\n return undefined\n }\n return { build, commit: commit.toLowerCase() }\n }\n\n const detectedInfo = parse(detected)\n const minimumInfo = parse(minimum)\n if (detectedInfo === undefined || minimumInfo === undefined) {\n return false\n }\n\n if (detectedInfo.build > minimumInfo.build) {\n return true\n }\n if (detectedInfo.build < minimumInfo.build) {\n return false\n }\n\n return detectedInfo.commit >= minimumInfo.commit\n}\n","import { type PaneDimensions, updatePaneSizes } from \"../pane-tracking\"\nimport type { PlanEmission } from \"../../core/emitter\"\nimport { createCoreError, isCoreError } from \"../../core/errors\"\nimport { resolveSplitOrientation, resolveSplitSize, type ResolvedSplitSize } from \"../../executor/split-step\"\nimport { resolveRequiredStepTargetPaneId } from \"../../executor/step-target\"\nimport { prepareTerminalCommands } from \"../../executor/terminal-command-preparation\"\nimport type { DryRunStep } from \"../../executor/terminal-backend\"\nimport { ErrorCodes } from \"../../utils/errors\"\nconst SINGLE_QUOTE = \"'\"\nconst SHELL_SINGLE_QUOTE_ESCAPE = `'\"'\"'`\n\ntype SplitArgumentSize =\n | ResolvedSplitSize\n | {\n readonly mode: \"cells-placeholder\"\n readonly cellsPlaceholder: string\n }\n\nexport type BuildWeztermDryRunStepsOptions = {\n readonly initialPaneId?: string\n readonly initialPaneSize?: PaneDimensions\n readonly detectedVersion?: string\n}\n\nexport const buildSplitArguments = (params: {\n readonly targetPaneId: string\n readonly splitSize: SplitArgumentSize\n readonly horizontal: boolean\n}): string[] => {\n const directionFlag = params.horizontal ? \"--right\" : \"--bottom\"\n if (params.splitSize.mode === \"percent\") {\n return [\"split-pane\", directionFlag, \"--percent\", params.splitSize.percentage, \"--pane-id\", params.targetPaneId]\n }\n\n if (params.splitSize.mode === \"cells\") {\n return [\"split-pane\", directionFlag, \"--cells\", params.splitSize.cells, \"--pane-id\", params.targetPaneId]\n }\n\n return [\"split-pane\", directionFlag, \"--cells\", params.splitSize.cellsPlaceholder, \"--pane-id\", params.targetPaneId]\n}\n\nexport const buildDryRunSteps = (\n emission: PlanEmission,\n options: BuildWeztermDryRunStepsOptions = {},\n): DryRunStep[] => {\n const steps: DryRunStep[] = []\n const paneSizes = new Map<string, PaneDimensions>()\n if (options.initialPaneId !== undefined && options.initialPaneSize !== undefined) {\n paneSizes.set(options.initialPaneId, options.initialPaneSize)\n }\n\n for (const step of emission.steps) {\n if (step.kind === \"split\") {\n const target = resolveRequiredStepTargetPaneId(step)\n const horizontal = resolveSplitOrientation(step) === \"horizontal\"\n const splitSize = resolveDryRunSplitSize({\n step,\n targetPaneId: target,\n paneSizes,\n orientation: horizontal ? \"horizontal\" : \"vertical\",\n detectedVersion: options.detectedVersion,\n })\n const args = buildSplitArguments({\n targetPaneId: target,\n splitSize,\n horizontal,\n })\n const summary = step.splitSizing?.mode === \"dynamic-cells\" ? `${step.summary} [dynamic-cells]` : step.summary\n steps.push({\n backend: \"wezterm\",\n summary,\n command: `wezterm cli ${args.join(\" \")}`,\n })\n continue\n }\n\n if (step.kind === \"focus\") {\n const target = resolveRequiredStepTargetPaneId(step)\n steps.push({\n backend: \"wezterm\",\n summary: step.summary,\n command: `wezterm cli activate-pane --pane-id ${target}`,\n })\n continue\n }\n\n throw createCoreError(\"execution\", {\n code: ErrorCodes.INVALID_PLAN,\n message: `Unsupported step kind in emission: ${String((step as { kind?: unknown }).kind)}`,\n path: step.id,\n })\n }\n\n const prepared = prepareTerminalCommands({\n terminals: emission.terminals,\n focusPaneVirtualId: emission.summary.focusPaneId,\n resolveRealPaneId: (virtualPaneId: string): string => virtualPaneId,\n onTemplateTokenError: ({ terminal, error }): never => {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.TEMPLATE_TOKEN_ERROR,\n message: `Template token resolution failed for pane ${terminal.virtualPaneId}: ${error.message}`,\n path: terminal.virtualPaneId,\n details: {\n command: terminal.command,\n tokenType: error.tokenType,\n availablePanes: error.availablePanes,\n },\n })\n },\n })\n\n const quoteForShellDisplay = (value: string): string => {\n return `${SINGLE_QUOTE}${value.split(SINGLE_QUOTE).join(SHELL_SINGLE_QUOTE_ESCAPE)}${SINGLE_QUOTE}`\n }\n\n for (const commandSet of prepared.commands) {\n const paneId = commandSet.terminal.virtualPaneId\n if (typeof commandSet.cwdCommand === \"string\") {\n steps.push({\n backend: \"wezterm\",\n summary: `set cwd for ${paneId}`,\n command: `wezterm cli send-text --pane-id ${paneId} --no-paste -- ${quoteForShellDisplay(commandSet.cwdCommand)}`,\n })\n }\n\n for (const envEntry of commandSet.envCommands) {\n steps.push({\n backend: \"wezterm\",\n summary: `set env ${envEntry.key} for ${paneId}`,\n command: `wezterm cli send-text --pane-id ${paneId} --no-paste -- ${quoteForShellDisplay(envEntry.command)}`,\n })\n }\n\n if (commandSet.command !== undefined) {\n steps.push({\n backend: \"wezterm\",\n summary: `run command for ${paneId}`,\n command: `wezterm cli send-text --pane-id ${paneId} --no-paste -- ${quoteForShellDisplay(commandSet.command.text)}`,\n })\n }\n }\n\n return steps\n}\n\nconst resolveDryRunSplitSize = ({\n step,\n targetPaneId,\n paneSizes,\n orientation,\n detectedVersion,\n}: {\n readonly step: PlanEmission[\"steps\"][number]\n readonly targetPaneId: string\n readonly paneSizes: Map<string, PaneDimensions>\n readonly orientation: \"horizontal\" | \"vertical\"\n readonly detectedVersion?: string\n}): SplitArgumentSize => {\n if (step.kind !== \"split\") {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.INVALID_PLAN,\n message: \"Dry-run split sizing requested for non-split step\",\n path: step.id,\n })\n }\n\n if (step.splitSizing?.mode === \"dynamic-cells\") {\n const paneSize = paneSizes.get(targetPaneId)\n const paneCells = paneSize ? (orientation === \"horizontal\" ? paneSize.cols : paneSize.rows) : undefined\n\n if (typeof paneCells !== \"number\") {\n return {\n mode: \"cells-placeholder\",\n cellsPlaceholder: \"<dynamic>\",\n }\n }\n\n try {\n const splitSize = resolveSplitSize(step, {\n paneCells,\n paneId: targetPaneId,\n detectedVersion,\n rawPaneRecord: {\n backend: \"wezterm\",\n paneId: targetPaneId,\n sourceFormat: \"unknown\",\n size: paneSize,\n },\n })\n\n if (splitSize.mode === \"cells\" && typeof step.createdPaneId === \"string\" && step.createdPaneId.length > 0) {\n updatePaneSizes({\n paneSizes,\n targetPaneId,\n createdPaneId: step.createdPaneId,\n orientation,\n targetCells: splitSize.targetCells,\n createdCells: splitSize.createdCells,\n })\n }\n\n if (splitSize.mode === \"cells\") {\n return splitSize\n }\n } catch (error) {\n if (isCoreError(error) && error.code === ErrorCodes.SPLIT_SIZE_RESOLUTION_FAILED) {\n return {\n mode: \"cells-placeholder\",\n cellsPlaceholder: \"<dynamic>\",\n }\n }\n throw error\n }\n\n return {\n mode: \"cells-placeholder\",\n cellsPlaceholder: \"<dynamic>\",\n }\n }\n\n return resolveSplitSize(step, {\n paneId: targetPaneId,\n detectedVersion,\n })\n}\n","import { createCoreError } from \"../../core/errors\"\nimport type { WindowMode } from \"../../models/types\"\nimport type { ConfirmPaneClosure } from \"../../contracts\"\nimport { waitForDelay } from \"../../utils/async\"\nimport { ErrorCodes } from \"../../utils/errors\"\nimport { killWeztermPane, type WeztermListResult } from \"./cli\"\nimport type { ExecuteWeztermCommand, ListWeztermWindows } from \"./shared\"\n\nconst PANE_REGISTRATION_RETRIES = 5\nconst PANE_REGISTRATION_DELAY_MS = 100\n\ntype InitialPaneResolution = {\n readonly paneId: string\n readonly windowId: string\n}\n\ntype CurrentWindowResolution = InitialPaneResolution & {\n readonly panesToClose: ReadonlyArray<string>\n}\n\nconst resolveCurrentWindow = async (context: {\n readonly list: WeztermListResult\n readonly prompt?: ConfirmPaneClosure\n readonly dryRun: boolean\n readonly logCommand: (args: ReadonlyArray<string>) => void\n readonly preferredPaneId?: string\n}): Promise<CurrentWindowResolution> => {\n const hasPreferredPane = typeof context.preferredPaneId === \"string\" && context.preferredPaneId.length > 0\n const preferredPaneId = hasPreferredPane ? (context.preferredPaneId as string) : undefined\n const preferredWindowId =\n preferredPaneId !== undefined ? findWindowContainingPane(context.list, preferredPaneId) : undefined\n\n const activeWindow =\n (preferredWindowId !== undefined\n ? context.list.windows.find((window) => window.windowId === preferredWindowId)\n : undefined) ??\n context.list.windows.find((window) => window.isActive) ??\n context.list.windows[0]\n\n if (!activeWindow) {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.TERMINAL_COMMAND_FAILED,\n message: \"No active wezterm window detected\",\n details: { hint: \"Launch wezterm and ensure a window is focused, or run with --new-window.\" },\n })\n }\n\n const activeTab =\n (preferredPaneId !== undefined\n ? activeWindow.tabs.find((tab) => tab.panes.some((pane) => pane.paneId === preferredPaneId))\n : undefined) ??\n activeWindow.tabs.find((tab) => tab.isActive) ??\n activeWindow.tabs[0]\n\n if (!activeTab) {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.TERMINAL_COMMAND_FAILED,\n message: \"No active wezterm tab detected\",\n path: activeWindow.windowId,\n details: { hint: \"Ensure a wezterm tab is focused before using --current-window.\" },\n })\n }\n\n const activePane =\n (preferredPaneId !== undefined ? activeTab.panes.find((pane) => pane.paneId === preferredPaneId) : undefined) ??\n activeTab.panes.find((pane) => pane.isActive) ??\n activeTab.panes[0]\n\n if (!activePane) {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.TERMINAL_COMMAND_FAILED,\n message: \"No active wezterm pane detected\",\n path: activeTab.tabId,\n details: { hint: \"Ensure a wezterm pane is active before using --current-window.\" },\n })\n }\n\n const panesToClose = activeTab.panes.filter((pane) => pane.paneId !== activePane.paneId).map((pane) => pane.paneId)\n\n if (panesToClose.length > 0) {\n let confirmed = true\n if (context.prompt) {\n confirmed = await context.prompt({ panesToClose, dryRun: context.dryRun })\n }\n\n if (confirmed !== true) {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.USER_CANCELLED,\n message: \"Aborted layout application for current wezterm window\",\n path: activePane.paneId,\n details: { panes: panesToClose },\n })\n }\n\n for (const paneId of panesToClose) {\n context.logCommand([\"kill-pane\", \"--pane-id\", paneId])\n await killWeztermPane(paneId)\n }\n }\n\n return {\n paneId: activePane.paneId,\n windowId: activeWindow.windowId,\n panesToClose,\n }\n}\n\nconst findActiveWindow = (\n list: WeztermListResult,\n): { windowId: string; tabs: (typeof list.windows)[number][\"tabs\"] } | undefined => {\n return list.windows.find((window) => window.isActive) ?? list.windows[0]\n}\n\nconst findWindowContainingPane = (list: WeztermListResult, paneId: string): string | undefined => {\n for (const window of list.windows) {\n for (const tab of window.tabs) {\n for (const pane of tab.panes) {\n if (pane.paneId === paneId) {\n return window.windowId\n }\n }\n }\n }\n return undefined\n}\n\nexport const findWorkspaceForPane = (list: WeztermListResult, paneId: string): string | undefined => {\n for (const window of list.windows) {\n for (const tab of window.tabs) {\n for (const pane of tab.panes) {\n if (pane.paneId === paneId) {\n return window.workspace\n }\n }\n }\n }\n return undefined\n}\n\nconst filterWindowsByWorkspace = (list: WeztermListResult, workspace?: string): WeztermListResult => {\n if (workspace === undefined || workspace.length === 0) {\n return list\n }\n const scoped = list.windows.filter((window) => window.workspace === workspace)\n if (scoped.length === 0) {\n return list\n }\n return { windows: scoped }\n}\n\nexport const collectPaneIdsForWindow = (list: WeztermListResult, windowId: string): Set<string> => {\n const targetWindow = list.windows.find((window) => window.windowId === windowId)\n if (!targetWindow) {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.TERMINAL_COMMAND_FAILED,\n message: `Wezterm window ${windowId} not found`,\n details: { windowId },\n })\n }\n\n const paneIds = targetWindow.tabs.flatMap((tab) => tab.panes.map((pane) => pane.paneId))\n return new Set(paneIds)\n}\n\nconst waitForPaneRegistration = async ({\n paneId,\n listWindows,\n windowHint,\n}: {\n readonly paneId: string\n readonly listWindows: ListWeztermWindows\n readonly windowHint?: string\n}): Promise<string> => {\n for (let attempt = 0; attempt < PANE_REGISTRATION_RETRIES; attempt += 1) {\n const snapshot = await listWindows()\n\n if (typeof windowHint === \"string\") {\n try {\n const panes = collectPaneIdsForWindow(snapshot, windowHint)\n if (panes.has(paneId)) {\n return windowHint\n }\n } catch {\n // window may not be ready yet; fall through to global search.\n }\n }\n\n const located = findWindowContainingPane(snapshot, paneId)\n if (typeof located === \"string\" && located.length > 0) {\n return located\n }\n\n if (attempt < PANE_REGISTRATION_RETRIES - 1) {\n await waitForDelay(PANE_REGISTRATION_DELAY_MS)\n }\n }\n\n throw createCoreError(\"execution\", {\n code: ErrorCodes.TERMINAL_COMMAND_FAILED,\n message: \"Unable to locate spawned wezterm window\",\n details: { paneId, hint: \"Verify that wezterm is running and the CLI client can connect.\" },\n })\n}\n\nconst extractSpawnPaneId = (output: string): string => {\n const trimmed = output.trim()\n if (trimmed.length === 0) {\n return \"\"\n }\n\n const lastLine = trimmed.split(\"\\n\").pop() ?? \"\"\n const tokens = lastLine.split(/\\s+/).filter((segment) => segment.length > 0)\n if (tokens.length === 0) {\n return \"\"\n }\n // wezterm cli spawn outputs pane-id first, followed by optional window or tab metadata\n const [paneId] = tokens\n if (typeof paneId !== \"string\") {\n return \"\"\n }\n return paneId.trim()\n}\n\nexport const resolveInitialPane = async ({\n windowMode,\n prompt,\n dryRun,\n listWindows,\n runCommand,\n logCommand,\n initialCwd,\n workspaceHint,\n initialList,\n preferredPaneId,\n}: {\n readonly windowMode: WindowMode\n readonly prompt?: ConfirmPaneClosure\n readonly dryRun: boolean\n readonly listWindows: ListWeztermWindows\n readonly runCommand: ExecuteWeztermCommand\n readonly logCommand: (args: ReadonlyArray<string>) => void\n readonly initialCwd?: string\n readonly workspaceHint?: string\n readonly initialList?: WeztermListResult\n readonly preferredPaneId?: string\n}): Promise<InitialPaneResolution> => {\n const hasPreferredPane = typeof preferredPaneId === \"string\" && preferredPaneId.length > 0\n const preferredPaneIdValue = hasPreferredPane ? (preferredPaneId as string) : undefined\n\n if (windowMode === \"current-window\") {\n const snapshot = initialList ?? (await listWindows())\n const scoped = filterWindowsByWorkspace(snapshot, workspaceHint)\n return resolveCurrentWindow({ list: scoped, prompt, dryRun, logCommand, preferredPaneId: preferredPaneIdValue })\n }\n\n const existingSnapshot = initialList ?? (await listWindows())\n const scopedExisting = filterWindowsByWorkspace(existingSnapshot, workspaceHint)\n const scopedPreferredWindowId =\n preferredPaneIdValue !== undefined ? findWindowContainingPane(scopedExisting, preferredPaneIdValue) : undefined\n const activeWindow =\n (scopedPreferredWindowId !== undefined\n ? scopedExisting.windows.find((window) => window.windowId === scopedPreferredWindowId)\n : undefined) ?? findActiveWindow(scopedExisting)\n\n if (activeWindow) {\n const args = [\"spawn\", \"--window-id\", activeWindow.windowId] as string[]\n if (typeof initialCwd === \"string\" && initialCwd.length > 0) {\n args.push(\"--cwd\", initialCwd)\n }\n const spawnOutput = await runCommand(args, {\n message: \"Failed to spawn wezterm tab\",\n })\n const paneId = extractSpawnPaneId(spawnOutput)\n if (paneId.length === 0) {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.TERMINAL_COMMAND_FAILED,\n message: \"wezterm spawn did not return a pane id\",\n details: { stdout: spawnOutput },\n })\n }\n const windowId = await waitForPaneRegistration({\n paneId,\n listWindows,\n windowHint: activeWindow.windowId,\n })\n return { paneId, windowId }\n }\n\n const args = [\"spawn\", \"--new-window\"] as string[]\n if (typeof initialCwd === \"string\" && initialCwd.length > 0) {\n args.push(\"--cwd\", initialCwd)\n }\n if (typeof workspaceHint === \"string\" && workspaceHint.length > 0) {\n args.push(\"--workspace\", workspaceHint)\n }\n const spawnOutput = await runCommand(args, {\n message: \"Failed to spawn wezterm window\",\n })\n const paneId = extractSpawnPaneId(spawnOutput)\n if (paneId.length === 0) {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.TERMINAL_COMMAND_FAILED,\n message: \"wezterm spawn did not return a pane id\",\n details: { stdout: spawnOutput },\n })\n }\n\n const newWindowId = await waitForPaneRegistration({\n paneId,\n listWindows,\n })\n return { paneId, windowId: newWindowId }\n}\n","import { createCoreError } from \"../../core/errors\"\nimport { ErrorCodes } from \"../../utils/errors\"\nimport { resolvePaneMapping } from \"../../utils/pane-map\"\nimport type { PaneMap } from \"./shared\"\n\nexport const registerPaneWithAncestors = (map: PaneMap, virtualId: string, realId: string): void => {\n map.set(virtualId, realId)\n\n let ancestor = virtualId\n while (ancestor.includes(\".\")) {\n ancestor = ancestor.slice(0, ancestor.lastIndexOf(\".\"))\n if (!map.has(ancestor)) {\n map.set(ancestor, realId)\n } else {\n break\n }\n }\n}\n\nexport const resolveRealPaneId = (\n paneMap: PaneMap,\n virtualId: string,\n context: { readonly stepId: string },\n): string => {\n const resolved = resolvePaneMapping(paneMap, virtualId)\n if (typeof resolved === \"string\" && resolved.length > 0) {\n return resolved\n }\n\n throw createCoreError(\"execution\", {\n code: ErrorCodes.INVALID_PANE,\n message: `Unknown wezterm pane mapping for ${virtualId}`,\n path: context.stepId,\n })\n}\n","import type { CommandStep, EmittedTerminal } from \"../../core/emitter\"\nimport { createCoreError } from \"../../core/errors\"\nimport { resolveSplitOrientation, resolveSplitSize } from \"../../executor/split-step\"\nimport { prepareTerminalCommands } from \"../../executor/terminal-command-preparation\"\nimport { waitForDelay } from \"../../utils/async\"\nimport { ErrorCodes } from \"../../utils/errors\"\nimport { buildSplitArguments } from \"./dry-run\"\nimport { collectPaneIdsForWindow } from \"./layout-resolution\"\nimport type { WeztermPaneSize, WeztermRawPaneRecord } from \"./list-parser\"\nimport { registerPaneWithAncestors, resolveRealPaneId } from \"./pane-map\"\nimport type { ExecuteWeztermCommand, ListWeztermWindows, LogPaneMapping, PaneMap } from \"./shared\"\nimport { WEZTERM_MINIMUM_VERSION, type WeztermListResult } from \"./cli\"\n\nconst findNewPaneId = (before: Set<string>, after: Set<string>): string | undefined => {\n for (const paneId of after) {\n if (!before.has(paneId)) {\n return paneId\n }\n }\n return undefined\n}\n\nconst appendCarriageReturn = (value: string): string => {\n return value.endsWith(\"\\r\") ? value : `${value}\\r`\n}\n\nconst sendTextToPane = async ({\n paneId,\n text,\n runCommand,\n context,\n}: {\n readonly paneId: string\n readonly text: string\n readonly runCommand: ExecuteWeztermCommand\n readonly context: { readonly message: string; readonly path: string; readonly details?: Record<string, unknown> }\n}): Promise<void> => {\n await runCommand([\"send-text\", \"--pane-id\", paneId, \"--no-paste\", \"--\", appendCarriageReturn(text)], context)\n}\n\nexport const applyFocusStep = async ({\n step,\n paneMap,\n runCommand,\n}: {\n readonly step: CommandStep\n readonly paneMap: PaneMap\n readonly runCommand: ExecuteWeztermCommand\n}): Promise<void> => {\n const targetVirtualId = step.targetPaneId\n if (typeof targetVirtualId !== \"string\" || targetVirtualId.length === 0) {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.INVALID_PANE,\n message: \"Focus step missing target pane metadata\",\n path: step.id,\n })\n }\n\n const targetRealId = resolveRealPaneId(paneMap, targetVirtualId, { stepId: step.id })\n\n await runCommand([\"activate-pane\", \"--pane-id\", targetRealId], {\n message: `Failed to execute focus step ${step.id}`,\n path: step.id,\n })\n}\n\nexport const applySplitStep = async ({\n step,\n paneMap,\n windowId,\n runCommand,\n listWindows,\n logPaneMapping,\n detectedVersion,\n}: {\n readonly step: CommandStep\n readonly paneMap: PaneMap\n readonly windowId: string\n readonly runCommand: ExecuteWeztermCommand\n readonly listWindows: ListWeztermWindows\n readonly logPaneMapping: LogPaneMapping\n readonly detectedVersion?: string\n}): Promise<void> => {\n const targetVirtualId = step.targetPaneId\n if (typeof targetVirtualId !== \"string\" || targetVirtualId.length === 0) {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.INVALID_PANE,\n message: \"Split step missing target pane metadata\",\n path: step.id,\n })\n }\n\n const targetRealId = resolveRealPaneId(paneMap, targetVirtualId, { stepId: step.id })\n\n const beforeList = await listWindows()\n const beforePaneIds = collectPaneIdsForWindow(beforeList, windowId)\n const orientation = resolveSplitOrientation(step)\n const targetPane = findPaneById(beforeList, targetRealId)\n const paneCells = resolvePaneCellsForOrientation(targetPane?.size, orientation)\n const splitSize = resolveSplitSize(step, {\n paneCells,\n paneId: targetRealId,\n requiredVersion: WEZTERM_MINIMUM_VERSION,\n detectedVersion,\n rawPaneRecord: targetPane?.rawPaneRecord,\n })\n\n const args = buildSplitArguments({\n targetPaneId: targetRealId,\n splitSize,\n horizontal: orientation === \"horizontal\",\n })\n\n await runCommand(args, {\n message: `Failed to execute split step ${step.id}`,\n path: step.id,\n })\n\n const afterList = await listWindows()\n const afterPaneIds = collectPaneIdsForWindow(afterList, windowId)\n\n const newPaneId = findNewPaneId(beforePaneIds, afterPaneIds)\n if (typeof newPaneId !== \"string\" || newPaneId.length === 0) {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.TERMINAL_COMMAND_FAILED,\n message: \"Unable to determine newly created wezterm pane\",\n path: step.id,\n })\n }\n\n if (typeof step.createdPaneId === \"string\" && step.createdPaneId.length > 0) {\n registerPaneWithAncestors(paneMap, step.createdPaneId, newPaneId)\n logPaneMapping(step.createdPaneId, newPaneId)\n }\n}\n\nconst findPaneById = (\n list: WeztermListResult,\n paneId: string,\n):\n | {\n readonly size?: WeztermPaneSize\n readonly rawPaneRecord?: WeztermRawPaneRecord\n }\n | undefined => {\n for (const window of list.windows) {\n for (const tab of window.tabs) {\n for (const pane of tab.panes) {\n if (pane.paneId === paneId) {\n return {\n size: pane.size,\n rawPaneRecord: pane.rawPaneRecord,\n }\n }\n }\n }\n }\n return undefined\n}\n\nconst resolvePaneCellsForOrientation = (\n size: { readonly cols?: number; readonly rows?: number } | undefined,\n orientation: \"horizontal\" | \"vertical\",\n): number | undefined => {\n if (orientation === \"horizontal\") {\n return size?.cols\n }\n return size?.rows\n}\n\nexport const applyTerminalCommands = async ({\n terminals,\n paneMap,\n runCommand,\n focusPaneVirtualId,\n}: {\n readonly terminals: ReadonlyArray<EmittedTerminal>\n readonly paneMap: PaneMap\n readonly runCommand: ExecuteWeztermCommand\n readonly focusPaneVirtualId: string\n}): Promise<void> => {\n if (!paneMap.has(focusPaneVirtualId)) {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.INVALID_PANE,\n message: `Unknown focus pane: ${focusPaneVirtualId}`,\n path: focusPaneVirtualId,\n })\n }\n\n const prepared = prepareTerminalCommands({\n terminals,\n focusPaneVirtualId,\n resolveRealPaneId: (virtualPaneId: string): string =>\n resolveRealPaneId(paneMap, virtualPaneId, {\n stepId: virtualPaneId,\n }),\n onTemplateTokenError: ({ terminal, error }): never => {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.TEMPLATE_TOKEN_ERROR,\n message: `Template token resolution failed for pane ${terminal.virtualPaneId}: ${error.message}`,\n path: terminal.virtualPaneId,\n details: {\n command: terminal.command,\n tokenType: error.tokenType,\n availablePanes: error.availablePanes,\n },\n })\n },\n })\n\n for (const commandSet of prepared.commands) {\n const { terminal, realPaneId } = commandSet\n\n if (typeof commandSet.cwdCommand === \"string\") {\n await sendTextToPane({\n paneId: realPaneId,\n text: commandSet.cwdCommand,\n runCommand,\n context: {\n message: `Failed to change directory for pane ${terminal.virtualPaneId}`,\n path: terminal.virtualPaneId,\n details: { cwd: terminal.cwd },\n },\n })\n }\n\n for (const envEntry of commandSet.envCommands) {\n await sendTextToPane({\n paneId: realPaneId,\n text: envEntry.command,\n runCommand,\n context: {\n message: `Failed to set environment variable ${envEntry.key}`,\n path: terminal.virtualPaneId,\n },\n })\n }\n\n if (commandSet.command !== undefined) {\n if (commandSet.command.delayMs > 0) {\n await waitForDelay(commandSet.command.delayMs)\n }\n\n await sendTextToPane({\n paneId: realPaneId,\n text: commandSet.command.text,\n runCommand,\n context: {\n message: `Failed to execute command for pane ${terminal.virtualPaneId}`,\n path: terminal.virtualPaneId,\n details: { command: terminal.command },\n },\n })\n }\n }\n}\n","import { execFileSync } from \"node:child_process\"\nimport type { PlanEmission } from \"../../core/emitter\"\nimport { createCoreError } from \"../../core/errors\"\nimport type {\n ApplyPlanParameters,\n ApplyPlanResult,\n DryRunStep,\n TerminalBackend,\n WeztermTerminalBackendContext,\n} from \"../../executor/terminal-backend\"\nimport { ErrorCodes } from \"../../utils/errors\"\nimport type { Logger } from \"../../utils/logger\"\nimport { listWeztermWindows, runWeztermCli, verifyWeztermAvailability, type WeztermListResult } from \"./cli\"\nimport { buildDryRunSteps } from \"./dry-run\"\nimport { findWorkspaceForPane, resolveInitialPane } from \"./layout-resolution\"\nimport { parseWeztermListResult } from \"./list-parser\"\nimport { registerPaneWithAncestors } from \"./pane-map\"\nimport { applyFocusStep, applySplitStep, applyTerminalCommands } from \"./step-execution\"\nimport type { ExecuteWeztermCommand, PaneMap } from \"./shared\"\nimport { buildNameToRealIdMap } from \"../../utils/template-tokens\"\n\nconst ensureVirtualPaneId = (emission: PlanEmission): string => {\n const { initialPaneId } = emission.summary\n if (typeof initialPaneId !== \"string\" || initialPaneId.length === 0) {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.INVALID_PLAN,\n message: \"Plan emission is missing initial pane metadata\",\n path: \"plan.initialPaneId\",\n })\n }\n return initialPaneId\n}\n\nexport const createWeztermBackend = (context: WeztermTerminalBackendContext): TerminalBackend => {\n let detectedVersion: string | undefined\n\n const formatCommand = (args: ReadonlyArray<string>): string => {\n return `wezterm cli ${args.join(\" \")}`\n }\n\n const logCommand = (args: ReadonlyArray<string>): void => {\n const message = `[wezterm] ${formatCommand(args)}`\n if (context.verbose) {\n context.logger.info(message)\n } else {\n context.logger.debug(message)\n }\n }\n\n const logPaneMapping = (virtualId: string, realId: string): void => {\n const message = `[wezterm] pane ${virtualId} -> ${realId}`\n if (context.verbose) {\n context.logger.info(message)\n } else {\n context.logger.debug(message)\n }\n }\n\n const runCommand: ExecuteWeztermCommand = async (args, errorContext) => {\n const commandArgs = [...args]\n logCommand(commandArgs)\n return runWeztermCli(commandArgs, errorContext)\n }\n\n const listWindows = async (): Promise<WeztermListResult> => {\n logCommand([\"list\", \"--format\", \"json\"])\n return listWeztermWindows()\n }\n\n const verifyEnvironment = async (): Promise<void> => {\n if (context.dryRun) {\n return\n }\n const verification = await verifyWeztermAvailability()\n detectedVersion = verification.version\n }\n\n const applyPlan = async ({ emission, windowMode }: ApplyPlanParameters): Promise<ApplyPlanResult> => {\n const initialVirtualPaneId = ensureVirtualPaneId(emission)\n const paneMap: PaneMap = new Map()\n const initialTerminal = emission.terminals.find((terminal) => terminal.virtualPaneId === initialVirtualPaneId)\n const initialCwd =\n typeof initialTerminal?.cwd === \"string\" && initialTerminal.cwd.length > 0 ? initialTerminal.cwd : context.cwd\n\n let cachedInitialList: WeztermListResult | undefined\n let workspaceHint: string | undefined\n if (typeof context.paneId === \"string\" && context.paneId.length > 0) {\n try {\n cachedInitialList = await listWindows()\n workspaceHint = findWorkspaceForPane(cachedInitialList, context.paneId)\n } catch {\n cachedInitialList = undefined\n workspaceHint = undefined\n }\n }\n\n const { paneId: initialPaneId, windowId } = await resolveInitialPane({\n windowMode,\n prompt: context.prompt,\n dryRun: context.dryRun,\n listWindows,\n runCommand,\n logCommand,\n initialCwd,\n workspaceHint,\n initialList: cachedInitialList,\n preferredPaneId: context.paneId,\n })\n registerPaneWithAncestors(paneMap, initialVirtualPaneId, initialPaneId)\n logPaneMapping(initialVirtualPaneId, initialPaneId)\n\n let executedSteps = 0\n\n for (const step of emission.steps) {\n if (step.kind === \"split\") {\n await applySplitStep({\n step,\n paneMap,\n windowId,\n runCommand,\n listWindows,\n logPaneMapping,\n detectedVersion,\n })\n executedSteps += 1\n } else if (step.kind === \"focus\") {\n await applyFocusStep({\n step,\n paneMap,\n runCommand,\n })\n executedSteps += 1\n } else {\n throw createCoreError(\"execution\", {\n code: ErrorCodes.INVALID_PLAN,\n message: `Unsupported step kind in emission: ${String((step as { kind?: unknown }).kind)}`,\n path: step.id,\n })\n }\n }\n\n await applyTerminalCommands({\n terminals: emission.terminals,\n paneMap,\n runCommand,\n focusPaneVirtualId: emission.summary.focusPaneId,\n })\n\n const focusVirtual = emission.summary.focusPaneId\n const focusPaneId = typeof focusVirtual === \"string\" ? paneMap.get(focusVirtual) : undefined\n\n return {\n executedSteps,\n focusPaneId,\n paneNameToRealId: buildNameToRealIdMap(emission.terminals, paneMap),\n windowId,\n }\n }\n\n return {\n verifyEnvironment,\n applyPlan,\n getDryRunSteps: (emission: PlanEmission): DryRunStep[] => {\n const actualPaneId =\n typeof context.paneId === \"string\" && context.paneId.length > 0 ? context.paneId : process.env.WEZTERM_PANE\n const initialPaneSize = resolveInitialWeztermPaneSize({\n paneId: actualPaneId,\n logger: context.logger,\n })\n return buildDryRunSteps(emission, {\n initialPaneId: emission.summary.initialPaneId,\n initialPaneSize,\n detectedVersion,\n })\n },\n }\n}\n\nconst resolveInitialWeztermPaneSize = ({\n paneId,\n logger,\n}: {\n readonly paneId: string | undefined\n readonly logger: Logger\n}): { readonly cols: number; readonly rows: number } | undefined => {\n if (typeof paneId !== \"string\" || paneId.length === 0) {\n return undefined\n }\n\n try {\n const stdout = execFileSync(\"wezterm\", [\"cli\", \"list\", \"--format\", \"json\"], {\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n })\n const parsed = parseWeztermListResult(stdout)\n if (parsed === undefined) {\n logger.debug(`[wezterm] Failed to parse pane list while resolving initial pane size for pane ${paneId}`)\n return undefined\n }\n for (const window of parsed.windows) {\n for (const tab of window.tabs) {\n for (const pane of tab.panes) {\n if (pane.paneId === paneId) {\n if (typeof pane.size?.cols === \"number\" && typeof pane.size?.rows === \"number\") {\n return { cols: pane.size.cols, rows: pane.size.rows }\n }\n return undefined\n }\n }\n }\n }\n return undefined\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error)\n logger.debug(`[wezterm] Failed to resolve initial pane size for pane ${paneId}: ${reason}`)\n return undefined\n }\n}\n","import type {\n TerminalBackend,\n TerminalBackendContext,\n TerminalBackendKind,\n TmuxTerminalBackendContext,\n WeztermTerminalBackendContext,\n} from \"./terminal-backend\"\nimport { createTmuxBackend } from \"../backends/tmux/backend\"\nimport { createWeztermBackend } from \"../backends/wezterm/backend\"\n\nexport function createTerminalBackend(kind: \"tmux\", context: TmuxTerminalBackendContext): TerminalBackend\nexport function createTerminalBackend(kind: \"wezterm\", context: WeztermTerminalBackendContext): TerminalBackend\nexport function createTerminalBackend(kind: TerminalBackendKind, context: TerminalBackendContext): TerminalBackend {\n if (kind === \"tmux\") {\n if (!(\"executor\" in context)) {\n throw new Error(\"tmux backend requires executor context\")\n }\n return createTmuxBackend(context)\n }\n\n if (kind === \"wezterm\") {\n return createWeztermBackend(context)\n }\n\n throw new Error(`Unsupported backend \"${kind}\"`)\n}\n","import type { TerminalBackendKind } from \"./terminal-backend\"\n\ntype ResolveBackendOptions = {\n readonly cliFlag?: TerminalBackendKind\n readonly presetBackend?: TerminalBackendKind\n readonly env: NodeJS.ProcessEnv\n}\n\nconst KNOWN_BACKENDS: TerminalBackendKind[] = [\"tmux\", \"wezterm\"]\n\nexport const resolveTerminalBackendKind = ({\n cliFlag,\n presetBackend,\n env,\n}: ResolveBackendOptions): TerminalBackendKind => {\n const selectedBackend = cliFlag ?? presetBackend\n if (selectedBackend !== undefined) {\n if (!KNOWN_BACKENDS.includes(selectedBackend)) {\n throw new Error(`Unknown backend \"${selectedBackend}\"`)\n }\n return selectedBackend\n }\n\n if (typeof env.TMUX === \"string\" && env.TMUX.trim().length > 0) {\n return \"tmux\"\n }\n\n return \"tmux\"\n}\n","import { execa } from \"execa\"\nimport { replaceTemplateTokens, TemplateTokenError } from \"../utils/template-tokens\"\nimport type { Logger } from \"../utils/logger\"\n\nexport type RunHostCommand = (command: string, options: { readonly cwd: string }) => Promise<void>\n\n// Guards against a hook command that hangs indefinitely (e.g. a misbehaving sidebar\n// tool). A timed-out execution rejects, which is handled the same as any other\n// hook failure below: logged as a warning and never surfaced as a CLI error.\nconst AFTER_APPLY_HOOK_TIMEOUT_MS = 30_000\n\nexport type AfterApplyHookContext = {\n readonly cwd: string\n readonly focusPaneId?: string\n readonly paneNameToRealId?: ReadonlyMap<string, string>\n readonly windowId?: string\n}\n\ntype RunAfterApplyHookInput = {\n readonly hookCommand: string | undefined\n readonly context: AfterApplyHookContext\n readonly logger: Logger\n readonly runHostCommand?: RunHostCommand\n}\n\n// Matches the {{this_pane}}/{{focus_pane}} tokens that this module resolves to\n// context.focusPaneId (see the comment below on why they share one value).\nconst FOCUS_PANE_TOKEN_PATTERN = /\\{\\{(?:this_pane|focus_pane)\\}\\}/\n\n// Matches {{window_id}}, resolved to context.windowId (the real tmux/wezterm window\n// id the layout was applied into, e.g. tmux's \"@5\"). tmux's `-t` does not expand\n// formats, so tools like vde-tmux-sidebar need this literal passed in.\nconst WINDOW_ID_TOKEN_PATTERN = /\\{\\{window_id\\}\\}/\n\n/**\n * Runs the `hooks.afterApply` preset command once, after a preset has been applied\n * successfully. Failures (token resolution or command execution) are logged as\n * warnings and never rejected/thrown, so they cannot affect the CLI's exit code -\n * the preset apply itself has already succeeded by the time this runs.\n */\nexport const runAfterApplyHook = async ({\n hookCommand,\n context,\n logger,\n runHostCommand = createDefaultRunHostCommand(),\n}: RunAfterApplyHookInput): Promise<void> => {\n if (typeof hookCommand !== \"string\" || hookCommand.length === 0) {\n return\n }\n\n // {{this_pane}}/{{focus_pane}} resolve to context.focusPaneId (see the comment\n // below), but replaceTemplateTokens substitutes them verbatim even when given an\n // empty string - it only validates {{pane_id:<name>}} lookups. Treat a missing\n // focus pane id as an unresolved token here too, rather than silently running the\n // command with an empty pane id spliced in.\n if (context.focusPaneId === undefined && FOCUS_PANE_TOKEN_PATTERN.test(hookCommand)) {\n logger.warn(\n \"hooks.afterApply skipped: failed to resolve template tokens ({{this_pane}}/{{focus_pane}} require a focus pane id, but none was available)\",\n )\n return\n }\n\n // {{window_id}} resolves to context.windowId. replaceTemplateTokens already throws\n // TemplateTokenError for this case (caught below), but that generic message doesn't\n // mention \"window id\" specifically; this guard produces a clearer warning up front\n // and doubles as defense-in-depth if that throw behavior ever changes.\n if (context.windowId === undefined && WINDOW_ID_TOKEN_PATTERN.test(hookCommand)) {\n logger.warn(\n \"hooks.afterApply skipped: failed to resolve template tokens ({{window_id}} requires a window id, but none was available)\",\n )\n return\n }\n\n let resolvedCommand: string\n try {\n resolvedCommand = replaceTemplateTokens({\n command: hookCommand,\n // A host-level hook is not \"sent\" to any particular tmux/wezterm pane the way\n // a terminal pane command is, so there is no distinct \"current pane\" for it.\n // The pane that ends up focused after the layout was applied is the closest\n // analogue, so {{this_pane}} and {{focus_pane}} intentionally resolve to the\n // same value here.\n currentPaneRealId: context.focusPaneId ?? \"\",\n focusPaneRealId: context.focusPaneId ?? \"\",\n nameToRealIdMap: context.paneNameToRealId ?? new Map<string, string>(),\n windowId: context.windowId,\n })\n } catch (error) {\n const reason = error instanceof TemplateTokenError ? error.message : String(error)\n logger.warn(`hooks.afterApply skipped: failed to resolve template tokens (${reason})`)\n return\n }\n\n // Mirrors real-executor.ts's \"Executing: <command>\" log; logger.info is already\n // gated on --verbose/VDE_VERBOSE by the shared logger implementation.\n logger.info(`Executing: ${resolvedCommand}`)\n\n try {\n await runHostCommand(resolvedCommand, { cwd: context.cwd })\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error)\n logger.warn(`hooks.afterApply failed: ${reason}`)\n }\n}\n\n/**\n * Executes the resolved hook command through the host shell (equivalent to\n * `sh -c <command>`), rather than splitting it into argv the way tmux commands\n * are executed. hooks.afterApply commands are user-authored, free-form shell\n * text (e.g. \"vde-tmux-sidebar open {{pane_id:sidebar}} | logger\") that may rely\n * on pipes, redirection, or shell expansion, so argv-style execution would break\n * common use cases.\n */\nexport const createDefaultRunHostCommand = (): RunHostCommand => {\n return async (command, { cwd }) => {\n await execa(command, { shell: true, cwd, timeout: AFTER_APPLY_HOOK_TIMEOUT_MS })\n }\n}\n","import chalk from \"chalk\"\n\nimport type { WindowMode } from \"../models/types\"\nimport type { DryRunStep } from \"../executor/terminal-backend\"\n\nexport const renderDryRun = (\n steps: ReadonlyArray<DryRunStep>,\n output: (message: string) => void = (message): void => console.log(message),\n): void => {\n output(chalk.bold(\"\\nPlanned terminal steps (dry-run)\"))\n steps.forEach((step, index) => {\n output(` ${index + 1}. [${step.backend}] ${step.summary}: ${step.command}`)\n })\n}\n\nexport const renderDryRunHook = (\n afterApply: string | undefined,\n output: (message: string) => void = (message): void => console.log(message),\n): void => {\n if (typeof afterApply !== \"string\" || afterApply.length === 0) {\n return\n }\n\n // Dry-run has not created any panes, so pane ids aren't known yet; show the raw,\n // unresolved hook command rather than attempting template token resolution.\n output(chalk.bold(\"\\nPlanned hooks (dry-run)\"))\n output(` 1. [afterApply] ${afterApply}`)\n}\n\nexport const buildPresetSource = (presetName?: string): string => {\n return typeof presetName === \"string\" && presetName.length > 0 ? `preset://${presetName}` : \"preset://default\"\n}\n\nexport const determineCliWindowMode = (options: {\n currentWindow?: boolean\n newWindow?: boolean\n}): WindowMode | undefined => {\n if (options.currentWindow === true && options.newWindow === true) {\n throw new Error(\"Cannot use --current-window and --new-window at the same time\")\n }\n\n if (options.currentWindow === true) {\n return \"current-window\"\n }\n\n if (options.newWindow === true) {\n return \"new-window\"\n }\n\n return undefined\n}\n","import { createInterface } from \"node:readline/promises\"\nimport { stdin as input, stdout as output } from \"node:process\"\nimport type { ConfirmPaneClosure, ConfirmPaneClosureContext } from \"../contracts\"\nimport type { Logger } from \"../utils/logger\"\n\nexport const createPaneKillPrompter = (logger: Logger): ConfirmPaneClosure => {\n return async ({ panesToClose, dryRun }: ConfirmPaneClosureContext): Promise<boolean> => {\n if (panesToClose.length === 0) {\n return true\n }\n\n const paneList = panesToClose.join(\", \")\n\n if (dryRun) {\n logger.warn(`[DRY RUN] Would close panes: ${paneList}`)\n return true\n }\n\n logger.warn(`This operation will close the following panes: ${paneList}`)\n\n if (input.isTTY !== true || output.isTTY !== true) {\n logger.error(\"Cannot prompt for confirmation because the terminal is not interactive\")\n return false\n }\n\n const rl = createInterface({ input, output })\n try {\n const answer = await rl.question(\"Continue? [y/N]: \")\n const normalized = answer.trim().toLowerCase()\n return normalized === \"y\" || normalized === \"yes\"\n } finally {\n rl.close()\n }\n }\n}\n","import type { WindowMode } from \"../models/types\"\n\ntype WindowModeSource = {\n readonly cli?: WindowMode\n readonly preset?: WindowMode\n readonly defaults?: WindowMode\n}\n\ntype WindowModeResolutionSource = \"cli\" | \"preset\" | \"defaults\" | \"fallback\"\n\ntype WindowModeResolution = {\n readonly mode: WindowMode\n readonly source: WindowModeResolutionSource\n}\n\nexport const resolveWindowMode = ({ cli, preset, defaults }: WindowModeSource): WindowModeResolution => {\n if (cli !== undefined) {\n return { mode: cli, source: \"cli\" }\n }\n\n if (preset !== undefined) {\n return { mode: preset, source: \"preset\" }\n }\n\n if (defaults !== undefined) {\n return { mode: defaults, source: \"defaults\" }\n }\n\n return { mode: \"new-window\", source: \"fallback\" }\n}\n","import { createTerminalBackend } from \"../executor/backend-factory\"\nimport { resolveTerminalBackendKind } from \"../executor/backend-resolver\"\nimport type { TerminalBackendKind } from \"../executor/terminal-backend\"\nimport type { CompiledPreset } from \"../core/index\"\nimport type { WindowMode } from \"../models/types\"\nimport type { CommandExecutor } from \"../contracts\"\nimport type { PresetManager } from \"../contracts\"\nimport type { Logger } from \"../utils/logger\"\nimport { runAfterApplyHook } from \"./after-apply-hook\"\nimport { buildPresetSource, determineCliWindowMode, renderDryRun, renderDryRunHook } from \"./command-helpers\"\nimport type { CoreBridge } from \"./core-bridge\"\nimport { createPaneKillPrompter } from \"./user-prompt\"\nimport { resolveWindowMode } from \"./window-mode\"\n\ntype ExecutePresetCliOptions = {\n readonly verbose: boolean\n readonly dryRun: boolean\n readonly currentWindow: boolean\n readonly newWindow: boolean\n readonly backend?: string\n}\n\ntype ExecutePresetInput = {\n readonly presetName: string | undefined\n readonly options: ExecutePresetCliOptions\n readonly skipLoadConfig?: boolean\n readonly presetManager: PresetManager\n readonly createCommandExecutor: (options: { verbose: boolean; dryRun: boolean }) => CommandExecutor\n readonly core: CoreBridge\n readonly logger: Logger\n readonly handleError: (error: unknown) => number\n readonly handlePipelineFailure: (error: unknown) => number\n readonly output?: (line: string) => void\n readonly cwd?: string\n readonly env?: NodeJS.ProcessEnv\n}\n\nexport const executePreset = async ({\n presetName,\n options,\n skipLoadConfig = false,\n presetManager,\n createCommandExecutor,\n core,\n logger,\n handleError,\n handlePipelineFailure,\n output = (line: string): void => console.log(line),\n cwd = process.cwd(),\n env = process.env,\n}: ExecutePresetInput): Promise<number> => {\n try {\n if (skipLoadConfig !== true) {\n await presetManager.loadConfig()\n }\n\n const preset =\n typeof presetName === \"string\" && presetName.length > 0\n ? presetManager.getPreset(presetName)\n : presetManager.getDefaultPreset()\n\n const windowModeResolution = resolveWindowModeForPreset({\n presetManager,\n options,\n presetWindowMode: preset.windowMode,\n })\n const windowMode = windowModeResolution.mode\n logger.info(`Window mode: ${windowMode} (source: ${windowModeResolution.source})`)\n const confirmPaneClosure = createPaneKillPrompter(logger)\n\n const executor = createCommandExecutor({\n verbose: options.verbose,\n dryRun: options.dryRun,\n })\n\n const backendKind = resolveTerminalBackendKind({\n cliFlag: options.backend as TerminalBackendKind | undefined,\n presetBackend: preset.backend,\n env,\n })\n logger.info(`Terminal backend: ${backendKind}`)\n const backendContextBase = {\n logger,\n dryRun: options.dryRun,\n verbose: options.verbose,\n prompt: confirmPaneClosure,\n cwd,\n paneId: env.WEZTERM_PANE,\n } as const\n\n const backend =\n backendKind === \"tmux\"\n ? createTerminalBackend(\"tmux\", {\n ...backendContextBase,\n executor,\n })\n : createTerminalBackend(\"wezterm\", backendContextBase)\n\n await backend.verifyEnvironment()\n\n if (options.dryRun === true) {\n output(\"[DRY RUN] No actual commands will be executed\")\n }\n\n let emission\n let compiledPreset: CompiledPreset\n try {\n const built = buildPlanEmission({\n core,\n preset,\n presetName,\n })\n emission = built.emission\n compiledPreset = built.compiledPreset\n } catch (error) {\n return handlePipelineFailure(error)\n }\n\n if (options.dryRun === true) {\n const dryRunSteps = backend.getDryRunSteps(emission)\n renderDryRun(dryRunSteps, output)\n renderDryRunHook(compiledPreset.hooks?.afterApply, output)\n } else {\n try {\n const executionResult = await backend.applyPlan({\n emission,\n windowMode,\n windowName: resolveWindowName({\n presetName,\n presetDisplayName: preset.name,\n }),\n })\n logger.info(`Executed ${executionResult.executedSteps} ${backendKind} steps`)\n\n const afterApplyCommand = compiledPreset.hooks?.afterApply\n if (afterApplyCommand !== undefined) {\n await runAfterApplyHook({\n hookCommand: afterApplyCommand,\n context: {\n cwd,\n focusPaneId: executionResult.focusPaneId,\n paneNameToRealId: executionResult.paneNameToRealId,\n windowId: executionResult.windowId,\n },\n logger,\n })\n }\n } catch (error) {\n return handlePipelineFailure(error)\n }\n }\n\n logger.success(`Applied preset \"${preset.name}\"`)\n return 0\n } catch (error) {\n return handleError(error)\n }\n}\n\nconst buildPlanEmission = ({\n core,\n preset,\n presetName,\n}: {\n readonly core: CoreBridge\n readonly preset: ReturnType<PresetManager[\"getDefaultPreset\"]>\n readonly presetName?: string\n}): {\n readonly emission: ReturnType<CoreBridge[\"emitPlan\"]>\n readonly compiledPreset: CompiledPreset\n} => {\n const compileResult = core.compilePresetFromValue({\n value: preset,\n source: buildPresetSource(presetName),\n })\n const planResult = core.createLayoutPlan({ preset: compileResult.preset })\n const emission = core.emitPlan({ plan: planResult.plan })\n return { emission, compiledPreset: compileResult.preset }\n}\n\nconst resolveWindowName = ({\n presetName,\n presetDisplayName,\n}: {\n readonly presetName: string | undefined\n readonly presetDisplayName?: string\n}): string => {\n return presetDisplayName ?? presetName ?? \"vde-layout\"\n}\n\nconst resolveWindowModeForPreset = ({\n presetManager,\n options,\n presetWindowMode,\n}: {\n readonly presetManager: PresetManager\n readonly options: ExecutePresetCliOptions\n readonly presetWindowMode: WindowMode | undefined\n}): ReturnType<typeof resolveWindowMode> => {\n const cliWindowMode = determineCliWindowMode({\n currentWindow: options.currentWindow,\n newWindow: options.newWindow,\n })\n const defaults = presetManager.getDefaults()\n return resolveWindowMode({\n cli: cliWindowMode,\n preset: presetWindowMode,\n defaults: defaults?.windowMode,\n })\n}\n","import { SELECT_SURFACE_MODES, SELECT_UI_MODES } from \"../models/schema\"\n\nexport const selectUiModes = SELECT_UI_MODES\nexport const selectSurfaceModes = SELECT_SURFACE_MODES\n\nexport type SelectUiMode = (typeof selectUiModes)[number]\nexport type SelectSurfaceMode = (typeof selectSurfaceModes)[number]\n\nconst selectUiModeSet = new Set<string>(selectUiModes)\nconst selectSurfaceModeSet = new Set<string>(selectSurfaceModes)\n\nconst isSelectUiMode = (value: string): value is SelectUiMode => {\n return selectUiModeSet.has(value)\n}\n\nconst isSelectSurfaceMode = (value: string): value is SelectSurfaceMode => {\n return selectSurfaceModeSet.has(value)\n}\n\nexport const normalizeSelectArgs = (args: readonly string[]): string[] => {\n const normalized: string[] = []\n\n for (let index = 0; index < args.length; index += 1) {\n const token = args[index]\n if (typeof token !== \"string\") {\n continue\n }\n\n if (token === \"--\") {\n normalized.push(...args.slice(index))\n break\n }\n\n if (typeof token === \"string\" && token.startsWith(\"--select=\")) {\n const mode = token.slice(\"--select=\".length)\n normalized.push(\"--select\")\n if (mode.length > 0) {\n normalized.push(\"--select-ui\", mode)\n }\n continue\n }\n\n if (token === \"--select\") {\n const nextToken = args[index + 1]\n if (typeof nextToken === \"string\" && isSelectUiMode(nextToken)) {\n normalized.push(\"--select\", \"--select-ui\", nextToken)\n index += 1\n continue\n }\n }\n\n normalized.push(token)\n }\n\n return normalized\n}\n\nexport const resolveSelectUiMode = (uiValue: string | undefined): SelectUiMode => {\n if (uiValue === undefined) {\n return \"auto\"\n }\n\n if (isSelectUiMode(uiValue)) {\n return uiValue\n }\n\n throw new Error(`Invalid value for --select-ui: \"${uiValue}\". Expected one of: ${selectUiModes.join(\", \")}`)\n}\n\nexport const resolveSelectSurfaceMode = (surfaceValue: string | undefined): SelectSurfaceMode => {\n if (surfaceValue === undefined) {\n return \"auto\"\n }\n\n if (isSelectSurfaceMode(surfaceValue)) {\n return surfaceValue\n }\n\n throw new Error(\n `Invalid value for --select-surface: \"${surfaceValue}\". Expected one of: ${selectSurfaceModes.join(\", \")}`,\n )\n}\n","import { Chalk } from \"chalk\"\nimport { execa } from \"execa\"\nimport stringWidth from \"string-width\"\nimport * as YAML from \"yaml\"\nimport type { PresetManager } from \"../contracts\"\nimport type { Preset, PresetInfo } from \"../models/types\"\nimport type { Logger } from \"../utils/logger\"\nimport { createEnvironmentError, ErrorCodes } from \"../utils/errors\"\nimport type { SelectSurfaceMode, SelectUiMode } from \"./select-args\"\n\nconst FZF_BINARY = \"fzf\"\nconst FZF_CHECK_TIMEOUT_MS = 5_000\nconst MAX_PREVIEW_BASE64_LENGTH = 64 * 1024\nconst RESERVED_FZF_ARGS = new Set([\"delimiter\", \"with-nth\", \"ansi\", \"preview\", \"preview-window\", \"tmux\"])\nconst selectorChalk = new Chalk({ level: 1 })\n\ntype ExecaLikeError = Error & {\n readonly code?: string\n readonly exitCode?: number\n readonly timedOut?: boolean\n}\n\ntype RunFzfInput = {\n readonly args: string[]\n readonly input: string\n readonly cwd: string\n readonly env: NodeJS.ProcessEnv\n}\n\ntype RunFzfResult = {\n readonly stdout: string\n}\n\nexport type SelectPresetResult =\n | {\n readonly status: \"selected\"\n readonly presetName: string\n }\n | {\n readonly status: \"cancelled\"\n }\n\nexport type SelectPresetInput = {\n readonly uiMode: SelectUiMode\n readonly surfaceMode: SelectSurfaceMode\n readonly tmuxPopupOptions?: string\n readonly fzfExtraArgs?: ReadonlyArray<string>\n readonly presetManager: PresetManager\n readonly logger: Logger\n readonly skipLoadConfig?: boolean\n readonly cwd?: string\n readonly env?: NodeJS.ProcessEnv\n readonly isInteractive?: () => boolean\n readonly checkFzfAvailability?: () => Promise<boolean>\n readonly runFzf?: (input: RunFzfInput) => Promise<RunFzfResult>\n}\n\ntype PresetRow = {\n readonly key: string\n readonly name: string\n readonly description: string\n readonly display: string\n readonly previewBase64: string\n}\n\ntype BuildPresetPreviewYamlInput = {\n readonly presetKey: string\n readonly preset: Preset\n}\n\nconst sanitizeTsvCell = (value: string | undefined): string => {\n return (value ?? \"\").replace(/[\\t\\r\\n]+/g, \" \")\n}\n\nconst padDisplayCell = (value: string, width: number): string => {\n const paddingLength = Math.max(0, width - stringWidth(value))\n return `${value}${\" \".repeat(paddingLength)}`\n}\n\nexport const buildPresetPreviewYaml = ({ presetKey, preset }: BuildPresetPreviewYamlInput): string => {\n return YAML.stringify({\n presets: {\n [presetKey]: preset,\n },\n })\n}\n\nconst defaultCheckFzfAvailability = async (): Promise<boolean> => {\n try {\n await execa(FZF_BINARY, [\"--version\"], {\n timeout: FZF_CHECK_TIMEOUT_MS,\n })\n return true\n } catch (error) {\n const execaError = error as ExecaLikeError\n if (\n execaError.code === \"ENOENT\" ||\n execaError.code === \"ETIMEDOUT\" ||\n execaError.code === \"ERR_EXECA_TIMEOUT\" ||\n execaError.timedOut === true\n ) {\n return false\n }\n throw error\n }\n}\n\nconst defaultRunFzf = async ({ args, input, cwd, env }: RunFzfInput): Promise<RunFzfResult> => {\n const result = await execa(FZF_BINARY, args, {\n input,\n cwd,\n env,\n stderr: \"inherit\",\n })\n return { stdout: result.stdout }\n}\n\nconst ensureFzfAvailable = async (checkFzfAvailability: () => Promise<boolean>): Promise<void> => {\n const available = await checkFzfAvailability()\n if (available) {\n return\n }\n\n throw createEnvironmentError(\"fzf is required for preset selection UI\", ErrorCodes.BACKEND_NOT_FOUND, {\n backend: \"fzf\",\n binary: FZF_BINARY,\n })\n}\n\nconst isTmuxSession = (env: NodeJS.ProcessEnv): boolean => {\n return typeof env.TMUX === \"string\" && env.TMUX.length > 0\n}\n\nconst resolveSurfaceMode = ({\n surfaceMode,\n env,\n}: {\n readonly surfaceMode: SelectSurfaceMode\n readonly env: NodeJS.ProcessEnv\n}): Exclude<SelectSurfaceMode, \"auto\"> => {\n if (surfaceMode === \"auto\") {\n return isTmuxSession(env) ? \"tmux-popup\" : \"inline\"\n }\n return surfaceMode\n}\n\nconst validateExtraFzfArgs = (fzfExtraArgs: ReadonlyArray<string>): void => {\n for (const arg of fzfExtraArgs) {\n if (typeof arg !== \"string\" || arg.length === 0) {\n throw new Error(\"Empty value is not allowed for --fzf-arg\")\n }\n\n if (!arg.startsWith(\"--\")) {\n continue\n }\n\n const withoutPrefix = arg.slice(2)\n if (withoutPrefix.length === 0) {\n continue\n }\n const optionName = withoutPrefix.split(\"=\")[0]\n if (optionName !== undefined && RESERVED_FZF_ARGS.has(optionName)) {\n throw new Error(`--fzf-arg cannot override reserved fzf option: --${optionName}`)\n }\n }\n}\n\nconst buildFzfArgs = ({\n surfaceMode,\n tmuxPopupOptions,\n fzfExtraArgs,\n env,\n}: {\n readonly surfaceMode: SelectSurfaceMode\n readonly tmuxPopupOptions: string | undefined\n readonly fzfExtraArgs: ReadonlyArray<string>\n readonly env: NodeJS.ProcessEnv\n}): string[] => {\n validateExtraFzfArgs(fzfExtraArgs)\n\n const resolvedSurfaceMode = resolveSurfaceMode({\n surfaceMode,\n env,\n })\n\n if (resolvedSurfaceMode === \"tmux-popup\" && isTmuxSession(env) !== true) {\n throw new Error(\"tmux popup selector surface requires running inside tmux\")\n }\n\n const surfaceArgs =\n resolvedSurfaceMode === \"tmux-popup\"\n ? [tmuxPopupOptions !== undefined ? `--tmux=${tmuxPopupOptions}` : \"--tmux\"]\n : []\n\n return [\n \"--delimiter=\\\\t\",\n \"--ansi\",\n \"--with-nth=2\",\n \"--prompt=preset> \",\n \"--layout=reverse\",\n \"--height=80%\",\n \"--border\",\n '--preview=node -e \\'process.stdout.write(Buffer.from(process.argv[1], \"base64\").toString(\"utf8\"))\\' {3}',\n \"--preview-window=right,60%,border-left,wrap\",\n ...surfaceArgs,\n ...fzfExtraArgs,\n ]\n}\n\nconst toPresetRows = ({\n presetInfos,\n presetManager,\n}: {\n readonly presetInfos: ReadonlyArray<PresetInfo>\n readonly presetManager: PresetManager\n}): ReadonlyArray<PresetRow> => {\n const rows = presetInfos.map((presetInfo) => {\n const key = sanitizeTsvCell(presetInfo.key)\n const name = sanitizeTsvCell(presetInfo.name)\n const description = sanitizeTsvCell(presetInfo.description)\n const preset = presetManager.getPreset(presetInfo.key)\n const previewYaml = buildPresetPreviewYaml({\n presetKey: presetInfo.key,\n preset,\n })\n const previewBase64 = Buffer.from(previewYaml, \"utf8\").toString(\"base64\")\n if (previewBase64.length > MAX_PREVIEW_BASE64_LENGTH) {\n throw new Error(\n `Preset preview is too large for fzf inline preview payload: \"${presetInfo.key}\" (${previewBase64.length} bytes)`,\n )\n }\n return {\n key,\n name,\n description,\n previewBase64,\n }\n })\n\n const keyColumnWidth = rows.reduce((maxWidth, row) => Math.max(maxWidth, stringWidth(row.key)), 0)\n const nameColumnWidth = rows.reduce((maxWidth, row) => Math.max(maxWidth, stringWidth(row.name)), 0)\n\n return rows.map((row) => {\n const key = padDisplayCell(row.key, keyColumnWidth)\n const name = padDisplayCell(row.name, nameColumnWidth)\n const description = row.description.length > 0 ? row.description : selectorChalk.gray(\"(no description)\")\n const display = `${selectorChalk.cyan(key)} ${selectorChalk.bold(name)} ${selectorChalk.dim(description)}`\n\n return {\n key: row.key,\n name: row.name,\n description: row.description,\n display,\n previewBase64: row.previewBase64,\n }\n })\n}\n\nconst buildFzfInput = (rows: ReadonlyArray<PresetRow>): string => {\n return rows\n .map((row, index) => {\n return [String(index), row.display, row.previewBase64].join(\"\\t\")\n })\n .join(\"\\n\")\n}\n\nconst parseSelectedPresetName = ({\n selectedLine,\n rows,\n}: {\n readonly selectedLine: string\n readonly rows: ReadonlyArray<PresetRow>\n}): string | null => {\n const trimmed = selectedLine.trim()\n if (trimmed.length === 0) {\n return null\n }\n\n const idCell = trimmed.split(\"\\t\")[0]\n const id = Number(idCell)\n if (!Number.isInteger(id) || id < 0 || id >= rows.length) {\n throw new Error(\"Invalid selection returned from fzf\")\n }\n\n return rows[id]?.key ?? null\n}\n\nconst runFzfSelector = async ({\n rows,\n fzfArgs,\n runFzf,\n cwd,\n env,\n}: {\n readonly rows: ReadonlyArray<PresetRow>\n readonly fzfArgs: ReadonlyArray<string>\n readonly runFzf: (input: RunFzfInput) => Promise<RunFzfResult>\n readonly cwd: string\n readonly env: NodeJS.ProcessEnv\n}): Promise<SelectPresetResult> => {\n try {\n const result = await runFzf({\n input: buildFzfInput(rows),\n args: [...fzfArgs],\n cwd,\n env,\n })\n\n const presetName = parseSelectedPresetName({\n selectedLine: result.stdout,\n rows,\n })\n if (presetName === null) {\n return { status: \"cancelled\" }\n }\n\n return {\n status: \"selected\",\n presetName,\n }\n } catch (error) {\n const execaError = error as ExecaLikeError\n if (execaError.exitCode === 130) {\n return { status: \"cancelled\" }\n }\n throw error\n }\n}\n\nexport const selectPreset = async ({\n uiMode,\n surfaceMode,\n tmuxPopupOptions,\n fzfExtraArgs = [],\n presetManager,\n logger,\n skipLoadConfig = false,\n cwd = process.cwd(),\n env = process.env,\n isInteractive = (): boolean =>\n process.stdin.isTTY === true && process.stdout.isTTY === true && process.stderr.isTTY === true,\n checkFzfAvailability = defaultCheckFzfAvailability,\n runFzf = defaultRunFzf,\n}: SelectPresetInput): Promise<SelectPresetResult> => {\n if (isInteractive() !== true) {\n throw new Error(\"Preset selection requires an interactive terminal\")\n }\n\n await ensureFzfAvailable(checkFzfAvailability)\n if (skipLoadConfig !== true) {\n await presetManager.loadConfig()\n }\n\n const presetInfos = presetManager.listPresets()\n if (presetInfos.length === 0) {\n throw new Error(\"No presets defined\")\n }\n\n const fzfArgs = buildFzfArgs({\n surfaceMode,\n tmuxPopupOptions,\n fzfExtraArgs,\n env,\n })\n\n logger.debug(`Preset selection UI: ${uiMode}`)\n\n const rows = toPresetRows({\n presetInfos,\n presetManager,\n })\n return runFzfSelector({\n rows,\n fzfArgs,\n runFzf,\n cwd,\n env,\n })\n}\n","import { defineCommand, parseArgs, renderUsage } from \"citty\"\nimport type { ArgsDef } from \"citty\"\nimport { createRequire } from \"module\"\nimport { createPresetManager } from \"../layout/preset\"\nimport { loadPackageVersion } from \"./package-version\"\nimport { createCliErrorHandlers } from \"./error-handling\"\nimport { applyRuntimeOptions, listPresets } from \"./runtime-and-list\"\nimport { executePreset } from \"./preset-execution\"\nimport type { CommandExecutor } from \"../contracts\"\nimport type { PresetManager } from \"../contracts\"\nimport { createRealExecutor, createDryRunExecutor } from \"../executor/index\"\nimport { createLogger, type Logger } from \"../utils/logger\"\nimport {\n normalizeSelectArgs,\n resolveSelectSurfaceMode,\n resolveSelectUiMode,\n selectSurfaceModes,\n selectUiModes,\n} from \"./select-args\"\nimport { selectPreset as defaultSelectPreset, type SelectPresetInput, type SelectPresetResult } from \"./preset-selector\"\nimport {\n compilePreset as defaultCompilePreset,\n compilePresetFromValue as defaultCompilePresetFromValue,\n createLayoutPlan as defaultCreateLayoutPlan,\n emitPlan as defaultEmitPlan,\n} from \"../core/index\"\nimport type { CoreBridge } from \"./core-bridge\"\nexport type { CoreBridge } from \"./core-bridge\"\n\ntype CLIOptions = {\n readonly presetManager?: PresetManager\n readonly createCommandExecutor?: (options: { verbose: boolean; dryRun: boolean }) => CommandExecutor\n readonly core?: CoreBridge\n readonly selectPreset?: (input: SelectPresetInput) => Promise<SelectPresetResult>\n}\n\nexport type CLI = {\n run(args?: string[]): Promise<number>\n}\n\nconst backendValues = [\"tmux\", \"wezterm\"] as const\nconst listCommandName = \"list\"\nconst EXIT_CODE_CANCELLED = 130\n\ntype OptionValueKind = \"boolean\" | \"value\"\n\ntype OptionSpec = {\n readonly kind: OptionValueKind\n readonly allowOptionLikeValue: boolean\n}\n\ntype OptionSpecs = {\n readonly longOptions: Map<string, OptionSpec>\n readonly shortOptions: Map<string, OptionSpec>\n}\n\nconst optionNamesAllowOptionLikeValue = new Set([\"fzfArg\", \"fzf-arg\"])\n\nconst toKebabCase = (value: string): string => {\n return value.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`)\n}\n\nconst toOptionSpec = (kind: OptionValueKind, optionName: string): OptionSpec => {\n return {\n kind,\n allowOptionLikeValue: optionNamesAllowOptionLikeValue.has(optionName),\n }\n}\n\nconst buildOptionSpecs = (argsDef: Readonly<ArgsDef>): OptionSpecs => {\n const longOptions = new Map<string, OptionSpec>()\n const shortOptions = new Map<string, OptionSpec>()\n\n for (const [argName, arg] of Object.entries(argsDef)) {\n if (arg.type === \"positional\") {\n continue\n }\n\n const valueKind: OptionValueKind = arg.type === \"boolean\" ? \"boolean\" : \"value\"\n const kebabName = toKebabCase(argName)\n longOptions.set(argName, toOptionSpec(valueKind, argName))\n longOptions.set(kebabName, toOptionSpec(valueKind, kebabName))\n\n const aliases =\n \"alias\" in arg ? (Array.isArray(arg.alias) ? arg.alias : typeof arg.alias === \"string\" ? [arg.alias] : []) : []\n for (const alias of aliases) {\n if (alias.length === 1) {\n shortOptions.set(alias, toOptionSpec(valueKind, alias))\n continue\n }\n\n longOptions.set(alias, toOptionSpec(valueKind, alias))\n const kebabAlias = toKebabCase(alias)\n longOptions.set(kebabAlias, toOptionSpec(valueKind, kebabAlias))\n }\n }\n\n return { longOptions, shortOptions }\n}\n\nconst validateRawOptions = (args: readonly string[], optionSpecs: OptionSpecs): void => {\n for (let index = 0; index < args.length; index += 1) {\n const token = args[index]\n if (typeof token !== \"string\") {\n continue\n }\n\n if (token === \"--\") {\n break\n }\n\n if (!token.startsWith(\"-\") || token === \"-\") {\n continue\n }\n\n if (token.startsWith(\"--\")) {\n const value = token.slice(2)\n if (value.length === 0) {\n continue\n }\n\n const separatorIndex = value.indexOf(\"=\")\n const rawOptionName = separatorIndex >= 0 ? value.slice(0, separatorIndex) : value\n const optionName = rawOptionName.startsWith(\"no-\") ? rawOptionName.slice(3) : rawOptionName\n const optionSpec = optionSpecs.longOptions.get(optionName)\n const kind = optionSpec?.kind\n\n if (kind === undefined) {\n throw new Error(`Unknown option: --${rawOptionName}`)\n }\n\n if (kind === \"value\") {\n if (separatorIndex >= 0) {\n const inlineValue = value.slice(separatorIndex + 1)\n if (inlineValue.length === 0) {\n throw new Error(`Missing value for option: --${optionName}`)\n }\n } else {\n const nextToken = args[index + 1]\n if (typeof nextToken !== \"string\" || nextToken.length === 0) {\n throw new Error(`Missing value for option: --${optionName}`)\n }\n if (nextToken.startsWith(\"-\") && optionSpec?.allowOptionLikeValue !== true) {\n throw new Error(`Missing value for option: --${optionName}`)\n }\n index += 1\n }\n }\n continue\n }\n\n const shortFlags = token.slice(1)\n for (let flagIndex = 0; flagIndex < shortFlags.length; flagIndex += 1) {\n const option = shortFlags[flagIndex]\n if (typeof option !== \"string\" || option.length === 0) {\n continue\n }\n\n const optionSpec = optionSpecs.shortOptions.get(option)\n const kind = optionSpec?.kind\n if (kind === undefined) {\n throw new Error(`Unknown option: -${option}`)\n }\n\n if (kind === \"value\") {\n if (flagIndex < shortFlags.length - 1) {\n break\n }\n\n const nextToken = args[index + 1]\n if (typeof nextToken !== \"string\" || nextToken.length === 0) {\n throw new Error(`Missing value for option: -${option}`)\n }\n if (nextToken.startsWith(\"-\") && optionSpec?.allowOptionLikeValue !== true) {\n throw new Error(`Missing value for option: -${option}`)\n }\n index += 1\n break\n }\n }\n }\n}\n\nconst getPositionals = (args: { readonly _: unknown[] }): string[] => {\n return args._.filter((value): value is string => typeof value === \"string\")\n}\n\nconst collectOptionValues = ({\n args,\n optionNames,\n}: {\n readonly args: readonly string[]\n readonly optionNames: ReadonlyArray<string>\n}): string[] => {\n const values: string[] = []\n const optionNameSet = new Set(optionNames)\n\n for (let index = 0; index < args.length; index += 1) {\n const token = args[index]\n if (typeof token !== \"string\") {\n continue\n }\n\n if (token === \"--\") {\n break\n }\n\n if (!token.startsWith(\"--\")) {\n continue\n }\n\n const eqIndex = token.indexOf(\"=\")\n const rawName = eqIndex >= 0 ? token.slice(2, eqIndex) : token.slice(2)\n if (optionNameSet.has(rawName) !== true) {\n continue\n }\n\n if (eqIndex >= 0) {\n values.push(token.slice(eqIndex + 1))\n continue\n }\n\n const nextToken = args[index + 1]\n if (typeof nextToken === \"string\") {\n values.push(nextToken)\n index += 1\n }\n }\n\n return values\n}\n\nexport const createCli = (options: CLIOptions = {}): CLI => {\n const presetManager = options.presetManager ?? createPresetManager()\n const createCommandExecutor =\n options.createCommandExecutor ??\n ((opts: { verbose: boolean; dryRun: boolean }): CommandExecutor => {\n if (opts.dryRun) {\n return createDryRunExecutor({ verbose: opts.verbose })\n }\n return createRealExecutor({ verbose: opts.verbose })\n })\n const selectPreset = options.selectPreset ?? defaultSelectPreset\n\n const core: CoreBridge =\n options.core ??\n ({\n compilePreset: defaultCompilePreset,\n compilePresetFromValue: defaultCompilePresetFromValue,\n createLayoutPlan: defaultCreateLayoutPlan,\n emitPlan: defaultEmitPlan,\n } as const)\n\n const require = createRequire(import.meta.url)\n const version = loadPackageVersion(require)\n let logger: Logger = createLogger()\n const errorHandlers = createCliErrorHandlers({\n getLogger: () => logger,\n })\n\n const rootArgsDef = {\n preset: {\n type: \"positional\",\n description: 'Preset name (defaults to \"default\" preset when omitted)',\n required: false,\n },\n verbose: {\n type: \"boolean\",\n description: \"Show detailed logs\",\n },\n dryRun: {\n type: \"boolean\",\n description: \"Display commands without executing\",\n },\n backend: {\n type: \"enum\",\n options: [...backendValues],\n description: \"Select terminal backend (tmux or wezterm)\",\n },\n config: {\n type: \"string\",\n valueHint: \"path\",\n description: \"Path to configuration file\",\n },\n currentWindow: {\n type: \"boolean\",\n description: \"Use the current tmux window for layout (kills other panes)\",\n },\n newWindow: {\n type: \"boolean\",\n description: \"Always create a new tmux window for layout\",\n },\n select: {\n type: \"boolean\",\n description: \"Select preset from interactive UI\",\n },\n selectUi: {\n type: \"enum\",\n options: [...selectUiModes],\n description: \"Select preset UI backend (auto or fzf)\",\n },\n selectSurface: {\n type: \"enum\",\n options: [...selectSurfaceModes],\n description: \"Select selector surface mode (auto, inline, or tmux-popup)\",\n },\n selectTmuxPopupOpts: {\n type: \"string\",\n valueHint: \"opts\",\n description: \"tmux popup options used for fzf --tmux=<opts> (example: 80%,70%)\",\n },\n fzfArg: {\n type: \"string\",\n valueHint: \"arg\",\n description: \"Additional argument passed to fzf selector (repeatable)\",\n },\n help: {\n type: \"boolean\",\n alias: \"h\",\n description: \"Show help\",\n },\n version: {\n type: \"boolean\",\n alias: \"v\",\n description: \"Show version\",\n },\n } satisfies ArgsDef\n\n const listCommand = defineCommand<typeof rootArgsDef>({\n meta: {\n name: listCommandName,\n description: \"List available presets\",\n },\n })\n\n const rootCommand = defineCommand({\n meta: {\n name: \"vde-layout\",\n description: \"VDE (Vibrant Development Environment) Layout Manager - tmux pane layout management tool\",\n version,\n },\n args: rootArgsDef,\n subCommands: {\n [listCommandName]: listCommand,\n },\n })\n\n const optionSpecs = buildOptionSpecs(rootArgsDef)\n\n const run = async (args: string[] = process.argv.slice(2)): Promise<number> => {\n logger = createLogger()\n\n try {\n const normalizedArgs = normalizeSelectArgs(args)\n validateRawOptions(normalizedArgs, optionSpecs)\n const parsedArgs = parseArgs(normalizedArgs, rootArgsDef)\n const fzfCliArgs = collectOptionValues({\n args: normalizedArgs,\n optionNames: [\"fzf-arg\", \"fzfArg\"],\n })\n const positionals = getPositionals(parsedArgs)\n const headPositional = positionals[0]\n\n if (parsedArgs.help === true) {\n const usage =\n headPositional === listCommandName\n ? await renderUsage(listCommand, rootCommand)\n : await renderUsage(rootCommand)\n console.log(`${usage}\\n`)\n return 0\n }\n\n if (parsedArgs.version === true) {\n console.log(version)\n return 0\n }\n\n logger = applyRuntimeOptions({\n runtimeOptions: {\n verbose: parsedArgs.verbose === true,\n config: typeof parsedArgs.config === \"string\" ? parsedArgs.config : undefined,\n },\n createLogger,\n presetManager,\n })\n\n if (headPositional === listCommandName) {\n const extraArgs = positionals.slice(1)\n if (extraArgs.length > 0) {\n throw new Error(\n `too many arguments for '${listCommandName}'. Expected 0 arguments but got ${extraArgs.length}.`,\n )\n }\n\n return await listPresets({\n presetManager,\n logger,\n onError: errorHandlers.handleError,\n })\n }\n\n if (positionals.length > 1) {\n throw new Error(`too many arguments. Expected at most 1 argument but got ${positionals.length}.`)\n }\n\n if (parsedArgs.selectUi !== undefined && parsedArgs.select !== true) {\n throw new Error(\"--select-ui requires --select\")\n }\n\n if (parsedArgs.selectSurface !== undefined && parsedArgs.select !== true) {\n throw new Error(\"--select-surface requires --select\")\n }\n\n if (parsedArgs.selectTmuxPopupOpts !== undefined && parsedArgs.select !== true) {\n throw new Error(\"--select-tmux-popup-opts requires --select\")\n }\n\n if (fzfCliArgs.length > 0 && parsedArgs.select !== true) {\n throw new Error(\"--fzf-arg requires --select\")\n }\n\n if (parsedArgs.select === true && typeof headPositional === \"string\" && headPositional.length > 0) {\n throw new Error(\"Cannot use preset argument with --select\")\n }\n\n let resolvedPresetName = headPositional\n let configLoaded = false\n if (parsedArgs.select === true) {\n await presetManager.loadConfig()\n configLoaded = true\n\n const selectorDefaults = presetManager.getDefaults()?.selector\n const selectUiMode = resolveSelectUiMode(\n typeof parsedArgs.selectUi === \"string\" ? parsedArgs.selectUi : selectorDefaults?.ui,\n )\n const selectSurfaceMode = resolveSelectSurfaceMode(\n typeof parsedArgs.selectSurface === \"string\" ? parsedArgs.selectSurface : selectorDefaults?.surface,\n )\n const selectTmuxPopupOptions =\n typeof parsedArgs.selectTmuxPopupOpts === \"string\"\n ? parsedArgs.selectTmuxPopupOpts\n : selectorDefaults?.tmuxPopupOpts\n const configFzfArgs = selectorDefaults?.fzf?.extraArgs ?? []\n const selection = await selectPreset({\n uiMode: selectUiMode,\n surfaceMode: selectSurfaceMode,\n tmuxPopupOptions: selectTmuxPopupOptions,\n fzfExtraArgs: [...configFzfArgs, ...fzfCliArgs],\n presetManager,\n logger,\n skipLoadConfig: true,\n })\n\n if (selection.status === \"cancelled\") {\n return EXIT_CODE_CANCELLED\n }\n\n resolvedPresetName = selection.presetName\n }\n\n return await executePreset({\n presetName: resolvedPresetName,\n skipLoadConfig: configLoaded,\n options: {\n verbose: parsedArgs.verbose === true,\n dryRun: parsedArgs.dryRun === true,\n currentWindow: parsedArgs.currentWindow === true,\n newWindow: parsedArgs.newWindow === true,\n backend: typeof parsedArgs.backend === \"string\" ? parsedArgs.backend : undefined,\n },\n presetManager,\n createCommandExecutor,\n core,\n logger,\n handleError: errorHandlers.handleError,\n handlePipelineFailure: errorHandlers.handlePipelineFailure,\n })\n } catch (error) {\n return errorHandlers.handleError(error)\n }\n }\n\n return { run }\n}\n","#!/usr/bin/env node\nimport { createCli } from \"./cli/index\"\n\n/**\n * Main entry point\n * Launches the CLI application\n */\nconst main = async (): Promise<void> => {\n const cli = createCli()\n try {\n // Pass arguments excluding the first two elements (node, script path) from process.argv\n const exitCode = await cli.run(process.argv.slice(2))\n if (typeof exitCode === \"number\" && exitCode !== 0) {\n process.exit(exitCode)\n }\n } catch (error) {\n // Format and display error message appropriately\n if (error instanceof Error) {\n console.error(\"Error:\", error.message)\n\n // Also display stack trace in debug mode\n if (process.env.VDE_DEBUG === \"true\") {\n console.error(error.stack)\n }\n } else {\n console.error(\"An unexpected error occurred:\", String(error))\n }\n\n process.exit(1)\n }\n}\n\n// Execute immediately\nvoid main()\n"],"mappings":"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"}