import { readUserToolkitConfig } from "../toolkit-config.js"; export type SubagentPresentation = | "manual" | "auto" | "inline" | "split" | "tab"; export interface SubagentUiConfig { presentation: SubagentPresentation; fallback: "inline" | "error"; keepOpen: boolean; retainCompletedMinutes: number; windowsTerminal: { size: number; shell: string }; } const DEFAULT_CONFIG: SubagentUiConfig = { presentation: "manual", fallback: "inline", keepOpen: true, retainCompletedMinutes: 60, windowsTerminal: { size: 0.45, shell: "pwsh.exe" }, }; function isPresentation(value: unknown): value is SubagentPresentation { return ["manual", "auto", "inline", "split", "tab"].includes(String(value)); } function readSection(value: unknown): Record { if (value === undefined) return {}; if (!value || typeof value !== "object" || Array.isArray(value)) { throw new Error("无法解析子 Agent UI 配置: subagents 必须是 JSON 对象"); } return value as Record; } function resolveConfiguredPresentation( raw: Record, override?: SubagentPresentation, ): SubagentPresentation { const value = override ?? raw.presentation ?? DEFAULT_CONFIG.presentation; if (isPresentation(value)) return value; throw new Error( "子 Agent presentation 必须是 manual、auto、inline、split 或 tab", ); } function resolveTerminalConfig(raw: Record): { size: number; shell: string; } { const value = raw.windowsTerminal && typeof raw.windowsTerminal === "object" ? (raw.windowsTerminal as Record) : {}; const size = typeof value.size === "number" ? value.size : 0.45; const shell = typeof value.shell === "string" && value.shell.trim() ? value.shell.trim() : DEFAULT_CONFIG.windowsTerminal.shell; return { size: Math.min(0.8, Math.max(0.2, size)), shell }; } export function loadSubagentUiConfig( override?: SubagentPresentation, ): SubagentUiConfig { const raw = readSection(readUserToolkitConfig().subagents); const retain = raw.retainCompletedMinutes; return { presentation: resolveConfiguredPresentation(raw, override), fallback: raw.fallback === "error" ? "error" : "inline", keepOpen: typeof raw.keepOpen === "boolean" ? raw.keepOpen : DEFAULT_CONFIG.keepOpen, retainCompletedMinutes: typeof retain === "number" && retain >= 1 ? retain : DEFAULT_CONFIG.retainCompletedMinutes, windowsTerminal: resolveTerminalConfig(raw), }; } export function resolvePresentation( config: SubagentUiConfig, ): "manual" | "inline" | "split" | "tab" { if (config.presentation !== "auto") return config.presentation; return process.platform === "win32" && process.env.WT_SESSION ? "split" : "inline"; }