mexus-cli 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/packages/server/dist/cli.mjs +43 -4
- package/packages/server/dist/cli.mjs.map +1 -1
- package/packages/web/dist/assets/{_basePickBy-Co7zHyMx.js → _basePickBy-DXIN2jRI.js} +1 -1
- package/packages/web/dist/assets/{_baseUniq-Dxx1kUxk.js → _baseUniq-BDywcd6l.js} +1 -1
- package/packages/web/dist/assets/{arc-BvdbVAwY.js → arc-DyeF6zm4.js} +1 -1
- package/packages/web/dist/assets/{architectureDiagram-2XIMDMQ5-NJEtmrih.js → architectureDiagram-2XIMDMQ5-DJLWO4Pj.js} +1 -1
- package/packages/web/dist/assets/{blockDiagram-WCTKOSBZ-NMdKrHRR.js → blockDiagram-WCTKOSBZ-BV82tfhi.js} +1 -1
- package/packages/web/dist/assets/{c4Diagram-IC4MRINW-Cid8liHK.js → c4Diagram-IC4MRINW-fu-JF9Ds.js} +1 -1
- package/packages/web/dist/assets/channel-DMMUT-ui.js +1 -0
- package/packages/web/dist/assets/{chunk-4BX2VUAB-C0Cpcxjt.js → chunk-4BX2VUAB-CviYIUxF.js} +1 -1
- package/packages/web/dist/assets/{chunk-55IACEB6-uCQWWVUa.js → chunk-55IACEB6-BPPHvGS8.js} +1 -1
- package/packages/web/dist/assets/{chunk-FMBD7UC4-j69k_AXR.js → chunk-FMBD7UC4-CUHRhjBX.js} +1 -1
- package/packages/web/dist/assets/{chunk-JSJVCQXG-BRb3U-tF.js → chunk-JSJVCQXG-C4BN-QRR.js} +1 -1
- package/packages/web/dist/assets/{chunk-KX2RTZJC-CMLyC_k7.js → chunk-KX2RTZJC-DbvSNohi.js} +1 -1
- package/packages/web/dist/assets/{chunk-NQ4KR5QH-DUQxdvVp.js → chunk-NQ4KR5QH-Dmi6UmQw.js} +1 -1
- package/packages/web/dist/assets/{chunk-QZHKN3VN-I_0dQXDN.js → chunk-QZHKN3VN-cq0CYVai.js} +1 -1
- package/packages/web/dist/assets/{chunk-WL4C6EOR-BR8lxAey.js → chunk-WL4C6EOR-DU7g3-p8.js} +1 -1
- package/packages/web/dist/assets/classDiagram-VBA2DB6C-VAN2n8PZ.js +1 -0
- package/packages/web/dist/assets/classDiagram-v2-RAHNMMFH-VAN2n8PZ.js +1 -0
- package/packages/web/dist/assets/clone-CvILe-_6.js +1 -0
- package/packages/web/dist/assets/{cose-bilkent-S5V4N54A-BF1cADHY.js → cose-bilkent-S5V4N54A-DcB6mhJx.js} +1 -1
- package/packages/web/dist/assets/{dagre-KLK3FWXG-DDt0p4vG.js → dagre-KLK3FWXG-CKsicAAq.js} +1 -1
- package/packages/web/dist/assets/{diagram-E7M64L7V-CTkR6JTl.js → diagram-E7M64L7V-DGe3_R9s.js} +1 -1
- package/packages/web/dist/assets/{diagram-IFDJBPK2-DKPHzwe0.js → diagram-IFDJBPK2-BZq50qti.js} +1 -1
- package/packages/web/dist/assets/{diagram-P4PSJMXO-k5sUOXg6.js → diagram-P4PSJMXO-nwlLLk4m.js} +1 -1
- package/packages/web/dist/assets/{erDiagram-INFDFZHY-HQ6gUchT.js → erDiagram-INFDFZHY-BMh-qsJC.js} +1 -1
- package/packages/web/dist/assets/{flowDiagram-PKNHOUZH-zQ6z0FfA.js → flowDiagram-PKNHOUZH-DR8q3sxn.js} +1 -1
- package/packages/web/dist/assets/{ganttDiagram-A5KZAMGK-7OanXR1G.js → ganttDiagram-A5KZAMGK-B27SJapO.js} +1 -1
- package/packages/web/dist/assets/{gitGraphDiagram-K3NZZRJ6-CWHj7ZAf.js → gitGraphDiagram-K3NZZRJ6-q-tTdScO.js} +1 -1
- package/packages/web/dist/assets/{graph-DGZqBZjC.js → graph-CMugmIWl.js} +1 -1
- package/packages/web/dist/assets/{index-ORmXz3Zu.js → index-Diaj_XhW.js} +212 -200
- package/packages/web/dist/assets/{index-DWMolj1f.css → index-Dmv7dA85.css} +1 -1
- package/packages/web/dist/assets/{infoDiagram-LFFYTUFH-yRz9H7FV.js → infoDiagram-LFFYTUFH-CK_zFXvT.js} +1 -1
- package/packages/web/dist/assets/{ishikawaDiagram-PHBUUO56-D9KVAEH1.js → ishikawaDiagram-PHBUUO56-BltT2ON5.js} +1 -1
- package/packages/web/dist/assets/{journeyDiagram-4ABVD52K-xYc2g_2E.js → journeyDiagram-4ABVD52K-Dy5sDS4Z.js} +1 -1
- package/packages/web/dist/assets/{kanban-definition-K7BYSVSG-C9ctSGeG.js → kanban-definition-K7BYSVSG-D5Ls_L8y.js} +1 -1
- package/packages/web/dist/assets/{layout-dR6Z9QBB.js → layout-DmCA190Q.js} +1 -1
- package/packages/web/dist/assets/{linear-C41sKDUx.js → linear-Xq2b2hkZ.js} +1 -1
- package/packages/web/dist/assets/{mindmap-definition-YRQLILUH-DnEvOt89.js → mindmap-definition-YRQLILUH-Bb9IeFFk.js} +1 -1
- package/packages/web/dist/assets/{pieDiagram-SKSYHLDU-Dwygi596.js → pieDiagram-SKSYHLDU-voM4tR2p.js} +1 -1
- package/packages/web/dist/assets/{quadrantDiagram-337W2JSQ-CGsDpSZv.js → quadrantDiagram-337W2JSQ-CWsXyyMa.js} +1 -1
- package/packages/web/dist/assets/{requirementDiagram-Z7DCOOCP-DrFNwpYL.js → requirementDiagram-Z7DCOOCP-CsOwpcMM.js} +1 -1
- package/packages/web/dist/assets/{sankeyDiagram-WA2Y5GQK-CKWlgXXF.js → sankeyDiagram-WA2Y5GQK-B6cIdL6Z.js} +1 -1
- package/packages/web/dist/assets/{sequenceDiagram-2WXFIKYE-DpbgNxFF.js → sequenceDiagram-2WXFIKYE-xbTir98k.js} +1 -1
- package/packages/web/dist/assets/{stateDiagram-RAJIS63D-UQV1zJr3.js → stateDiagram-RAJIS63D-BYDksMZW.js} +1 -1
- package/packages/web/dist/assets/stateDiagram-v2-FVOUBMTO-B4eba8Bu.js +1 -0
- package/packages/web/dist/assets/{timeline-definition-YZTLITO2-CBNnAMDu.js → timeline-definition-YZTLITO2-D6_c0hm9.js} +1 -1
- package/packages/web/dist/assets/{treemap-KZPCXAKY-DQg0JG5Z.js → treemap-KZPCXAKY-D0Xw90T6.js} +1 -1
- package/packages/web/dist/assets/{vennDiagram-LZ73GAT5-6EhbiWUV.js → vennDiagram-LZ73GAT5-D_T_iazZ.js} +1 -1
- package/packages/web/dist/assets/{xychartDiagram-JWTSCODW-DrTSQ6rp.js → xychartDiagram-JWTSCODW-CBckvVCD.js} +1 -1
- package/packages/web/dist/index.html +2 -2
- package/packages/web/dist/assets/channel-ggzcU6fx.js +0 -1
- package/packages/web/dist/assets/classDiagram-VBA2DB6C-qeSRjRBc.js +0 -1
- package/packages/web/dist/assets/classDiagram-v2-RAHNMMFH-qeSRjRBc.js +0 -1
- package/packages/web/dist/assets/clone-CGAMRvPs.js +0 -1
- package/packages/web/dist/assets/stateDiagram-v2-FVOUBMTO-CmZylZ6s.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/workspace/ConfigManager.ts","../src/cli.ts","../src/index.ts","../src/pty/PtyManager.ts","../src/comm/StatuslineParser.ts","../src/comm/ShellReadyDetector.ts","../src/comm/AgentReadyDetector.ts","../src/comm/OutputStateAnalyzer.ts","../src/pty/ActivityParser.ts","../src/runtime/AcpRuntime.ts","../src/git/WorktreeManager.ts","../src/git/GitService.ts","../src/workspace/WorkspaceManager.ts","../src/workspace/AgentsYamlWriter.ts","../src/fs/FsWatcher.ts","../src/ws/handlers.ts","../src/deps/DependencyAnalyzer.ts","../src/history/SessionRecorder.ts","../src/workspace/SessionDiscovery.ts"],"sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\nimport os from 'node:os'\nimport { execFile } from 'node:child_process'\nimport { promisify } from 'node:util'\nimport yaml from 'js-yaml'\nimport type { GlobalConfig, WorkspaceConfig, AgentDefinition, AgentAvailability } from '../types.ts'\n\nconst execFileAsync = promisify(execFile)\n\nconst GLOBAL_DIR = path.join(os.homedir(), '.nexus')\nconst GLOBAL_CONFIG_PATH = path.join(GLOBAL_DIR, 'config.yaml')\n\nconst DEFAULT_GLOBAL_CONFIG: GlobalConfig = {\n version: '1',\n defaults: {\n shell: process.env.SHELL || '/bin/bash',\n scrollback_lines: 5000,\n grid_columns: 2,\n history_retention_days: 30,\n theme: 'dark-ide',\n },\n agents: {\n claudecode: {\n bin: 'claude',\n continue_flag: '--continue',\n resume_flag: '--resume',\n yolo_flag: '--dangerously-skip-permissions',\n statusline: true,\n transport: 'pty',\n env: {},\n },\n codex: {\n bin: 'codex',\n continue_flag: '',\n resume_flag: '',\n yolo_flag: '',\n statusline: false,\n transport: 'pty',\n env: {},\n },\n opencode: {\n bin: 'opencode',\n continue_flag: '--continue',\n resume_flag: '',\n yolo_flag: '--yolo',\n statusline: false,\n transport: 'acp',\n env: {},\n },\n 'kimi-cli': {\n bin: 'kimi',\n continue_flag: '--continue',\n resume_flag: '',\n yolo_flag: '',\n statusline: false,\n transport: 'pty',\n env: {},\n },\n qodercli: {\n bin: 'qodercli',\n continue_flag: '-c',\n resume_flag: '-r',\n yolo_flag: '--yolo',\n statusline: false,\n transport: 'pty',\n env: {},\n },\n },\n}\n\nexport class ConfigManager {\n private globalConfig: GlobalConfig | null = null\n private workspaceConfig: WorkspaceConfig | null = null\n private projectDir: string\n\n constructor(projectDir: string) {\n this.projectDir = projectDir\n }\n\n loadGlobalConfig(): GlobalConfig {\n if (this.globalConfig) return this.globalConfig\n\n if (fs.existsSync(GLOBAL_CONFIG_PATH)) {\n const content = fs.readFileSync(GLOBAL_CONFIG_PATH, 'utf-8')\n this.globalConfig = yaml.load(content) as GlobalConfig\n // Merge in any default agents or missing fields from the saved config\n let updated = false\n for (const [key, def] of Object.entries(DEFAULT_GLOBAL_CONFIG.agents)) {\n if (!this.globalConfig.agents[key]) {\n this.globalConfig.agents[key] = def\n updated = true\n } else {\n // Merge missing fields from defaults into existing agent definition\n const existing = this.globalConfig.agents[key]\n for (const [field, value] of Object.entries(def)) {\n if (!(field in existing)) {\n (existing as Record<string, unknown>)[field] = value\n updated = true\n }\n }\n }\n }\n if (updated) {\n this.saveGlobalConfig(this.globalConfig)\n }\n } else {\n this.globalConfig = { ...DEFAULT_GLOBAL_CONFIG }\n // Agent detection is async now — save defaults first, detect in background\n this.saveGlobalConfig(this.globalConfig)\n this.detectAgentsAsync().then((detected) => {\n if (Object.keys(detected).length > 0 && this.globalConfig) {\n this.globalConfig.agents = { ...this.globalConfig.agents, ...detected }\n this.saveGlobalConfig(this.globalConfig)\n }\n }).catch(() => { /* ignore detection failure */ })\n }\n\n return this.globalConfig\n }\n\n private saveGlobalConfig(config: GlobalConfig): void {\n fs.mkdirSync(GLOBAL_DIR, { recursive: true })\n fs.writeFileSync(GLOBAL_CONFIG_PATH, yaml.dump(config, { lineWidth: -1 }))\n }\n\n loadWorkspaceConfig(): WorkspaceConfig | null {\n if (this.workspaceConfig) return this.workspaceConfig\n\n const configPath = path.join(this.projectDir, '.nexus', 'config.yaml')\n if (fs.existsSync(configPath)) {\n const content = fs.readFileSync(configPath, 'utf-8')\n const parsed = yaml.load(content) as WorkspaceConfig | null\n if (parsed) {\n if (!Array.isArray(parsed.panes)) parsed.panes = []\n this.workspaceConfig = parsed\n return this.workspaceConfig\n }\n }\n\n return null\n }\n\n saveWorkspaceConfig(config: WorkspaceConfig): void {\n const nexusDir = path.join(this.projectDir, '.nexus')\n fs.mkdirSync(nexusDir, { recursive: true })\n const configPath = path.join(nexusDir, 'config.yaml')\n fs.writeFileSync(configPath, yaml.dump(config, { lineWidth: -1 }))\n this.workspaceConfig = config\n }\n\n initWorkspace(): WorkspaceConfig {\n const existing = this.loadWorkspaceConfig()\n if (existing) return existing\n\n const dirName = path.basename(this.projectDir)\n const isGit = fs.existsSync(path.join(this.projectDir, '.git'))\n\n const config: WorkspaceConfig = {\n version: '1',\n name: dirName,\n description: '',\n repository: {\n path: '.',\n git: isGit,\n },\n panes: [],\n }\n\n this.saveWorkspaceConfig(config)\n return config\n }\n\n private async detectAgentsAsync(): Promise<Record<string, AgentDefinition>> {\n const agents: Record<string, AgentDefinition> = {}\n\n const agentBins: Array<{ key: string; bin: string; flag: string; statusline: boolean; transport: 'pty' | 'acp' }> = [\n { key: 'claudecode', bin: 'claude', flag: '--continue', statusline: true, transport: 'pty' },\n { key: 'codex', bin: 'codex', flag: '', statusline: false, transport: 'pty' },\n { key: 'opencode', bin: 'opencode', flag: '--continue', statusline: false, transport: 'acp' },\n { key: 'kimi-cli', bin: 'kimi', flag: '--continue', statusline: false, transport: 'pty' },\n { key: 'qodercli', bin: 'qodercli', flag: '-c', statusline: false, transport: 'pty' },\n ]\n\n const results = await Promise.allSettled(\n agentBins.map(async (agent) => {\n await execFileAsync('which', [agent.bin], { timeout: 3000 })\n return agent\n })\n )\n\n for (const result of results) {\n if (result.status === 'fulfilled') {\n const agent = result.value\n agents[agent.key] = {\n bin: agent.bin,\n continue_flag: agent.flag,\n statusline: agent.statusline,\n transport: agent.transport,\n env: {},\n }\n }\n }\n\n return agents\n }\n\n getAgentDefinition(agentType: string): AgentDefinition | undefined {\n const global = this.loadGlobalConfig()\n return global.agents[agentType]\n }\n\n getShell(): string {\n const global = this.loadGlobalConfig()\n const configured = global.defaults.shell\n // Prefer zsh > configured > $SHELL > /bin/sh\n // Include macOS Homebrew paths for Apple Silicon and Intel\n const candidates = [\n '/opt/homebrew/bin/zsh', // macOS Apple Silicon Homebrew\n '/usr/local/bin/zsh', // macOS Intel Homebrew\n '/usr/bin/zsh', // Linux\n '/bin/zsh', // macOS default / Linux\n configured,\n process.env.SHELL,\n '/bin/bash',\n '/bin/sh',\n ]\n for (const sh of candidates) {\n if (!sh) continue\n try {\n fs.accessSync(sh, fs.constants.X_OK)\n return sh\n } catch {\n // try next\n }\n }\n return '/bin/sh'\n }\n\n /**\n * Check which agents are available (installed) on the system.\n * Returns a record of agentType → { installed, bin, installHint }\n */\n async checkAgentAvailability(): Promise<Record<string, AgentAvailability>> {\n const global = this.loadGlobalConfig()\n const knownAgents: Array<{ key: string; bin: string; installHint: string }> = [\n { key: 'claudecode', bin: 'claude', installHint: 'npm install -g @anthropic-ai/claude-code' },\n { key: 'codex', bin: 'codex', installHint: 'npm install -g @openai/codex' },\n { key: 'opencode', bin: 'opencode', installHint: 'go install github.com/opencode-ai/opencode@latest' },\n { key: 'kimi-cli', bin: 'kimi', installHint: 'pip install kimi-cli' },\n { key: 'qodercli', bin: 'qodercli', installHint: 'See https://docs.qoder.com/zh/cli/using-cli' },\n ]\n\n const checks = await Promise.allSettled(\n knownAgents.map(async (agent) => {\n const def = global.agents[agent.key]\n const bin = def?.bin || agent.bin\n try {\n await execFileAsync('which', [bin], { timeout: 3000 })\n return { ...agent, bin, installed: true }\n } catch {\n return { ...agent, bin, installed: false }\n }\n })\n )\n\n const result: Record<string, AgentAvailability> = {}\n for (const check of checks) {\n if (check.status === 'fulfilled') {\n const { key, bin, installHint, installed } = check.value\n result[key] = { installed, bin, installHint }\n }\n }\n\n return result\n }\n\n updateGlobalConfig(config: GlobalConfig): void {\n this.globalConfig = config\n this.saveGlobalConfig(config)\n }\n\n getProjectDir(): string {\n return this.projectDir\n }\n}\n","import path from 'node:path'\nimport fs from 'node:fs'\nimport { startServer } from './index.ts'\n\n// Check Node.js version — node-pty requires Node 22+\nconst nodeVersion = parseInt(process.versions.node.split('.')[0], 10)\nif (nodeVersion < 22) {\n console.error(`Error: Nexus requires Node.js >= 22, but you are running v${process.versions.node}`)\n console.error(` Please upgrade: nvm install 22 && nvm use 22`)\n process.exit(1)\n}\n\n// Clean up parent session env so spawned PTYs don't detect nesting\ndelete process.env.CLAUDECODE\ndelete process.env.CLAUDE_CODE\ndelete process.env.CLAUDE_CODE_ENTRYPOINT\n\nconst DEFAULT_PORT = 7700\n\nfunction printUsage() {\n console.log(`\n Usage: nexus [command] [directory]\n\n Commands:\n start [dir] Start the Nexus server (default)\n init [dir] Initialize .nexus/ config in a project\n status [dir] Show workspace status\n stop Stop the running server\n\n Arguments:\n dir Path to the project directory (defaults to cwd)\n\n Environment:\n NEXUS_PORT Server port (default: ${DEFAULT_PORT})\n\n Examples:\n nexus # Start in current directory\n nexus ~/projects/my-app # Start with a specific project\n nexus start ~/projects/app # Explicit start command\n nexus init . # Initialize config in cwd\n`.trimEnd())\n}\n\nfunction findProjectRoot(startDir: string): string {\n const home = process.env.HOME || process.env.USERPROFILE || ''\n\n // Walk up from startDir, prefer the highest-level match\n // (monorepo root, not a nested package)\n // Stop at HOME — never go above it\n let dir = startDir\n let bestMatch = startDir\n\n while (dir !== path.dirname(dir)) {\n if (fs.existsSync(path.join(dir, 'pnpm-workspace.yaml'))) {\n return dir // pnpm monorepo root is definitive\n }\n if (\n fs.existsSync(path.join(dir, '.git')) ||\n fs.existsSync(path.join(dir, '.nexus'))\n ) {\n bestMatch = dir\n }\n const parent = path.dirname(dir)\n // Don't traverse above HOME directory\n if (home && parent === home && dir !== startDir) break\n dir = parent\n }\n\n // Warn if resolved to HOME — likely a mistake\n if (home && bestMatch === home && startDir === home) {\n console.warn(`Warning: Running Nexus in HOME directory (${home}).`)\n console.warn(` Consider: nexus <project-path>`)\n }\n\n return bestMatch\n}\n\nfunction resolveProjectDir(dirArg?: string): string {\n if (process.env.NEXUS_PROJECT_DIR) {\n return path.resolve(process.env.NEXUS_PROJECT_DIR)\n }\n if (dirArg) {\n const resolved = path.resolve(dirArg)\n if (!fs.existsSync(resolved)) {\n console.error(`Error: directory does not exist: ${resolved}`)\n process.exit(1)\n }\n if (!fs.statSync(resolved).isDirectory()) {\n console.error(`Error: not a directory: ${resolved}`)\n process.exit(1)\n }\n return resolved\n }\n return findProjectRoot(process.cwd())\n}\n\nconst COMMANDS = new Set(['start', 'init', 'status', 'stop', 'help'])\n\nasync function main() {\n const args = process.argv.slice(2)\n\n // Parse command and directory argument\n // Support: nexus <dir>, nexus <cmd> <dir>, nexus <cmd>\n let command: string\n let dirArg: string | undefined\n\n if (args.length === 0) {\n command = 'start'\n } else if (args[0] === '--help' || args[0] === '-h') {\n command = 'help'\n } else if (COMMANDS.has(args[0])) {\n command = args[0]\n dirArg = args[1]\n } else {\n // First arg is not a known command — treat it as a directory\n command = 'start'\n dirArg = args[0]\n }\n\n if (command === 'help') {\n printUsage()\n return\n }\n\n const projectDir = resolveProjectDir(dirArg)\n\n switch (command) {\n case 'start': {\n const port = parseInt(process.env.NEXUS_PORT || String(DEFAULT_PORT), 10)\n await startServer(port, projectDir)\n\n // Auto-open browser (non-blocking, failure is ok)\n const url = `http://localhost:${port}`\n import('open').then((mod) => mod.default(url)).catch(() => {})\n\n // Check agent availability after server is up (non-blocking)\n const { ConfigManager: CM } = await import('./workspace/ConfigManager.ts')\n const cm = new CM(projectDir)\n cm.loadGlobalConfig()\n cm.checkAgentAvailability().then((availability) => {\n const missing = Object.entries(availability).filter(([, a]) => !a.installed)\n if (missing.length > 0) {\n console.log('\\n Optional agents not found:')\n for (const [key, info] of missing) {\n console.log(` \\u26A0 ${key} (${info.bin}) — install: ${info.installHint}`)\n }\n console.log()\n }\n }).catch(() => {})\n break\n }\n\n case 'init': {\n const { ConfigManager } = await import('./workspace/ConfigManager.ts')\n const configManager = new ConfigManager(projectDir)\n configManager.loadGlobalConfig()\n configManager.initWorkspace()\n console.log(`Initialized .nexus/ in ${projectDir}`)\n break\n }\n\n case 'status': {\n const { ConfigManager } = await import('./workspace/ConfigManager.ts')\n const configManager = new ConfigManager(projectDir)\n const wsConfig = configManager.loadWorkspaceConfig()\n if (!wsConfig) {\n console.log('No .nexus/config.yaml found. Run `nexus init` first.')\n break\n }\n console.log(`Workspace: ${wsConfig.name}`)\n console.log(`Panes: ${wsConfig.panes.length}`)\n for (const pane of wsConfig.panes) {\n console.log(` - ${pane.id} [${pane.agent}] ${pane.name}${pane.task ? ` — ${pane.task}` : ''}`)\n }\n break\n }\n\n case 'stop': {\n try {\n const port = parseInt(process.env.NEXUS_PORT || String(DEFAULT_PORT), 10)\n const res = await fetch(`http://localhost:${port}/api/health`)\n if (res.ok) {\n console.log('Sending shutdown signal...')\n process.kill(process.pid, 'SIGTERM')\n }\n } catch {\n console.log('No running Nexus server found.')\n }\n break\n }\n\n default:\n console.error(`Unknown command: ${command}`)\n printUsage()\n process.exit(1)\n }\n}\n\nmain().catch((err) => {\n console.error('Fatal error:', err)\n process.exit(1)\n})\n","import Fastify from 'fastify'\nimport fastifyWebsocket from '@fastify/websocket'\nimport fastifyStatic from '@fastify/static'\nimport path from 'node:path'\nimport fs from 'node:fs'\nimport yaml from 'js-yaml'\nimport { fileURLToPath } from 'node:url'\nimport { ConfigManager } from './workspace/ConfigManager.ts'\nimport { WorkspaceManager } from './workspace/WorkspaceManager.ts'\nimport { AgentsYamlWriter } from './workspace/AgentsYamlWriter.ts'\nimport { FsWatcher } from './fs/FsWatcher.ts'\nimport { GitService } from './git/GitService.ts'\nimport { setupWsHandlers } from './ws/handlers.ts'\nimport { DependencyAnalyzer } from './deps/DependencyAnalyzer.ts'\nimport { SessionRecorder } from './history/SessionRecorder.ts'\nimport { SessionDiscovery } from './workspace/SessionDiscovery.ts'\nimport type { GlobalConfig } from './types.ts'\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url))\n\nexport async function startServer(port: number, projectDir: string) {\n const fastify = Fastify({ logger: false })\n\n // Managers\n const configManager = new ConfigManager(projectDir)\n configManager.loadGlobalConfig()\n\n const workspaceManager = new WorkspaceManager(configManager)\n await workspaceManager.init()\n\n // agents.yaml writer — updates on pane state changes\n const agentsWriter = new AgentsYamlWriter(projectDir)\n\n workspaceManager.onEvents({\n onPaneAdded: () => agentsWriter.update(workspaceManager.getPanes()),\n onPaneRemoved: () => agentsWriter.update(workspaceManager.getPanes()),\n onPaneStatus: () => agentsWriter.update(workspaceManager.getPanes()),\n onPaneMeta: () => agentsWriter.update(workspaceManager.getPanes()),\n })\n\n // Session recorder — records replay history\n const wsConfig = configManager.loadWorkspaceConfig()\n const globalConfig = configManager.loadGlobalConfig()\n const recorder = new SessionRecorder(projectDir, wsConfig?.name || 'Nexus', globalConfig.defaults.history_retention_days)\n\n workspaceManager.onEvents({\n onPaneAdded: (pane) => recorder.onPaneAdded(pane),\n onPaneRemoved: (paneId) => recorder.onPaneRemoved(paneId),\n onPaneStatus: (paneId, status) => {\n const panes = workspaceManager.getPanes()\n const pane = panes.find((p) => p.id === paneId)\n recorder.onPaneStatus(paneId, status, pane)\n },\n onPaneMeta: (paneId, meta) => recorder.onPaneMeta(paneId, meta),\n onTerminalData: (paneId, data) => recorder.onTerminalData(paneId, data),\n onPaneActivity: (paneId, activity) => recorder.onPaneActivity(paneId, activity),\n })\n\n // File system watcher\n const fsWatcher = new FsWatcher(projectDir)\n fsWatcher.onTreeChange((tree) => {\n workspaceManager.emitFileTree(tree)\n })\n fsWatcher.onFileChange((activity) => {\n workspaceManager.emitFileActivity(activity)\n // Also feed file changes to session recorder for diff capture\n recorder.onFileActivityForReplay(activity)\n })\n try {\n fsWatcher.start()\n } catch (err) {\n console.warn('[FsWatcher] Failed to start file watcher:', (err as Error).message)\n }\n\n // Git service\n const gitService = new GitService(projectDir)\n gitService.onDiffChange((result) => {\n workspaceManager.emitGitDiff(result)\n })\n try {\n await gitService.start()\n } catch (err) {\n console.warn('[GitService] Failed to start git service:', (err as Error).message)\n }\n\n // WebSocket\n await fastify.register(fastifyWebsocket)\n\n fastify.get('/nexus-ws', { websocket: true }, (socket, req) => {\n console.log('[WS] Upgrade request from', req.ip)\n try {\n setupWsHandlers(socket, workspaceManager, gitService)\n\n // Send initial file tree and git diffs to new client\n const tree = fsWatcher.getTree()\n if (tree.length > 0) {\n socket.send(JSON.stringify({ type: 'fs.tree', tree }))\n }\n const { unstaged, staged } = gitService.getCurrentDiffs()\n if (unstaged.length > 0 || staged.length > 0) {\n socket.send(JSON.stringify({ type: 'git.diff', unstaged, staged }))\n }\n console.log('[WS] Client connected')\n\n socket.on('close', (code: number, reason: Buffer) => {\n console.log(`[WS] Client disconnected: code=${code} reason=${reason.toString()}`)\n })\n socket.on('error', (err: Error) => {\n console.error('[WS] Socket error:', err)\n })\n } catch (err) {\n console.error('[WS] Error in connection handler:', err)\n }\n })\n\n // Health check\n fastify.get('/api/health', async () => {\n return { status: 'ok' }\n })\n\n // Agent availability endpoint\n fastify.get('/api/agents', async () => {\n return await configManager.checkAgentAvailability()\n })\n\n // Global config endpoints\n fastify.get('/api/config', async () => {\n return configManager.loadGlobalConfig()\n })\n\n fastify.put('/api/config', async (request, reply) => {\n try {\n const config = request.body as GlobalConfig\n configManager.updateGlobalConfig(config)\n return { success: true }\n } catch (err) {\n reply.code(400)\n return { error: 'Invalid config' }\n }\n })\n\n // Session discovery (claude sessions list)\n const sessionDiscovery = new SessionDiscovery(configManager)\n\n fastify.get('/api/sessions', async (request) => {\n const { agent } = request.query as { agent?: string }\n const external = await sessionDiscovery.listSessions(agent || 'claudecode')\n // Merge with Nexus internal sessions, dedup by sessionId\n const internal = workspaceManager.getSessionList()\n const seen = new Set(internal.map((s) => s.sessionId))\n const merged = [\n ...internal.map((s) => ({\n sessionId: s.sessionId,\n summary: s.paneName,\n model: s.model,\n costUsd: s.costUsd,\n numTurns: undefined as number | undefined,\n createdAt: s.timestamp,\n updatedAt: s.timestamp,\n projectPath: undefined as string | undefined,\n source: 'nexus' as const,\n })),\n ...external.filter((s) => !seen.has(s.sessionId)),\n ]\n return merged\n })\n\n // Replay history endpoints\n fastify.get('/api/replay/sessions', async () => {\n return SessionRecorder.listSessions(projectDir)\n })\n\n fastify.get('/api/replay/sessions/:sessionId', async (request, reply) => {\n const { sessionId } = request.params as { sessionId: string }\n const session = SessionRecorder.getSession(projectDir, sessionId)\n if (!session) { reply.code(404); return { error: 'Session not found' } }\n return session\n })\n\n fastify.get('/api/replay/sessions/:sessionId/turns/:turnId', async (request, reply) => {\n const { sessionId, turnId } = request.params as { sessionId: string; turnId: string }\n const turn = SessionRecorder.getTurn(projectDir, sessionId, turnId)\n if (!turn) { reply.code(404); return { error: 'Turn not found' } }\n return turn\n })\n\n // Delete a single replay session\n fastify.delete('/api/replay/sessions/:sessionId', async (request) => {\n const { sessionId } = request.params as { sessionId: string }\n const deleted = SessionRecorder.deleteSession(projectDir, sessionId)\n return { success: deleted }\n })\n\n // Delete all replay sessions\n fastify.delete('/api/replay/sessions', async () => {\n const count = SessionRecorder.deleteAllSessions(projectDir)\n return { success: true, deleted: count }\n })\n\n // Dependency graph endpoint — cached with TTL to avoid repeated full-scan\n let depGraphCache: { graph: ReturnType<DependencyAnalyzer['analyze']>; ts: number } | null = null\n const DEP_CACHE_TTL = 30_000 // 30s\n\n fastify.get('/api/deps', async () => {\n const now = Date.now()\n if (depGraphCache && now - depGraphCache.ts < DEP_CACHE_TTL) {\n return depGraphCache.graph\n }\n const analyzer = new DependencyAnalyzer(projectDir)\n const graph = analyzer.analyze()\n depGraphCache = { graph, ts: now }\n return graph\n })\n\n // File read endpoint\n fastify.get('/api/file', async (request, reply) => {\n const { path: filePath } = request.query as { path?: string }\n if (!filePath) {\n reply.code(400)\n return { error: 'Missing path parameter' }\n }\n\n // Security: reject paths with .. or absolute paths\n if (filePath.includes('..') || path.isAbsolute(filePath)) {\n reply.code(403)\n return { error: 'Invalid path' }\n }\n\n const fullPath = path.resolve(projectDir, filePath)\n\n // Ensure resolved path is within projectDir\n if (!fullPath.startsWith(projectDir)) {\n reply.code(403)\n return { error: 'Path traversal not allowed' }\n }\n\n try {\n const content = fs.readFileSync(fullPath, 'utf-8')\n return { content, path: filePath }\n } catch {\n reply.code(404)\n return { error: 'File not found' }\n }\n })\n\n // Raw file endpoint — serves binary files with correct MIME type\n fastify.get('/api/file/raw', async (request, reply) => {\n const { path: filePath } = request.query as { path?: string }\n if (!filePath) {\n reply.code(400)\n return { error: 'Missing path parameter' }\n }\n if (filePath.includes('..') || path.isAbsolute(filePath)) {\n reply.code(403)\n return { error: 'Invalid path' }\n }\n const fullPath = path.resolve(projectDir, filePath)\n if (!fullPath.startsWith(projectDir)) {\n reply.code(403)\n return { error: 'Path traversal not allowed' }\n }\n if (!fs.existsSync(fullPath)) {\n reply.code(404)\n return { error: 'File not found' }\n }\n const ext = path.extname(fullPath).toLowerCase()\n const mimeMap: Record<string, string> = {\n '.png': 'image/png', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg',\n '.gif': 'image/gif', '.webp': 'image/webp', '.ico': 'image/x-icon',\n '.bmp': 'image/bmp', '.avif': 'image/avif',\n '.pdf': 'application/pdf',\n '.svg': 'image/svg+xml',\n }\n const mime = mimeMap[ext] || 'application/octet-stream'\n const stream = fs.createReadStream(fullPath)\n reply.type(mime)\n return reply.send(stream)\n })\n\n // Notes CRUD — persisted to .nexus/notes.yaml\n const notesPath = path.join(projectDir, '.nexus', 'notes.yaml')\n\n fastify.get('/api/notes', async () => {\n try {\n const raw = fs.readFileSync(notesPath, 'utf-8')\n const data = yaml.load(raw) as { notes?: unknown[] }\n return { notes: data?.notes || [] }\n } catch {\n return { notes: [] }\n }\n })\n\n fastify.put('/api/notes', async (request, reply) => {\n try {\n const { notes } = request.body as { notes: unknown[] }\n fs.mkdirSync(path.dirname(notesPath), { recursive: true })\n fs.writeFileSync(notesPath, yaml.dump({ notes }, { lineWidth: -1 }), 'utf-8')\n return { success: true }\n } catch (err) {\n reply.code(400)\n return { error: 'Failed to save notes' }\n }\n })\n\n // Serve static frontend in production\n const webDistPath = path.resolve(__dirname, '../../web/dist')\n if (!fs.existsSync(webDistPath)) {\n console.warn(` [Warning] Frontend not found at ${webDistPath}`)\n console.warn(` Run 'pnpm run build:web' to build the frontend, or use dev mode.`)\n }\n if (fs.existsSync(webDistPath)) {\n await fastify.register(fastifyStatic, {\n root: webDistPath,\n prefix: '/',\n })\n\n // SPA fallback for client-side routing\n fastify.setNotFoundHandler((_req, reply) => {\n reply.sendFile('index.html')\n })\n }\n\n // Graceful shutdown\n const shutdown = async () => {\n console.log('\\nShutting down...')\n recorder.flush()\n agentsWriter.flush(workspaceManager.getPanes())\n fsWatcher.close()\n gitService.close()\n await workspaceManager.shutdown()\n await fastify.close()\n process.exit(0)\n }\n\n process.on('SIGINT', shutdown)\n process.on('SIGTERM', shutdown)\n\n try {\n await fastify.listen({ port, host: '0.0.0.0' })\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'EADDRINUSE') {\n console.error(`Port ${port} is already in use. Kill the existing process or use a different port:`)\n console.error(` NEXUS_PORT=7800 pnpm dev`)\n console.error(` # or find and kill: lsof -i :${port}`)\n process.exit(1)\n }\n throw err\n }\n console.log(`Nexus server running at http://localhost:${port}`)\n console.log(` Project dir: ${projectDir}`)\n console.log(` File tree: ${fsWatcher.getTree().length} top-level entries`)\n const { unstaged: u, staged: s } = gitService.getCurrentDiffs()\n console.log(` Git diffs: ${u.length} unstaged, ${s.length} staged`)\n\n return { fastify, workspaceManager, configManager }\n}\n","import * as pty from 'node-pty'\nimport fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport type { PaneConfig, PaneStatus, PaneMeta, AgentDefinition, FileActivity } from '../types.ts'\nimport { StatuslineParser } from '../comm/StatuslineParser.ts'\nimport { ShellReadyDetector } from '../comm/ShellReadyDetector.ts'\nimport { AgentReadyDetector } from '../comm/AgentReadyDetector.ts'\nimport { OutputStateAnalyzer } from '../comm/OutputStateAnalyzer.ts'\nimport { ActivityParser } from './ActivityParser.ts'\nimport type { ConfigManager } from '../workspace/ConfigManager.ts'\n\nconst MAX_SCROLLBACK_BYTES = 512 * 1024 // 512KB per pane\n\ninterface PtyEntry {\n pty: pty.IPty\n config: PaneConfig\n status: PaneStatus\n meta: PaneMeta\n parser: StatuslineParser\n activityParser: ActivityParser\n stateAnalyzer: OutputStateAnalyzer\n shellDetector: ShellReadyDetector | null\n agentDetector: AgentReadyDetector | null\n scrollback: string[]\n scrollbackBytes: number\n onDataCallbacks: Array<(data: string) => void>\n onStatusCallbacks: Array<(status: PaneStatus) => void>\n onMetaCallbacks: Array<(meta: PaneMeta) => void>\n onActivityCallbacks: Array<(activity: FileActivity) => void>\n}\n\nexport class PtyManager {\n private entries = new Map<string, PtyEntry>()\n private configManager: ConfigManager\n\n constructor(configManager: ConfigManager) {\n this.configManager = configManager\n }\n\n spawn(paneId: string, config: PaneConfig, cols = 80, rows = 24): number {\n if (this.entries.has(paneId)) {\n this.kill(paneId)\n }\n\n const shell = this.configManager.getShell()\n console.log(`[PTY] Using shell: ${shell} for pane ${paneId}`)\n const projectDir = this.configManager.getProjectDir()\n // Worktree panes use worktreePath as base; shared panes use projectDir\n const basePath = (config.isolation === 'worktree' && config.worktreePath)\n ? config.worktreePath\n : projectDir\n let cwd = config.workdir\n ? path.resolve(basePath, config.workdir)\n : basePath\n\n // Validate cwd exists — posix_spawnp fails if cwd is invalid\n if (!fs.existsSync(cwd)) {\n console.warn(`[PTY] cwd does not exist: ${cwd}, falling back to ${projectDir}`)\n cwd = fs.existsSync(projectDir) ? projectDir : os.homedir()\n }\n\n // Validate shell binary exists, fall back gracefully\n let resolvedShell = shell\n if (!fs.existsSync(resolvedShell)) {\n const fallbacks = ['/bin/zsh', '/bin/bash', '/bin/sh']\n const found = fallbacks.find(s => fs.existsSync(s))\n console.error(`[PTY] Shell binary not found: ${resolvedShell}, falling back to ${found || '/bin/sh'}`)\n resolvedShell = found || '/bin/sh'\n }\n\n const agentDef = this.configManager.getAgentDefinition(config.agent)\n const isAgent = agentDef && config.agent !== '__shell__'\n\n // Build environment from agent definition\n // Filter out all Claude-related env vars to prevent nested session detection\n const env: Record<string, string> = {}\n for (const [key, value] of Object.entries(process.env)) {\n if (value !== undefined && !key.startsWith('CLAUDE') && key !== 'CLAUDECODE') {\n env[key] = value\n }\n }\n if (agentDef?.env) {\n // Block dangerous env vars that could be used for injection\n const BLOCKED_ENV_KEYS = new Set([\n 'PATH', 'LD_PRELOAD', 'LD_LIBRARY_PATH',\n 'DYLD_INSERT_LIBRARIES', 'DYLD_LIBRARY_PATH', 'DYLD_FRAMEWORK_PATH',\n ])\n for (const [key, value] of Object.entries(agentDef.env)) {\n if (BLOCKED_ENV_KEYS.has(key)) {\n console.warn(`[PTY] Ignoring blocked env var from agent config: ${key}`)\n continue\n }\n // Resolve ${VAR} references from process.env\n const resolved = value.replace(/\\$\\{(\\w+)\\}/g, (_, varName: string) => {\n return process.env[varName] || ''\n })\n if (resolved) env[key] = resolved\n }\n }\n\n // Ensure PATH is set — on some systems (e.g. macOS launchd) it may be missing\n if (!env.PATH) {\n env.PATH = '/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin'\n if (process.platform === 'darwin') {\n env.PATH = '/opt/homebrew/bin:/opt/homebrew/sbin:' + env.PATH\n }\n }\n\n console.log(`[PTY] Spawning pane ${paneId}: shell=${resolvedShell}, cwd=${cwd}`)\n\n const term = pty.spawn(resolvedShell, [], {\n name: 'xterm-256color',\n cols,\n rows,\n cwd,\n env,\n })\n\n // Create communication components\n const shellDetector = isAgent\n ? new ShellReadyDetector(paneId, { stripSentinel: true })\n : null\n\n const stateAnalyzer = new OutputStateAnalyzer({\n idleThresholdMs: 5000,\n onStatusChange: (status) => {\n const e = this.entries.get(paneId)\n if (e) {\n e.status = status\n for (const cb of e.onStatusCallbacks) {\n cb(status)\n }\n }\n },\n })\n\n const entry: PtyEntry = {\n pty: term,\n config,\n status: 'running',\n meta: {},\n parser: new StatuslineParser(),\n activityParser: new ActivityParser(),\n stateAnalyzer,\n shellDetector,\n agentDetector: null, // Created after shell is ready\n scrollback: [],\n scrollbackBytes: 0,\n onDataCallbacks: [],\n onStatusCallbacks: [],\n onMetaCallbacks: [],\n onActivityCallbacks: [],\n }\n\n this.entries.set(paneId, entry)\n\n // Handle PTY output\n term.onData((data: string) => {\n // Feed shell ready detector (strips sentinel from output)\n let processedData = data\n if (entry.shellDetector && !entry.shellDetector.isDone) {\n processedData = entry.shellDetector.feed(data)\n }\n\n // Feed agent ready detector\n if (entry.agentDetector && !entry.agentDetector.isDone) {\n entry.agentDetector.feed(processedData)\n }\n\n const { cleanData, meta } = entry.parser.parse(processedData)\n\n if (cleanData) {\n // Feed state analyzer (hot path — just timestamp + timer reset)\n entry.stateAnalyzer.onOutput()\n\n // Buffer for scrollback replay\n entry.scrollback.push(cleanData)\n entry.scrollbackBytes += cleanData.length\n // Trim if over budget — batch splice instead of shift() loop to avoid O(n²)\n if (entry.scrollbackBytes > MAX_SCROLLBACK_BYTES) {\n let bytesToRemove = entry.scrollbackBytes - MAX_SCROLLBACK_BYTES\n let removeCount = 0\n while (removeCount < entry.scrollback.length - 1 && bytesToRemove > 0) {\n bytesToRemove -= entry.scrollback[removeCount].length\n entry.scrollbackBytes -= entry.scrollback[removeCount].length\n removeCount++\n }\n if (removeCount > 0) {\n entry.scrollback.splice(0, removeCount)\n }\n }\n\n for (const cb of entry.onDataCallbacks) {\n cb(cleanData)\n }\n }\n\n if (meta) {\n entry.meta = { ...entry.meta, ...meta }\n\n // Feed to state analyzer and agent ready detector\n entry.stateAnalyzer.onMeta(meta)\n if (entry.agentDetector && !entry.agentDetector.isDone) {\n entry.agentDetector.onMeta(meta)\n }\n\n for (const cb of entry.onMetaCallbacks) {\n cb(entry.meta)\n }\n }\n\n // Parse file activity from PTY output (attributed to this pane)\n if (config.agent !== '__shell__') {\n const activity = entry.activityParser.parse(data)\n if (activity) {\n for (const cb of entry.onActivityCallbacks) {\n cb(activity)\n }\n }\n }\n })\n\n // Handle PTY exit\n term.onExit(({ exitCode }) => {\n const e = this.entries.get(paneId)\n if (e) {\n e.stateAnalyzer.onExit(exitCode)\n // Dispose detectors\n e.shellDetector?.dispose()\n e.agentDetector?.dispose()\n }\n })\n\n // Shell ready → Agent command → Agent ready → Task\n if (isAgent && shellDetector) {\n this.startAgentSequence(paneId, config, agentDef!, shellDetector)\n }\n\n return term.pid\n }\n\n /**\n * Orchestrates the shell → agent → task startup sequence using\n * event-driven detectors instead of hardcoded setTimeout delays.\n */\n private async startAgentSequence(\n paneId: string,\n config: PaneConfig,\n agentDef: AgentDefinition,\n shellDetector: ShellReadyDetector,\n ): Promise<void> {\n const entry = this.entries.get(paneId)\n if (!entry) return\n\n // Step 1: Wait for shell to be ready\n const shellResult = await shellDetector.start(entry.pty)\n if (!this.entries.has(paneId)) return // pane was killed while waiting\n\n console.log(`[PTY] Shell ready for ${paneId}: detected=${shellResult.detected} (${shellResult.elapsedMs}ms)`)\n\n // Step 2: Send agent command\n this.sendAgentCommand(paneId, config, agentDef)\n\n // Step 3: If there's a task, wait for agent to be ready before sending\n if (config.task && config.restore !== 'manual') {\n const agentDetector = new AgentReadyDetector({\n quiescenceMs: 3000,\n hardTimeoutMs: 15000,\n })\n entry.agentDetector = agentDetector\n\n const agentResult = await agentDetector.start()\n if (!this.entries.has(paneId)) return // pane was killed while waiting\n\n console.log(`[PTY] Agent ready for ${paneId}: reason=${agentResult.reason} (${agentResult.elapsedMs}ms)`)\n\n // Send the task\n entry.pty.write(config.task + '\\r')\n }\n }\n\n private sendAgentCommand(paneId: string, config: PaneConfig, agentDef: AgentDefinition): void {\n const entry = this.entries.get(paneId)\n if (!entry) return\n\n let cmd = agentDef.bin\n\n // Add resume flag with specific session ID\n if (config.restore === 'resume' && config.sessionId && agentDef.resume_flag) {\n cmd += ` ${agentDef.resume_flag} ${config.sessionId}`\n } else if (config.restore === 'continue' && agentDef.continue_flag) {\n // Add continue flag to resume latest session\n cmd += ` ${agentDef.continue_flag}`\n }\n\n // Add yolo flag if enabled\n if (config.yolo && agentDef.yolo_flag) {\n cmd += ` ${agentDef.yolo_flag}`\n }\n\n // Send the command to start the agent\n entry.pty.write(cmd + '\\r')\n }\n\n write(paneId: string, data: string): void {\n const entry = this.entries.get(paneId)\n if (entry) {\n entry.pty.write(data)\n }\n }\n\n resize(paneId: string, cols: number, rows: number): void {\n const entry = this.entries.get(paneId)\n if (entry) {\n try {\n entry.pty.resize(cols, rows)\n } catch {\n // PTY may not be ready yet (ENOTTY), ignore\n }\n }\n }\n\n kill(paneId: string): void {\n const entry = this.entries.get(paneId)\n if (entry) {\n // Clean up comm components\n entry.stateAnalyzer.dispose()\n entry.shellDetector?.dispose()\n entry.agentDetector?.dispose()\n entry.parser.reset()\n\n // Clear callback arrays to break closure references and prevent leaks\n entry.onDataCallbacks.length = 0\n entry.onStatusCallbacks.length = 0\n entry.onMetaCallbacks.length = 0\n entry.onActivityCallbacks.length = 0\n\n try {\n entry.pty.kill()\n } catch {\n // Process may already be dead\n }\n this.entries.delete(paneId)\n }\n }\n\n killAll(): void {\n for (const [paneId] of this.entries) {\n this.kill(paneId)\n }\n }\n\n getStatus(paneId: string): PaneStatus {\n return this.entries.get(paneId)?.status || 'stopped'\n }\n\n getMeta(paneId: string): PaneMeta {\n return this.entries.get(paneId)?.meta || {}\n }\n\n getPid(paneId: string): number | undefined {\n return this.entries.get(paneId)?.pty.pid\n }\n\n onData(paneId: string, callback: (data: string) => void): void {\n const entry = this.entries.get(paneId)\n if (entry) {\n entry.onDataCallbacks.push(callback)\n }\n }\n\n onStatus(paneId: string, callback: (status: PaneStatus) => void): void {\n const entry = this.entries.get(paneId)\n if (entry) {\n entry.onStatusCallbacks.push(callback)\n }\n }\n\n onMeta(paneId: string, callback: (meta: PaneMeta) => void): void {\n const entry = this.entries.get(paneId)\n if (entry) {\n entry.onMetaCallbacks.push(callback)\n }\n }\n\n onActivity(paneId: string, callback: (activity: FileActivity) => void): void {\n const entry = this.entries.get(paneId)\n if (entry) {\n entry.onActivityCallbacks.push(callback)\n }\n }\n\n getScrollback(paneId: string): string {\n const entry = this.entries.get(paneId)\n if (!entry) return ''\n return entry.scrollback.join('')\n }\n\n has(paneId: string): boolean {\n return this.entries.has(paneId)\n }\n}\n","import type { PaneMeta } from '../types.ts'\n\n/**\n * Parses Claude Code statusline JSON from PTY output.\n *\n * Hardened version with multi-layer validation:\n * 1. Line must parse as valid JSON\n * 2. Must contain at least 2 known statusline fields (eliminates random JSON)\n * 3. Field types are strictly validated\n *\n * Performance:\n * - Fast-path: lines that don't start with '{' are skipped with zero overhead.\n * - Buffer is only used for incomplete lines; complete lines are processed inline.\n * - JSON.parse is only attempted on candidate lines, not all output.\n */\n\n// The known statusline field names and their expected types\nconst KNOWN_FIELDS: Record<string, string> = {\n model: 'string',\n session_id: 'string',\n cost_usd: 'number',\n context_used_pct: 'number',\n cwd: 'string',\n tool_name: 'string',\n // Claude Code may add more fields — add them here as discovered\n}\n\n// Minimum number of known fields required to classify as statusline\nconst MIN_KNOWN_FIELDS = 2\n\n// Max buffer size — if a line exceeds this without a newline, discard buffer\nconst MAX_BUFFER_SIZE = 64 * 1024 // 64KB\n\nexport class StatuslineParser {\n private buffer = ''\n\n /**\n * Process raw PTY output data.\n * Returns { cleanData, meta } where cleanData has statusline JSON stripped\n * and meta contains parsed metadata (if any was found).\n */\n parse(data: string): { cleanData: string; meta: PaneMeta | null } {\n let meta: PaneMeta | null = null\n\n // Fast path: no newline means partial chunk (keystroke echo, prompt).\n // Buffer it but pass through immediately.\n if (!data.includes('\\n')) {\n this.buffer += data\n // Prevent unbounded buffer growth (e.g., binary output without newlines)\n if (this.buffer.length > MAX_BUFFER_SIZE) {\n this.buffer = ''\n }\n return { cleanData: data, meta: null }\n }\n\n const combined = this.buffer + data\n this.buffer = ''\n\n const lines = combined.split('\\n')\n\n // Last element is trailing content (empty if data ended with \\n)\n const trailing = lines.pop() || ''\n if (trailing) {\n this.buffer = trailing\n }\n\n const cleanLines: string[] = []\n\n for (const line of lines) {\n const trimmed = line.trim()\n\n // Fast reject: not a JSON candidate\n if (trimmed.length < 10 || trimmed.charCodeAt(0) !== 0x7B /* '{' */) {\n cleanLines.push(line)\n continue\n }\n\n // Must end with '}'\n if (trimmed.charCodeAt(trimmed.length - 1) !== 0x7D /* '}' */) {\n cleanLines.push(line)\n continue\n }\n\n // Attempt JSON parse\n let parsed: Record<string, unknown>\n try {\n parsed = JSON.parse(trimmed)\n } catch {\n cleanLines.push(line)\n continue\n }\n\n // Validate: must be a plain object with enough known fields\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n cleanLines.push(line)\n continue\n }\n\n if (this.isStatuslineJson(parsed)) {\n meta = this.extractMeta(parsed)\n // Strip this line from terminal output\n continue\n }\n\n // Valid JSON but not a statusline — pass through\n cleanLines.push(line)\n }\n\n // Reconstruct output\n let cleanData = cleanLines.join('\\n')\n if (cleanLines.length > 0) {\n cleanData += '\\n'\n }\n\n return { cleanData, meta }\n }\n\n /**\n * Reset internal buffer state. Useful when restarting a pane.\n */\n reset(): void {\n this.buffer = ''\n }\n\n private isStatuslineJson(obj: Record<string, unknown>): boolean {\n let matchCount = 0\n for (const [field, expectedType] of Object.entries(KNOWN_FIELDS)) {\n if (field in obj) {\n // Type must also match\n if (typeof obj[field] === expectedType) {\n matchCount++\n }\n }\n }\n return matchCount >= MIN_KNOWN_FIELDS\n }\n\n private extractMeta(obj: Record<string, unknown>): PaneMeta {\n const meta: PaneMeta = {}\n\n if (typeof obj.model === 'string') {\n meta.model = obj.model\n }\n if (typeof obj.context_used_pct === 'number') {\n meta.contextUsedPct = obj.context_used_pct\n }\n if (typeof obj.cost_usd === 'number') {\n meta.costUsd = obj.cost_usd\n }\n if (typeof obj.session_id === 'string') {\n meta.sessionId = obj.session_id\n }\n if (typeof obj.cwd === 'string') {\n meta.cwd = obj.cwd\n }\n\n return meta\n }\n}\n","import type { IPty } from 'node-pty'\n\n/**\n * Detects when a shell process is ready to receive commands.\n *\n * Strategy: write an echo sentinel command into the PTY immediately after spawn.\n * The sentinel queues behind .bashrc/.zshrc sourcing and executes only when\n * the shell is interactive and ready. We watch the PTY output for the sentinel\n * value and resolve the promise.\n *\n * Performance notes:\n * - The sentinel is a single small write; no polling loop.\n * - The onData listener is removed as soon as the sentinel is found or the\n * timeout fires, so there is zero ongoing overhead.\n * - The sentinel string includes paneId to avoid cross-pane collisions.\n */\n\nconst FALLBACK_TIMEOUT_MS = 8000\n\nexport interface ShellReadyOptions {\n /** Milliseconds before giving up and resolving anyway. Default 8000. */\n timeoutMs?: number\n /** If true, suppress the sentinel echo from reaching downstream consumers. */\n stripSentinel?: boolean\n}\n\nexport interface ShellReadyResult {\n /** Whether the sentinel was detected (true) or we timed out (false). */\n detected: boolean\n /** Milliseconds elapsed from injection to detection/timeout. */\n elapsedMs: number\n}\n\nexport class ShellReadyDetector {\n private sentinel: string\n private resolve!: (result: ShellReadyResult) => void\n private promise: Promise<ShellReadyResult>\n private startTime: number\n private timer: ReturnType<typeof setTimeout> | null = null\n private disposed = false\n\n // Exposed for testing — accumulated raw output chunks\n private chunks: string[] = []\n\n constructor(\n private paneId: string,\n private options: ShellReadyOptions = {},\n ) {\n // Use a unique, unlikely-to-collide sentinel value\n this.sentinel = `__NEXUS_RDY_${paneId}_${Date.now().toString(36)}__`\n this.startTime = Date.now()\n\n this.promise = new Promise<ShellReadyResult>((resolve) => {\n this.resolve = resolve\n })\n }\n\n /**\n * Inject the sentinel into the shell and start watching.\n * Call this immediately after pty.spawn().\n *\n * Returns a promise that resolves when the shell is ready.\n * The caller should await this before sending any agent command.\n */\n start(term: IPty): Promise<ShellReadyResult> {\n const timeoutMs = this.options.timeoutMs ?? FALLBACK_TIMEOUT_MS\n\n // Inject sentinel echo — the shell will execute this after .bashrc finishes\n term.write(`echo ${this.sentinel}\\r`)\n\n // Set up fallback timeout\n this.timer = setTimeout(() => {\n if (!this.disposed) {\n this.disposed = true\n this.resolve({\n detected: false,\n elapsedMs: Date.now() - this.startTime,\n })\n }\n }, timeoutMs)\n\n return this.promise\n }\n\n /**\n * Feed PTY output data into the detector.\n * Call this from the PTY onData handler.\n *\n * Returns the data with the sentinel line stripped if `stripSentinel` is true\n * and the sentinel was found in this chunk. Otherwise returns the data as-is.\n */\n feed(data: string): string {\n if (this.disposed) return data\n\n this.chunks.push(data)\n\n // Check if sentinel appears in accumulated data\n // We check chunks to handle the case where sentinel spans two chunks\n const recent = this.chunks.length <= 3\n ? this.chunks.join('')\n : this.chunks.slice(-3).join('')\n\n if (recent.includes(this.sentinel)) {\n this.disposed = true\n if (this.timer) {\n clearTimeout(this.timer)\n this.timer = null\n }\n this.resolve({\n detected: true,\n elapsedMs: Date.now() - this.startTime,\n })\n // Free reference to accumulated chunks\n this.chunks = []\n\n if (this.options.stripSentinel) {\n return this.stripSentinelFromData(data)\n }\n }\n\n return data\n }\n\n /**\n * Whether the detector has finished (either by detection or timeout).\n */\n get isDone(): boolean {\n return this.disposed\n }\n\n /**\n * Clean up without resolving (e.g., if the PTY is killed before ready).\n */\n dispose(): void {\n if (!this.disposed) {\n this.disposed = true\n if (this.timer) {\n clearTimeout(this.timer)\n this.timer = null\n }\n this.resolve({\n detected: false,\n elapsedMs: Date.now() - this.startTime,\n })\n }\n this.chunks = []\n }\n\n private stripSentinelFromData(data: string): string {\n // Remove the sentinel line and surrounding echo command artifacts\n // The echo command produces: `echo __NEXUS_RDY_...__\\r\\n__NEXUS_RDY_...__\\r\\n`\n // We want to strip both the command echo and the output\n const lines = data.split('\\n')\n const filtered = lines.filter((line) => !line.includes(this.sentinel))\n return filtered.join('\\n')\n }\n}\n","import type { PaneMeta } from '../types.ts'\n\n/**\n * Detects when an Agent process has finished initializing and is ready\n * to receive user input (tasks, review comments, etc.).\n *\n * Strategy (layered, first match wins):\n * 1. Statusline detection — if the StatuslineParser emits a meta event with\n * a session_id, the agent is live and ready.\n * 2. Prompt pattern — detect known agent prompt patterns in terminal output\n * (e.g., Claude Code's `❯` or `>` prompt after init banner).\n * 3. Output quiescence — if the agent stops producing output for a\n * configurable interval, assume it's waiting for input.\n * 4. Hard timeout — resolve regardless after a maximum wait.\n *\n * Performance:\n * - No polling; purely event-driven via feed() / onMeta() calls.\n * - Single timer for quiescence; re-armed on each output chunk.\n * - All listeners removed on resolve.\n */\n\nconst DEFAULT_QUIESCENCE_MS = 3000\nconst DEFAULT_HARD_TIMEOUT_MS = 15000\n\n// Known agent prompt patterns (after ANSI stripping)\nconst PROMPT_PATTERNS = [\n /❯\\s*$/, // Claude Code prompt\n />\\s*$/, // Generic prompt\n /\\$\\s*$/, // Shell-style prompt (some agents)\n /waiting for input/i,\n]\n\nexport interface AgentReadyOptions {\n /** Ms of output silence before assuming ready. Default 3000. */\n quiescenceMs?: number\n /** Hard timeout ms. Default 15000. */\n hardTimeoutMs?: number\n /** Additional prompt regex patterns for custom agents. */\n extraPromptPatterns?: RegExp[]\n}\n\nexport type AgentReadyReason = 'statusline' | 'prompt' | 'quiescence' | 'timeout'\n\nexport interface AgentReadyResult {\n reason: AgentReadyReason\n elapsedMs: number\n}\n\nexport class AgentReadyDetector {\n private resolve!: (result: AgentReadyResult) => void\n private promise: Promise<AgentReadyResult>\n private startTime: number\n private disposed = false\n\n private quiescenceTimer: ReturnType<typeof setTimeout> | null = null\n private hardTimer: ReturnType<typeof setTimeout> | null = null\n\n private quiescenceMs: number\n private promptPatterns: RegExp[]\n\n constructor(private options: AgentReadyOptions = {}) {\n this.startTime = Date.now()\n this.quiescenceMs = options.quiescenceMs ?? DEFAULT_QUIESCENCE_MS\n this.promptPatterns = [\n ...PROMPT_PATTERNS,\n ...(options.extraPromptPatterns || []),\n ]\n\n this.promise = new Promise<AgentReadyResult>((resolve) => {\n this.resolve = resolve\n })\n }\n\n /**\n * Start the detection timers. Returns a promise that resolves when the\n * agent is deemed ready.\n */\n start(): Promise<AgentReadyResult> {\n const hardTimeoutMs = this.options.hardTimeoutMs ?? DEFAULT_HARD_TIMEOUT_MS\n\n // Hard timeout\n this.hardTimer = setTimeout(() => {\n this.finish('timeout')\n }, hardTimeoutMs)\n\n // Start initial quiescence timer (agent may not produce any output\n // if it's immediately ready)\n this.resetQuiescence()\n\n return this.promise\n }\n\n /**\n * Feed terminal output from the agent. Resets quiescence timer and\n * checks for prompt patterns.\n */\n feed(data: string): void {\n if (this.disposed) return\n\n // Reset quiescence timer on any output\n this.resetQuiescence()\n\n // Check for prompt patterns (strip ANSI first)\n const clean = stripAnsi(data)\n // Only check the last portion — prompt appears at end of output\n const tail = clean.slice(-200)\n\n for (const pattern of this.promptPatterns) {\n if (pattern.test(tail)) {\n this.finish('prompt')\n return\n }\n }\n }\n\n /**\n * Called when a statusline meta event is received. If it contains a\n * session_id, the agent is definitely ready.\n */\n onMeta(meta: PaneMeta): void {\n if (this.disposed) return\n\n if (meta.sessionId) {\n this.finish('statusline')\n }\n }\n\n get isDone(): boolean {\n return this.disposed\n }\n\n dispose(): void {\n if (!this.disposed) {\n this.disposed = true\n this.clearTimers()\n this.resolve({\n reason: 'timeout',\n elapsedMs: Date.now() - this.startTime,\n })\n }\n }\n\n private finish(reason: AgentReadyReason): void {\n if (this.disposed) return\n this.disposed = true\n this.clearTimers()\n this.resolve({\n reason,\n elapsedMs: Date.now() - this.startTime,\n })\n }\n\n private resetQuiescence(): void {\n if (this.quiescenceTimer) {\n clearTimeout(this.quiescenceTimer)\n }\n this.quiescenceTimer = setTimeout(() => {\n this.finish('quiescence')\n }, this.quiescenceMs)\n }\n\n private clearTimers(): void {\n if (this.quiescenceTimer) {\n clearTimeout(this.quiescenceTimer)\n this.quiescenceTimer = null\n }\n if (this.hardTimer) {\n clearTimeout(this.hardTimer)\n this.hardTimer = null\n }\n }\n}\n\n// Lightweight ANSI stripper — only needs to handle enough for prompt detection\nfunction stripAnsi(str: string): string {\n return str\n .replace(/\\x1b\\][^\\x07]*(?:\\x07|\\x1b\\\\)/g, '') // OSC\n .replace(/\\x1b\\[[0-9;]*[a-zA-Z]/g, '') // CSI\n .replace(/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f]/g, '') // control chars\n}\n","import type { PaneMeta, PaneStatus } from '../types.ts'\n\n/**\n * Infers Agent behavioral state from PTY output patterns and statusline metadata.\n *\n * State machine:\n * running — Agent is producing output (actively working)\n * waiting — Agent has stopped producing output for `idleThresholdMs`\n * (likely waiting for user input or confirmation)\n * idle — Extended silence (`idleThresholdMs * 3`), process still alive\n * stopped — Process exited normally\n * error — Process exited with non-zero code\n *\n * The stopped/error states are set externally (from PTY exit handler),\n * not by this analyzer.\n *\n * Performance:\n * - Single setTimeout for idle detection; re-armed per output chunk.\n * - onOutput() is called on every PTY data event, so it must be fast:\n * just a timestamp update + timer reset.\n * - Meta changes are infrequent and cheap to process.\n * - No string inspection on the hot path (prompt detection is in AgentReadyDetector).\n */\n\nconst DEFAULT_IDLE_THRESHOLD_MS = 5000\n\nexport interface OutputStateOptions {\n /** Ms of silence before transitioning running→waiting. Default 5000. */\n idleThresholdMs?: number\n /** Callback when inferred status changes. */\n onStatusChange?: (status: PaneStatus) => void\n}\n\nexport class OutputStateAnalyzer {\n private currentStatus: PaneStatus = 'running'\n private lastOutputTime = 0\n private lastContextPct: number | null = null\n private idleTimer: ReturnType<typeof setTimeout> | null = null\n private extendedIdleTimer: ReturnType<typeof setTimeout> | null = null\n\n private idleThresholdMs: number\n private onStatusChange?: (status: PaneStatus) => void\n\n constructor(options: OutputStateOptions = {}) {\n this.idleThresholdMs = options.idleThresholdMs ?? DEFAULT_IDLE_THRESHOLD_MS\n this.onStatusChange = options.onStatusChange\n this.lastOutputTime = Date.now()\n }\n\n /**\n * Call on every PTY output chunk. Must be fast — hot path.\n */\n onOutput(): void {\n this.lastOutputTime = Date.now()\n\n // If we were waiting/idle, transition back to running\n if (this.currentStatus === 'waiting' || this.currentStatus === 'idle') {\n this.setStatus('running')\n }\n\n this.resetIdleTimers()\n }\n\n /**\n * Call when a statusline meta event is received.\n * Context usage changes confirm the agent is actively working.\n */\n onMeta(meta: PaneMeta): void {\n if (meta.contextUsedPct !== undefined) {\n if (this.lastContextPct !== null && meta.contextUsedPct > this.lastContextPct) {\n // Context grew — agent is definitely working\n if (this.currentStatus !== 'running') {\n this.setStatus('running')\n }\n this.resetIdleTimers()\n }\n this.lastContextPct = meta.contextUsedPct\n }\n }\n\n /**\n * Call when the PTY process exits. Overrides any inferred state.\n */\n onExit(exitCode: number): void {\n this.clearTimers()\n this.setStatus(exitCode === 0 ? 'stopped' : 'error')\n }\n\n /**\n * Get the current inferred status.\n */\n getStatus(): PaneStatus {\n return this.currentStatus\n }\n\n /**\n * Milliseconds since last output.\n */\n getSilenceMs(): number {\n return Date.now() - this.lastOutputTime\n }\n\n /**\n * Clean up timers.\n */\n dispose(): void {\n this.clearTimers()\n }\n\n private setStatus(status: PaneStatus): void {\n if (status === this.currentStatus) return\n this.currentStatus = status\n this.onStatusChange?.(status)\n }\n\n private resetIdleTimers(): void {\n this.clearTimers()\n\n // Stage 1: running → waiting\n this.idleTimer = setTimeout(() => {\n if (this.currentStatus === 'running') {\n this.setStatus('waiting')\n }\n\n // Stage 2: waiting → idle (3x threshold)\n this.extendedIdleTimer = setTimeout(() => {\n if (this.currentStatus === 'waiting') {\n this.setStatus('idle')\n }\n }, this.idleThresholdMs * 2)\n }, this.idleThresholdMs)\n }\n\n private clearTimers(): void {\n if (this.idleTimer) {\n clearTimeout(this.idleTimer)\n this.idleTimer = null\n }\n if (this.extendedIdleTimer) {\n clearTimeout(this.extendedIdleTimer)\n this.extendedIdleTimer = null\n }\n }\n}\n","export type FileAction = 'read' | 'edit' | 'write' | 'create' | 'delete' | 'bash'\n\nexport interface FileActivity {\n file: string\n action: FileAction\n timestamp: number\n}\n\n// More complete ANSI stripping — handles OSC sequences, cursor movement, etc.\nfunction stripAnsi(str: string): string {\n return str\n .replace(/\\x1b\\][^\\x07]*(?:\\x07|\\x1b\\\\)/g, '') // OSC sequences\n .replace(/\\x1b\\[[0-9;]*[a-zA-Z]/g, '') // CSI sequences\n .replace(/\\x1b[()][AB012]/g, '') // Character set selection\n .replace(/\\x1b[>=<]/g, '') // Keypad/cursor mode\n .replace(/\\x0f|\\x0e/g, '') // SI/SO\n .replace(/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f]/g, '') // Other control chars\n}\n\n/**\n * Parses Claude Code PTY output to detect file operations.\n * Claude Code outputs tool usage with various ANSI-styled formats.\n * This parser strips ANSI codes and matches known patterns.\n */\nconst MAX_BUFFER_SIZE = 64 * 1024 // 64KB — same as StatuslineParser\n\nexport class ActivityParser {\n private buffer = ''\n private lastFile = ''\n private lastTime = 0\n private readonly DEDUP_MS = 2000 // Ignore same file within 2s\n\n parse(data: string): FileActivity | null {\n if (!data.includes('\\n')) {\n this.buffer += data\n // Prevent unbounded buffer growth (e.g., binary output without newlines)\n if (this.buffer.length > MAX_BUFFER_SIZE) {\n this.buffer = ''\n }\n return null\n }\n\n const lines = (this.buffer + data).split('\\n')\n this.buffer = ''\n\n const trailing = lines.pop() || ''\n if (trailing) {\n this.buffer = trailing\n }\n\n // Check all lines, return first match\n for (const line of lines) {\n const activity = this.parseLine(line)\n if (activity) {\n // Dedup: skip if same file within DEDUP_MS\n if (activity.file === this.lastFile && activity.timestamp - this.lastTime < this.DEDUP_MS) {\n continue\n }\n this.lastFile = activity.file\n this.lastTime = activity.timestamp\n return activity\n }\n }\n\n return null\n }\n\n private parseLine(line: string): FileActivity | null {\n const clean = stripAnsi(line).trim()\n if (!clean || clean.length < 5) return null\n\n // ── Claude Code specific patterns ──\n\n // Pattern: \"⎿ Read file_path\" or \"⎿ Edit file_path\" (Claude Code tool result markers)\n const toolResultMatch = clean.match(\n /^[⎿│├└┌┐┘┤┬┴┼╭╮╰╯─━]?\\s*(Read|Edit|Write|MultiEdit|Create|Delete|Glob|Grep|Bash)\\s+(.+)/i,\n )\n if (toolResultMatch) {\n return this.buildActivity(toolResultMatch[1], toolResultMatch[2])\n }\n\n // Pattern: Tool name at start of line followed by path — \"Read src/foo.ts\"\n // Must be exact tool name, not part of a sentence\n const toolStartMatch = clean.match(\n /^(Read|Edit|Write|MultiEdit|Create|Delete)\\s+([^\\s(][^\\s]*\\.\\w{1,10})\\b/,\n )\n if (toolStartMatch) {\n return this.buildActivity(toolStartMatch[1], toolStartMatch[2])\n }\n\n // Pattern: Tool name with parenthesized path — \"Read(src/foo.ts)\" or \"Edit(file_path=...)\"\n const parenMatch = clean.match(\n /\\b(Read|Edit|Write|MultiEdit|Create|Delete)\\((?:file_path\\s*[:=]\\s*)?[\"']?([^\"')]+\\.\\w{1,10})[\"']?\\)/i,\n )\n if (parenMatch) {\n return this.buildActivity(parenMatch[1], parenMatch[2])\n }\n\n // Pattern: \"file_path\": \"src/foo.ts\" (JSON-like in tool output)\n const jsonFieldMatch = clean.match(\n /[\"']?file_path[\"']?\\s*[:=]\\s*[\"']([^\"']+\\.\\w{1,10})[\"']/i,\n )\n if (jsonFieldMatch) {\n const action = this.inferActionFromContext(clean)\n return this.buildActivity(action, jsonFieldMatch[1])\n }\n\n // Pattern: \"── Read: src/foo.ts\" or \"Read: src/foo.ts\"\n const colonMatch = clean.match(\n /(?:─+\\s*)?(Read|Edit|Write|MultiEdit|Create|Delete)\\s*:\\s*(.+?)(?:\\s*─+)?$/i,\n )\n if (colonMatch) {\n return this.buildActivity(colonMatch[1], colonMatch[2])\n }\n\n // Pattern: Spinner chars + tool — \"⠿ Edit src/foo.ts\" / \"✓ Write src/bar.ts\"\n const spinnerMatch = clean.match(\n /[⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏⠿✓✗✔✘●◉▶▸►◆◇■□▪▫★☆○◎]\\s*(Read|Edit|Write|MultiEdit|Create|Delete)\\s+(.+)/i,\n )\n if (spinnerMatch) {\n return this.buildActivity(spinnerMatch[1], spinnerMatch[2])\n }\n\n // Pattern: Indented path after tool header (continuation line)\n // e.g., \" /relative/path/file.ts\" or \" path/to/file.ts\"\n // Only if line is just a path with leading whitespace\n const indentedPathMatch = clean.match(\n /^([a-zA-Z0-9_][a-zA-Z0-9_./\\-]*\\.\\w{1,10})$/,\n )\n if (indentedPathMatch && line.startsWith(' ')) {\n return this.buildActivity('Read', indentedPathMatch[1])\n }\n\n return null\n }\n\n private buildActivity(toolName: string, rawPath: string): FileActivity | null {\n const file = this.cleanPath(rawPath)\n if (!file || !this.isValidPath(file)) return null\n\n const action = this.toolToAction(toolName)\n return { file, action, timestamp: Date.now() }\n }\n\n private toolToAction(tool: string): FileAction {\n switch (tool.toLowerCase()) {\n case 'read':\n case 'glob':\n case 'grep':\n return 'read'\n case 'edit':\n case 'multiedit':\n return 'edit'\n case 'write':\n return 'write'\n case 'create':\n return 'create'\n case 'delete':\n return 'delete'\n case 'bash':\n return 'bash'\n default:\n return 'read'\n }\n }\n\n private inferActionFromContext(line: string): string {\n const lower = line.toLowerCase()\n if (lower.includes('edit') || lower.includes('old_string') || lower.includes('new_string')) return 'Edit'\n if (lower.includes('write') || lower.includes('content')) return 'Write'\n if (lower.includes('delete') || lower.includes('remove')) return 'Delete'\n return 'Read'\n }\n\n private cleanPath(raw: string): string {\n return raw\n .trim()\n .replace(/^['\"`]+|['\"`]+$/g, '')\n .replace(/^\\.\\//, '')\n .replace(/\\s+.*$/, '') // Remove anything after whitespace\n .replace(/[,;:)]+$/, '') // Remove trailing punctuation\n .replace(/^\\(/, '') // Remove leading paren\n }\n\n // Paths under these prefixes are Nexus internals or noise — ignore them\n private static IGNORED_PREFIXES = ['.nexus/', 'node_modules/', '.git/']\n\n private isValidPath(file: string): boolean {\n if (!file || file.length < 3) return false\n // Must have a file extension\n if (!/\\.\\w{1,10}$/.test(file)) return false\n // Must not be absolute path or URL\n if (file.startsWith('/') || file.includes('://')) return false\n // Skip Nexus internal and noise paths\n for (const prefix of ActivityParser.IGNORED_PREFIXES) {\n if (file.startsWith(prefix)) return false\n }\n // No suspicious chars\n if (/[<>|&$`\\\\{}[\\]]/.test(file)) return false\n // Reasonable length\n const parts = file.split('/')\n if (parts.length > 15) return false\n for (const part of parts) {\n if (part.length > 100 || part.length === 0) return false\n }\n return true\n }\n}\n","import { spawn, type ChildProcessWithoutNullStreams } from 'node:child_process'\nimport fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport type {\n AgentDefinition,\n ConversationEvent,\n FileActivity,\n PaneConfig,\n PaneMeta,\n PaneStatus,\n} from '../types.ts'\nimport type { ConfigManager } from '../workspace/ConfigManager.ts'\n\nconst MAX_SCROLLBACK_BYTES = 512 * 1024\n\ninterface PendingRequest {\n resolve: (value: unknown) => void\n reject: (error: Error) => void\n}\n\ninterface AcpEntry {\n proc: ChildProcessWithoutNullStreams\n config: PaneConfig\n status: PaneStatus\n meta: PaneMeta\n nextRequestId: number\n nextMessageId: number\n nextToolId: number\n pending: Map<number, PendingRequest>\n stdoutBuffer: string\n scrollback: string[]\n scrollbackBytes: number\n onDataCallbacks: Array<(data: string) => void>\n onStatusCallbacks: Array<(status: PaneStatus) => void>\n onMetaCallbacks: Array<(meta: PaneMeta) => void>\n onConversationCallbacks: Array<(event: ConversationEvent) => void>\n onActivityCallbacks: Array<(activity: FileActivity) => void>\n}\n\nfunction resolveAgentEnv(agentDef: AgentDefinition | undefined): Record<string, string> {\n const env: Record<string, string> = {}\n for (const [key, value] of Object.entries(process.env)) {\n if (value !== undefined && !key.startsWith('CLAUDE') && key !== 'CLAUDECODE') {\n env[key] = value\n }\n }\n\n if (agentDef?.env) {\n const blocked = new Set([\n 'PATH', 'LD_PRELOAD', 'LD_LIBRARY_PATH',\n 'DYLD_INSERT_LIBRARIES', 'DYLD_LIBRARY_PATH', 'DYLD_FRAMEWORK_PATH',\n ])\n for (const [key, value] of Object.entries(agentDef.env)) {\n if (blocked.has(key)) continue\n env[key] = value.replace(/\\$\\{(\\w+)\\}/g, (_, name: string) => process.env[name] || '')\n }\n }\n\n if (!env.PATH) {\n env.PATH = '/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin'\n if (process.platform === 'darwin') {\n env.PATH = `/opt/homebrew/bin:/opt/homebrew/sbin:${env.PATH}`\n }\n }\n\n return env\n}\n\nexport class AcpRuntime {\n private entries = new Map<string, AcpEntry>()\n private configManager: ConfigManager\n\n constructor(configManager: ConfigManager) {\n this.configManager = configManager\n }\n\n spawn(paneId: string, config: PaneConfig): number | undefined {\n if (this.entries.has(paneId)) {\n this.kill(paneId)\n }\n\n const projectDir = this.configManager.getProjectDir()\n const basePath = (config.isolation === 'worktree' && config.worktreePath)\n ? config.worktreePath\n : projectDir\n let cwd = config.workdir\n ? path.resolve(basePath, config.workdir)\n : basePath\n\n if (!fs.existsSync(cwd)) {\n cwd = fs.existsSync(projectDir) ? projectDir : os.homedir()\n }\n\n const agentDef = this.configManager.getAgentDefinition(config.agent)\n if (!agentDef) {\n throw new Error(`Missing agent definition for ${config.agent}`)\n }\n\n const env = resolveAgentEnv(agentDef)\n const proc = spawn(agentDef.bin, ['acp'], {\n cwd,\n env,\n stdio: ['pipe', 'pipe', 'pipe'],\n })\n\n const entry: AcpEntry = {\n proc,\n config,\n status: 'running',\n meta: { cwd },\n nextRequestId: 1,\n nextMessageId: 1,\n nextToolId: 1,\n pending: new Map(),\n stdoutBuffer: '',\n scrollback: [],\n scrollbackBytes: 0,\n onDataCallbacks: [],\n onStatusCallbacks: [],\n onMetaCallbacks: [],\n onConversationCallbacks: [],\n onActivityCallbacks: [],\n }\n\n this.entries.set(paneId, entry)\n\n proc.stdout.setEncoding('utf8')\n proc.stderr.setEncoding('utf8')\n\n proc.stdout.on('data', (chunk: string) => this.handleStdout(paneId, chunk))\n proc.stderr.on('data', (chunk: string) => {\n this.emitTerminal(paneId, `[acp stderr] ${chunk}`)\n })\n proc.on('exit', (code, signal) => {\n const e = this.entries.get(paneId)\n if (!e) return\n for (const pending of e.pending.values()) {\n pending.reject(new Error(`ACP process exited (${code ?? 'null'}${signal ? `, ${signal}` : ''})`))\n }\n e.pending.clear()\n this.setStatus(paneId, code === 0 ? 'stopped' : 'error')\n })\n\n this.bootstrap(paneId, cwd, config).catch((err) => {\n this.emitTerminal(paneId, `[acp error] ${(err as Error).message}\\n`)\n this.setStatus(paneId, 'error')\n })\n\n return proc.pid\n }\n\n private async bootstrap(paneId: string, cwd: string, config: PaneConfig): Promise<void> {\n const initResult = await this.request(paneId, 'initialize', {\n protocolVersion: 1,\n clientInfo: { name: 'nexus', version: '0.1.0' },\n clientCapabilities: {},\n })\n\n const loadedSessionId = config.restore === 'resume' && config.sessionId\n ? await this.tryLoadSession(paneId, config.sessionId)\n : null\n\n const sessionResult = loadedSessionId\n ? { sessionId: loadedSessionId }\n : await this.request(paneId, 'session/new', {\n cwd,\n })\n\n const sessionId = this.extractSessionId(sessionResult) || this.extractSessionId(initResult) || config.sessionId\n if (sessionId) {\n this.updateMeta(paneId, { sessionId, cwd })\n } else {\n this.updateMeta(paneId, { cwd })\n }\n\n this.emitConversation(paneId, { type: 'status', status: 'idle' })\n this.setStatus(paneId, 'idle')\n\n if (config.task && config.restore !== 'manual') {\n await this.sendPrompt(paneId, config.task)\n }\n }\n\n private async tryLoadSession(paneId: string, sessionId: string): Promise<string | null> {\n try {\n const result = await this.request(paneId, 'session/load', { sessionId })\n return this.extractSessionId(result) || sessionId\n } catch {\n return null\n }\n }\n\n async sendPrompt(paneId: string, text: string): Promise<void> {\n const entry = this.entries.get(paneId)\n if (!entry) return\n\n const sessionId = entry.meta.sessionId || entry.config.sessionId\n const messageId = `user-${entry.nextMessageId++}`\n this.emitConversation(paneId, { type: 'message', messageId, role: 'user', text })\n this.emitTerminal(paneId, `\\n> ${text}\\n\\n`)\n this.setStatus(paneId, 'running')\n this.emitConversation(paneId, { type: 'status', status: 'running' })\n\n const params: Record<string, unknown> = {\n prompt: [{ type: 'text', text }],\n }\n if (sessionId) params.sessionId = sessionId\n\n await this.request(paneId, 'session/prompt', params)\n\n // Some ACP servers stream updates but do not send an explicit \"idle\" event.\n // We leave the pane in running until an update or request completion arrives.\n }\n\n onData(paneId: string, cb: (data: string) => void): void {\n const entry = this.entries.get(paneId)\n if (entry) entry.onDataCallbacks.push(cb)\n }\n\n onStatus(paneId: string, cb: (status: PaneStatus) => void): void {\n const entry = this.entries.get(paneId)\n if (entry) entry.onStatusCallbacks.push(cb)\n }\n\n onMeta(paneId: string, cb: (meta: PaneMeta) => void): void {\n const entry = this.entries.get(paneId)\n if (entry) entry.onMetaCallbacks.push(cb)\n }\n\n onConversation(paneId: string, cb: (event: ConversationEvent) => void): void {\n const entry = this.entries.get(paneId)\n if (entry) entry.onConversationCallbacks.push(cb)\n }\n\n onActivity(paneId: string, cb: (activity: FileActivity) => void): void {\n const entry = this.entries.get(paneId)\n if (entry) entry.onActivityCallbacks.push(cb)\n }\n\n write(_paneId: string, _data: string): void {\n // ACP-backed panes do not accept raw terminal input on the primary session.\n }\n\n resize(_paneId: string, _cols: number, _rows: number): void {\n // No-op for the initial minimal ACP path.\n }\n\n getScrollback(paneId: string): string {\n const entry = this.entries.get(paneId)\n return entry ? entry.scrollback.join('') : ''\n }\n\n kill(paneId: string): void {\n const entry = this.entries.get(paneId)\n if (!entry) return\n entry.proc.kill()\n this.entries.delete(paneId)\n }\n\n killAll(): void {\n for (const paneId of this.entries.keys()) {\n this.kill(paneId)\n }\n }\n\n private handleStdout(paneId: string, chunk: string): void {\n const entry = this.entries.get(paneId)\n if (!entry) return\n\n entry.stdoutBuffer += chunk\n while (true) {\n const newline = entry.stdoutBuffer.indexOf('\\n')\n if (newline === -1) break\n const line = entry.stdoutBuffer.slice(0, newline).trim()\n entry.stdoutBuffer = entry.stdoutBuffer.slice(newline + 1)\n if (!line) continue\n\n try {\n const message = JSON.parse(line) as Record<string, unknown>\n this.handleMessage(paneId, message)\n } catch {\n this.emitTerminal(paneId, line + '\\n')\n }\n }\n }\n\n private handleMessage(paneId: string, message: Record<string, unknown>): void {\n const entry = this.entries.get(paneId)\n if (!entry) return\n\n if (typeof message.id === 'number') {\n const pending = entry.pending.get(message.id)\n if (pending) {\n entry.pending.delete(message.id)\n if ('error' in message && message.error) {\n const err = message.error as { message?: string }\n pending.reject(new Error(err?.message || 'ACP request failed'))\n } else {\n pending.resolve(message.result)\n }\n }\n return\n }\n\n if (message.method === 'session/update') {\n const params = (message.params || {}) as Record<string, unknown>\n this.handleSessionUpdate(paneId, params)\n return\n }\n }\n\n private handleSessionUpdate(paneId: string, params: Record<string, unknown>): void {\n const sessionId = this.extractSessionId(params)\n if (sessionId) {\n this.updateMeta(paneId, { sessionId })\n }\n\n const rawUpdate = params.update || params.delta || params.event || params\n const updates = Array.isArray(rawUpdate) ? rawUpdate : [rawUpdate]\n\n for (const update of updates) {\n if (!update || typeof update !== 'object') continue\n const record = update as Record<string, unknown>\n const kind = String(record.type || record.kind || '')\n const content = this.extractText(record)\n\n if (kind.includes('agent_message')) {\n const messageId = `assistant-${this.entries.get(paneId)?.nextMessageId ?? 1}`\n this.emitConversation(paneId, {\n type: 'message',\n messageId,\n role: 'assistant',\n text: content,\n append: true,\n })\n if (content) {\n this.emitTerminal(paneId, content)\n }\n this.setStatus(paneId, 'running')\n } else if (kind.includes('tool_call')) {\n const toolCallId = `tool-${this.entries.get(paneId)?.nextToolId ?? 1}`\n this.emitConversation(paneId, {\n type: 'tool',\n toolCallId,\n title: String(record.title || record.name || 'tool'),\n status: kind.includes('update') ? 'in_progress' : 'pending',\n text: content || undefined,\n })\n if (content) {\n this.emitTerminal(paneId, `\\n[tool] ${content}\\n`)\n }\n } else if (kind.includes('turn') || kind.includes('done') || kind.includes('completed')) {\n this.setStatus(paneId, 'idle')\n this.emitConversation(paneId, { type: 'status', status: 'idle' })\n }\n }\n }\n\n private extractText(record: Record<string, unknown>): string {\n const direct = record.text || record.delta || record.content\n if (typeof direct === 'string') return direct\n if (Array.isArray(direct)) {\n return direct\n .map((item) => {\n if (typeof item === 'string') return item\n if (item && typeof item === 'object' && typeof (item as Record<string, unknown>).text === 'string') {\n return String((item as Record<string, unknown>).text)\n }\n return ''\n })\n .join('')\n }\n if (direct && typeof direct === 'object' && typeof (direct as Record<string, unknown>).text === 'string') {\n return String((direct as Record<string, unknown>).text)\n }\n return ''\n }\n\n private request(paneId: string, method: string, params: Record<string, unknown>): Promise<unknown> {\n const entry = this.entries.get(paneId)\n if (!entry) {\n return Promise.reject(new Error(`Missing ACP entry for ${paneId}`))\n }\n\n const id = entry.nextRequestId++\n const payload = JSON.stringify({ jsonrpc: '2.0', id, method, params }) + '\\n'\n entry.proc.stdin.write(payload)\n\n return new Promise((resolve, reject) => {\n entry.pending.set(id, { resolve, reject })\n })\n }\n\n private extractSessionId(result: unknown): string | undefined {\n if (!result || typeof result !== 'object') return undefined\n const record = result as Record<string, unknown>\n if (typeof record.sessionId === 'string') return record.sessionId\n if (typeof record.session_id === 'string') return record.session_id\n if (record.session && typeof record.session === 'object') {\n const nested = record.session as Record<string, unknown>\n if (typeof nested.id === 'string') return nested.id\n if (typeof nested.sessionId === 'string') return nested.sessionId\n }\n return undefined\n }\n\n private emitTerminal(paneId: string, data: string): void {\n const entry = this.entries.get(paneId)\n if (!entry || !data) return\n\n entry.scrollback.push(data)\n entry.scrollbackBytes += data.length\n if (entry.scrollbackBytes > MAX_SCROLLBACK_BYTES) {\n let bytesToRemove = entry.scrollbackBytes - MAX_SCROLLBACK_BYTES\n let removeCount = 0\n while (removeCount < entry.scrollback.length - 1 && bytesToRemove > 0) {\n bytesToRemove -= entry.scrollback[removeCount].length\n entry.scrollbackBytes -= entry.scrollback[removeCount].length\n removeCount++\n }\n if (removeCount > 0) entry.scrollback.splice(0, removeCount)\n }\n\n for (const cb of entry.onDataCallbacks) {\n cb(data)\n }\n }\n\n private setStatus(paneId: string, status: PaneStatus): void {\n const entry = this.entries.get(paneId)\n if (!entry || entry.status === status) return\n entry.status = status\n for (const cb of entry.onStatusCallbacks) {\n cb(status)\n }\n }\n\n private updateMeta(paneId: string, meta: PaneMeta): void {\n const entry = this.entries.get(paneId)\n if (!entry) return\n entry.meta = { ...entry.meta, ...meta }\n for (const cb of entry.onMetaCallbacks) {\n cb(entry.meta)\n }\n }\n\n private emitConversation(paneId: string, event: ConversationEvent): void {\n const entry = this.entries.get(paneId)\n if (!entry) return\n for (const cb of entry.onConversationCallbacks) {\n cb(event)\n }\n }\n}\n","import path from 'node:path'\nimport fs from 'node:fs'\nimport { simpleGit, type SimpleGit } from 'simple-git'\n\ninterface WorktreeEntry {\n path: string\n branch: string\n baseBranch: string\n}\n\nexport class WorktreeManager {\n private projectDir: string\n private git: SimpleGit\n private worktrees = new Map<string, WorktreeEntry>()\n\n constructor(projectDir: string) {\n this.projectDir = projectDir\n this.git = simpleGit(projectDir)\n }\n\n /**\n * Create a git worktree + branch for a pane.\n * Returns the worktree disk path and branch name.\n */\n async create(paneId: string, paneName: string): Promise<{ worktreePath: string; branch: string }> {\n const baseBranch = await this.getCurrentBranch()\n const slug = this.slugify(paneName)\n const branch = `nexus/${paneId}-${slug}`\n const worktreePath = path.join(this.projectDir, '.nexus', 'worktrees', paneId)\n\n // Clean up if leftover from previous session\n if (fs.existsSync(worktreePath)) {\n await this.forceRemoveWorktree(worktreePath)\n }\n\n // Delete branch if it already exists (stale from previous session)\n try {\n await this.git.raw(['branch', '-D', branch])\n } catch {\n // Branch doesn't exist, fine\n }\n\n fs.mkdirSync(path.dirname(worktreePath), { recursive: true })\n await this.git.raw(['worktree', 'add', '-b', branch, worktreePath, baseBranch])\n\n const entry: WorktreeEntry = { path: worktreePath, branch, baseBranch }\n this.worktrees.set(paneId, entry)\n\n return { worktreePath, branch }\n }\n\n /**\n * Restore a worktree from a previous session.\n * If the worktree directory still exists, re-register it.\n * If not, recreate it from the existing branch.\n * Returns false if the branch no longer exists (stale config).\n */\n async restore(paneId: string, branch: string, worktreePath: string): Promise<boolean> {\n // Determine base branch\n const baseBranch = await this.getCurrentBranch()\n\n // Check if branch exists\n try {\n await this.git.raw(['rev-parse', '--verify', branch])\n } catch {\n // Branch doesn't exist — stale config, can't restore\n return false\n }\n\n if (fs.existsSync(worktreePath)) {\n // Worktree directory still exists (non-graceful shutdown) — just re-register\n this.worktrees.set(paneId, { path: worktreePath, branch, baseBranch })\n return true\n }\n\n // Recreate worktree from existing branch\n try {\n // Clean up any stale git worktree metadata\n await this.git.raw(['worktree', 'prune']).catch(() => {})\n fs.mkdirSync(path.dirname(worktreePath), { recursive: true })\n await this.git.raw(['worktree', 'add', worktreePath, branch])\n this.worktrees.set(paneId, { path: worktreePath, branch, baseBranch })\n return true\n } catch (err) {\n console.warn(`[WorktreeManager] Failed to restore worktree for ${paneId}:`, (err as Error).message)\n return false\n }\n }\n\n /**\n * Remove a worktree. Branch is kept for later merge/PR.\n */\n async remove(paneId: string): Promise<void> {\n const entry = this.worktrees.get(paneId)\n if (!entry) return\n\n await this.forceRemoveWorktree(entry.path)\n this.worktrees.delete(paneId)\n }\n\n /**\n * Remove worktree and also delete the branch.\n */\n async removeWithBranch(paneId: string): Promise<void> {\n const entry = this.worktrees.get(paneId)\n if (!entry) return\n\n await this.forceRemoveWorktree(entry.path)\n\n try {\n await this.git.raw(['branch', '-D', entry.branch])\n } catch {\n // Branch may not exist\n }\n\n this.worktrees.delete(paneId)\n }\n\n /**\n * Get diffs for a worktree pane relative to its base branch.\n */\n async getDiffs(paneId: string): Promise<{ file: string; status: string; hunks: string }[]> {\n const entry = this.worktrees.get(paneId)\n if (!entry) return []\n\n const wtGit = simpleGit(entry.path)\n const diffs: { file: string; status: string; hunks: string }[] = []\n\n try {\n // Get status in the worktree (uncommitted changes)\n const status = await wtGit.status()\n\n // Also get committed changes vs base branch\n const committedDiff = await wtGit.diff([`${entry.baseBranch}...HEAD`]).catch(() => '')\n const uncommittedDiff = await wtGit.diff()\n const stagedDiff = await wtGit.diff(['--cached'])\n const combinedDiff = [committedDiff, uncommittedDiff, stagedDiff].filter(Boolean).join('\\n')\n\n // Collect all changed files\n const allFiles = new Set<string>()\n const fileStatuses = new Map<string, string>()\n\n // From committed diff vs base\n if (committedDiff) {\n const parsed = this.parseFileDiffs(committedDiff)\n for (const [file] of parsed) {\n allFiles.add(file)\n fileStatuses.set(file, 'modified')\n }\n }\n\n // From working tree status\n for (const file of status.created) {\n allFiles.add(file)\n fileStatuses.set(file, 'added')\n }\n for (const file of status.modified) {\n allFiles.add(file)\n if (!fileStatuses.has(file)) fileStatuses.set(file, 'modified')\n }\n for (const file of status.deleted) {\n allFiles.add(file)\n fileStatuses.set(file, 'deleted')\n }\n for (const file of status.renamed) {\n allFiles.add(file.to)\n fileStatuses.set(file.to, 'renamed')\n }\n for (const file of status.staged) {\n if (!allFiles.has(file)) {\n allFiles.add(file)\n fileStatuses.set(file, 'modified')\n }\n }\n\n // Parse hunks\n const hunkMap = combinedDiff ? this.parseFileDiffs(combinedDiff) : new Map<string, string>()\n\n for (const file of allFiles) {\n diffs.push({\n file,\n status: fileStatuses.get(file) || 'modified',\n hunks: hunkMap.get(file) || '',\n })\n }\n } catch (err) {\n console.warn(`[WorktreeManager] getDiffs failed for ${paneId}:`, (err as Error).message)\n }\n\n return diffs\n }\n\n /**\n * Merge the worktree branch into the base branch (e.g. main).\n * First commits any uncommitted changes in the worktree, then merges.\n */\n async merge(paneId: string): Promise<{ success: boolean; message: string }> {\n const entry = this.worktrees.get(paneId)\n if (!entry) {\n return { success: false, message: 'Worktree not found for this pane' }\n }\n\n const wtGit = simpleGit(entry.path)\n\n try {\n // Auto-commit any uncommitted changes in the worktree\n const status = await wtGit.status()\n const hasChanges = status.modified.length > 0 || status.created.length > 0\n || status.deleted.length > 0 || status.staged.length > 0\n || status.not_added.length > 0\n\n if (hasChanges) {\n await wtGit.add('-A')\n await wtGit.commit(`nexus: auto-commit before merge (${entry.branch})`)\n }\n\n // Check if there are any commits to merge\n const log = await wtGit.log([`${entry.baseBranch}..${entry.branch}`])\n if (log.total === 0) {\n return { success: false, message: 'No changes to merge' }\n }\n\n // Merge from main repo (not worktree) to avoid \"can't merge into checked-out branch\" issue\n await this.git.merge([entry.branch])\n\n return {\n success: true,\n message: `Merged ${log.total} commit${log.total !== 1 ? 's' : ''} from ${entry.branch} into ${entry.baseBranch}`,\n }\n } catch (err) {\n // If merge failed due to conflict, abort it\n try {\n await this.git.merge(['--abort'])\n } catch {\n // ignore abort failure\n }\n return {\n success: false,\n message: `Merge conflict: ${(err as Error).message}`,\n }\n }\n }\n\n /**\n * Discard all changes: remove worktree and delete the branch.\n */\n async discard(paneId: string): Promise<{ success: boolean; message: string }> {\n const entry = this.worktrees.get(paneId)\n if (!entry) {\n return { success: false, message: 'Worktree not found for this pane' }\n }\n\n const branch = entry.branch\n await this.forceRemoveWorktree(entry.path)\n\n try {\n await this.git.raw(['branch', '-D', branch])\n } catch {\n // Branch may not exist\n }\n\n this.worktrees.delete(paneId)\n return { success: true, message: `Discarded branch ${branch}` }\n }\n\n getWorktreePath(paneId: string): string | undefined {\n return this.worktrees.get(paneId)?.path\n }\n\n getBranch(paneId: string): string | undefined {\n return this.worktrees.get(paneId)?.branch\n }\n\n getBaseBranch(paneId: string): string | undefined {\n return this.worktrees.get(paneId)?.baseBranch\n }\n\n has(paneId: string): boolean {\n return this.worktrees.has(paneId)\n }\n\n /**\n * Clean up all worktrees on shutdown.\n */\n async removeAll(): Promise<void> {\n for (const [paneId] of this.worktrees) {\n await this.remove(paneId)\n }\n }\n\n private async getCurrentBranch(): Promise<string> {\n try {\n const branch = await this.git.revparse(['--abbrev-ref', 'HEAD'])\n return branch.trim() || 'HEAD'\n } catch {\n return 'HEAD'\n }\n }\n\n private slugify(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9\\u4e00-\\u9fff]+/g, '-')\n .replace(/^-|-$/g, '')\n .slice(0, 30)\n }\n\n private async forceRemoveWorktree(wtPath: string): Promise<void> {\n try {\n await this.git.raw(['worktree', 'remove', '--force', wtPath])\n } catch {\n // Worktree may already be gone; clean up directory manually\n try {\n fs.rmSync(wtPath, { recursive: true, force: true })\n await this.git.raw(['worktree', 'prune'])\n } catch {\n // Best effort\n }\n }\n }\n\n private parseFileDiffs(diffText: string): Map<string, string> {\n const result = new Map<string, string>()\n const fileSections = diffText.split(/^diff --git /m).filter(Boolean)\n\n for (const section of fileSections) {\n const headerMatch = section.match(/^a\\/(.+?) b\\/(.+)/)\n if (!headerMatch) continue\n const filename = headerMatch[2]\n result.set(filename, `diff --git ${section}`)\n }\n\n return result\n }\n}\n","import path from 'node:path'\nimport { simpleGit, type SimpleGit } from 'simple-git'\nimport { watch, type FSWatcher } from 'chokidar'\nimport type { FileDiff } from '../types.ts'\n\nexport interface GitDiffResult {\n unstaged: FileDiff[]\n staged: FileDiff[]\n}\n\nexport class GitService {\n private git: SimpleGit\n private projectDir: string\n private gitWatcher: FSWatcher | null = null\n private workWatcher: FSWatcher | null = null\n private debounceTimer: ReturnType<typeof setTimeout> | null = null\n private workDebounceTimer: ReturnType<typeof setTimeout> | null = null\n private listeners = new Set<(result: GitDiffResult) => void>()\n private currentResult: GitDiffResult = { unstaged: [], staged: [] }\n\n constructor(projectDir: string) {\n this.projectDir = projectDir\n this.git = simpleGit(projectDir)\n }\n\n async start(): Promise<void> {\n const isRepo = await this.git.checkIsRepo()\n if (!isRepo) return\n\n await this.refresh()\n\n const scheduleRefresh = () => {\n if (this.debounceTimer) clearTimeout(this.debounceTimer)\n this.debounceTimer = setTimeout(() => {\n this.refresh()\n }, 1000)\n }\n\n const gitDir = path.join(this.projectDir, '.git')\n this.gitWatcher = watch([\n path.join(gitDir, 'index'),\n path.join(gitDir, 'HEAD'),\n path.join(gitDir, 'refs'),\n ], {\n persistent: true,\n ignoreInitial: true,\n })\n this.gitWatcher.on('all', scheduleRefresh)\n\n // Working tree watcher — uses a longer debounce to avoid flooding\n // git diff on every keystroke when agents are writing files\n const scheduleWorkRefresh = () => {\n if (this.workDebounceTimer) clearTimeout(this.workDebounceTimer)\n this.workDebounceTimer = setTimeout(() => {\n this.refresh()\n }, 3000)\n }\n\n this.workWatcher = watch(this.projectDir, {\n ignored: (filePath: string) => {\n const basename = path.basename(filePath)\n return basename === '.git' || basename === 'node_modules' || basename === '.nexus' || basename === 'dist'\n },\n persistent: true,\n ignoreInitial: true,\n depth: 5,\n })\n this.workWatcher.on('all', scheduleWorkRefresh)\n }\n\n async refresh(): Promise<void> {\n try {\n const result = await Promise.race([\n this.getDiffs(),\n new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error('git diff timeout')), 15000)\n ),\n ])\n this.currentResult = result\n this.notifyListeners()\n } catch (err) {\n if ((err as Error).message === 'git diff timeout') {\n console.warn('[GitService] git diff timed out (15s), using cached result')\n }\n // Other git failures also silently use cached result\n }\n }\n\n getCurrentDiffs(): GitDiffResult {\n return this.currentResult\n }\n\n onDiffChange(callback: (result: GitDiffResult) => void): () => void {\n this.listeners.add(callback)\n return () => this.listeners.delete(callback)\n }\n\n // ─── Stage / Unstage ─────────────────────────────────────\n\n async acceptFile(file: string): Promise<void> {\n await this.git.add(file)\n await this.refresh()\n }\n\n async acceptAll(): Promise<void> {\n await this.git.add('-A')\n await this.refresh()\n }\n\n async unstageFile(file: string): Promise<void> {\n await this.git.reset(['HEAD', '--', file])\n await this.refresh()\n }\n\n async unstageAll(): Promise<void> {\n await this.git.reset(['HEAD'])\n await this.refresh()\n }\n\n // ─── Discard ──────────────────────────────────────────────\n\n async discardFile(file: string): Promise<void> {\n const status = await this.git.status()\n const isUntracked = status.not_added.includes(file) || status.created.includes(file)\n\n if (isUntracked) {\n const fullPath = path.join(this.projectDir, file)\n const fs = await import('node:fs')\n if (fs.existsSync(fullPath)) {\n fs.unlinkSync(fullPath)\n }\n } else {\n await this.git.checkout(['--', file])\n try {\n await this.git.reset(['HEAD', '--', file])\n } catch {\n // May not be staged, ignore\n }\n }\n await this.refresh()\n }\n\n async discardAll(): Promise<void> {\n await this.git.checkout(['--', '.'])\n await this.git.clean('f', ['-d'])\n await this.refresh()\n }\n\n // ─── Commit / Push ────────────────────────────────────────\n\n async commit(message: string): Promise<string> {\n const result = await this.git.commit(message)\n await this.refresh()\n const summary = result.summary\n return `${summary.changes} file${summary.changes !== 1 ? 's' : ''}, +${summary.insertions} -${summary.deletions}`\n }\n\n async push(): Promise<string> {\n await this.git.push()\n await this.refresh()\n return 'Pushed successfully'\n }\n\n async getBranchInfo(): Promise<{ branch: string; remote?: string; ahead: number; behind: number }> {\n const status = await this.git.status()\n return {\n branch: status.current || 'HEAD',\n remote: status.tracking || undefined,\n ahead: status.ahead,\n behind: status.behind,\n }\n }\n\n // ─── Cleanup ──────────────────────────────────────────────\n\n close(): void {\n if (this.debounceTimer) clearTimeout(this.debounceTimer)\n if (this.workDebounceTimer) clearTimeout(this.workDebounceTimer)\n this.gitWatcher?.close()\n this.gitWatcher = null\n this.workWatcher?.close()\n this.workWatcher = null\n }\n\n // ─── Internal ─────────────────────────────────────────────\n\n private async getDiffs(): Promise<GitDiffResult> {\n const status = await this.git.status()\n const unstaged: FileDiff[] = []\n const staged: FileDiff[] = []\n\n // Get unified diffs\n const [unstagedDiffText, stagedDiffText] = await Promise.all([\n this.git.diff(),\n this.git.diff(['--cached']),\n ])\n\n const unstagedHunks = this.parseFileDiffs(unstagedDiffText)\n const stagedHunks = this.parseFileDiffs(stagedDiffText)\n\n const stagedFiles = new Set<string>(status.staged)\n\n // ─── Unstaged changes ───────────────────────────────────\n for (const file of status.not_added) {\n unstaged.push({ file, status: 'added', hunks: '' })\n }\n for (const file of status.created) {\n if (!stagedFiles.has(file)) {\n unstaged.push({ file, status: 'added', hunks: '' })\n }\n }\n for (const file of status.deleted) {\n if (!stagedFiles.has(file)) {\n unstaged.push({ file, status: 'deleted', hunks: '' })\n }\n }\n for (const file of status.modified) {\n unstaged.push({ file, status: 'modified', hunks: unstagedHunks.get(file) || '' })\n }\n for (const file of status.renamed) {\n if (!stagedFiles.has(file.to)) {\n unstaged.push({ file: file.to, status: 'renamed', hunks: '' })\n }\n }\n\n // Attach hunks to unstaged entries that don't have them yet\n for (const diff of unstaged) {\n if (!diff.hunks && unstagedHunks.has(diff.file)) {\n diff.hunks = unstagedHunks.get(diff.file)!\n }\n }\n\n // For untracked files, try to show content\n for (const diff of unstaged) {\n if (diff.status === 'added' && !diff.hunks) {\n try {\n const content = await this.git.show([`:${diff.file}`]).catch(() => null)\n if (content) {\n diff.hunks = `--- /dev/null\\n+++ b/${diff.file}\\n@@ -0,0 +1 @@\\n+${content}`\n }\n } catch {\n // Skip\n }\n }\n }\n\n // ─── Staged changes ─────────────────────────────────────\n // Use status.files for accurate staged file detection\n for (const fileResult of status.files) {\n const indexStatus = fileResult.index\n if (!indexStatus || indexStatus === '?' || indexStatus === ' ') continue\n\n const file = fileResult.path\n let diffStatus: FileDiff['status'] = 'modified'\n if (indexStatus === 'A') diffStatus = 'added'\n else if (indexStatus === 'D') diffStatus = 'deleted'\n else if (indexStatus === 'R') diffStatus = 'renamed'\n\n staged.push({\n file,\n status: diffStatus,\n hunks: stagedHunks.get(file) || '',\n })\n }\n\n return { unstaged, staged }\n }\n\n private parseFileDiffs(diffText: string): Map<string, string> {\n const result = new Map<string, string>()\n if (!diffText) return result\n const fileSections = diffText.split(/^diff --git /m).filter(Boolean)\n\n for (const section of fileSections) {\n const headerMatch = section.match(/^a\\/(.+?) b\\/(.+)/)\n if (!headerMatch) continue\n const filename = headerMatch[2]\n result.set(filename, `diff --git ${section}`)\n }\n\n return result\n }\n\n private notifyListeners(): void {\n for (const listener of this.listeners) {\n listener(this.currentResult)\n }\n }\n}\n","import type {\n ConversationEvent,\n PaneConfig,\n PaneState,\n PaneCreateConfig,\n WorkspaceState,\n RestoreMode,\n PaneStatus,\n PaneMeta,\n FileNode,\n FileDiff,\n FileActivity,\n SessionInfo,\n} from '../types.ts'\nimport type { GitDiffResult } from '../git/GitService.ts'\nimport { PtyManager } from '../pty/PtyManager.ts'\nimport { AcpRuntime } from '../runtime/AcpRuntime.ts'\nimport { ConfigManager } from './ConfigManager.ts'\nimport { WorktreeManager } from '../git/WorktreeManager.ts'\nimport { GitService } from '../git/GitService.ts'\n\nlet paneCounter = 0\n\nfunction nextPaneId(): string {\n return `pane-${++paneCounter}`\n}\n\nexport interface EventHandlers {\n onPaneAdded?: (pane: PaneState) => void\n onPaneRemoved?: (paneId: string) => void\n onConversationEvent?: (paneId: string, event: ConversationEvent) => void\n onPaneStatus?: (paneId: string, status: PaneStatus) => void\n onPaneMeta?: (paneId: string, meta: PaneMeta) => void\n onTerminalData?: (paneId: string, data: string) => void\n onPaneActivity?: (paneId: string, activity: FileActivity) => void\n onFileActivity?: (activity: FileActivity) => void\n onFileTree?: (tree: FileNode[]) => void\n onGitDiff?: (result: GitDiffResult) => void\n onPaneDiff?: (paneId: string, diffs: FileDiff[]) => void\n}\n\ntype ListenerKey = keyof EventHandlers\n\nexport class WorkspaceManager {\n private panes = new Map<string, PaneState>()\n private ptyManager: PtyManager\n private acpRuntime: AcpRuntime\n private configManager: ConfigManager\n private worktreeManager: WorktreeManager\n private perPaneGitServices = new Map<string, GitService>()\n private wsName = ''\n private wsDescription = ''\n\n // Serialize config writes to prevent race conditions when closing multiple panes\n private configWriteLock: Promise<void> = Promise.resolve()\n\n // Multi-client event listener sets\n private listeners: { [K in ListenerKey]: Set<NonNullable<EventHandlers[K]>> } = {\n onPaneAdded: new Set(),\n onPaneRemoved: new Set(),\n onConversationEvent: new Set(),\n onPaneStatus: new Set(),\n onPaneMeta: new Set(),\n onTerminalData: new Set(),\n onPaneActivity: new Set(),\n onFileActivity: new Set(),\n onFileTree: new Set(),\n onGitDiff: new Set(),\n onPaneDiff: new Set(),\n }\n\n constructor(configManager: ConfigManager) {\n this.configManager = configManager\n this.ptyManager = new PtyManager(configManager)\n this.acpRuntime = new AcpRuntime(configManager)\n this.worktreeManager = new WorktreeManager(configManager.getProjectDir())\n }\n\n async init(): Promise<void> {\n const wsConfig = this.configManager.initWorkspace()\n this.wsName = wsConfig.name\n this.wsDescription = wsConfig.description || ''\n if (!Array.isArray(wsConfig.panes)) wsConfig.panes = []\n\n // Sync paneCounter to avoid id collisions with restored panes\n for (const p of wsConfig.panes) {\n const match = p.id.match(/^pane-(\\d+)$/)\n if (match) {\n const num = parseInt(match[1], 10)\n if (num >= paneCounter) paneCounter = num\n }\n }\n\n // Restore panes from config (skip failures — stale panes from previous sessions)\n // Auto-resume: if a pane has a saved sessionId, always use --resume regardless of original restore mode\n let failCount = 0\n for (const paneConfig of wsConfig.panes) {\n if (paneConfig.sessionId && paneConfig.agent !== '__shell__') {\n paneConfig.restore = 'resume'\n }\n\n // Restore worktree if needed\n if (paneConfig.isolation === 'worktree' && paneConfig.branch && paneConfig.worktreePath) {\n try {\n const restored = await this.worktreeManager.restore(paneConfig.id, paneConfig.branch, paneConfig.worktreePath)\n if (!restored) {\n console.warn(`Skipping worktree pane ${paneConfig.id} (${paneConfig.name}): branch no longer exists`)\n failCount++\n continue\n }\n } catch (err) {\n console.warn(`Skipping worktree pane ${paneConfig.id} (${paneConfig.name}): restore failed:`, (err as Error).message)\n failCount++\n continue\n }\n }\n\n try {\n this.spawnPane(paneConfig)\n\n // Start per-pane git service for worktree panes\n if (paneConfig.isolation === 'worktree' && paneConfig.worktreePath) {\n await this.startPaneGitService(paneConfig.id, paneConfig.worktreePath)\n }\n } catch (err) {\n console.warn(`Skipping stale pane ${paneConfig.id} (${paneConfig.name}):`, (err as Error).message)\n failCount++\n }\n }\n // Clean stale panes from config if any failed\n if (failCount > 0) {\n wsConfig.panes = wsConfig.panes.filter((p) => this.panes.has(p.id))\n this.configManager.saveWorkspaceConfig(wsConfig)\n }\n }\n\n getState(): WorkspaceState {\n return {\n name: this.wsName,\n description: this.wsDescription,\n projectDir: this.configManager.getProjectDir(),\n panes: Array.from(this.panes.values()),\n }\n }\n\n getPanes(): PaneState[] {\n return Array.from(this.panes.values())\n }\n\n async createPane(createConfig: PaneCreateConfig): Promise<PaneState> {\n const isShell = createConfig.agent === '__shell__'\n const id = isShell ? '__shell__' : nextPaneId()\n const isolation = createConfig.isolation || 'shared'\n\n // Extract cols/rows (transient, not persisted in PaneConfig)\n const { cols, rows, ...rest } = createConfig\n\n const config: PaneConfig = {\n id,\n ...rest,\n yolo: rest.yolo || false,\n isolation,\n sessionId: rest.sessionId,\n }\n\n // Create worktree if requested\n if (isolation === 'worktree' && !isShell) {\n try {\n const { worktreePath, branch } = await this.worktreeManager.create(id, createConfig.name)\n config.worktreePath = worktreePath\n config.branch = branch\n } catch (err) {\n console.error(`Failed to create worktree for pane ${id}:`, err)\n throw err\n }\n }\n\n try {\n const pane = this.spawnPane(config, cols, rows)\n\n // Start per-pane git service for worktree panes\n if (isolation === 'worktree' && config.worktreePath) {\n await this.startPaneGitService(id, config.worktreePath)\n }\n\n // Don't persist the bottom shell pane to workspace config\n if (!isShell) {\n this.persistPaneConfig(config)\n }\n return pane\n } catch (err) {\n // Clean up worktree on spawn failure\n if (isolation === 'worktree') {\n await this.worktreeManager.removeWithBranch(id)\n }\n console.error(`Failed to create pane ${id}:`, err)\n throw err\n }\n }\n\n async closePane(paneId: string): Promise<void> {\n const pane = this.panes.get(paneId)\n if (pane?.runtime === 'acp') {\n this.acpRuntime.kill(paneId)\n } else {\n this.ptyManager.kill(paneId)\n }\n\n // Clean up worktree resources\n if (pane?.isolation === 'worktree') {\n this.stopPaneGitService(paneId)\n await this.worktreeManager.remove(paneId)\n }\n\n this.panes.delete(paneId)\n this.emit('onPaneRemoved', paneId)\n this.removePaneFromConfig(paneId)\n }\n\n restartPane(paneId: string, mode: RestoreMode, sessionId?: string): void {\n const existingState = this.panes.get(paneId)\n if (!existingState) return\n\n if (existingState.runtime === 'acp') {\n this.acpRuntime.kill(paneId)\n } else {\n this.ptyManager.kill(paneId)\n }\n\n // For resume mode, use the provided sessionId or fall back to the last known one\n const resolvedSessionId = mode === 'resume'\n ? (sessionId || existingState.sessionId || existingState.meta.sessionId)\n : undefined\n\n const config: PaneConfig = {\n id: paneId,\n name: existingState.name,\n agent: existingState.agent,\n workdir: existingState.workdir,\n task: existingState.task,\n restore: mode,\n isolation: existingState.isolation,\n yolo: existingState.yolo || false,\n worktreePath: existingState.worktreePath,\n branch: existingState.branch,\n sessionId: resolvedSessionId,\n }\n\n this.spawnPane(config)\n this.updatePaneConfigSessionId(paneId, resolvedSessionId)\n }\n\n async mergeWorktree(paneId: string): Promise<{ success: boolean; message: string }> {\n const pane = this.panes.get(paneId)\n if (!pane || pane.isolation !== 'worktree') {\n return { success: false, message: 'Pane is not a worktree pane' }\n }\n return this.worktreeManager.merge(paneId)\n }\n\n async discardWorktree(paneId: string): Promise<{ success: boolean; message: string }> {\n const pane = this.panes.get(paneId)\n if (!pane || pane.isolation !== 'worktree') {\n return { success: false, message: 'Pane is not a worktree pane' }\n }\n\n // Stop per-pane git service\n this.stopPaneGitService(paneId)\n\n // Discard worktree and branch\n const result = await this.worktreeManager.discard(paneId)\n\n if (result.success) {\n // Clear worktree info from pane state (pane stays open but no longer isolated)\n pane.isolation = 'shared'\n pane.worktreePath = undefined\n pane.branch = undefined\n // Emit empty diffs to clear the UI\n this.emit('onPaneDiff', paneId, [])\n }\n\n return result\n }\n\n writeToPane(paneId: string, data: string): void {\n const pane = this.panes.get(paneId)\n if (!pane) return\n if (pane.runtime === 'acp') {\n this.acpRuntime.write(paneId, data)\n return\n }\n this.ptyManager.write(paneId, data)\n }\n\n sendConversationToPane(paneId: string, text: string): Promise<void> {\n const pane = this.panes.get(paneId)\n if (!pane) return Promise.resolve()\n if (pane.runtime === 'acp') {\n return this.acpRuntime.sendPrompt(paneId, text)\n }\n this.ptyManager.write(paneId, text + '\\r')\n return Promise.resolve()\n }\n\n resizePane(paneId: string, cols: number, rows: number): void {\n const pane = this.panes.get(paneId)\n if (!pane) return\n if (pane.runtime === 'acp') {\n this.acpRuntime.resize(paneId, cols, rows)\n return\n }\n this.ptyManager.resize(paneId, cols, rows)\n }\n\n getScrollback(paneId: string): string {\n const pane = this.panes.get(paneId)\n if (!pane) return ''\n return pane.runtime === 'acp'\n ? this.acpRuntime.getScrollback(paneId)\n : this.ptyManager.getScrollback(paneId)\n }\n\n // ─── Event Registration (multi-client safe) ────────────────\n\n /**\n * Register event handlers for a client. Returns a cleanup function\n * that removes only this client's handlers.\n */\n onEvents(handlers: EventHandlers): () => void {\n const cleanups: Array<() => void> = []\n\n for (const key of Object.keys(handlers) as ListenerKey[]) {\n const handler = handlers[key]\n if (handler) {\n const set = this.listeners[key] as Set<typeof handler>\n set.add(handler)\n cleanups.push(() => set.delete(handler))\n }\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup()\n }\n }\n }\n\n // Broadcast events (called by services)\n emitFileTree(tree: FileNode[]): void {\n this.emit('onFileTree', tree)\n }\n\n emitGitDiff(result: GitDiffResult): void {\n this.emit('onGitDiff', result)\n }\n\n emitFileActivity(activity: FileActivity): void {\n this.emit('onFileActivity', activity)\n }\n\n async refreshPaneDiff(paneId: string): Promise<void> {\n const gitService = this.perPaneGitServices.get(paneId)\n if (gitService) {\n await gitService.refresh()\n }\n }\n\n /**\n * Get current per-pane diffs (for initial sync on WS connect).\n */\n getPaneDiffs(): Map<string, FileDiff[]> {\n const result = new Map<string, FileDiff[]>()\n for (const [paneId, gitService] of this.perPaneGitServices) {\n result.set(paneId, gitService.getCurrentDiffs().unstaged)\n }\n return result\n }\n\n // ─── Internal ─────────────────────────────────────────────\n\n private emit<K extends ListenerKey>(key: K, ...args: Parameters<NonNullable<EventHandlers[K]>>): void {\n const set = this.listeners[key] as Set<(...a: typeof args) => void>\n for (const listener of set) {\n listener(...args)\n }\n }\n\n private spawnPane(config: PaneConfig, cols?: number, rows?: number): PaneState {\n const runtime = this.resolveRuntime(config.agent)\n const pid = runtime === 'acp'\n ? this.acpRuntime.spawn(config.id, config)\n : this.ptyManager.spawn(config.id, config, cols || 80, rows || 24)\n\n const pane: PaneState = {\n id: config.id,\n name: config.name,\n agent: config.agent,\n workdir: config.workdir,\n task: config.task,\n restore: config.restore,\n isolation: config.isolation || 'shared',\n yolo: config.yolo || false,\n branch: config.branch,\n worktreePath: config.worktreePath,\n sessionId: config.sessionId,\n runtime,\n status: 'running',\n pid,\n meta: {},\n startedAt: new Date().toISOString(),\n }\n\n this.panes.set(config.id, pane)\n this.emit('onPaneAdded', pane)\n\n const runtimeAdapter = runtime === 'acp' ? this.acpRuntime : this.ptyManager\n\n runtimeAdapter.onData(config.id, (data) => {\n this.emit('onTerminalData', config.id, data)\n })\n\n runtimeAdapter.onStatus(config.id, (status) => {\n const p = this.panes.get(config.id)\n if (p) {\n p.status = status\n this.emit('onPaneStatus', config.id, status)\n }\n })\n\n runtimeAdapter.onMeta(config.id, (meta) => {\n const p = this.panes.get(config.id)\n if (p) {\n p.meta = meta\n // Persist sessionId from statusline to PaneState and config.yaml for auto-resume\n if (meta.sessionId && meta.sessionId !== p.sessionId) {\n p.sessionId = meta.sessionId\n this.updatePaneConfigSessionId(config.id, meta.sessionId)\n }\n this.emit('onPaneMeta', config.id, meta)\n }\n })\n\n runtimeAdapter.onActivity(config.id, (activity) => {\n this.emit('onPaneActivity', config.id, activity)\n })\n\n if (runtime === 'acp') {\n this.acpRuntime.onConversation(config.id, (event) => {\n this.emit('onConversationEvent', config.id, event)\n })\n }\n\n return pane\n }\n\n private resolveRuntime(agentType: PaneState['agent']): PaneState['runtime'] {\n if (agentType === '__shell__') return 'pty'\n const def = this.configManager.getAgentDefinition(agentType)\n return def?.transport || 'pty'\n }\n\n private async startPaneGitService(paneId: string, worktreePath: string): Promise<void> {\n const gitService = new GitService(worktreePath)\n gitService.onDiffChange((result) => {\n // Tag each unstaged diff with the paneId (worktree panes show unstaged only)\n const tagged = result.unstaged.map((d) => ({ ...d, paneId }))\n this.emit('onPaneDiff', paneId, tagged)\n })\n await gitService.start()\n this.perPaneGitServices.set(paneId, gitService)\n }\n\n private stopPaneGitService(paneId: string): void {\n const gitService = this.perPaneGitServices.get(paneId)\n if (gitService) {\n gitService.close()\n this.perPaneGitServices.delete(paneId)\n }\n }\n\n private persistPaneConfig(config: PaneConfig): void {\n this.serializedConfigWrite(() => {\n const wsConfig = this.configManager.loadWorkspaceConfig()\n if (wsConfig) {\n wsConfig.panes.push(config)\n this.configManager.saveWorkspaceConfig(wsConfig)\n }\n })\n }\n\n private updatePaneConfigSessionId(paneId: string, sessionId?: string): void {\n this.serializedConfigWrite(() => {\n const wsConfig = this.configManager.loadWorkspaceConfig()\n if (wsConfig) {\n const paneConfig = wsConfig.panes.find((p) => p.id === paneId)\n if (paneConfig) {\n paneConfig.sessionId = sessionId\n this.configManager.saveWorkspaceConfig(wsConfig)\n }\n }\n })\n }\n\n getSessionList(paneId?: string): SessionInfo[] {\n const sessions: SessionInfo[] = []\n for (const pane of this.panes.values()) {\n if (pane.agent === '__shell__') continue\n if (paneId && pane.id !== paneId) continue\n if (pane.meta.sessionId || pane.sessionId) {\n sessions.push({\n sessionId: (pane.meta.sessionId || pane.sessionId)!,\n paneId: pane.id,\n paneName: pane.name,\n agent: pane.agent,\n timestamp: pane.startedAt || new Date().toISOString(),\n costUsd: pane.meta.costUsd,\n contextUsedPct: pane.meta.contextUsedPct,\n model: pane.meta.model,\n })\n }\n }\n // Also include sessions from config that aren't currently running\n const wsConfig = this.configManager.loadWorkspaceConfig()\n if (wsConfig) {\n for (const pc of wsConfig.panes) {\n if (pc.sessionId && !sessions.find((s) => s.sessionId === pc.sessionId)) {\n if (paneId && pc.id !== paneId) continue\n sessions.push({\n sessionId: pc.sessionId,\n paneId: pc.id,\n paneName: pc.name,\n agent: pc.agent,\n timestamp: '',\n })\n }\n }\n }\n return sessions\n }\n\n private removePaneFromConfig(paneId: string): void {\n this.serializedConfigWrite(() => {\n const wsConfig = this.configManager.loadWorkspaceConfig()\n if (wsConfig) {\n wsConfig.panes = wsConfig.panes.filter((p) => p.id !== paneId)\n this.configManager.saveWorkspaceConfig(wsConfig)\n }\n })\n }\n\n /**\n * Serialize config file writes to prevent race conditions\n * when multiple panes are created/closed simultaneously.\n */\n private serializedConfigWrite(fn: () => void): void {\n this.configWriteLock = this.configWriteLock.then(() => {\n try {\n fn()\n } catch (err) {\n console.error('[WorkspaceManager] Config write failed:', err)\n }\n })\n }\n\n async shutdown(): Promise<void> {\n this.ptyManager.killAll()\n this.acpRuntime.killAll()\n // Close per-pane git services (worktree directories are preserved for restore)\n for (const [paneId] of this.perPaneGitServices) {\n this.stopPaneGitService(paneId)\n }\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport yaml from 'js-yaml'\nimport type { PaneState } from '../types.ts'\n\nexport class AgentsYamlWriter {\n private projectDir: string\n private debounceTimer: ReturnType<typeof setTimeout> | null = null\n\n constructor(projectDir: string) {\n this.projectDir = projectDir\n }\n\n /**\n * Write agents.yaml with current pane states. Debounced to avoid excessive writes.\n */\n update(panes: PaneState[]): void {\n if (this.debounceTimer) clearTimeout(this.debounceTimer)\n this.debounceTimer = setTimeout(() => {\n this.writeFile(panes)\n }, 500)\n }\n\n /**\n * Write immediately without debouncing.\n */\n flush(panes: PaneState[]): void {\n if (this.debounceTimer) clearTimeout(this.debounceTimer)\n this.writeFile(panes)\n }\n\n private writeFile(panes: PaneState[]): void {\n const nexusDir = path.join(this.projectDir, '.nexus')\n fs.mkdirSync(nexusDir, { recursive: true })\n\n // Filter out the bottom shell pane\n const visible = panes.filter((p) => p.agent !== '__shell__')\n\n const data = {\n updated_at: new Date().toISOString(),\n panes: visible.map((p) => {\n const basePath = (p.isolation === 'worktree' && p.worktreePath)\n ? p.worktreePath\n : this.projectDir\n return {\n id: p.id,\n name: p.name,\n agent: p.agent,\n runtime: p.runtime,\n pid: p.pid,\n status: p.status,\n isolation: p.isolation || 'shared',\n branch: p.branch || undefined,\n workdir: p.workdir\n ? path.resolve(basePath, p.workdir)\n : basePath,\n task: p.task || undefined,\n model: p.meta.model || undefined,\n context_used_pct: p.meta.contextUsedPct ?? undefined,\n cost_usd: p.meta.costUsd ?? undefined,\n session_id: p.meta.sessionId || undefined,\n started_at: p.startedAt || undefined,\n }\n }),\n }\n\n const filePath = path.join(nexusDir, 'agents.yaml')\n fs.writeFileSync(filePath, yaml.dump(data, { lineWidth: -1 }))\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { watch, type FSWatcher } from 'chokidar'\nimport type { FileNode, FileActivity } from '../types.ts'\n\nconst IGNORED_DIRS = new Set([\n 'node_modules',\n '.git',\n '.nexus',\n 'dist',\n '.cache',\n '.turbo',\n '__pycache__',\n])\n\nconst IGNORED_FILES = new Set([\n '.DS_Store',\n 'Thumbs.db',\n])\n\nexport class FsWatcher {\n private projectDir: string\n private watcher: FSWatcher | null = null\n private tree: FileNode[] = []\n private debounceTimer: ReturnType<typeof setTimeout> | null = null\n private listeners = new Set<(tree: FileNode[]) => void>()\n private fileChangeListeners = new Set<(activity: FileActivity) => void>()\n private recentChanges = new Map<string, number>() // path → timestamp for dedup\n\n constructor(projectDir: string) {\n this.projectDir = projectDir\n }\n\n start(): void {\n // Build initial tree synchronously\n this.tree = this.buildTree(this.projectDir, 0)\n this.notifyListeners()\n\n // Watch top-level directory only (depth 0) for structural changes\n // Use function-based ignored to reliably filter out heavy directories\n this.watcher = watch(this.projectDir, {\n ignored: (filePath: string) => {\n const basename = path.basename(filePath)\n return IGNORED_DIRS.has(basename) || IGNORED_FILES.has(basename)\n },\n persistent: true,\n ignoreInitial: true,\n depth: 5,\n })\n\n const scheduleRebuild = () => {\n if (this.debounceTimer) clearTimeout(this.debounceTimer)\n this.debounceTimer = setTimeout(() => {\n const newTree = this.buildTree(this.projectDir, 0)\n // Skip broadcast if tree hasn't structurally changed\n if (this.treeFingerprint(newTree) === this.treeFingerprint(this.tree)) return\n this.tree = newTree\n this.notifyListeners()\n }, 300)\n }\n\n // Emit individual file change events for activity tracking\n const emitFileChange = (eventType: 'add' | 'change' | 'unlink', filePath: string) => {\n // Only emit for files, not directories\n const relativePath = path.relative(this.projectDir, filePath)\n if (!relativePath || relativePath.startsWith('..')) return\n // Skip files without extension (likely directories or special files)\n if (!/\\.\\w{1,10}$/.test(path.basename(filePath))) return\n // Dedup: skip if same file changed within 1s\n const now = Date.now()\n const lastChange = this.recentChanges.get(relativePath)\n if (lastChange && now - lastChange < 1000) return\n this.recentChanges.set(relativePath, now)\n // Clean old entries periodically\n if (this.recentChanges.size > 200) {\n for (const [key, ts] of this.recentChanges) {\n if (now - ts > 10000) this.recentChanges.delete(key)\n }\n }\n\n const actionMap = { add: 'create' as const, change: 'edit' as const, unlink: 'delete' as const }\n const activity: FileActivity = {\n file: relativePath,\n action: actionMap[eventType],\n timestamp: now,\n }\n for (const listener of this.fileChangeListeners) {\n listener(activity)\n }\n }\n\n this.watcher.on('add', (p) => { emitFileChange('add', p); scheduleRebuild() })\n this.watcher.on('change', (p) => { emitFileChange('change', p) })\n this.watcher.on('unlink', (p) => { emitFileChange('unlink', p); scheduleRebuild() })\n this.watcher.on('addDir', scheduleRebuild)\n this.watcher.on('unlinkDir', scheduleRebuild)\n this.watcher.on('error', () => {\n // Silently handle watcher errors (e.g., ENOSPC)\n // Tree is still built synchronously, just won't auto-update\n })\n }\n\n getTree(): FileNode[] {\n return this.tree\n }\n\n onTreeChange(callback: (tree: FileNode[]) => void): () => void {\n this.listeners.add(callback)\n return () => this.listeners.delete(callback)\n }\n\n onFileChange(callback: (activity: FileActivity) => void): () => void {\n this.fileChangeListeners.add(callback)\n return () => this.fileChangeListeners.delete(callback)\n }\n\n close(): void {\n if (this.debounceTimer) clearTimeout(this.debounceTimer)\n this.watcher?.close()\n this.watcher = null\n }\n\n private notifyListeners(): void {\n for (const listener of this.listeners) {\n listener(this.tree)\n }\n }\n\n private treeFingerprint(tree: FileNode[]): string {\n // Fast structural fingerprint: concatenate paths and types\n const parts: string[] = []\n const walk = (nodes: FileNode[]) => {\n for (const n of nodes) {\n parts.push(n.path)\n if (n.children) walk(n.children)\n }\n }\n walk(tree)\n return parts.join('\\n')\n }\n\n private buildTree(dirPath: string, depth: number): FileNode[] {\n if (depth > 5) return [] // Match chokidar watch depth\n\n try {\n const entries = fs.readdirSync(dirPath, { withFileTypes: true })\n const nodes: FileNode[] = []\n\n for (const entry of entries) {\n if (IGNORED_DIRS.has(entry.name) || IGNORED_FILES.has(entry.name)) continue\n\n const fullPath = path.join(dirPath, entry.name)\n const relativePath = path.relative(this.projectDir, fullPath)\n\n if (entry.isDirectory()) {\n nodes.push({\n name: entry.name,\n path: relativePath,\n type: 'directory',\n children: this.buildTree(fullPath, depth + 1),\n })\n } else if (entry.isFile()) {\n nodes.push({\n name: entry.name,\n path: relativePath,\n type: 'file',\n })\n }\n }\n\n // Sort: directories first, then files, alphabetical within each group\n nodes.sort((a, b) => {\n if (a.type !== b.type) return a.type === 'directory' ? -1 : 1\n return a.name.localeCompare(b.name)\n })\n\n return nodes\n } catch {\n return []\n }\n }\n}\n","import type { WebSocket } from '@fastify/websocket'\nimport type { ClientEvent, ServerEvent } from '../types.ts'\nimport type { WorkspaceManager } from '../workspace/WorkspaceManager.ts'\nimport type { GitService } from '../git/GitService.ts'\n\nexport function setupWsHandlers(\n socket: WebSocket,\n workspaceManager: WorkspaceManager,\n gitService?: GitService,\n): void {\n const send = (event: ServerEvent) => {\n if (socket.readyState === socket.OPEN) {\n socket.send(JSON.stringify(event))\n }\n }\n\n // Send initial workspace state\n const state = workspaceManager.getState()\n send({\n type: 'workspace.state',\n state,\n })\n\n // Replay terminal scrollback for each pane asynchronously.\n // Uses setImmediate to yield between panes and between chunks,\n // preventing event loop starvation with 10+ panes × 512KB scrollback.\n const SCROLLBACK_CHUNK_SIZE = 512 * 1024 // 512KB per message — matches server-side scrollback limit\n const replayScrollback = async () => {\n for (const pane of state.panes) {\n const scrollback = workspaceManager.getScrollback(pane.id)\n if (!scrollback) continue\n if (scrollback.length <= SCROLLBACK_CHUNK_SIZE) {\n send({ type: 'terminal.output', paneId: pane.id, data: scrollback })\n } else {\n for (let i = 0; i < scrollback.length; i += SCROLLBACK_CHUNK_SIZE) {\n if (socket.readyState !== socket.OPEN) return // bail if disconnected\n send({ type: 'terminal.output', paneId: pane.id, data: scrollback.slice(i, i + SCROLLBACK_CHUNK_SIZE) })\n // Yield to event loop between chunks\n await new Promise<void>((resolve) => setImmediate(resolve))\n }\n }\n }\n }\n replayScrollback().catch(() => { /* socket may have closed */ })\n\n // Send initial per-pane diffs for worktree panes\n const paneDiffs = workspaceManager.getPaneDiffs()\n for (const [paneId, diffs] of paneDiffs) {\n if (diffs.length > 0) {\n send({ type: 'pane.diff', paneId, diffs })\n }\n }\n\n // Send initial branch info\n gitService?.getBranchInfo()\n .then((info) => send({ type: 'git.branchInfo', ...info }))\n .catch(() => {})\n\n // Register event handlers for this client (multi-client safe)\n const cleanup = workspaceManager.onEvents({\n onTerminalData: (paneId, data) => {\n send({ type: 'terminal.output', paneId, data })\n },\n onConversationEvent: (paneId, event) => {\n send({ type: 'conversation.event', paneId, event })\n },\n onPaneStatus: (paneId, status) => {\n send({ type: 'pane.status', paneId, status })\n },\n onPaneMeta: (paneId, meta) => {\n send({ type: 'pane.meta', paneId, meta })\n },\n onPaneAdded: (pane) => {\n send({ type: 'pane.added', pane })\n },\n onPaneRemoved: (paneId) => {\n send({ type: 'pane.removed', paneId })\n },\n onPaneActivity: (paneId, activity) => {\n send({ type: 'pane.activity', paneId, activity })\n },\n onFileActivity: (activity) => {\n send({ type: 'file.activity', activity })\n },\n onPaneDiff: (paneId, diffs) => {\n send({ type: 'pane.diff', paneId, diffs })\n },\n onFileTree: (tree) => {\n send({ type: 'fs.tree', tree })\n },\n onGitDiff: (result) => {\n send({ type: 'git.diff', unstaged: result.unstaged, staged: result.staged })\n },\n })\n\n // Handle incoming messages from client\n socket.on('message', (raw: { toString(): string }) => {\n let event: ClientEvent\n try {\n event = JSON.parse(raw.toString()) as ClientEvent\n } catch {\n return\n }\n\n switch (event.type) {\n case 'terminal.input':\n try {\n workspaceManager.writeToPane(event.paneId, event.data)\n } catch {\n // Pane may have been closed between events — silently ignore\n }\n break\n\n case 'terminal.resize':\n try {\n workspaceManager.resizePane(event.paneId, event.cols, event.rows)\n } catch {\n // Pane may have been closed — ignore\n }\n break\n\n case 'conversation.send':\n workspaceManager.sendConversationToPane(event.paneId, event.text).catch((err) => {\n console.error('conversation.send failed:', err)\n })\n break\n\n case 'pane.create':\n workspaceManager.createPane(event.config).catch((err) => {\n console.error('pane.create failed:', err)\n })\n break\n\n case 'pane.close':\n workspaceManager.closePane(event.paneId).catch((err) => {\n console.error('pane.close failed:', err)\n })\n break\n\n case 'pane.restart':\n workspaceManager.restartPane(event.paneId, event.mode, event.sessionId)\n break\n\n case 'session.list':\n send({ type: 'session.list', paneId: event.paneId, sessions: workspaceManager.getSessionList(event.paneId) })\n break\n\n case 'git.refresh':\n gitService?.refresh()\n break\n\n case 'git.accept':\n gitService?.acceptFile(event.file).catch((err) => {\n console.error('git.accept failed:', err)\n })\n break\n\n case 'git.accept.all':\n gitService?.acceptAll().catch((err) => {\n console.error('git.accept.all failed:', err)\n })\n break\n\n case 'git.discard':\n gitService?.discardFile(event.file).catch((err) => {\n console.error('git.discard failed:', err)\n })\n break\n\n case 'git.discard.all':\n gitService?.discardAll().catch((err) => {\n console.error('git.discard.all failed:', err)\n })\n break\n\n case 'git.unstage':\n gitService?.unstageFile(event.file).catch((err) => {\n console.error('git.unstage failed:', err)\n })\n break\n\n case 'git.unstage.all':\n gitService?.unstageAll().catch((err) => {\n console.error('git.unstage.all failed:', err)\n })\n break\n\n case 'git.commit':\n if (gitService) {\n gitService.commit(event.message)\n .then((summary) => {\n send({ type: 'git.result', action: 'commit', success: true, message: summary })\n // Also refresh branch info after commit\n return gitService.getBranchInfo()\n })\n .then((info) => {\n send({ type: 'git.branchInfo', ...info })\n })\n .catch((err) => {\n send({ type: 'git.result', action: 'commit', success: false, message: String(err) })\n })\n }\n break\n\n case 'git.push':\n if (gitService) {\n gitService.push()\n .then((summary) => {\n send({ type: 'git.result', action: 'push', success: true, message: summary })\n return gitService.getBranchInfo()\n })\n .then((info) => {\n send({ type: 'git.branchInfo', ...info })\n })\n .catch((err) => {\n send({ type: 'git.result', action: 'push', success: false, message: String(err) })\n })\n }\n break\n\n case 'pane.merge':\n workspaceManager.mergeWorktree(event.paneId)\n .then((result) => {\n send({ type: 'pane.merge.result', paneId: event.paneId, ...result })\n // Refresh global git diff after merge\n gitService?.refresh()\n })\n .catch((err) => {\n send({ type: 'pane.merge.result', paneId: event.paneId, success: false, message: String(err) })\n })\n break\n\n case 'pane.discard':\n workspaceManager.discardWorktree(event.paneId)\n .then((result) => {\n send({ type: 'pane.merge.result', paneId: event.paneId, ...result })\n gitService?.refresh()\n })\n .catch((err) => {\n send({ type: 'pane.merge.result', paneId: event.paneId, success: false, message: String(err) })\n })\n break\n\n case 'pane.diff.refresh':\n workspaceManager.refreshPaneDiff(event.paneId)\n break\n\n case 'workspace.save':\n break\n\n case 'review.comment': {\n // Send review comment to agent pane as terminal input\n const { paneId: targetPaneId, comment } = event\n const targetPane = workspaceManager.getPanes().find((p) => p.id === targetPaneId)\n if (targetPane && comment.content.trim()) {\n const msg = [\n '',\n `[Review Comment] ${comment.file}:${comment.line}`,\n comment.content.trim(),\n '',\n ].join('\\n')\n workspaceManager.writeToPane(targetPaneId, msg + '\\n')\n }\n break\n }\n\n case 'broadcast.send':\n case 'task.dispatch':\n // P2 features — no-op for now\n break\n }\n })\n\n socket.on('close', () => {\n cleanup()\n })\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\n\n// ─── Types ───────────────────────────────────────────────────\n\nexport interface DepNode {\n id: string // relative file path (e.g., \"src/index.ts\")\n imports: string[] // resolved relative paths this file imports\n}\n\nexport interface DepGraph {\n nodes: DepNode[]\n root: string // project root (absolute)\n}\n\n// ─── Import regex patterns ───────────────────────────────────\n\n// Matches: import ... from 'specifier' or import 'specifier'\nconst IMPORT_FROM_RE = /import\\s+(?:[\\s\\S]*?\\s+from\\s+)?['\"]([^'\"]+)['\"]/g\n// Matches: export ... from 'specifier'\nconst EXPORT_FROM_RE = /export\\s+(?:[\\s\\S]*?\\s+from\\s+)?['\"]([^'\"]+)['\"]/g\n// Matches: require('specifier')\nconst REQUIRE_RE = /require\\s*\\(\\s*['\"]([^'\"]+)['\"]\\s*\\)/g\n// Matches: import('specifier') — dynamic import\nconst DYNAMIC_IMPORT_RE = /import\\s*\\(\\s*['\"]([^'\"]+)['\"]\\s*\\)/g\n\nconst JS_TS_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx', '.mjs', '.mts', '.cjs', '.cts'])\nconst RESOLVE_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.mts', '', '/index.ts', '/index.tsx', '/index.js', '/index.jsx']\n\n// Directories to skip\nconst SKIP_DIRS = new Set(['node_modules', '.git', 'dist', 'build', '.next', '.nuxt', 'coverage', '.nexus', '.turbo', '.cache'])\n\n// ─── DependencyAnalyzer ─────────────────────────────────────\n\nexport class DependencyAnalyzer {\n private projectDir: string\n\n constructor(projectDir: string) {\n this.projectDir = projectDir\n }\n\n /**\n * Scan the project directory and build a dependency graph.\n * Only analyzes JS/TS files with relative imports.\n */\n analyze(): DepGraph {\n const files = this.collectFiles(this.projectDir)\n const nodes: DepNode[] = []\n\n for (const absPath of files) {\n const relPath = path.relative(this.projectDir, absPath)\n const imports = this.extractImports(absPath, relPath)\n nodes.push({ id: relPath, imports })\n }\n\n return { nodes, root: this.projectDir }\n }\n\n private collectFiles(dir: string, depth = 0): string[] {\n if (depth > 8) return [] // safety limit\n const files: string[] = []\n\n let entries: fs.Dirent[]\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true })\n } catch {\n return files\n }\n\n for (const entry of entries) {\n if (entry.name.startsWith('.') && entry.name !== '.') continue\n const fullPath = path.join(dir, entry.name)\n\n if (entry.isDirectory()) {\n if (SKIP_DIRS.has(entry.name)) continue\n files.push(...this.collectFiles(fullPath, depth + 1))\n } else if (entry.isFile()) {\n const ext = path.extname(entry.name)\n if (JS_TS_EXTENSIONS.has(ext)) {\n files.push(fullPath)\n }\n }\n }\n\n return files\n }\n\n private extractImports(absPath: string, relPath: string): string[] {\n let content: string\n try {\n content = fs.readFileSync(absPath, 'utf-8')\n } catch {\n return []\n }\n\n const specifiers = new Set<string>()\n const patterns = [IMPORT_FROM_RE, EXPORT_FROM_RE, REQUIRE_RE, DYNAMIC_IMPORT_RE]\n\n for (const pattern of patterns) {\n pattern.lastIndex = 0\n let match: RegExpExecArray | null\n while ((match = pattern.exec(content)) !== null) {\n const spec = match[1]\n // Only resolve relative imports (skip node_modules / bare specifiers)\n if (spec.startsWith('.')) {\n specifiers.add(spec)\n }\n }\n }\n\n // Resolve specifiers to relative file paths\n const imports: string[] = []\n const fileDir = path.dirname(absPath)\n\n for (const spec of specifiers) {\n const resolved = this.resolveSpecifier(fileDir, spec)\n if (resolved) {\n const resolvedRel = path.relative(this.projectDir, resolved)\n imports.push(resolvedRel)\n }\n }\n\n return imports\n }\n\n private resolveSpecifier(fromDir: string, specifier: string): string | null {\n const base = path.resolve(fromDir, specifier)\n\n for (const ext of RESOLVE_EXTENSIONS) {\n const candidate = base + ext\n try {\n if (fs.statSync(candidate).isFile()) {\n return candidate\n }\n } catch {\n // not found, try next\n }\n }\n\n return null\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { execFile } from 'node:child_process'\nimport type {\n PaneState,\n PaneStatus,\n PaneMeta,\n FileActivity,\n AgentType,\n ReplayEvent,\n ReplayTurn,\n ReplaySession,\n ReplaySessionSummary,\n} from '../types.ts'\n\n/**\n * SessionRecorder records workspace events into Turn-based replay files.\n *\n * Structure:\n * .nexus/history/\n * sessions.json — array of session summaries (index)\n * session-<id>/\n * session.json — full session metadata (panes, timing)\n * turn-<id>.json — one file per turn (events array)\n *\n * A \"Turn\" is one idle→running→idle cycle of an agent pane.\n * Terminal output is sampled (batched per 200ms) to keep file sizes sane.\n */\n\nconst HISTORY_DIR = '.nexus/history'\nconst SESSIONS_INDEX = 'sessions.json'\nconst TERMINAL_BATCH_MS = 200\nconst MAX_TERMINAL_BYTES_PER_TURN = 256 * 1024 // 256KB cap per turn\nconst MAX_SESSIONS = 50\n\ninterface ActiveTurn {\n turn: ReplayTurn\n terminalBuffer: string\n terminalFlushTimer: ReturnType<typeof setTimeout> | null\n terminalBytes: number\n filesRead: Set<string>\n filesEdited: Set<string>\n filesCreated: Set<string>\n}\n\nexport class SessionRecorder {\n private projectDir: string\n private session: ReplaySession\n private sessionDir: string\n private activeTurns = new Map<string, ActiveTurn>() // paneId -> current turn\n private turnCounter = 0\n private retentionDays: number\n\n constructor(projectDir: string, projectName: string, retentionDays = 30) {\n this.projectDir = projectDir\n const sessionId = `s-${Date.now()}`\n this.sessionDir = path.join(projectDir, HISTORY_DIR, sessionId)\n fs.mkdirSync(this.sessionDir, { recursive: true })\n\n this.retentionDays = retentionDays\n\n this.session = {\n id: sessionId,\n startedAt: Date.now(),\n endedAt: null,\n projectDir,\n projectName,\n panes: [],\n turns: [], // lightweight refs only — full data in turn files\n }\n }\n\n // ─── Event Hooks (called by WorkspaceManager wiring) ─────\n\n onPaneAdded(pane: PaneState): void {\n if (pane.agent === '__shell__') return\n const exists = this.session.panes.find((p) => p.id === pane.id)\n if (!exists) {\n this.session.panes.push({\n id: pane.id,\n name: pane.name,\n agent: pane.agent,\n task: pane.task,\n })\n }\n // A new pane in 'running' state starts a turn immediately\n if (pane.status === 'running') {\n this.startTurn(pane.id, pane.name, pane.agent, pane.task)\n }\n }\n\n onPaneRemoved(paneId: string): void {\n this.endTurn(paneId)\n }\n\n onPaneStatus(paneId: string, status: PaneStatus, pane?: PaneState): void {\n if (!pane || pane.agent === '__shell__') return\n\n const active = this.activeTurns.get(paneId)\n\n if (status === 'running' && !active) {\n // idle → running: start a new turn\n this.startTurn(paneId, pane.name, pane.agent, pane.task)\n } else if ((status === 'idle' || status === 'stopped' || status === 'error') && active) {\n // running → idle/stopped/error: end the turn\n this.recordStatusEvent(paneId, status)\n this.endTurn(paneId)\n } else if (active) {\n // intermediate status change (e.g. running → waiting → running)\n this.recordStatusEvent(paneId, status)\n }\n }\n\n onPaneMeta(paneId: string, meta: PaneMeta): void {\n const active = this.activeTurns.get(paneId)\n if (!active) return\n\n const event: ReplayEvent = {\n t: Date.now() - active.turn.startedAt,\n type: 'meta',\n paneId,\n meta,\n }\n active.turn.events.push(event)\n }\n\n onTerminalData(paneId: string, data: string): void {\n const active = this.activeTurns.get(paneId)\n if (!active) return\n\n // Cap terminal data per turn\n if (active.terminalBytes >= MAX_TERMINAL_BYTES_PER_TURN) return\n\n active.terminalBuffer += data\n active.terminalBytes += data.length\n\n // Batch terminal writes to reduce event count\n if (!active.terminalFlushTimer) {\n active.terminalFlushTimer = setTimeout(() => {\n this.flushTerminalBuffer(paneId)\n }, TERMINAL_BATCH_MS)\n }\n }\n\n onPaneActivity(paneId: string, activity: FileActivity): void {\n const active = this.activeTurns.get(paneId)\n if (!active) return\n\n const event: ReplayEvent = {\n t: Date.now() - active.turn.startedAt,\n type: 'activity',\n paneId,\n activity: { ...activity },\n }\n active.turn.events.push(event)\n\n // Track summary\n switch (activity.action) {\n case 'read':\n active.filesRead.add(activity.file)\n break\n case 'edit':\n case 'write':\n active.filesEdited.add(activity.file)\n break\n case 'create':\n active.filesCreated.add(activity.file)\n break\n }\n\n // Async capture diff for write operations\n if (activity.action === 'edit' || activity.action === 'write' || activity.action === 'create') {\n this.captureDiff(activity.file).then((diff) => {\n if (diff) {\n event.activity = { ...event.activity!, diff }\n }\n }).catch(() => { /* ignore diff capture failures */ })\n }\n }\n\n /** Also accept file-level activity (from FsWatcher) attributed to the most recently active pane */\n onFileActivityForReplay(activity: FileActivity): void {\n // Try to attribute to any active turn (prefer most recent)\n if (this.activeTurns.size === 0) return\n\n // If only one active turn, attribute to it; otherwise skip (ambiguous)\n if (this.activeTurns.size !== 1) return\n\n const [paneId, active] = [...this.activeTurns.entries()][0]\n\n // Skip if this file was already recorded by pane activity within 2s\n let recentActivity: ReplayEvent | undefined\n for (let i = active.turn.events.length - 1; i >= 0; i--) {\n const e = active.turn.events[i]\n if (e.type === 'activity' && e.activity?.file === activity.file) {\n recentActivity = e\n break\n }\n }\n if (recentActivity && (Date.now() - active.turn.startedAt - recentActivity.t) < 2000) return\n\n const event: ReplayEvent = {\n t: Date.now() - active.turn.startedAt,\n type: 'activity',\n paneId,\n activity: { ...activity },\n }\n active.turn.events.push(event)\n\n // Capture diff\n if (activity.action === 'edit' || activity.action === 'create') {\n this.captureDiff(activity.file).then((diff) => {\n if (diff) {\n event.activity = { ...event.activity!, diff }\n }\n }).catch(() => {})\n }\n }\n\n // ─── Session Lifecycle ────────────────────────────────────\n\n /** Flush all active turns and write session index. Called on shutdown. */\n flush(): void {\n // End all active turns\n for (const paneId of [...this.activeTurns.keys()]) {\n this.endTurn(paneId)\n }\n\n this.session.endedAt = Date.now()\n this.writeSessionFile()\n this.updateSessionsIndex()\n }\n\n // ─── Query API ────────────────────────────────────────────\n\n static listSessions(projectDir: string): ReplaySessionSummary[] {\n const indexPath = path.join(projectDir, HISTORY_DIR, SESSIONS_INDEX)\n if (!fs.existsSync(indexPath)) return []\n try {\n const data = JSON.parse(fs.readFileSync(indexPath, 'utf-8'))\n return Array.isArray(data) ? data : []\n } catch {\n return []\n }\n }\n\n static getSession(projectDir: string, sessionId: string): ReplaySession | null {\n const sessionPath = path.join(projectDir, HISTORY_DIR, sessionId, 'session.json')\n if (!fs.existsSync(sessionPath)) return null\n try {\n return JSON.parse(fs.readFileSync(sessionPath, 'utf-8'))\n } catch {\n return null\n }\n }\n\n static getTurn(projectDir: string, sessionId: string, turnId: string): ReplayTurn | null {\n const turnPath = path.join(projectDir, HISTORY_DIR, sessionId, `${turnId}.json`)\n if (!fs.existsSync(turnPath)) return null\n try {\n return JSON.parse(fs.readFileSync(turnPath, 'utf-8'))\n } catch {\n return null\n }\n }\n\n /** Delete a single session and its directory. Returns true if deleted. */\n static deleteSession(projectDir: string, sessionId: string): boolean {\n // Remove session directory\n const sessionDir = path.join(projectDir, HISTORY_DIR, sessionId)\n if (fs.existsSync(sessionDir)) {\n fs.rmSync(sessionDir, { recursive: true, force: true })\n }\n\n // Remove from index\n const indexPath = path.join(projectDir, HISTORY_DIR, SESSIONS_INDEX)\n if (fs.existsSync(indexPath)) {\n try {\n let sessions: ReplaySessionSummary[] = JSON.parse(fs.readFileSync(indexPath, 'utf-8'))\n const before = sessions.length\n sessions = sessions.filter(s => s.id !== sessionId)\n if (sessions.length < before) {\n fs.writeFileSync(indexPath, JSON.stringify(sessions, null, 2))\n return true\n }\n } catch { /* ignore */ }\n }\n return false\n }\n\n /** Delete all sessions. Returns the number of sessions deleted. */\n static deleteAllSessions(projectDir: string): number {\n const sessions = SessionRecorder.listSessions(projectDir)\n let count = 0\n for (const session of sessions) {\n const sessionDir = path.join(projectDir, HISTORY_DIR, session.id)\n if (fs.existsSync(sessionDir)) {\n fs.rmSync(sessionDir, { recursive: true, force: true })\n count++\n }\n }\n // Reset index\n const indexPath = path.join(projectDir, HISTORY_DIR, SESSIONS_INDEX)\n fs.writeFileSync(indexPath, JSON.stringify([], null, 2))\n return count\n }\n\n /**\n * Passive cleanup: prune sessions exceeding max count or older than retentionDays.\n * Called automatically when saving a new session.\n */\n static pruneOldSessions(projectDir: string, retentionDays: number): number {\n const indexPath = path.join(projectDir, HISTORY_DIR, SESSIONS_INDEX)\n if (!fs.existsSync(indexPath)) return 0\n\n let sessions: ReplaySessionSummary[]\n try {\n sessions = JSON.parse(fs.readFileSync(indexPath, 'utf-8'))\n } catch { return 0 }\n\n const cutoff = Date.now() - retentionDays * 24 * 60 * 60 * 1000\n const keep: ReplaySessionSummary[] = []\n const remove: ReplaySessionSummary[] = []\n\n for (const s of sessions) {\n if (s.startedAt < cutoff || keep.length >= MAX_SESSIONS) {\n remove.push(s)\n } else {\n keep.push(s)\n }\n }\n\n if (remove.length === 0) return 0\n\n // Delete session directories\n for (const s of remove) {\n const sessionDir = path.join(projectDir, HISTORY_DIR, s.id)\n if (fs.existsSync(sessionDir)) {\n fs.rmSync(sessionDir, { recursive: true, force: true })\n }\n }\n\n fs.writeFileSync(indexPath, JSON.stringify(keep, null, 2))\n return remove.length\n }\n\n // ─── Internal ─────────────────────────────────────────────\n\n private startTurn(paneId: string, paneName: string, agent: AgentType, task?: string): void {\n // End any existing turn for this pane first\n if (this.activeTurns.has(paneId)) {\n this.endTurn(paneId)\n }\n\n const turnId = `turn-${++this.turnCounter}`\n const turn: ReplayTurn = {\n id: turnId,\n paneId,\n paneName,\n agent,\n startedAt: Date.now(),\n endedAt: null,\n task,\n events: [],\n summary: {\n filesRead: 0,\n filesEdited: 0,\n filesCreated: 0,\n terminalBytes: 0,\n durationMs: 0,\n },\n }\n\n this.activeTurns.set(paneId, {\n turn,\n terminalBuffer: '',\n terminalFlushTimer: null,\n terminalBytes: 0,\n filesRead: new Set(),\n filesEdited: new Set(),\n filesCreated: new Set(),\n })\n }\n\n private endTurn(paneId: string): void {\n const active = this.activeTurns.get(paneId)\n if (!active) return\n\n // Flush any remaining terminal buffer\n this.flushTerminalBuffer(paneId)\n\n const turn = active.turn\n turn.endedAt = Date.now()\n turn.summary = {\n filesRead: active.filesRead.size,\n filesEdited: active.filesEdited.size,\n filesCreated: active.filesCreated.size,\n terminalBytes: active.terminalBytes,\n durationMs: turn.endedAt - turn.startedAt,\n }\n\n // Only save turns with meaningful content\n if (turn.events.length > 0) {\n this.writeTurnFile(turn)\n // Store lightweight ref in session (without events)\n this.session.turns.push({\n ...turn,\n events: [], // don't duplicate events in session file\n })\n }\n\n this.activeTurns.delete(paneId)\n }\n\n private recordStatusEvent(paneId: string, status: PaneStatus): void {\n const active = this.activeTurns.get(paneId)\n if (!active) return\n active.turn.events.push({\n t: Date.now() - active.turn.startedAt,\n type: 'status',\n paneId,\n status,\n })\n }\n\n private flushTerminalBuffer(paneId: string): void {\n const active = this.activeTurns.get(paneId)\n if (!active || !active.terminalBuffer) return\n\n if (active.terminalFlushTimer) {\n clearTimeout(active.terminalFlushTimer)\n active.terminalFlushTimer = null\n }\n\n active.turn.events.push({\n t: Date.now() - active.turn.startedAt,\n type: 'terminal',\n paneId,\n data: active.terminalBuffer,\n })\n active.terminalBuffer = ''\n }\n\n /** Capture git diff for a single file. Returns unified diff string or null. */\n private captureDiff(file: string): Promise<string | null> {\n return new Promise((resolve) => {\n // Try git diff first (for tracked files), fall back to git diff --no-index for new files\n execFile('git', ['diff', '--no-color', '-U3', '--', file], {\n cwd: this.projectDir,\n timeout: 3000,\n maxBuffer: 128 * 1024,\n }, (err, stdout) => {\n if (stdout && stdout.trim()) {\n resolve(stdout.trim())\n return\n }\n // For untracked (new) files, show full content as diff\n execFile('git', ['diff', '--no-color', '--no-index', '/dev/null', file], {\n cwd: this.projectDir,\n timeout: 3000,\n maxBuffer: 128 * 1024,\n }, (_err2, stdout2) => {\n resolve(stdout2?.trim() || null)\n })\n })\n })\n }\n\n private writeTurnFile(turn: ReplayTurn): void {\n const turnPath = path.join(this.sessionDir, `${turn.id}.json`)\n fs.writeFileSync(turnPath, JSON.stringify(turn))\n }\n\n private writeSessionFile(): void {\n const sessionPath = path.join(this.sessionDir, 'session.json')\n fs.writeFileSync(sessionPath, JSON.stringify(this.session, null, 2))\n }\n\n private updateSessionsIndex(): void {\n const indexPath = path.join(this.projectDir, HISTORY_DIR, SESSIONS_INDEX)\n let sessions: ReplaySessionSummary[] = []\n\n if (fs.existsSync(indexPath)) {\n try {\n sessions = JSON.parse(fs.readFileSync(indexPath, 'utf-8'))\n } catch { /* start fresh */ }\n }\n\n const totalDurationMs = this.session.endedAt\n ? this.session.endedAt - this.session.startedAt\n : 0\n\n sessions.unshift({\n id: this.session.id,\n startedAt: this.session.startedAt,\n endedAt: this.session.endedAt,\n projectName: this.session.projectName,\n turnCount: this.session.turns.length,\n paneCount: this.session.panes.length,\n totalDurationMs,\n })\n\n fs.writeFileSync(indexPath, JSON.stringify(sessions, null, 2))\n\n // Passive cleanup: prune sessions exceeding retention or max count\n const pruned = SessionRecorder.pruneOldSessions(this.projectDir, this.retentionDays)\n if (pruned > 0) {\n console.log(`[SessionRecorder] Pruned ${pruned} old session(s)`)\n }\n }\n}\n","import { execFile } from 'node:child_process'\nimport { promisify } from 'node:util'\nimport type { ConfigManager } from './ConfigManager.ts'\n\nconst execFileAsync = promisify(execFile)\n\nexport interface ClaudeSession {\n session_id: string\n project_path?: string\n model?: string\n cost_usd?: number\n duration_ms?: number\n created_at?: string\n updated_at?: string\n summary?: string\n num_turns?: number\n}\n\nexport interface DiscoveredSession {\n sessionId: string\n summary?: string\n model?: string\n costUsd?: number\n numTurns?: number\n createdAt?: string\n updatedAt?: string\n projectPath?: string\n source: 'nexus' | 'external'\n}\n\nconst CACHE_TTL = 30_000 // 30s\n\nexport class SessionDiscovery {\n private configManager: ConfigManager\n private cache: { sessions: DiscoveredSession[]; ts: number } | null = null\n\n constructor(configManager: ConfigManager) {\n this.configManager = configManager\n }\n\n async listSessions(agentType = 'claudecode'): Promise<DiscoveredSession[]> {\n const now = Date.now()\n if (this.cache && now - this.cache.ts < CACHE_TTL) {\n return this.cache.sessions\n }\n\n const sessions = await this.fetchSessions(agentType)\n this.cache = { sessions, ts: now }\n return sessions\n }\n\n private async fetchSessions(agentType: string): Promise<DiscoveredSession[]> {\n const agentDef = this.configManager.getAgentDefinition(agentType)\n if (!agentDef || agentDef.bin !== 'claude') {\n return []\n }\n\n try {\n const { stdout } = await execFileAsync(agentDef.bin, ['sessions', 'list', '--output', 'json'], {\n timeout: 10_000,\n env: { ...process.env },\n })\n\n const parsed = JSON.parse(stdout.trim())\n const items: ClaudeSession[] = Array.isArray(parsed) ? parsed : (parsed.sessions || [])\n\n return items.map((s) => ({\n sessionId: s.session_id,\n summary: s.summary,\n model: s.model,\n costUsd: s.cost_usd,\n numTurns: s.num_turns,\n createdAt: s.created_at,\n updatedAt: s.updated_at,\n projectPath: s.project_path,\n source: 'external' as const,\n }))\n } catch (err) {\n console.warn('[SessionDiscovery] Failed to list sessions:', (err as Error).message)\n return []\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAO,QAAQ;AACf,SAAS,gBAAgB;AACzB,SAAS,iBAAiB;AAC1B,OAAO,UAAU;AALjB,IAQM,eAEA,YACA,oBAEA,uBA0DO;AAvEb;AAAA;AAAA;AAQA,IAAM,gBAAgB,UAAU,QAAQ;AAExC,IAAM,aAAa,KAAK,KAAK,GAAG,QAAQ,GAAG,QAAQ;AACnD,IAAM,qBAAqB,KAAK,KAAK,YAAY,aAAa;AAE9D,IAAM,wBAAsC;AAAA,MAC1C,SAAS;AAAA,MACT,UAAU;AAAA,QACR,OAAO,QAAQ,IAAI,SAAS;AAAA,QAC5B,kBAAkB;AAAA,QAClB,cAAc;AAAA,QACd,wBAAwB;AAAA,QACxB,OAAO;AAAA,MACT;AAAA,MACA,QAAQ;AAAA,QACN,YAAY;AAAA,UACV,KAAK;AAAA,UACL,eAAe;AAAA,UACf,aAAa;AAAA,UACb,WAAW;AAAA,UACX,YAAY;AAAA,UACZ,WAAW;AAAA,UACX,KAAK,CAAC;AAAA,QACR;AAAA,QACA,OAAO;AAAA,UACL,KAAK;AAAA,UACL,eAAe;AAAA,UACf,aAAa;AAAA,UACb,WAAW;AAAA,UACX,YAAY;AAAA,UACZ,WAAW;AAAA,UACX,KAAK,CAAC;AAAA,QACR;AAAA,QACA,UAAU;AAAA,UACR,KAAK;AAAA,UACL,eAAe;AAAA,UACf,aAAa;AAAA,UACb,WAAW;AAAA,UACX,YAAY;AAAA,UACZ,WAAW;AAAA,UACX,KAAK,CAAC;AAAA,QACR;AAAA,QACA,YAAY;AAAA,UACV,KAAK;AAAA,UACL,eAAe;AAAA,UACf,aAAa;AAAA,UACb,WAAW;AAAA,UACX,YAAY;AAAA,UACZ,WAAW;AAAA,UACX,KAAK,CAAC;AAAA,QACR;AAAA,QACA,UAAU;AAAA,UACR,KAAK;AAAA,UACL,eAAe;AAAA,UACf,aAAa;AAAA,UACb,WAAW;AAAA,UACX,YAAY;AAAA,UACZ,WAAW;AAAA,UACX,KAAK,CAAC;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEO,IAAM,gBAAN,MAAoB;AAAA,MACjB,eAAoC;AAAA,MACpC,kBAA0C;AAAA,MAC1C;AAAA,MAER,YAAY,YAAoB;AAC9B,aAAK,aAAa;AAAA,MACpB;AAAA,MAEA,mBAAiC;AAC/B,YAAI,KAAK,aAAc,QAAO,KAAK;AAEnC,YAAI,GAAG,WAAW,kBAAkB,GAAG;AACrC,gBAAM,UAAU,GAAG,aAAa,oBAAoB,OAAO;AAC3D,eAAK,eAAe,KAAK,KAAK,OAAO;AAErC,cAAI,UAAU;AACd,qBAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,sBAAsB,MAAM,GAAG;AACrE,gBAAI,CAAC,KAAK,aAAa,OAAO,GAAG,GAAG;AAClC,mBAAK,aAAa,OAAO,GAAG,IAAI;AAChC,wBAAU;AAAA,YACZ,OAAO;AAEL,oBAAM,WAAW,KAAK,aAAa,OAAO,GAAG;AAC7C,yBAAW,CAAC,OAAO,KAAK,KAAK,OAAO,QAAQ,GAAG,GAAG;AAChD,oBAAI,EAAE,SAAS,WAAW;AACxB,kBAAC,SAAqC,KAAK,IAAI;AAC/C,4BAAU;AAAA,gBACZ;AAAA,cACF;AAAA,YACF;AAAA,UACF;AACA,cAAI,SAAS;AACX,iBAAK,iBAAiB,KAAK,YAAY;AAAA,UACzC;AAAA,QACF,OAAO;AACL,eAAK,eAAe,EAAE,GAAG,sBAAsB;AAE/C,eAAK,iBAAiB,KAAK,YAAY;AACvC,eAAK,kBAAkB,EAAE,KAAK,CAAC,aAAa;AAC1C,gBAAI,OAAO,KAAK,QAAQ,EAAE,SAAS,KAAK,KAAK,cAAc;AACzD,mBAAK,aAAa,SAAS,EAAE,GAAG,KAAK,aAAa,QAAQ,GAAG,SAAS;AACtE,mBAAK,iBAAiB,KAAK,YAAY;AAAA,YACzC;AAAA,UACF,CAAC,EAAE,MAAM,MAAM;AAAA,UAAiC,CAAC;AAAA,QACnD;AAEA,eAAO,KAAK;AAAA,MACd;AAAA,MAEQ,iBAAiB,QAA4B;AACnD,WAAG,UAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AAC5C,WAAG,cAAc,oBAAoB,KAAK,KAAK,QAAQ,EAAE,WAAW,GAAG,CAAC,CAAC;AAAA,MAC3E;AAAA,MAEA,sBAA8C;AAC5C,YAAI,KAAK,gBAAiB,QAAO,KAAK;AAEtC,cAAM,aAAa,KAAK,KAAK,KAAK,YAAY,UAAU,aAAa;AACrE,YAAI,GAAG,WAAW,UAAU,GAAG;AAC7B,gBAAM,UAAU,GAAG,aAAa,YAAY,OAAO;AACnD,gBAAM,SAAS,KAAK,KAAK,OAAO;AAChC,cAAI,QAAQ;AACV,gBAAI,CAAC,MAAM,QAAQ,OAAO,KAAK,EAAG,QAAO,QAAQ,CAAC;AAClD,iBAAK,kBAAkB;AACvB,mBAAO,KAAK;AAAA,UACd;AAAA,QACF;AAEA,eAAO;AAAA,MACT;AAAA,MAEA,oBAAoB,QAA+B;AACjD,cAAM,WAAW,KAAK,KAAK,KAAK,YAAY,QAAQ;AACpD,WAAG,UAAU,UAAU,EAAE,WAAW,KAAK,CAAC;AAC1C,cAAM,aAAa,KAAK,KAAK,UAAU,aAAa;AACpD,WAAG,cAAc,YAAY,KAAK,KAAK,QAAQ,EAAE,WAAW,GAAG,CAAC,CAAC;AACjE,aAAK,kBAAkB;AAAA,MACzB;AAAA,MAEA,gBAAiC;AAC/B,cAAM,WAAW,KAAK,oBAAoB;AAC1C,YAAI,SAAU,QAAO;AAErB,cAAM,UAAU,KAAK,SAAS,KAAK,UAAU;AAC7C,cAAM,QAAQ,GAAG,WAAW,KAAK,KAAK,KAAK,YAAY,MAAM,CAAC;AAE9D,cAAM,SAA0B;AAAA,UAC9B,SAAS;AAAA,UACT,MAAM;AAAA,UACN,aAAa;AAAA,UACb,YAAY;AAAA,YACV,MAAM;AAAA,YACN,KAAK;AAAA,UACP;AAAA,UACA,OAAO,CAAC;AAAA,QACV;AAEA,aAAK,oBAAoB,MAAM;AAC/B,eAAO;AAAA,MACT;AAAA,MAEA,MAAc,oBAA8D;AAC1E,cAAM,SAA0C,CAAC;AAEjD,cAAM,YAA8G;AAAA,UAClH,EAAE,KAAK,cAAc,KAAK,UAAU,MAAM,cAAc,YAAY,MAAM,WAAW,MAAM;AAAA,UAC3F,EAAE,KAAK,SAAS,KAAK,SAAS,MAAM,IAAI,YAAY,OAAO,WAAW,MAAM;AAAA,UAC5E,EAAE,KAAK,YAAY,KAAK,YAAY,MAAM,cAAc,YAAY,OAAO,WAAW,MAAM;AAAA,UAC5F,EAAE,KAAK,YAAY,KAAK,QAAQ,MAAM,cAAc,YAAY,OAAO,WAAW,MAAM;AAAA,UACxF,EAAE,KAAK,YAAY,KAAK,YAAY,MAAM,MAAM,YAAY,OAAO,WAAW,MAAM;AAAA,QACtF;AAEA,cAAM,UAAU,MAAM,QAAQ;AAAA,UAC5B,UAAU,IAAI,OAAO,UAAU;AAC7B,kBAAM,cAAc,SAAS,CAAC,MAAM,GAAG,GAAG,EAAE,SAAS,IAAK,CAAC;AAC3D,mBAAO;AAAA,UACT,CAAC;AAAA,QACH;AAEA,mBAAW,UAAU,SAAS;AAC5B,cAAI,OAAO,WAAW,aAAa;AACjC,kBAAM,QAAQ,OAAO;AACrB,mBAAO,MAAM,GAAG,IAAI;AAAA,cAClB,KAAK,MAAM;AAAA,cACX,eAAe,MAAM;AAAA,cACrB,YAAY,MAAM;AAAA,cAClB,WAAW,MAAM;AAAA,cACjB,KAAK,CAAC;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAEA,eAAO;AAAA,MACT;AAAA,MAEA,mBAAmB,WAAgD;AACjE,cAAM,SAAS,KAAK,iBAAiB;AACrC,eAAO,OAAO,OAAO,SAAS;AAAA,MAChC;AAAA,MAEA,WAAmB;AACjB,cAAM,SAAS,KAAK,iBAAiB;AACrC,cAAM,aAAa,OAAO,SAAS;AAGnC,cAAM,aAAa;AAAA,UACjB;AAAA;AAAA,UACA;AAAA;AAAA,UACA;AAAA;AAAA,UACA;AAAA;AAAA,UACA;AAAA,UACA,QAAQ,IAAI;AAAA,UACZ;AAAA,UACA;AAAA,QACF;AACA,mBAAW,MAAM,YAAY;AAC3B,cAAI,CAAC,GAAI;AACT,cAAI;AACF,eAAG,WAAW,IAAI,GAAG,UAAU,IAAI;AACnC,mBAAO;AAAA,UACT,QAAQ;AAAA,UAER;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,MAAM,yBAAqE;AACzE,cAAM,SAAS,KAAK,iBAAiB;AACrC,cAAM,cAAwE;AAAA,UAC5E,EAAE,KAAK,cAAc,KAAK,UAAU,aAAa,2CAA2C;AAAA,UAC5F,EAAE,KAAK,SAAS,KAAK,SAAS,aAAa,+BAA+B;AAAA,UAC1E,EAAE,KAAK,YAAY,KAAK,YAAY,aAAa,oDAAoD;AAAA,UACrG,EAAE,KAAK,YAAY,KAAK,QAAQ,aAAa,uBAAuB;AAAA,UACpE,EAAE,KAAK,YAAY,KAAK,YAAY,aAAa,8CAA8C;AAAA,QACjG;AAEA,cAAM,SAAS,MAAM,QAAQ;AAAA,UAC3B,YAAY,IAAI,OAAO,UAAU;AAC/B,kBAAM,MAAM,OAAO,OAAO,MAAM,GAAG;AACnC,kBAAM,MAAM,KAAK,OAAO,MAAM;AAC9B,gBAAI;AACF,oBAAM,cAAc,SAAS,CAAC,GAAG,GAAG,EAAE,SAAS,IAAK,CAAC;AACrD,qBAAO,EAAE,GAAG,OAAO,KAAK,WAAW,KAAK;AAAA,YAC1C,QAAQ;AACN,qBAAO,EAAE,GAAG,OAAO,KAAK,WAAW,MAAM;AAAA,YAC3C;AAAA,UACF,CAAC;AAAA,QACH;AAEA,cAAM,SAA4C,CAAC;AACnD,mBAAW,SAAS,QAAQ;AAC1B,cAAI,MAAM,WAAW,aAAa;AAChC,kBAAM,EAAE,KAAK,KAAK,aAAa,UAAU,IAAI,MAAM;AACnD,mBAAO,GAAG,IAAI,EAAE,WAAW,KAAK,YAAY;AAAA,UAC9C;AAAA,QACF;AAEA,eAAO;AAAA,MACT;AAAA,MAEA,mBAAmB,QAA4B;AAC7C,aAAK,eAAe;AACpB,aAAK,iBAAiB,MAAM;AAAA,MAC9B;AAAA,MAEA,gBAAwB;AACtB,eAAO,KAAK;AAAA,MACd;AAAA,IACF;AAAA;AAAA;;;AC7RA,OAAOA,YAAU;AACjB,OAAOC,UAAQ;;;ACMf;AAPA,OAAO,aAAa;AACpB,OAAO,sBAAsB;AAC7B,OAAO,mBAAmB;AAC1B,OAAOC,YAAU;AACjB,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,qBAAqB;;;ACN9B,YAAY,SAAS;AACrB,OAAOC,SAAQ;AACf,OAAOC,SAAQ;AACf,OAAOC,WAAU;;;ACcjB,IAAM,eAAuC;AAAA,EAC3C,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,kBAAkB;AAAA,EAClB,KAAK;AAAA,EACL,WAAW;AAAA;AAEb;AAGA,IAAM,mBAAmB;AAGzB,IAAM,kBAAkB,KAAK;AAEtB,IAAM,mBAAN,MAAuB;AAAA,EACpB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOjB,MAAM,MAA4D;AAChE,QAAI,OAAwB;AAI5B,QAAI,CAAC,KAAK,SAAS,IAAI,GAAG;AACxB,WAAK,UAAU;AAEf,UAAI,KAAK,OAAO,SAAS,iBAAiB;AACxC,aAAK,SAAS;AAAA,MAChB;AACA,aAAO,EAAE,WAAW,MAAM,MAAM,KAAK;AAAA,IACvC;AAEA,UAAM,WAAW,KAAK,SAAS;AAC/B,SAAK,SAAS;AAEd,UAAM,QAAQ,SAAS,MAAM,IAAI;AAGjC,UAAM,WAAW,MAAM,IAAI,KAAK;AAChC,QAAI,UAAU;AACZ,WAAK,SAAS;AAAA,IAChB;AAEA,UAAM,aAAuB,CAAC;AAE9B,eAAW,QAAQ,OAAO;AACxB,YAAM,UAAU,KAAK,KAAK;AAG1B,UAAI,QAAQ,SAAS,MAAM,QAAQ,WAAW,CAAC,MAAM,KAAgB;AACnE,mBAAW,KAAK,IAAI;AACpB;AAAA,MACF;AAGA,UAAI,QAAQ,WAAW,QAAQ,SAAS,CAAC,MAAM,KAAgB;AAC7D,mBAAW,KAAK,IAAI;AACpB;AAAA,MACF;AAGA,UAAI;AACJ,UAAI;AACF,iBAAS,KAAK,MAAM,OAAO;AAAA,MAC7B,QAAQ;AACN,mBAAW,KAAK,IAAI;AACpB;AAAA,MACF;AAGA,UAAI,OAAO,WAAW,YAAY,WAAW,QAAQ,MAAM,QAAQ,MAAM,GAAG;AAC1E,mBAAW,KAAK,IAAI;AACpB;AAAA,MACF;AAEA,UAAI,KAAK,iBAAiB,MAAM,GAAG;AACjC,eAAO,KAAK,YAAY,MAAM;AAE9B;AAAA,MACF;AAGA,iBAAW,KAAK,IAAI;AAAA,IACtB;AAGA,QAAI,YAAY,WAAW,KAAK,IAAI;AACpC,QAAI,WAAW,SAAS,GAAG;AACzB,mBAAa;AAAA,IACf;AAEA,WAAO,EAAE,WAAW,KAAK;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,SAAS;AAAA,EAChB;AAAA,EAEQ,iBAAiB,KAAuC;AAC9D,QAAI,aAAa;AACjB,eAAW,CAAC,OAAO,YAAY,KAAK,OAAO,QAAQ,YAAY,GAAG;AAChE,UAAI,SAAS,KAAK;AAEhB,YAAI,OAAO,IAAI,KAAK,MAAM,cAAc;AACtC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,WAAO,cAAc;AAAA,EACvB;AAAA,EAEQ,YAAY,KAAwC;AAC1D,UAAM,OAAiB,CAAC;AAExB,QAAI,OAAO,IAAI,UAAU,UAAU;AACjC,WAAK,QAAQ,IAAI;AAAA,IACnB;AACA,QAAI,OAAO,IAAI,qBAAqB,UAAU;AAC5C,WAAK,iBAAiB,IAAI;AAAA,IAC5B;AACA,QAAI,OAAO,IAAI,aAAa,UAAU;AACpC,WAAK,UAAU,IAAI;AAAA,IACrB;AACA,QAAI,OAAO,IAAI,eAAe,UAAU;AACtC,WAAK,YAAY,IAAI;AAAA,IACvB;AACA,QAAI,OAAO,IAAI,QAAQ,UAAU;AAC/B,WAAK,MAAM,IAAI;AAAA,IACjB;AAEA,WAAO;AAAA,EACT;AACF;;;AC7IA,IAAM,sBAAsB;AAgBrB,IAAM,qBAAN,MAAyB;AAAA,EAW9B,YACU,QACA,UAA6B,CAAC,GACtC;AAFQ;AACA;AAGR,SAAK,WAAW,eAAe,MAAM,IAAI,KAAK,IAAI,EAAE,SAAS,EAAE,CAAC;AAChE,SAAK,YAAY,KAAK,IAAI;AAE1B,SAAK,UAAU,IAAI,QAA0B,CAAC,YAAY;AACxD,WAAK,UAAU;AAAA,IACjB,CAAC;AAAA,EACH;AAAA,EArBQ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAA8C;AAAA,EAC9C,WAAW;AAAA;AAAA,EAGX,SAAmB,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsB5B,MAAM,MAAuC;AAC3C,UAAM,YAAY,KAAK,QAAQ,aAAa;AAG5C,SAAK,MAAM,QAAQ,KAAK,QAAQ,IAAI;AAGpC,SAAK,QAAQ,WAAW,MAAM;AAC5B,UAAI,CAAC,KAAK,UAAU;AAClB,aAAK,WAAW;AAChB,aAAK,QAAQ;AAAA,UACX,UAAU;AAAA,UACV,WAAW,KAAK,IAAI,IAAI,KAAK;AAAA,QAC/B,CAAC;AAAA,MACH;AAAA,IACF,GAAG,SAAS;AAEZ,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,KAAK,MAAsB;AACzB,QAAI,KAAK,SAAU,QAAO;AAE1B,SAAK,OAAO,KAAK,IAAI;AAIrB,UAAM,SAAS,KAAK,OAAO,UAAU,IACjC,KAAK,OAAO,KAAK,EAAE,IACnB,KAAK,OAAO,MAAM,EAAE,EAAE,KAAK,EAAE;AAEjC,QAAI,OAAO,SAAS,KAAK,QAAQ,GAAG;AAClC,WAAK,WAAW;AAChB,UAAI,KAAK,OAAO;AACd,qBAAa,KAAK,KAAK;AACvB,aAAK,QAAQ;AAAA,MACf;AACA,WAAK,QAAQ;AAAA,QACX,UAAU;AAAA,QACV,WAAW,KAAK,IAAI,IAAI,KAAK;AAAA,MAC/B,CAAC;AAED,WAAK,SAAS,CAAC;AAEf,UAAI,KAAK,QAAQ,eAAe;AAC9B,eAAO,KAAK,sBAAsB,IAAI;AAAA,MACxC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,SAAkB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,UAAgB;AACd,QAAI,CAAC,KAAK,UAAU;AAClB,WAAK,WAAW;AAChB,UAAI,KAAK,OAAO;AACd,qBAAa,KAAK,KAAK;AACvB,aAAK,QAAQ;AAAA,MACf;AACA,WAAK,QAAQ;AAAA,QACX,UAAU;AAAA,QACV,WAAW,KAAK,IAAI,IAAI,KAAK;AAAA,MAC/B,CAAC;AAAA,IACH;AACA,SAAK,SAAS,CAAC;AAAA,EACjB;AAAA,EAEQ,sBAAsB,MAAsB;AAIlD,UAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,UAAM,WAAW,MAAM,OAAO,CAAC,SAAS,CAAC,KAAK,SAAS,KAAK,QAAQ,CAAC;AACrE,WAAO,SAAS,KAAK,IAAI;AAAA,EAC3B;AACF;;;ACvIA,IAAM,wBAAwB;AAC9B,IAAM,0BAA0B;AAGhC,IAAM,kBAAkB;AAAA,EACtB;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AACF;AAkBO,IAAM,qBAAN,MAAyB;AAAA,EAY9B,YAAoB,UAA6B,CAAC,GAAG;AAAjC;AAClB,SAAK,YAAY,KAAK,IAAI;AAC1B,SAAK,eAAe,QAAQ,gBAAgB;AAC5C,SAAK,iBAAiB;AAAA,MACpB,GAAG;AAAA,MACH,GAAI,QAAQ,uBAAuB,CAAC;AAAA,IACtC;AAEA,SAAK,UAAU,IAAI,QAA0B,CAAC,YAAY;AACxD,WAAK,UAAU;AAAA,IACjB,CAAC;AAAA,EACH;AAAA,EAtBQ;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EAEX,kBAAwD;AAAA,EACxD,YAAkD;AAAA,EAElD;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBR,QAAmC;AACjC,UAAM,gBAAgB,KAAK,QAAQ,iBAAiB;AAGpD,SAAK,YAAY,WAAW,MAAM;AAChC,WAAK,OAAO,SAAS;AAAA,IACvB,GAAG,aAAa;AAIhB,SAAK,gBAAgB;AAErB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,KAAK,MAAoB;AACvB,QAAI,KAAK,SAAU;AAGnB,SAAK,gBAAgB;AAGrB,UAAM,QAAQ,UAAU,IAAI;AAE5B,UAAM,OAAO,MAAM,MAAM,IAAI;AAE7B,eAAW,WAAW,KAAK,gBAAgB;AACzC,UAAI,QAAQ,KAAK,IAAI,GAAG;AACtB,aAAK,OAAO,QAAQ;AACpB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,MAAsB;AAC3B,QAAI,KAAK,SAAU;AAEnB,QAAI,KAAK,WAAW;AAClB,WAAK,OAAO,YAAY;AAAA,IAC1B;AAAA,EACF;AAAA,EAEA,IAAI,SAAkB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,UAAgB;AACd,QAAI,CAAC,KAAK,UAAU;AAClB,WAAK,WAAW;AAChB,WAAK,YAAY;AACjB,WAAK,QAAQ;AAAA,QACX,QAAQ;AAAA,QACR,WAAW,KAAK,IAAI,IAAI,KAAK;AAAA,MAC/B,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEQ,OAAO,QAAgC;AAC7C,QAAI,KAAK,SAAU;AACnB,SAAK,WAAW;AAChB,SAAK,YAAY;AACjB,SAAK,QAAQ;AAAA,MACX;AAAA,MACA,WAAW,KAAK,IAAI,IAAI,KAAK;AAAA,IAC/B,CAAC;AAAA,EACH;AAAA,EAEQ,kBAAwB;AAC9B,QAAI,KAAK,iBAAiB;AACxB,mBAAa,KAAK,eAAe;AAAA,IACnC;AACA,SAAK,kBAAkB,WAAW,MAAM;AACtC,WAAK,OAAO,YAAY;AAAA,IAC1B,GAAG,KAAK,YAAY;AAAA,EACtB;AAAA,EAEQ,cAAoB;AAC1B,QAAI,KAAK,iBAAiB;AACxB,mBAAa,KAAK,eAAe;AACjC,WAAK,kBAAkB;AAAA,IACzB;AACA,QAAI,KAAK,WAAW;AAClB,mBAAa,KAAK,SAAS;AAC3B,WAAK,YAAY;AAAA,IACnB;AAAA,EACF;AACF;AAGA,SAAS,UAAU,KAAqB;AACtC,SAAO,IACJ,QAAQ,kCAAkC,EAAE,EAC5C,QAAQ,0BAA0B,EAAE,EACpC,QAAQ,iCAAiC,EAAE;AAChD;;;AC3JA,IAAM,4BAA4B;AAS3B,IAAM,sBAAN,MAA0B;AAAA,EACvB,gBAA4B;AAAA,EAC5B,iBAAiB;AAAA,EACjB,iBAAgC;AAAA,EAChC,YAAkD;AAAA,EAClD,oBAA0D;AAAA,EAE1D;AAAA,EACA;AAAA,EAER,YAAY,UAA8B,CAAC,GAAG;AAC5C,SAAK,kBAAkB,QAAQ,mBAAmB;AAClD,SAAK,iBAAiB,QAAQ;AAC9B,SAAK,iBAAiB,KAAK,IAAI;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,WAAiB;AACf,SAAK,iBAAiB,KAAK,IAAI;AAG/B,QAAI,KAAK,kBAAkB,aAAa,KAAK,kBAAkB,QAAQ;AACrE,WAAK,UAAU,SAAS;AAAA,IAC1B;AAEA,SAAK,gBAAgB;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,MAAsB;AAC3B,QAAI,KAAK,mBAAmB,QAAW;AACrC,UAAI,KAAK,mBAAmB,QAAQ,KAAK,iBAAiB,KAAK,gBAAgB;AAE7E,YAAI,KAAK,kBAAkB,WAAW;AACpC,eAAK,UAAU,SAAS;AAAA,QAC1B;AACA,aAAK,gBAAgB;AAAA,MACvB;AACA,WAAK,iBAAiB,KAAK;AAAA,IAC7B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,UAAwB;AAC7B,SAAK,YAAY;AACjB,SAAK,UAAU,aAAa,IAAI,YAAY,OAAO;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA,EAKA,YAAwB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,eAAuB;AACrB,WAAO,KAAK,IAAI,IAAI,KAAK;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKA,UAAgB;AACd,SAAK,YAAY;AAAA,EACnB;AAAA,EAEQ,UAAU,QAA0B;AAC1C,QAAI,WAAW,KAAK,cAAe;AACnC,SAAK,gBAAgB;AACrB,SAAK,iBAAiB,MAAM;AAAA,EAC9B;AAAA,EAEQ,kBAAwB;AAC9B,SAAK,YAAY;AAGjB,SAAK,YAAY,WAAW,MAAM;AAChC,UAAI,KAAK,kBAAkB,WAAW;AACpC,aAAK,UAAU,SAAS;AAAA,MAC1B;AAGA,WAAK,oBAAoB,WAAW,MAAM;AACxC,YAAI,KAAK,kBAAkB,WAAW;AACpC,eAAK,UAAU,MAAM;AAAA,QACvB;AAAA,MACF,GAAG,KAAK,kBAAkB,CAAC;AAAA,IAC7B,GAAG,KAAK,eAAe;AAAA,EACzB;AAAA,EAEQ,cAAoB;AAC1B,QAAI,KAAK,WAAW;AAClB,mBAAa,KAAK,SAAS;AAC3B,WAAK,YAAY;AAAA,IACnB;AACA,QAAI,KAAK,mBAAmB;AAC1B,mBAAa,KAAK,iBAAiB;AACnC,WAAK,oBAAoB;AAAA,IAC3B;AAAA,EACF;AACF;;;ACtIA,SAASC,WAAU,KAAqB;AACtC,SAAO,IACJ,QAAQ,kCAAkC,EAAE,EAC5C,QAAQ,0BAA0B,EAAE,EACpC,QAAQ,oBAAoB,EAAE,EAC9B,QAAQ,cAAc,EAAE,EACxB,QAAQ,cAAc,EAAE,EACxB,QAAQ,iCAAiC,EAAE;AAChD;AAOA,IAAMC,mBAAkB,KAAK;AAEtB,IAAM,iBAAN,MAAM,gBAAe;AAAA,EAClB,SAAS;AAAA,EACT,WAAW;AAAA,EACX,WAAW;AAAA,EACF,WAAW;AAAA;AAAA,EAE5B,MAAM,MAAmC;AACvC,QAAI,CAAC,KAAK,SAAS,IAAI,GAAG;AACxB,WAAK,UAAU;AAEf,UAAI,KAAK,OAAO,SAASA,kBAAiB;AACxC,aAAK,SAAS;AAAA,MAChB;AACA,aAAO;AAAA,IACT;AAEA,UAAM,SAAS,KAAK,SAAS,MAAM,MAAM,IAAI;AAC7C,SAAK,SAAS;AAEd,UAAM,WAAW,MAAM,IAAI,KAAK;AAChC,QAAI,UAAU;AACZ,WAAK,SAAS;AAAA,IAChB;AAGA,eAAW,QAAQ,OAAO;AACxB,YAAM,WAAW,KAAK,UAAU,IAAI;AACpC,UAAI,UAAU;AAEZ,YAAI,SAAS,SAAS,KAAK,YAAY,SAAS,YAAY,KAAK,WAAW,KAAK,UAAU;AACzF;AAAA,QACF;AACA,aAAK,WAAW,SAAS;AACzB,aAAK,WAAW,SAAS;AACzB,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,UAAU,MAAmC;AACnD,UAAM,QAAQD,WAAU,IAAI,EAAE,KAAK;AACnC,QAAI,CAAC,SAAS,MAAM,SAAS,EAAG,QAAO;AAKvC,UAAM,kBAAkB,MAAM;AAAA,MAC5B;AAAA,IACF;AACA,QAAI,iBAAiB;AACnB,aAAO,KAAK,cAAc,gBAAgB,CAAC,GAAG,gBAAgB,CAAC,CAAC;AAAA,IAClE;AAIA,UAAM,iBAAiB,MAAM;AAAA,MAC3B;AAAA,IACF;AACA,QAAI,gBAAgB;AAClB,aAAO,KAAK,cAAc,eAAe,CAAC,GAAG,eAAe,CAAC,CAAC;AAAA,IAChE;AAGA,UAAM,aAAa,MAAM;AAAA,MACvB;AAAA,IACF;AACA,QAAI,YAAY;AACd,aAAO,KAAK,cAAc,WAAW,CAAC,GAAG,WAAW,CAAC,CAAC;AAAA,IACxD;AAGA,UAAM,iBAAiB,MAAM;AAAA,MAC3B;AAAA,IACF;AACA,QAAI,gBAAgB;AAClB,YAAM,SAAS,KAAK,uBAAuB,KAAK;AAChD,aAAO,KAAK,cAAc,QAAQ,eAAe,CAAC,CAAC;AAAA,IACrD;AAGA,UAAM,aAAa,MAAM;AAAA,MACvB;AAAA,IACF;AACA,QAAI,YAAY;AACd,aAAO,KAAK,cAAc,WAAW,CAAC,GAAG,WAAW,CAAC,CAAC;AAAA,IACxD;AAGA,UAAM,eAAe,MAAM;AAAA,MACzB;AAAA,IACF;AACA,QAAI,cAAc;AAChB,aAAO,KAAK,cAAc,aAAa,CAAC,GAAG,aAAa,CAAC,CAAC;AAAA,IAC5D;AAKA,UAAM,oBAAoB,MAAM;AAAA,MAC9B;AAAA,IACF;AACA,QAAI,qBAAqB,KAAK,WAAW,GAAG,GAAG;AAC7C,aAAO,KAAK,cAAc,QAAQ,kBAAkB,CAAC,CAAC;AAAA,IACxD;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,cAAc,UAAkB,SAAsC;AAC5E,UAAM,OAAO,KAAK,UAAU,OAAO;AACnC,QAAI,CAAC,QAAQ,CAAC,KAAK,YAAY,IAAI,EAAG,QAAO;AAE7C,UAAM,SAAS,KAAK,aAAa,QAAQ;AACzC,WAAO,EAAE,MAAM,QAAQ,WAAW,KAAK,IAAI,EAAE;AAAA,EAC/C;AAAA,EAEQ,aAAa,MAA0B;AAC7C,YAAQ,KAAK,YAAY,GAAG;AAAA,MAC1B,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAAA,EAEQ,uBAAuB,MAAsB;AACnD,UAAM,QAAQ,KAAK,YAAY;AAC/B,QAAI,MAAM,SAAS,MAAM,KAAK,MAAM,SAAS,YAAY,KAAK,MAAM,SAAS,YAAY,EAAG,QAAO;AACnG,QAAI,MAAM,SAAS,OAAO,KAAK,MAAM,SAAS,SAAS,EAAG,QAAO;AACjE,QAAI,MAAM,SAAS,QAAQ,KAAK,MAAM,SAAS,QAAQ,EAAG,QAAO;AACjE,WAAO;AAAA,EACT;AAAA,EAEQ,UAAU,KAAqB;AACrC,WAAO,IACJ,KAAK,EACL,QAAQ,oBAAoB,EAAE,EAC9B,QAAQ,SAAS,EAAE,EACnB,QAAQ,UAAU,EAAE,EACpB,QAAQ,YAAY,EAAE,EACtB,QAAQ,OAAO,EAAE;AAAA,EACtB;AAAA;AAAA,EAGA,OAAe,mBAAmB,CAAC,WAAW,iBAAiB,OAAO;AAAA,EAE9D,YAAY,MAAuB;AACzC,QAAI,CAAC,QAAQ,KAAK,SAAS,EAAG,QAAO;AAErC,QAAI,CAAC,cAAc,KAAK,IAAI,EAAG,QAAO;AAEtC,QAAI,KAAK,WAAW,GAAG,KAAK,KAAK,SAAS,KAAK,EAAG,QAAO;AAEzD,eAAW,UAAU,gBAAe,kBAAkB;AACpD,UAAI,KAAK,WAAW,MAAM,EAAG,QAAO;AAAA,IACtC;AAEA,QAAI,kBAAkB,KAAK,IAAI,EAAG,QAAO;AAEzC,UAAM,QAAQ,KAAK,MAAM,GAAG;AAC5B,QAAI,MAAM,SAAS,GAAI,QAAO;AAC9B,eAAW,QAAQ,OAAO;AACxB,UAAI,KAAK,SAAS,OAAO,KAAK,WAAW,EAAG,QAAO;AAAA,IACrD;AACA,WAAO;AAAA,EACT;AACF;;;ALnMA,IAAM,uBAAuB,MAAM;AAoB5B,IAAM,aAAN,MAAiB;AAAA,EACd,UAAU,oBAAI,IAAsB;AAAA,EACpC;AAAA,EAER,YAAY,eAA8B;AACxC,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEA,MAAM,QAAgB,QAAoB,OAAO,IAAI,OAAO,IAAY;AACtE,QAAI,KAAK,QAAQ,IAAI,MAAM,GAAG;AAC5B,WAAK,KAAK,MAAM;AAAA,IAClB;AAEA,UAAM,QAAQ,KAAK,cAAc,SAAS;AAC1C,YAAQ,IAAI,sBAAsB,KAAK,aAAa,MAAM,EAAE;AAC5D,UAAM,aAAa,KAAK,cAAc,cAAc;AAEpD,UAAM,WAAY,OAAO,cAAc,cAAc,OAAO,eACxD,OAAO,eACP;AACJ,QAAI,MAAM,OAAO,UACbE,MAAK,QAAQ,UAAU,OAAO,OAAO,IACrC;AAGJ,QAAI,CAACC,IAAG,WAAW,GAAG,GAAG;AACvB,cAAQ,KAAK,6BAA6B,GAAG,qBAAqB,UAAU,EAAE;AAC9E,YAAMA,IAAG,WAAW,UAAU,IAAI,aAAaC,IAAG,QAAQ;AAAA,IAC5D;AAGA,QAAI,gBAAgB;AACpB,QAAI,CAACD,IAAG,WAAW,aAAa,GAAG;AACjC,YAAM,YAAY,CAAC,YAAY,aAAa,SAAS;AACrD,YAAM,QAAQ,UAAU,KAAK,OAAKA,IAAG,WAAW,CAAC,CAAC;AAClD,cAAQ,MAAM,iCAAiC,aAAa,qBAAqB,SAAS,SAAS,EAAE;AACrG,sBAAgB,SAAS;AAAA,IAC3B;AAEA,UAAM,WAAW,KAAK,cAAc,mBAAmB,OAAO,KAAK;AACnE,UAAM,UAAU,YAAY,OAAO,UAAU;AAI7C,UAAM,MAA8B,CAAC;AACrC,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,GAAG,GAAG;AACtD,UAAI,UAAU,UAAa,CAAC,IAAI,WAAW,QAAQ,KAAK,QAAQ,cAAc;AAC5E,YAAI,GAAG,IAAI;AAAA,MACb;AAAA,IACF;AACA,QAAI,UAAU,KAAK;AAEjB,YAAM,mBAAmB,oBAAI,IAAI;AAAA,QAC/B;AAAA,QAAQ;AAAA,QAAc;AAAA,QACtB;AAAA,QAAyB;AAAA,QAAqB;AAAA,MAChD,CAAC;AACD,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,SAAS,GAAG,GAAG;AACvD,YAAI,iBAAiB,IAAI,GAAG,GAAG;AAC7B,kBAAQ,KAAK,qDAAqD,GAAG,EAAE;AACvE;AAAA,QACF;AAEA,cAAM,WAAW,MAAM,QAAQ,gBAAgB,CAAC,GAAG,YAAoB;AACrE,iBAAO,QAAQ,IAAI,OAAO,KAAK;AAAA,QACjC,CAAC;AACD,YAAI,SAAU,KAAI,GAAG,IAAI;AAAA,MAC3B;AAAA,IACF;AAGA,QAAI,CAAC,IAAI,MAAM;AACb,UAAI,OAAO;AACX,UAAI,QAAQ,aAAa,UAAU;AACjC,YAAI,OAAO,0CAA0C,IAAI;AAAA,MAC3D;AAAA,IACF;AAEA,YAAQ,IAAI,uBAAuB,MAAM,WAAW,aAAa,SAAS,GAAG,EAAE;AAE/E,UAAM,OAAW,UAAM,eAAe,CAAC,GAAG;AAAA,MACxC,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAGD,UAAM,gBAAgB,UAClB,IAAI,mBAAmB,QAAQ,EAAE,eAAe,KAAK,CAAC,IACtD;AAEJ,UAAM,gBAAgB,IAAI,oBAAoB;AAAA,MAC5C,iBAAiB;AAAA,MACjB,gBAAgB,CAAC,WAAW;AAC1B,cAAM,IAAI,KAAK,QAAQ,IAAI,MAAM;AACjC,YAAI,GAAG;AACL,YAAE,SAAS;AACX,qBAAW,MAAM,EAAE,mBAAmB;AACpC,eAAG,MAAM;AAAA,UACX;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAED,UAAM,QAAkB;AAAA,MACtB,KAAK;AAAA,MACL;AAAA,MACA,QAAQ;AAAA,MACR,MAAM,CAAC;AAAA,MACP,QAAQ,IAAI,iBAAiB;AAAA,MAC7B,gBAAgB,IAAI,eAAe;AAAA,MACnC;AAAA,MACA;AAAA,MACA,eAAe;AAAA;AAAA,MACf,YAAY,CAAC;AAAA,MACb,iBAAiB;AAAA,MACjB,iBAAiB,CAAC;AAAA,MAClB,mBAAmB,CAAC;AAAA,MACpB,iBAAiB,CAAC;AAAA,MAClB,qBAAqB,CAAC;AAAA,IACxB;AAEA,SAAK,QAAQ,IAAI,QAAQ,KAAK;AAG9B,SAAK,OAAO,CAAC,SAAiB;AAE5B,UAAI,gBAAgB;AACpB,UAAI,MAAM,iBAAiB,CAAC,MAAM,cAAc,QAAQ;AACtD,wBAAgB,MAAM,cAAc,KAAK,IAAI;AAAA,MAC/C;AAGA,UAAI,MAAM,iBAAiB,CAAC,MAAM,cAAc,QAAQ;AACtD,cAAM,cAAc,KAAK,aAAa;AAAA,MACxC;AAEA,YAAM,EAAE,WAAW,KAAK,IAAI,MAAM,OAAO,MAAM,aAAa;AAE5D,UAAI,WAAW;AAEb,cAAM,cAAc,SAAS;AAG7B,cAAM,WAAW,KAAK,SAAS;AAC/B,cAAM,mBAAmB,UAAU;AAEnC,YAAI,MAAM,kBAAkB,sBAAsB;AAChD,cAAI,gBAAgB,MAAM,kBAAkB;AAC5C,cAAI,cAAc;AAClB,iBAAO,cAAc,MAAM,WAAW,SAAS,KAAK,gBAAgB,GAAG;AACrE,6BAAiB,MAAM,WAAW,WAAW,EAAE;AAC/C,kBAAM,mBAAmB,MAAM,WAAW,WAAW,EAAE;AACvD;AAAA,UACF;AACA,cAAI,cAAc,GAAG;AACnB,kBAAM,WAAW,OAAO,GAAG,WAAW;AAAA,UACxC;AAAA,QACF;AAEA,mBAAW,MAAM,MAAM,iBAAiB;AACtC,aAAG,SAAS;AAAA,QACd;AAAA,MACF;AAEA,UAAI,MAAM;AACR,cAAM,OAAO,EAAE,GAAG,MAAM,MAAM,GAAG,KAAK;AAGtC,cAAM,cAAc,OAAO,IAAI;AAC/B,YAAI,MAAM,iBAAiB,CAAC,MAAM,cAAc,QAAQ;AACtD,gBAAM,cAAc,OAAO,IAAI;AAAA,QACjC;AAEA,mBAAW,MAAM,MAAM,iBAAiB;AACtC,aAAG,MAAM,IAAI;AAAA,QACf;AAAA,MACF;AAGA,UAAI,OAAO,UAAU,aAAa;AAChC,cAAM,WAAW,MAAM,eAAe,MAAM,IAAI;AAChD,YAAI,UAAU;AACZ,qBAAW,MAAM,MAAM,qBAAqB;AAC1C,eAAG,QAAQ;AAAA,UACb;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAGD,SAAK,OAAO,CAAC,EAAE,SAAS,MAAM;AAC5B,YAAM,IAAI,KAAK,QAAQ,IAAI,MAAM;AACjC,UAAI,GAAG;AACL,UAAE,cAAc,OAAO,QAAQ;AAE/B,UAAE,eAAe,QAAQ;AACzB,UAAE,eAAe,QAAQ;AAAA,MAC3B;AAAA,IACF,CAAC;AAGD,QAAI,WAAW,eAAe;AAC5B,WAAK,mBAAmB,QAAQ,QAAQ,UAAW,aAAa;AAAA,IAClE;AAEA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,mBACZ,QACA,QACA,UACA,eACe;AACf,UAAM,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACrC,QAAI,CAAC,MAAO;AAGZ,UAAM,cAAc,MAAM,cAAc,MAAM,MAAM,GAAG;AACvD,QAAI,CAAC,KAAK,QAAQ,IAAI,MAAM,EAAG;AAE/B,YAAQ,IAAI,yBAAyB,MAAM,cAAc,YAAY,QAAQ,KAAK,YAAY,SAAS,KAAK;AAG5G,SAAK,iBAAiB,QAAQ,QAAQ,QAAQ;AAG9C,QAAI,OAAO,QAAQ,OAAO,YAAY,UAAU;AAC9C,YAAM,gBAAgB,IAAI,mBAAmB;AAAA,QAC3C,cAAc;AAAA,QACd,eAAe;AAAA,MACjB,CAAC;AACD,YAAM,gBAAgB;AAEtB,YAAM,cAAc,MAAM,cAAc,MAAM;AAC9C,UAAI,CAAC,KAAK,QAAQ,IAAI,MAAM,EAAG;AAE/B,cAAQ,IAAI,yBAAyB,MAAM,YAAY,YAAY,MAAM,KAAK,YAAY,SAAS,KAAK;AAGxG,YAAM,IAAI,MAAM,OAAO,OAAO,IAAI;AAAA,IACpC;AAAA,EACF;AAAA,EAEQ,iBAAiB,QAAgB,QAAoB,UAAiC;AAC5F,UAAM,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACrC,QAAI,CAAC,MAAO;AAEZ,QAAI,MAAM,SAAS;AAGnB,QAAI,OAAO,YAAY,YAAY,OAAO,aAAa,SAAS,aAAa;AAC3E,aAAO,IAAI,SAAS,WAAW,IAAI,OAAO,SAAS;AAAA,IACrD,WAAW,OAAO,YAAY,cAAc,SAAS,eAAe;AAElE,aAAO,IAAI,SAAS,aAAa;AAAA,IACnC;AAGA,QAAI,OAAO,QAAQ,SAAS,WAAW;AACrC,aAAO,IAAI,SAAS,SAAS;AAAA,IAC/B;AAGA,UAAM,IAAI,MAAM,MAAM,IAAI;AAAA,EAC5B;AAAA,EAEA,MAAM,QAAgB,MAAoB;AACxC,UAAM,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACrC,QAAI,OAAO;AACT,YAAM,IAAI,MAAM,IAAI;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,OAAO,QAAgB,MAAc,MAAoB;AACvD,UAAM,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACrC,QAAI,OAAO;AACT,UAAI;AACF,cAAM,IAAI,OAAO,MAAM,IAAI;AAAA,MAC7B,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA,EAEA,KAAK,QAAsB;AACzB,UAAM,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACrC,QAAI,OAAO;AAET,YAAM,cAAc,QAAQ;AAC5B,YAAM,eAAe,QAAQ;AAC7B,YAAM,eAAe,QAAQ;AAC7B,YAAM,OAAO,MAAM;AAGnB,YAAM,gBAAgB,SAAS;AAC/B,YAAM,kBAAkB,SAAS;AACjC,YAAM,gBAAgB,SAAS;AAC/B,YAAM,oBAAoB,SAAS;AAEnC,UAAI;AACF,cAAM,IAAI,KAAK;AAAA,MACjB,QAAQ;AAAA,MAER;AACA,WAAK,QAAQ,OAAO,MAAM;AAAA,IAC5B;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,eAAW,CAAC,MAAM,KAAK,KAAK,SAAS;AACnC,WAAK,KAAK,MAAM;AAAA,IAClB;AAAA,EACF;AAAA,EAEA,UAAU,QAA4B;AACpC,WAAO,KAAK,QAAQ,IAAI,MAAM,GAAG,UAAU;AAAA,EAC7C;AAAA,EAEA,QAAQ,QAA0B;AAChC,WAAO,KAAK,QAAQ,IAAI,MAAM,GAAG,QAAQ,CAAC;AAAA,EAC5C;AAAA,EAEA,OAAO,QAAoC;AACzC,WAAO,KAAK,QAAQ,IAAI,MAAM,GAAG,IAAI;AAAA,EACvC;AAAA,EAEA,OAAO,QAAgB,UAAwC;AAC7D,UAAM,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACrC,QAAI,OAAO;AACT,YAAM,gBAAgB,KAAK,QAAQ;AAAA,IACrC;AAAA,EACF;AAAA,EAEA,SAAS,QAAgB,UAA8C;AACrE,UAAM,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACrC,QAAI,OAAO;AACT,YAAM,kBAAkB,KAAK,QAAQ;AAAA,IACvC;AAAA,EACF;AAAA,EAEA,OAAO,QAAgB,UAA0C;AAC/D,UAAM,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACrC,QAAI,OAAO;AACT,YAAM,gBAAgB,KAAK,QAAQ;AAAA,IACrC;AAAA,EACF;AAAA,EAEA,WAAW,QAAgB,UAAkD;AAC3E,UAAM,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACrC,QAAI,OAAO;AACT,YAAM,oBAAoB,KAAK,QAAQ;AAAA,IACzC;AAAA,EACF;AAAA,EAEA,cAAc,QAAwB;AACpC,UAAM,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACrC,QAAI,CAAC,MAAO,QAAO;AACnB,WAAO,MAAM,WAAW,KAAK,EAAE;AAAA,EACjC;AAAA,EAEA,IAAI,QAAyB;AAC3B,WAAO,KAAK,QAAQ,IAAI,MAAM;AAAA,EAChC;AACF;;;AMlZA,SAAS,SAAAE,cAAkD;AAC3D,OAAOC,SAAQ;AACf,OAAOC,SAAQ;AACf,OAAOC,WAAU;AAWjB,IAAMC,wBAAuB,MAAM;AA0BnC,SAAS,gBAAgB,UAA+D;AACtF,QAAM,MAA8B,CAAC;AACrC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,GAAG,GAAG;AACtD,QAAI,UAAU,UAAa,CAAC,IAAI,WAAW,QAAQ,KAAK,QAAQ,cAAc;AAC5E,UAAI,GAAG,IAAI;AAAA,IACb;AAAA,EACF;AAEA,MAAI,UAAU,KAAK;AACjB,UAAM,UAAU,oBAAI,IAAI;AAAA,MACtB;AAAA,MAAQ;AAAA,MAAc;AAAA,MACtB;AAAA,MAAyB;AAAA,MAAqB;AAAA,IAChD,CAAC;AACD,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,SAAS,GAAG,GAAG;AACvD,UAAI,QAAQ,IAAI,GAAG,EAAG;AACtB,UAAI,GAAG,IAAI,MAAM,QAAQ,gBAAgB,CAAC,GAAG,SAAiB,QAAQ,IAAI,IAAI,KAAK,EAAE;AAAA,IACvF;AAAA,EACF;AAEA,MAAI,CAAC,IAAI,MAAM;AACb,QAAI,OAAO;AACX,QAAI,QAAQ,aAAa,UAAU;AACjC,UAAI,OAAO,wCAAwC,IAAI,IAAI;AAAA,IAC7D;AAAA,EACF;AAEA,SAAO;AACT;AAEO,IAAM,aAAN,MAAiB;AAAA,EACd,UAAU,oBAAI,IAAsB;AAAA,EACpC;AAAA,EAER,YAAY,eAA8B;AACxC,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEA,MAAM,QAAgB,QAAwC;AAC5D,QAAI,KAAK,QAAQ,IAAI,MAAM,GAAG;AAC5B,WAAK,KAAK,MAAM;AAAA,IAClB;AAEA,UAAM,aAAa,KAAK,cAAc,cAAc;AACpD,UAAM,WAAY,OAAO,cAAc,cAAc,OAAO,eACxD,OAAO,eACP;AACJ,QAAI,MAAM,OAAO,UACbD,MAAK,QAAQ,UAAU,OAAO,OAAO,IACrC;AAEJ,QAAI,CAACF,IAAG,WAAW,GAAG,GAAG;AACvB,YAAMA,IAAG,WAAW,UAAU,IAAI,aAAaC,IAAG,QAAQ;AAAA,IAC5D;AAEA,UAAM,WAAW,KAAK,cAAc,mBAAmB,OAAO,KAAK;AACnE,QAAI,CAAC,UAAU;AACb,YAAM,IAAI,MAAM,gCAAgC,OAAO,KAAK,EAAE;AAAA,IAChE;AAEA,UAAM,MAAM,gBAAgB,QAAQ;AACpC,UAAM,OAAOF,OAAM,SAAS,KAAK,CAAC,KAAK,GAAG;AAAA,MACxC;AAAA,MACA;AAAA,MACA,OAAO,CAAC,QAAQ,QAAQ,MAAM;AAAA,IAChC,CAAC;AAED,UAAM,QAAkB;AAAA,MACtB;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,MACR,MAAM,EAAE,IAAI;AAAA,MACZ,eAAe;AAAA,MACf,eAAe;AAAA,MACf,YAAY;AAAA,MACZ,SAAS,oBAAI,IAAI;AAAA,MACjB,cAAc;AAAA,MACd,YAAY,CAAC;AAAA,MACb,iBAAiB;AAAA,MACjB,iBAAiB,CAAC;AAAA,MAClB,mBAAmB,CAAC;AAAA,MACpB,iBAAiB,CAAC;AAAA,MAClB,yBAAyB,CAAC;AAAA,MAC1B,qBAAqB,CAAC;AAAA,IACxB;AAEA,SAAK,QAAQ,IAAI,QAAQ,KAAK;AAE9B,SAAK,OAAO,YAAY,MAAM;AAC9B,SAAK,OAAO,YAAY,MAAM;AAE9B,SAAK,OAAO,GAAG,QAAQ,CAAC,UAAkB,KAAK,aAAa,QAAQ,KAAK,CAAC;AAC1E,SAAK,OAAO,GAAG,QAAQ,CAAC,UAAkB;AACxC,WAAK,aAAa,QAAQ,gBAAgB,KAAK,EAAE;AAAA,IACnD,CAAC;AACD,SAAK,GAAG,QAAQ,CAAC,MAAM,WAAW;AAChC,YAAM,IAAI,KAAK,QAAQ,IAAI,MAAM;AACjC,UAAI,CAAC,EAAG;AACR,iBAAW,WAAW,EAAE,QAAQ,OAAO,GAAG;AACxC,gBAAQ,OAAO,IAAI,MAAM,uBAAuB,QAAQ,MAAM,GAAG,SAAS,KAAK,MAAM,KAAK,EAAE,GAAG,CAAC;AAAA,MAClG;AACA,QAAE,QAAQ,MAAM;AAChB,WAAK,UAAU,QAAQ,SAAS,IAAI,YAAY,OAAO;AAAA,IACzD,CAAC;AAED,SAAK,UAAU,QAAQ,KAAK,MAAM,EAAE,MAAM,CAAC,QAAQ;AACjD,WAAK,aAAa,QAAQ,eAAgB,IAAc,OAAO;AAAA,CAAI;AACnE,WAAK,UAAU,QAAQ,OAAO;AAAA,IAChC,CAAC;AAED,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,UAAU,QAAgB,KAAa,QAAmC;AACtF,UAAM,aAAa,MAAM,KAAK,QAAQ,QAAQ,cAAc;AAAA,MAC1D,iBAAiB;AAAA,MACjB,YAAY,EAAE,MAAM,SAAS,SAAS,QAAQ;AAAA,MAC9C,oBAAoB,CAAC;AAAA,IACvB,CAAC;AAED,UAAM,kBAAkB,OAAO,YAAY,YAAY,OAAO,YAC1D,MAAM,KAAK,eAAe,QAAQ,OAAO,SAAS,IAClD;AAEJ,UAAM,gBAAgB,kBAClB,EAAE,WAAW,gBAAgB,IAC7B,MAAM,KAAK,QAAQ,QAAQ,eAAe;AAAA,MAC1C;AAAA,IACF,CAAC;AAEH,UAAM,YAAY,KAAK,iBAAiB,aAAa,KAAK,KAAK,iBAAiB,UAAU,KAAK,OAAO;AACtG,QAAI,WAAW;AACb,WAAK,WAAW,QAAQ,EAAE,WAAW,IAAI,CAAC;AAAA,IAC5C,OAAO;AACL,WAAK,WAAW,QAAQ,EAAE,IAAI,CAAC;AAAA,IACjC;AAEA,SAAK,iBAAiB,QAAQ,EAAE,MAAM,UAAU,QAAQ,OAAO,CAAC;AAChE,SAAK,UAAU,QAAQ,MAAM;AAE7B,QAAI,OAAO,QAAQ,OAAO,YAAY,UAAU;AAC9C,YAAM,KAAK,WAAW,QAAQ,OAAO,IAAI;AAAA,IAC3C;AAAA,EACF;AAAA,EAEA,MAAc,eAAe,QAAgB,WAA2C;AACtF,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,QAAQ,QAAQ,gBAAgB,EAAE,UAAU,CAAC;AACvE,aAAO,KAAK,iBAAiB,MAAM,KAAK;AAAA,IAC1C,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,QAAgB,MAA6B;AAC5D,UAAM,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACrC,QAAI,CAAC,MAAO;AAEZ,UAAM,YAAY,MAAM,KAAK,aAAa,MAAM,OAAO;AACvD,UAAM,YAAY,QAAQ,MAAM,eAAe;AAC/C,SAAK,iBAAiB,QAAQ,EAAE,MAAM,WAAW,WAAW,MAAM,QAAQ,KAAK,CAAC;AAChF,SAAK,aAAa,QAAQ;AAAA,IAAO,IAAI;AAAA;AAAA,CAAM;AAC3C,SAAK,UAAU,QAAQ,SAAS;AAChC,SAAK,iBAAiB,QAAQ,EAAE,MAAM,UAAU,QAAQ,UAAU,CAAC;AAEnE,UAAM,SAAkC;AAAA,MACtC,QAAQ,CAAC,EAAE,MAAM,QAAQ,KAAK,CAAC;AAAA,IACjC;AACA,QAAI,UAAW,QAAO,YAAY;AAElC,UAAM,KAAK,QAAQ,QAAQ,kBAAkB,MAAM;AAAA,EAIrD;AAAA,EAEA,OAAO,QAAgB,IAAkC;AACvD,UAAM,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACrC,QAAI,MAAO,OAAM,gBAAgB,KAAK,EAAE;AAAA,EAC1C;AAAA,EAEA,SAAS,QAAgB,IAAwC;AAC/D,UAAM,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACrC,QAAI,MAAO,OAAM,kBAAkB,KAAK,EAAE;AAAA,EAC5C;AAAA,EAEA,OAAO,QAAgB,IAAoC;AACzD,UAAM,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACrC,QAAI,MAAO,OAAM,gBAAgB,KAAK,EAAE;AAAA,EAC1C;AAAA,EAEA,eAAe,QAAgB,IAA8C;AAC3E,UAAM,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACrC,QAAI,MAAO,OAAM,wBAAwB,KAAK,EAAE;AAAA,EAClD;AAAA,EAEA,WAAW,QAAgB,IAA4C;AACrE,UAAM,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACrC,QAAI,MAAO,OAAM,oBAAoB,KAAK,EAAE;AAAA,EAC9C;AAAA,EAEA,MAAM,SAAiB,OAAqB;AAAA,EAE5C;AAAA,EAEA,OAAO,SAAiB,OAAe,OAAqB;AAAA,EAE5D;AAAA,EAEA,cAAc,QAAwB;AACpC,UAAM,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACrC,WAAO,QAAQ,MAAM,WAAW,KAAK,EAAE,IAAI;AAAA,EAC7C;AAAA,EAEA,KAAK,QAAsB;AACzB,UAAM,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACrC,QAAI,CAAC,MAAO;AACZ,UAAM,KAAK,KAAK;AAChB,SAAK,QAAQ,OAAO,MAAM;AAAA,EAC5B;AAAA,EAEA,UAAgB;AACd,eAAW,UAAU,KAAK,QAAQ,KAAK,GAAG;AACxC,WAAK,KAAK,MAAM;AAAA,IAClB;AAAA,EACF;AAAA,EAEQ,aAAa,QAAgB,OAAqB;AACxD,UAAM,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACrC,QAAI,CAAC,MAAO;AAEZ,UAAM,gBAAgB;AACtB,WAAO,MAAM;AACX,YAAM,UAAU,MAAM,aAAa,QAAQ,IAAI;AAC/C,UAAI,YAAY,GAAI;AACpB,YAAM,OAAO,MAAM,aAAa,MAAM,GAAG,OAAO,EAAE,KAAK;AACvD,YAAM,eAAe,MAAM,aAAa,MAAM,UAAU,CAAC;AACzD,UAAI,CAAC,KAAM;AAEX,UAAI;AACF,cAAM,UAAU,KAAK,MAAM,IAAI;AAC/B,aAAK,cAAc,QAAQ,OAAO;AAAA,MACpC,QAAQ;AACN,aAAK,aAAa,QAAQ,OAAO,IAAI;AAAA,MACvC;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,cAAc,QAAgB,SAAwC;AAC5E,UAAM,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACrC,QAAI,CAAC,MAAO;AAEZ,QAAI,OAAO,QAAQ,OAAO,UAAU;AAClC,YAAM,UAAU,MAAM,QAAQ,IAAI,QAAQ,EAAE;AAC5C,UAAI,SAAS;AACX,cAAM,QAAQ,OAAO,QAAQ,EAAE;AAC/B,YAAI,WAAW,WAAW,QAAQ,OAAO;AACvC,gBAAM,MAAM,QAAQ;AACpB,kBAAQ,OAAO,IAAI,MAAM,KAAK,WAAW,oBAAoB,CAAC;AAAA,QAChE,OAAO;AACL,kBAAQ,QAAQ,QAAQ,MAAM;AAAA,QAChC;AAAA,MACF;AACA;AAAA,IACF;AAEA,QAAI,QAAQ,WAAW,kBAAkB;AACvC,YAAM,SAAU,QAAQ,UAAU,CAAC;AACnC,WAAK,oBAAoB,QAAQ,MAAM;AACvC;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,oBAAoB,QAAgB,QAAuC;AACjF,UAAM,YAAY,KAAK,iBAAiB,MAAM;AAC9C,QAAI,WAAW;AACb,WAAK,WAAW,QAAQ,EAAE,UAAU,CAAC;AAAA,IACvC;AAEA,UAAM,YAAY,OAAO,UAAU,OAAO,SAAS,OAAO,SAAS;AACnE,UAAM,UAAU,MAAM,QAAQ,SAAS,IAAI,YAAY,CAAC,SAAS;AAEjE,eAAW,UAAU,SAAS;AAC5B,UAAI,CAAC,UAAU,OAAO,WAAW,SAAU;AAC3C,YAAM,SAAS;AACf,YAAM,OAAO,OAAO,OAAO,QAAQ,OAAO,QAAQ,EAAE;AACpD,YAAM,UAAU,KAAK,YAAY,MAAM;AAEvC,UAAI,KAAK,SAAS,eAAe,GAAG;AAClC,cAAM,YAAY,aAAa,KAAK,QAAQ,IAAI,MAAM,GAAG,iBAAiB,CAAC;AAC3E,aAAK,iBAAiB,QAAQ;AAAA,UAC5B,MAAM;AAAA,UACN;AAAA,UACA,MAAM;AAAA,UACN,MAAM;AAAA,UACN,QAAQ;AAAA,QACV,CAAC;AACD,YAAI,SAAS;AACX,eAAK,aAAa,QAAQ,OAAO;AAAA,QACnC;AACA,aAAK,UAAU,QAAQ,SAAS;AAAA,MAClC,WAAW,KAAK,SAAS,WAAW,GAAG;AACrC,cAAM,aAAa,QAAQ,KAAK,QAAQ,IAAI,MAAM,GAAG,cAAc,CAAC;AACpE,aAAK,iBAAiB,QAAQ;AAAA,UAC5B,MAAM;AAAA,UACN;AAAA,UACA,OAAO,OAAO,OAAO,SAAS,OAAO,QAAQ,MAAM;AAAA,UACnD,QAAQ,KAAK,SAAS,QAAQ,IAAI,gBAAgB;AAAA,UAClD,MAAM,WAAW;AAAA,QACnB,CAAC;AACD,YAAI,SAAS;AACX,eAAK,aAAa,QAAQ;AAAA,SAAY,OAAO;AAAA,CAAI;AAAA,QACnD;AAAA,MACF,WAAW,KAAK,SAAS,MAAM,KAAK,KAAK,SAAS,MAAM,KAAK,KAAK,SAAS,WAAW,GAAG;AACvF,aAAK,UAAU,QAAQ,MAAM;AAC7B,aAAK,iBAAiB,QAAQ,EAAE,MAAM,UAAU,QAAQ,OAAO,CAAC;AAAA,MAClE;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,YAAY,QAAyC;AAC3D,UAAM,SAAS,OAAO,QAAQ,OAAO,SAAS,OAAO;AACrD,QAAI,OAAO,WAAW,SAAU,QAAO;AACvC,QAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,aAAO,OACJ,IAAI,CAAC,SAAS;AACb,YAAI,OAAO,SAAS,SAAU,QAAO;AACrC,YAAI,QAAQ,OAAO,SAAS,YAAY,OAAQ,KAAiC,SAAS,UAAU;AAClG,iBAAO,OAAQ,KAAiC,IAAI;AAAA,QACtD;AACA,eAAO;AAAA,MACT,CAAC,EACA,KAAK,EAAE;AAAA,IACZ;AACA,QAAI,UAAU,OAAO,WAAW,YAAY,OAAQ,OAAmC,SAAS,UAAU;AACxG,aAAO,OAAQ,OAAmC,IAAI;AAAA,IACxD;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,QAAQ,QAAgB,QAAgB,QAAmD;AACjG,UAAM,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACrC,QAAI,CAAC,OAAO;AACV,aAAO,QAAQ,OAAO,IAAI,MAAM,yBAAyB,MAAM,EAAE,CAAC;AAAA,IACpE;AAEA,UAAM,KAAK,MAAM;AACjB,UAAM,UAAU,KAAK,UAAU,EAAE,SAAS,OAAO,IAAI,QAAQ,OAAO,CAAC,IAAI;AACzE,UAAM,KAAK,MAAM,MAAM,OAAO;AAE9B,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,YAAM,QAAQ,IAAI,IAAI,EAAE,SAAS,OAAO,CAAC;AAAA,IAC3C,CAAC;AAAA,EACH;AAAA,EAEQ,iBAAiB,QAAqC;AAC5D,QAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;AAClD,UAAM,SAAS;AACf,QAAI,OAAO,OAAO,cAAc,SAAU,QAAO,OAAO;AACxD,QAAI,OAAO,OAAO,eAAe,SAAU,QAAO,OAAO;AACzD,QAAI,OAAO,WAAW,OAAO,OAAO,YAAY,UAAU;AACxD,YAAM,SAAS,OAAO;AACtB,UAAI,OAAO,OAAO,OAAO,SAAU,QAAO,OAAO;AACjD,UAAI,OAAO,OAAO,cAAc,SAAU,QAAO,OAAO;AAAA,IAC1D;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,aAAa,QAAgB,MAAoB;AACvD,UAAM,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACrC,QAAI,CAAC,SAAS,CAAC,KAAM;AAErB,UAAM,WAAW,KAAK,IAAI;AAC1B,UAAM,mBAAmB,KAAK;AAC9B,QAAI,MAAM,kBAAkBI,uBAAsB;AAChD,UAAI,gBAAgB,MAAM,kBAAkBA;AAC5C,UAAI,cAAc;AAClB,aAAO,cAAc,MAAM,WAAW,SAAS,KAAK,gBAAgB,GAAG;AACrE,yBAAiB,MAAM,WAAW,WAAW,EAAE;AAC/C,cAAM,mBAAmB,MAAM,WAAW,WAAW,EAAE;AACvD;AAAA,MACF;AACA,UAAI,cAAc,EAAG,OAAM,WAAW,OAAO,GAAG,WAAW;AAAA,IAC7D;AAEA,eAAW,MAAM,MAAM,iBAAiB;AACtC,SAAG,IAAI;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,UAAU,QAAgB,QAA0B;AAC1D,UAAM,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACrC,QAAI,CAAC,SAAS,MAAM,WAAW,OAAQ;AACvC,UAAM,SAAS;AACf,eAAW,MAAM,MAAM,mBAAmB;AACxC,SAAG,MAAM;AAAA,IACX;AAAA,EACF;AAAA,EAEQ,WAAW,QAAgB,MAAsB;AACvD,UAAM,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACrC,QAAI,CAAC,MAAO;AACZ,UAAM,OAAO,EAAE,GAAG,MAAM,MAAM,GAAG,KAAK;AACtC,eAAW,MAAM,MAAM,iBAAiB;AACtC,SAAG,MAAM,IAAI;AAAA,IACf;AAAA,EACF;AAAA,EAEQ,iBAAiB,QAAgB,OAAgC;AACvE,UAAM,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACrC,QAAI,CAAC,MAAO;AACZ,eAAW,MAAM,MAAM,yBAAyB;AAC9C,SAAG,KAAK;AAAA,IACV;AAAA,EACF;AACF;;;ACtcA,OAAOC,WAAU;AACjB,OAAOC,SAAQ;AACf,SAAS,iBAAiC;AAQnC,IAAM,kBAAN,MAAsB;AAAA,EACnB;AAAA,EACA;AAAA,EACA,YAAY,oBAAI,IAA2B;AAAA,EAEnD,YAAY,YAAoB;AAC9B,SAAK,aAAa;AAClB,SAAK,MAAM,UAAU,UAAU;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,OAAO,QAAgB,UAAqE;AAChG,UAAM,aAAa,MAAM,KAAK,iBAAiB;AAC/C,UAAM,OAAO,KAAK,QAAQ,QAAQ;AAClC,UAAM,SAAS,SAAS,MAAM,IAAI,IAAI;AACtC,UAAM,eAAeD,MAAK,KAAK,KAAK,YAAY,UAAU,aAAa,MAAM;AAG7E,QAAIC,IAAG,WAAW,YAAY,GAAG;AAC/B,YAAM,KAAK,oBAAoB,YAAY;AAAA,IAC7C;AAGA,QAAI;AACF,YAAM,KAAK,IAAI,IAAI,CAAC,UAAU,MAAM,MAAM,CAAC;AAAA,IAC7C,QAAQ;AAAA,IAER;AAEA,IAAAA,IAAG,UAAUD,MAAK,QAAQ,YAAY,GAAG,EAAE,WAAW,KAAK,CAAC;AAC5D,UAAM,KAAK,IAAI,IAAI,CAAC,YAAY,OAAO,MAAM,QAAQ,cAAc,UAAU,CAAC;AAE9E,UAAM,QAAuB,EAAE,MAAM,cAAc,QAAQ,WAAW;AACtE,SAAK,UAAU,IAAI,QAAQ,KAAK;AAEhC,WAAO,EAAE,cAAc,OAAO;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,QAAQ,QAAgB,QAAgB,cAAwC;AAEpF,UAAM,aAAa,MAAM,KAAK,iBAAiB;AAG/C,QAAI;AACF,YAAM,KAAK,IAAI,IAAI,CAAC,aAAa,YAAY,MAAM,CAAC;AAAA,IACtD,QAAQ;AAEN,aAAO;AAAA,IACT;AAEA,QAAIC,IAAG,WAAW,YAAY,GAAG;AAE/B,WAAK,UAAU,IAAI,QAAQ,EAAE,MAAM,cAAc,QAAQ,WAAW,CAAC;AACrE,aAAO;AAAA,IACT;AAGA,QAAI;AAEF,YAAM,KAAK,IAAI,IAAI,CAAC,YAAY,OAAO,CAAC,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AACxD,MAAAA,IAAG,UAAUD,MAAK,QAAQ,YAAY,GAAG,EAAE,WAAW,KAAK,CAAC;AAC5D,YAAM,KAAK,IAAI,IAAI,CAAC,YAAY,OAAO,cAAc,MAAM,CAAC;AAC5D,WAAK,UAAU,IAAI,QAAQ,EAAE,MAAM,cAAc,QAAQ,WAAW,CAAC;AACrE,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,cAAQ,KAAK,oDAAoD,MAAM,KAAM,IAAc,OAAO;AAClG,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAO,QAA+B;AAC1C,UAAM,QAAQ,KAAK,UAAU,IAAI,MAAM;AACvC,QAAI,CAAC,MAAO;AAEZ,UAAM,KAAK,oBAAoB,MAAM,IAAI;AACzC,SAAK,UAAU,OAAO,MAAM;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAiB,QAA+B;AACpD,UAAM,QAAQ,KAAK,UAAU,IAAI,MAAM;AACvC,QAAI,CAAC,MAAO;AAEZ,UAAM,KAAK,oBAAoB,MAAM,IAAI;AAEzC,QAAI;AACF,YAAM,KAAK,IAAI,IAAI,CAAC,UAAU,MAAM,MAAM,MAAM,CAAC;AAAA,IACnD,QAAQ;AAAA,IAER;AAEA,SAAK,UAAU,OAAO,MAAM;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAS,QAA4E;AACzF,UAAM,QAAQ,KAAK,UAAU,IAAI,MAAM;AACvC,QAAI,CAAC,MAAO,QAAO,CAAC;AAEpB,UAAM,QAAQ,UAAU,MAAM,IAAI;AAClC,UAAM,QAA2D,CAAC;AAElE,QAAI;AAEF,YAAM,SAAS,MAAM,MAAM,OAAO;AAGlC,YAAM,gBAAgB,MAAM,MAAM,KAAK,CAAC,GAAG,MAAM,UAAU,SAAS,CAAC,EAAE,MAAM,MAAM,EAAE;AACrF,YAAM,kBAAkB,MAAM,MAAM,KAAK;AACzC,YAAM,aAAa,MAAM,MAAM,KAAK,CAAC,UAAU,CAAC;AAChD,YAAM,eAAe,CAAC,eAAe,iBAAiB,UAAU,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAG3F,YAAM,WAAW,oBAAI,IAAY;AACjC,YAAM,eAAe,oBAAI,IAAoB;AAG7C,UAAI,eAAe;AACjB,cAAM,SAAS,KAAK,eAAe,aAAa;AAChD,mBAAW,CAAC,IAAI,KAAK,QAAQ;AAC3B,mBAAS,IAAI,IAAI;AACjB,uBAAa,IAAI,MAAM,UAAU;AAAA,QACnC;AAAA,MACF;AAGA,iBAAW,QAAQ,OAAO,SAAS;AACjC,iBAAS,IAAI,IAAI;AACjB,qBAAa,IAAI,MAAM,OAAO;AAAA,MAChC;AACA,iBAAW,QAAQ,OAAO,UAAU;AAClC,iBAAS,IAAI,IAAI;AACjB,YAAI,CAAC,aAAa,IAAI,IAAI,EAAG,cAAa,IAAI,MAAM,UAAU;AAAA,MAChE;AACA,iBAAW,QAAQ,OAAO,SAAS;AACjC,iBAAS,IAAI,IAAI;AACjB,qBAAa,IAAI,MAAM,SAAS;AAAA,MAClC;AACA,iBAAW,QAAQ,OAAO,SAAS;AACjC,iBAAS,IAAI,KAAK,EAAE;AACpB,qBAAa,IAAI,KAAK,IAAI,SAAS;AAAA,MACrC;AACA,iBAAW,QAAQ,OAAO,QAAQ;AAChC,YAAI,CAAC,SAAS,IAAI,IAAI,GAAG;AACvB,mBAAS,IAAI,IAAI;AACjB,uBAAa,IAAI,MAAM,UAAU;AAAA,QACnC;AAAA,MACF;AAGA,YAAM,UAAU,eAAe,KAAK,eAAe,YAAY,IAAI,oBAAI,IAAoB;AAE3F,iBAAW,QAAQ,UAAU;AAC3B,cAAM,KAAK;AAAA,UACT;AAAA,UACA,QAAQ,aAAa,IAAI,IAAI,KAAK;AAAA,UAClC,OAAO,QAAQ,IAAI,IAAI,KAAK;AAAA,QAC9B,CAAC;AAAA,MACH;AAAA,IACF,SAAS,KAAK;AACZ,cAAQ,KAAK,yCAAyC,MAAM,KAAM,IAAc,OAAO;AAAA,IACzF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,MAAM,QAAgE;AAC1E,UAAM,QAAQ,KAAK,UAAU,IAAI,MAAM;AACvC,QAAI,CAAC,OAAO;AACV,aAAO,EAAE,SAAS,OAAO,SAAS,mCAAmC;AAAA,IACvE;AAEA,UAAM,QAAQ,UAAU,MAAM,IAAI;AAElC,QAAI;AAEF,YAAM,SAAS,MAAM,MAAM,OAAO;AAClC,YAAM,aAAa,OAAO,SAAS,SAAS,KAAK,OAAO,QAAQ,SAAS,KACpE,OAAO,QAAQ,SAAS,KAAK,OAAO,OAAO,SAAS,KACpD,OAAO,UAAU,SAAS;AAE/B,UAAI,YAAY;AACd,cAAM,MAAM,IAAI,IAAI;AACpB,cAAM,MAAM,OAAO,oCAAoC,MAAM,MAAM,GAAG;AAAA,MACxE;AAGA,YAAM,MAAM,MAAM,MAAM,IAAI,CAAC,GAAG,MAAM,UAAU,KAAK,MAAM,MAAM,EAAE,CAAC;AACpE,UAAI,IAAI,UAAU,GAAG;AACnB,eAAO,EAAE,SAAS,OAAO,SAAS,sBAAsB;AAAA,MAC1D;AAGA,YAAM,KAAK,IAAI,MAAM,CAAC,MAAM,MAAM,CAAC;AAEnC,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS,UAAU,IAAI,KAAK,UAAU,IAAI,UAAU,IAAI,MAAM,EAAE,SAAS,MAAM,MAAM,SAAS,MAAM,UAAU;AAAA,MAChH;AAAA,IACF,SAAS,KAAK;AAEZ,UAAI;AACF,cAAM,KAAK,IAAI,MAAM,CAAC,SAAS,CAAC;AAAA,MAClC,QAAQ;AAAA,MAER;AACA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS,mBAAoB,IAAc,OAAO;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAQ,QAAgE;AAC5E,UAAM,QAAQ,KAAK,UAAU,IAAI,MAAM;AACvC,QAAI,CAAC,OAAO;AACV,aAAO,EAAE,SAAS,OAAO,SAAS,mCAAmC;AAAA,IACvE;AAEA,UAAM,SAAS,MAAM;AACrB,UAAM,KAAK,oBAAoB,MAAM,IAAI;AAEzC,QAAI;AACF,YAAM,KAAK,IAAI,IAAI,CAAC,UAAU,MAAM,MAAM,CAAC;AAAA,IAC7C,QAAQ;AAAA,IAER;AAEA,SAAK,UAAU,OAAO,MAAM;AAC5B,WAAO,EAAE,SAAS,MAAM,SAAS,oBAAoB,MAAM,GAAG;AAAA,EAChE;AAAA,EAEA,gBAAgB,QAAoC;AAClD,WAAO,KAAK,UAAU,IAAI,MAAM,GAAG;AAAA,EACrC;AAAA,EAEA,UAAU,QAAoC;AAC5C,WAAO,KAAK,UAAU,IAAI,MAAM,GAAG;AAAA,EACrC;AAAA,EAEA,cAAc,QAAoC;AAChD,WAAO,KAAK,UAAU,IAAI,MAAM,GAAG;AAAA,EACrC;AAAA,EAEA,IAAI,QAAyB;AAC3B,WAAO,KAAK,UAAU,IAAI,MAAM;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAA2B;AAC/B,eAAW,CAAC,MAAM,KAAK,KAAK,WAAW;AACrC,YAAM,KAAK,OAAO,MAAM;AAAA,IAC1B;AAAA,EACF;AAAA,EAEA,MAAc,mBAAoC;AAChD,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,IAAI,SAAS,CAAC,gBAAgB,MAAM,CAAC;AAC/D,aAAO,OAAO,KAAK,KAAK;AAAA,IAC1B,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,QAAQ,MAAsB;AACpC,WAAO,KACJ,YAAY,EACZ,QAAQ,4BAA4B,GAAG,EACvC,QAAQ,UAAU,EAAE,EACpB,MAAM,GAAG,EAAE;AAAA,EAChB;AAAA,EAEA,MAAc,oBAAoB,QAA+B;AAC/D,QAAI;AACF,YAAM,KAAK,IAAI,IAAI,CAAC,YAAY,UAAU,WAAW,MAAM,CAAC;AAAA,IAC9D,QAAQ;AAEN,UAAI;AACF,QAAAC,IAAG,OAAO,QAAQ,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAClD,cAAM,KAAK,IAAI,IAAI,CAAC,YAAY,OAAO,CAAC;AAAA,MAC1C,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,eAAe,UAAuC;AAC5D,UAAM,SAAS,oBAAI,IAAoB;AACvC,UAAM,eAAe,SAAS,MAAM,eAAe,EAAE,OAAO,OAAO;AAEnE,eAAW,WAAW,cAAc;AAClC,YAAM,cAAc,QAAQ,MAAM,mBAAmB;AACrD,UAAI,CAAC,YAAa;AAClB,YAAM,WAAW,YAAY,CAAC;AAC9B,aAAO,IAAI,UAAU,cAAc,OAAO,EAAE;AAAA,IAC9C;AAEA,WAAO;AAAA,EACT;AACF;;;AC9UA,OAAOC,WAAU;AACjB,SAAS,aAAAC,kBAAiC;AAC1C,SAAS,aAA6B;AAQ/B,IAAM,aAAN,MAAiB;AAAA,EACd;AAAA,EACA;AAAA,EACA,aAA+B;AAAA,EAC/B,cAAgC;AAAA,EAChC,gBAAsD;AAAA,EACtD,oBAA0D;AAAA,EAC1D,YAAY,oBAAI,IAAqC;AAAA,EACrD,gBAA+B,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,EAAE;AAAA,EAElE,YAAY,YAAoB;AAC9B,SAAK,aAAa;AAClB,SAAK,MAAMA,WAAU,UAAU;AAAA,EACjC;AAAA,EAEA,MAAM,QAAuB;AAC3B,UAAM,SAAS,MAAM,KAAK,IAAI,YAAY;AAC1C,QAAI,CAAC,OAAQ;AAEb,UAAM,KAAK,QAAQ;AAEnB,UAAM,kBAAkB,MAAM;AAC5B,UAAI,KAAK,cAAe,cAAa,KAAK,aAAa;AACvD,WAAK,gBAAgB,WAAW,MAAM;AACpC,aAAK,QAAQ;AAAA,MACf,GAAG,GAAI;AAAA,IACT;AAEA,UAAM,SAASD,MAAK,KAAK,KAAK,YAAY,MAAM;AAChD,SAAK,aAAa,MAAM;AAAA,MACtBA,MAAK,KAAK,QAAQ,OAAO;AAAA,MACzBA,MAAK,KAAK,QAAQ,MAAM;AAAA,MACxBA,MAAK,KAAK,QAAQ,MAAM;AAAA,IAC1B,GAAG;AAAA,MACD,YAAY;AAAA,MACZ,eAAe;AAAA,IACjB,CAAC;AACD,SAAK,WAAW,GAAG,OAAO,eAAe;AAIzC,UAAM,sBAAsB,MAAM;AAChC,UAAI,KAAK,kBAAmB,cAAa,KAAK,iBAAiB;AAC/D,WAAK,oBAAoB,WAAW,MAAM;AACxC,aAAK,QAAQ;AAAA,MACf,GAAG,GAAI;AAAA,IACT;AAEA,SAAK,cAAc,MAAM,KAAK,YAAY;AAAA,MACxC,SAAS,CAAC,aAAqB;AAC7B,cAAM,WAAWA,MAAK,SAAS,QAAQ;AACvC,eAAO,aAAa,UAAU,aAAa,kBAAkB,aAAa,YAAY,aAAa;AAAA,MACrG;AAAA,MACA,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,OAAO;AAAA,IACT,CAAC;AACD,SAAK,YAAY,GAAG,OAAO,mBAAmB;AAAA,EAChD;AAAA,EAEA,MAAM,UAAyB;AAC7B,QAAI;AACF,YAAM,SAAS,MAAM,QAAQ,KAAK;AAAA,QAChC,KAAK,SAAS;AAAA,QACd,IAAI;AAAA,UAAe,CAAC,GAAG,WACrB,WAAW,MAAM,OAAO,IAAI,MAAM,kBAAkB,CAAC,GAAG,IAAK;AAAA,QAC/D;AAAA,MACF,CAAC;AACD,WAAK,gBAAgB;AACrB,WAAK,gBAAgB;AAAA,IACvB,SAAS,KAAK;AACZ,UAAK,IAAc,YAAY,oBAAoB;AACjD,gBAAQ,KAAK,4DAA4D;AAAA,MAC3E;AAAA,IAEF;AAAA,EACF;AAAA,EAEA,kBAAiC;AAC/B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,aAAa,UAAuD;AAClE,SAAK,UAAU,IAAI,QAAQ;AAC3B,WAAO,MAAM,KAAK,UAAU,OAAO,QAAQ;AAAA,EAC7C;AAAA;AAAA,EAIA,MAAM,WAAW,MAA6B;AAC5C,UAAM,KAAK,IAAI,IAAI,IAAI;AACvB,UAAM,KAAK,QAAQ;AAAA,EACrB;AAAA,EAEA,MAAM,YAA2B;AAC/B,UAAM,KAAK,IAAI,IAAI,IAAI;AACvB,UAAM,KAAK,QAAQ;AAAA,EACrB;AAAA,EAEA,MAAM,YAAY,MAA6B;AAC7C,UAAM,KAAK,IAAI,MAAM,CAAC,QAAQ,MAAM,IAAI,CAAC;AACzC,UAAM,KAAK,QAAQ;AAAA,EACrB;AAAA,EAEA,MAAM,aAA4B;AAChC,UAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC;AAC7B,UAAM,KAAK,QAAQ;AAAA,EACrB;AAAA;AAAA,EAIA,MAAM,YAAY,MAA6B;AAC7C,UAAM,SAAS,MAAM,KAAK,IAAI,OAAO;AACrC,UAAM,cAAc,OAAO,UAAU,SAAS,IAAI,KAAK,OAAO,QAAQ,SAAS,IAAI;AAEnF,QAAI,aAAa;AACf,YAAM,WAAWA,MAAK,KAAK,KAAK,YAAY,IAAI;AAChD,YAAME,OAAK,MAAM,OAAO,IAAS;AACjC,UAAIA,KAAG,WAAW,QAAQ,GAAG;AAC3B,QAAAA,KAAG,WAAW,QAAQ;AAAA,MACxB;AAAA,IACF,OAAO;AACL,YAAM,KAAK,IAAI,SAAS,CAAC,MAAM,IAAI,CAAC;AACpC,UAAI;AACF,cAAM,KAAK,IAAI,MAAM,CAAC,QAAQ,MAAM,IAAI,CAAC;AAAA,MAC3C,QAAQ;AAAA,MAER;AAAA,IACF;AACA,UAAM,KAAK,QAAQ;AAAA,EACrB;AAAA,EAEA,MAAM,aAA4B;AAChC,UAAM,KAAK,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC;AACnC,UAAM,KAAK,IAAI,MAAM,KAAK,CAAC,IAAI,CAAC;AAChC,UAAM,KAAK,QAAQ;AAAA,EACrB;AAAA;AAAA,EAIA,MAAM,OAAO,SAAkC;AAC7C,UAAM,SAAS,MAAM,KAAK,IAAI,OAAO,OAAO;AAC5C,UAAM,KAAK,QAAQ;AACnB,UAAM,UAAU,OAAO;AACvB,WAAO,GAAG,QAAQ,OAAO,QAAQ,QAAQ,YAAY,IAAI,MAAM,EAAE,MAAM,QAAQ,UAAU,KAAK,QAAQ,SAAS;AAAA,EACjH;AAAA,EAEA,MAAM,OAAwB;AAC5B,UAAM,KAAK,IAAI,KAAK;AACpB,UAAM,KAAK,QAAQ;AACnB,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,gBAA6F;AACjG,UAAM,SAAS,MAAM,KAAK,IAAI,OAAO;AACrC,WAAO;AAAA,MACL,QAAQ,OAAO,WAAW;AAAA,MAC1B,QAAQ,OAAO,YAAY;AAAA,MAC3B,OAAO,OAAO;AAAA,MACd,QAAQ,OAAO;AAAA,IACjB;AAAA,EACF;AAAA;AAAA,EAIA,QAAc;AACZ,QAAI,KAAK,cAAe,cAAa,KAAK,aAAa;AACvD,QAAI,KAAK,kBAAmB,cAAa,KAAK,iBAAiB;AAC/D,SAAK,YAAY,MAAM;AACvB,SAAK,aAAa;AAClB,SAAK,aAAa,MAAM;AACxB,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA,EAIA,MAAc,WAAmC;AAC/C,UAAM,SAAS,MAAM,KAAK,IAAI,OAAO;AACrC,UAAM,WAAuB,CAAC;AAC9B,UAAM,SAAqB,CAAC;AAG5B,UAAM,CAAC,kBAAkB,cAAc,IAAI,MAAM,QAAQ,IAAI;AAAA,MAC3D,KAAK,IAAI,KAAK;AAAA,MACd,KAAK,IAAI,KAAK,CAAC,UAAU,CAAC;AAAA,IAC5B,CAAC;AAED,UAAM,gBAAgB,KAAK,eAAe,gBAAgB;AAC1D,UAAM,cAAc,KAAK,eAAe,cAAc;AAEtD,UAAM,cAAc,IAAI,IAAY,OAAO,MAAM;AAGjD,eAAW,QAAQ,OAAO,WAAW;AACnC,eAAS,KAAK,EAAE,MAAM,QAAQ,SAAS,OAAO,GAAG,CAAC;AAAA,IACpD;AACA,eAAW,QAAQ,OAAO,SAAS;AACjC,UAAI,CAAC,YAAY,IAAI,IAAI,GAAG;AAC1B,iBAAS,KAAK,EAAE,MAAM,QAAQ,SAAS,OAAO,GAAG,CAAC;AAAA,MACpD;AAAA,IACF;AACA,eAAW,QAAQ,OAAO,SAAS;AACjC,UAAI,CAAC,YAAY,IAAI,IAAI,GAAG;AAC1B,iBAAS,KAAK,EAAE,MAAM,QAAQ,WAAW,OAAO,GAAG,CAAC;AAAA,MACtD;AAAA,IACF;AACA,eAAW,QAAQ,OAAO,UAAU;AAClC,eAAS,KAAK,EAAE,MAAM,QAAQ,YAAY,OAAO,cAAc,IAAI,IAAI,KAAK,GAAG,CAAC;AAAA,IAClF;AACA,eAAW,QAAQ,OAAO,SAAS;AACjC,UAAI,CAAC,YAAY,IAAI,KAAK,EAAE,GAAG;AAC7B,iBAAS,KAAK,EAAE,MAAM,KAAK,IAAI,QAAQ,WAAW,OAAO,GAAG,CAAC;AAAA,MAC/D;AAAA,IACF;AAGA,eAAW,QAAQ,UAAU;AAC3B,UAAI,CAAC,KAAK,SAAS,cAAc,IAAI,KAAK,IAAI,GAAG;AAC/C,aAAK,QAAQ,cAAc,IAAI,KAAK,IAAI;AAAA,MAC1C;AAAA,IACF;AAGA,eAAW,QAAQ,UAAU;AAC3B,UAAI,KAAK,WAAW,WAAW,CAAC,KAAK,OAAO;AAC1C,YAAI;AACF,gBAAM,UAAU,MAAM,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC,EAAE,MAAM,MAAM,IAAI;AACvE,cAAI,SAAS;AACX,iBAAK,QAAQ;AAAA,QAAwB,KAAK,IAAI;AAAA;AAAA,GAAqB,OAAO;AAAA,UAC5E;AAAA,QACF,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF;AAIA,eAAW,cAAc,OAAO,OAAO;AACrC,YAAM,cAAc,WAAW;AAC/B,UAAI,CAAC,eAAe,gBAAgB,OAAO,gBAAgB,IAAK;AAEhE,YAAM,OAAO,WAAW;AACxB,UAAI,aAAiC;AACrC,UAAI,gBAAgB,IAAK,cAAa;AAAA,eAC7B,gBAAgB,IAAK,cAAa;AAAA,eAClC,gBAAgB,IAAK,cAAa;AAE3C,aAAO,KAAK;AAAA,QACV;AAAA,QACA,QAAQ;AAAA,QACR,OAAO,YAAY,IAAI,IAAI,KAAK;AAAA,MAClC,CAAC;AAAA,IACH;AAEA,WAAO,EAAE,UAAU,OAAO;AAAA,EAC5B;AAAA,EAEQ,eAAe,UAAuC;AAC5D,UAAM,SAAS,oBAAI,IAAoB;AACvC,QAAI,CAAC,SAAU,QAAO;AACtB,UAAM,eAAe,SAAS,MAAM,eAAe,EAAE,OAAO,OAAO;AAEnE,eAAW,WAAW,cAAc;AAClC,YAAM,cAAc,QAAQ,MAAM,mBAAmB;AACrD,UAAI,CAAC,YAAa;AAClB,YAAM,WAAW,YAAY,CAAC;AAC9B,aAAO,IAAI,UAAU,cAAc,OAAO,EAAE;AAAA,IAC9C;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,kBAAwB;AAC9B,eAAW,YAAY,KAAK,WAAW;AACrC,eAAS,KAAK,aAAa;AAAA,IAC7B;AAAA,EACF;AACF;;;AC3QA,IAAI,cAAc;AAElB,SAAS,aAAqB;AAC5B,SAAO,QAAQ,EAAE,WAAW;AAC9B;AAkBO,IAAM,mBAAN,MAAuB;AAAA,EACpB,QAAQ,oBAAI,IAAuB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,qBAAqB,oBAAI,IAAwB;AAAA,EACjD,SAAS;AAAA,EACT,gBAAgB;AAAA;AAAA,EAGhB,kBAAiC,QAAQ,QAAQ;AAAA;AAAA,EAGjD,YAAwE;AAAA,IAC9E,aAAa,oBAAI,IAAI;AAAA,IACrB,eAAe,oBAAI,IAAI;AAAA,IACvB,qBAAqB,oBAAI,IAAI;AAAA,IAC7B,cAAc,oBAAI,IAAI;AAAA,IACtB,YAAY,oBAAI,IAAI;AAAA,IACpB,gBAAgB,oBAAI,IAAI;AAAA,IACxB,gBAAgB,oBAAI,IAAI;AAAA,IACxB,gBAAgB,oBAAI,IAAI;AAAA,IACxB,YAAY,oBAAI,IAAI;AAAA,IACpB,WAAW,oBAAI,IAAI;AAAA,IACnB,YAAY,oBAAI,IAAI;AAAA,EACtB;AAAA,EAEA,YAAY,eAA8B;AACxC,SAAK,gBAAgB;AACrB,SAAK,aAAa,IAAI,WAAW,aAAa;AAC9C,SAAK,aAAa,IAAI,WAAW,aAAa;AAC9C,SAAK,kBAAkB,IAAI,gBAAgB,cAAc,cAAc,CAAC;AAAA,EAC1E;AAAA,EAEA,MAAM,OAAsB;AAC1B,UAAM,WAAW,KAAK,cAAc,cAAc;AAClD,SAAK,SAAS,SAAS;AACvB,SAAK,gBAAgB,SAAS,eAAe;AAC7C,QAAI,CAAC,MAAM,QAAQ,SAAS,KAAK,EAAG,UAAS,QAAQ,CAAC;AAGtD,eAAW,KAAK,SAAS,OAAO;AAC9B,YAAM,QAAQ,EAAE,GAAG,MAAM,cAAc;AACvC,UAAI,OAAO;AACT,cAAM,MAAM,SAAS,MAAM,CAAC,GAAG,EAAE;AACjC,YAAI,OAAO,YAAa,eAAc;AAAA,MACxC;AAAA,IACF;AAIA,QAAI,YAAY;AAChB,eAAW,cAAc,SAAS,OAAO;AACvC,UAAI,WAAW,aAAa,WAAW,UAAU,aAAa;AAC5D,mBAAW,UAAU;AAAA,MACvB;AAGA,UAAI,WAAW,cAAc,cAAc,WAAW,UAAU,WAAW,cAAc;AACvF,YAAI;AACF,gBAAM,WAAW,MAAM,KAAK,gBAAgB,QAAQ,WAAW,IAAI,WAAW,QAAQ,WAAW,YAAY;AAC7G,cAAI,CAAC,UAAU;AACb,oBAAQ,KAAK,0BAA0B,WAAW,EAAE,KAAK,WAAW,IAAI,4BAA4B;AACpG;AACA;AAAA,UACF;AAAA,QACF,SAAS,KAAK;AACZ,kBAAQ,KAAK,0BAA0B,WAAW,EAAE,KAAK,WAAW,IAAI,sBAAuB,IAAc,OAAO;AACpH;AACA;AAAA,QACF;AAAA,MACF;AAEA,UAAI;AACF,aAAK,UAAU,UAAU;AAGzB,YAAI,WAAW,cAAc,cAAc,WAAW,cAAc;AAClE,gBAAM,KAAK,oBAAoB,WAAW,IAAI,WAAW,YAAY;AAAA,QACvE;AAAA,MACF,SAAS,KAAK;AACZ,gBAAQ,KAAK,uBAAuB,WAAW,EAAE,KAAK,WAAW,IAAI,MAAO,IAAc,OAAO;AACjG;AAAA,MACF;AAAA,IACF;AAEA,QAAI,YAAY,GAAG;AACjB,eAAS,QAAQ,SAAS,MAAM,OAAO,CAAC,MAAM,KAAK,MAAM,IAAI,EAAE,EAAE,CAAC;AAClE,WAAK,cAAc,oBAAoB,QAAQ;AAAA,IACjD;AAAA,EACF;AAAA,EAEA,WAA2B;AACzB,WAAO;AAAA,MACL,MAAM,KAAK;AAAA,MACX,aAAa,KAAK;AAAA,MAClB,YAAY,KAAK,cAAc,cAAc;AAAA,MAC7C,OAAO,MAAM,KAAK,KAAK,MAAM,OAAO,CAAC;AAAA,IACvC;AAAA,EACF;AAAA,EAEA,WAAwB;AACtB,WAAO,MAAM,KAAK,KAAK,MAAM,OAAO,CAAC;AAAA,EACvC;AAAA,EAEA,MAAM,WAAW,cAAoD;AACnE,UAAM,UAAU,aAAa,UAAU;AACvC,UAAM,KAAK,UAAU,cAAc,WAAW;AAC9C,UAAM,YAAY,aAAa,aAAa;AAG5C,UAAM,EAAE,MAAM,MAAM,GAAG,KAAK,IAAI;AAEhC,UAAM,SAAqB;AAAA,MACzB;AAAA,MACA,GAAG;AAAA,MACH,MAAM,KAAK,QAAQ;AAAA,MACnB;AAAA,MACA,WAAW,KAAK;AAAA,IAClB;AAGA,QAAI,cAAc,cAAc,CAAC,SAAS;AACxC,UAAI;AACF,cAAM,EAAE,cAAc,OAAO,IAAI,MAAM,KAAK,gBAAgB,OAAO,IAAI,aAAa,IAAI;AACxF,eAAO,eAAe;AACtB,eAAO,SAAS;AAAA,MAClB,SAAS,KAAK;AACZ,gBAAQ,MAAM,sCAAsC,EAAE,KAAK,GAAG;AAC9D,cAAM;AAAA,MACR;AAAA,IACF;AAEA,QAAI;AACF,YAAM,OAAO,KAAK,UAAU,QAAQ,MAAM,IAAI;AAG9C,UAAI,cAAc,cAAc,OAAO,cAAc;AACnD,cAAM,KAAK,oBAAoB,IAAI,OAAO,YAAY;AAAA,MACxD;AAGA,UAAI,CAAC,SAAS;AACZ,aAAK,kBAAkB,MAAM;AAAA,MAC/B;AACA,aAAO;AAAA,IACT,SAAS,KAAK;AAEZ,UAAI,cAAc,YAAY;AAC5B,cAAM,KAAK,gBAAgB,iBAAiB,EAAE;AAAA,MAChD;AACA,cAAQ,MAAM,yBAAyB,EAAE,KAAK,GAAG;AACjD,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,UAAU,QAA+B;AAC7C,UAAM,OAAO,KAAK,MAAM,IAAI,MAAM;AAClC,QAAI,MAAM,YAAY,OAAO;AAC3B,WAAK,WAAW,KAAK,MAAM;AAAA,IAC7B,OAAO;AACL,WAAK,WAAW,KAAK,MAAM;AAAA,IAC7B;AAGA,QAAI,MAAM,cAAc,YAAY;AAClC,WAAK,mBAAmB,MAAM;AAC9B,YAAM,KAAK,gBAAgB,OAAO,MAAM;AAAA,IAC1C;AAEA,SAAK,MAAM,OAAO,MAAM;AACxB,SAAK,KAAK,iBAAiB,MAAM;AACjC,SAAK,qBAAqB,MAAM;AAAA,EAClC;AAAA,EAEA,YAAY,QAAgB,MAAmB,WAA0B;AACvE,UAAM,gBAAgB,KAAK,MAAM,IAAI,MAAM;AAC3C,QAAI,CAAC,cAAe;AAEpB,QAAI,cAAc,YAAY,OAAO;AACnC,WAAK,WAAW,KAAK,MAAM;AAAA,IAC7B,OAAO;AACL,WAAK,WAAW,KAAK,MAAM;AAAA,IAC7B;AAGA,UAAM,oBAAoB,SAAS,WAC9B,aAAa,cAAc,aAAa,cAAc,KAAK,YAC5D;AAEJ,UAAM,SAAqB;AAAA,MACzB,IAAI;AAAA,MACJ,MAAM,cAAc;AAAA,MACpB,OAAO,cAAc;AAAA,MACrB,SAAS,cAAc;AAAA,MACvB,MAAM,cAAc;AAAA,MACpB,SAAS;AAAA,MACT,WAAW,cAAc;AAAA,MACzB,MAAM,cAAc,QAAQ;AAAA,MAC5B,cAAc,cAAc;AAAA,MAC5B,QAAQ,cAAc;AAAA,MACtB,WAAW;AAAA,IACb;AAEA,SAAK,UAAU,MAAM;AACrB,SAAK,0BAA0B,QAAQ,iBAAiB;AAAA,EAC1D;AAAA,EAEA,MAAM,cAAc,QAAgE;AAClF,UAAM,OAAO,KAAK,MAAM,IAAI,MAAM;AAClC,QAAI,CAAC,QAAQ,KAAK,cAAc,YAAY;AAC1C,aAAO,EAAE,SAAS,OAAO,SAAS,8BAA8B;AAAA,IAClE;AACA,WAAO,KAAK,gBAAgB,MAAM,MAAM;AAAA,EAC1C;AAAA,EAEA,MAAM,gBAAgB,QAAgE;AACpF,UAAM,OAAO,KAAK,MAAM,IAAI,MAAM;AAClC,QAAI,CAAC,QAAQ,KAAK,cAAc,YAAY;AAC1C,aAAO,EAAE,SAAS,OAAO,SAAS,8BAA8B;AAAA,IAClE;AAGA,SAAK,mBAAmB,MAAM;AAG9B,UAAM,SAAS,MAAM,KAAK,gBAAgB,QAAQ,MAAM;AAExD,QAAI,OAAO,SAAS;AAElB,WAAK,YAAY;AACjB,WAAK,eAAe;AACpB,WAAK,SAAS;AAEd,WAAK,KAAK,cAAc,QAAQ,CAAC,CAAC;AAAA,IACpC;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,YAAY,QAAgB,MAAoB;AAC9C,UAAM,OAAO,KAAK,MAAM,IAAI,MAAM;AAClC,QAAI,CAAC,KAAM;AACX,QAAI,KAAK,YAAY,OAAO;AAC1B,WAAK,WAAW,MAAM,QAAQ,IAAI;AAClC;AAAA,IACF;AACA,SAAK,WAAW,MAAM,QAAQ,IAAI;AAAA,EACpC;AAAA,EAEA,uBAAuB,QAAgB,MAA6B;AAClE,UAAM,OAAO,KAAK,MAAM,IAAI,MAAM;AAClC,QAAI,CAAC,KAAM,QAAO,QAAQ,QAAQ;AAClC,QAAI,KAAK,YAAY,OAAO;AAC1B,aAAO,KAAK,WAAW,WAAW,QAAQ,IAAI;AAAA,IAChD;AACA,SAAK,WAAW,MAAM,QAAQ,OAAO,IAAI;AACzC,WAAO,QAAQ,QAAQ;AAAA,EACzB;AAAA,EAEA,WAAW,QAAgB,MAAc,MAAoB;AAC3D,UAAM,OAAO,KAAK,MAAM,IAAI,MAAM;AAClC,QAAI,CAAC,KAAM;AACX,QAAI,KAAK,YAAY,OAAO;AAC1B,WAAK,WAAW,OAAO,QAAQ,MAAM,IAAI;AACzC;AAAA,IACF;AACA,SAAK,WAAW,OAAO,QAAQ,MAAM,IAAI;AAAA,EAC3C;AAAA,EAEA,cAAc,QAAwB;AACpC,UAAM,OAAO,KAAK,MAAM,IAAI,MAAM;AAClC,QAAI,CAAC,KAAM,QAAO;AAClB,WAAO,KAAK,YAAY,QACpB,KAAK,WAAW,cAAc,MAAM,IACpC,KAAK,WAAW,cAAc,MAAM;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,SAAS,UAAqC;AAC5C,UAAM,WAA8B,CAAC;AAErC,eAAW,OAAO,OAAO,KAAK,QAAQ,GAAoB;AACxD,YAAM,UAAU,SAAS,GAAG;AAC5B,UAAI,SAAS;AACX,cAAM,MAAM,KAAK,UAAU,GAAG;AAC9B,YAAI,IAAI,OAAO;AACf,iBAAS,KAAK,MAAM,IAAI,OAAO,OAAO,CAAC;AAAA,MACzC;AAAA,IACF;AAEA,WAAO,MAAM;AACX,iBAAW,WAAW,UAAU;AAC9B,gBAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,aAAa,MAAwB;AACnC,SAAK,KAAK,cAAc,IAAI;AAAA,EAC9B;AAAA,EAEA,YAAY,QAA6B;AACvC,SAAK,KAAK,aAAa,MAAM;AAAA,EAC/B;AAAA,EAEA,iBAAiB,UAA8B;AAC7C,SAAK,KAAK,kBAAkB,QAAQ;AAAA,EACtC;AAAA,EAEA,MAAM,gBAAgB,QAA+B;AACnD,UAAM,aAAa,KAAK,mBAAmB,IAAI,MAAM;AACrD,QAAI,YAAY;AACd,YAAM,WAAW,QAAQ;AAAA,IAC3B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,eAAwC;AACtC,UAAM,SAAS,oBAAI,IAAwB;AAC3C,eAAW,CAAC,QAAQ,UAAU,KAAK,KAAK,oBAAoB;AAC1D,aAAO,IAAI,QAAQ,WAAW,gBAAgB,EAAE,QAAQ;AAAA,IAC1D;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAIQ,KAA4B,QAAW,MAAuD;AACpG,UAAM,MAAM,KAAK,UAAU,GAAG;AAC9B,eAAW,YAAY,KAAK;AAC1B,eAAS,GAAG,IAAI;AAAA,IAClB;AAAA,EACF;AAAA,EAEQ,UAAU,QAAoB,MAAe,MAA0B;AAC7E,UAAM,UAAU,KAAK,eAAe,OAAO,KAAK;AAChD,UAAM,MAAM,YAAY,QACpB,KAAK,WAAW,MAAM,OAAO,IAAI,MAAM,IACvC,KAAK,WAAW,MAAM,OAAO,IAAI,QAAQ,QAAQ,IAAI,QAAQ,EAAE;AAEnE,UAAM,OAAkB;AAAA,MACtB,IAAI,OAAO;AAAA,MACX,MAAM,OAAO;AAAA,MACb,OAAO,OAAO;AAAA,MACd,SAAS,OAAO;AAAA,MAChB,MAAM,OAAO;AAAA,MACb,SAAS,OAAO;AAAA,MAChB,WAAW,OAAO,aAAa;AAAA,MAC/B,MAAM,OAAO,QAAQ;AAAA,MACrB,QAAQ,OAAO;AAAA,MACf,cAAc,OAAO;AAAA,MACrB,WAAW,OAAO;AAAA,MAClB;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,MACA,MAAM,CAAC;AAAA,MACP,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC;AAEA,SAAK,MAAM,IAAI,OAAO,IAAI,IAAI;AAC9B,SAAK,KAAK,eAAe,IAAI;AAE7B,UAAM,iBAAiB,YAAY,QAAQ,KAAK,aAAa,KAAK;AAElE,mBAAe,OAAO,OAAO,IAAI,CAAC,SAAS;AACzC,WAAK,KAAK,kBAAkB,OAAO,IAAI,IAAI;AAAA,IAC7C,CAAC;AAED,mBAAe,SAAS,OAAO,IAAI,CAAC,WAAW;AAC7C,YAAM,IAAI,KAAK,MAAM,IAAI,OAAO,EAAE;AAClC,UAAI,GAAG;AACL,UAAE,SAAS;AACX,aAAK,KAAK,gBAAgB,OAAO,IAAI,MAAM;AAAA,MAC7C;AAAA,IACF,CAAC;AAED,mBAAe,OAAO,OAAO,IAAI,CAAC,SAAS;AACzC,YAAM,IAAI,KAAK,MAAM,IAAI,OAAO,EAAE;AAClC,UAAI,GAAG;AACL,UAAE,OAAO;AAET,YAAI,KAAK,aAAa,KAAK,cAAc,EAAE,WAAW;AACpD,YAAE,YAAY,KAAK;AACnB,eAAK,0BAA0B,OAAO,IAAI,KAAK,SAAS;AAAA,QAC1D;AACA,aAAK,KAAK,cAAc,OAAO,IAAI,IAAI;AAAA,MACzC;AAAA,IACF,CAAC;AAED,mBAAe,WAAW,OAAO,IAAI,CAAC,aAAa;AACjD,WAAK,KAAK,kBAAkB,OAAO,IAAI,QAAQ;AAAA,IACjD,CAAC;AAED,QAAI,YAAY,OAAO;AACrB,WAAK,WAAW,eAAe,OAAO,IAAI,CAAC,UAAU;AACnD,aAAK,KAAK,uBAAuB,OAAO,IAAI,KAAK;AAAA,MACnD,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,eAAe,WAAqD;AAC1E,QAAI,cAAc,YAAa,QAAO;AACtC,UAAM,MAAM,KAAK,cAAc,mBAAmB,SAAS;AAC3D,WAAO,KAAK,aAAa;AAAA,EAC3B;AAAA,EAEA,MAAc,oBAAoB,QAAgB,cAAqC;AACrF,UAAM,aAAa,IAAI,WAAW,YAAY;AAC9C,eAAW,aAAa,CAAC,WAAW;AAElC,YAAM,SAAS,OAAO,SAAS,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,EAAE;AAC5D,WAAK,KAAK,cAAc,QAAQ,MAAM;AAAA,IACxC,CAAC;AACD,UAAM,WAAW,MAAM;AACvB,SAAK,mBAAmB,IAAI,QAAQ,UAAU;AAAA,EAChD;AAAA,EAEQ,mBAAmB,QAAsB;AAC/C,UAAM,aAAa,KAAK,mBAAmB,IAAI,MAAM;AACrD,QAAI,YAAY;AACd,iBAAW,MAAM;AACjB,WAAK,mBAAmB,OAAO,MAAM;AAAA,IACvC;AAAA,EACF;AAAA,EAEQ,kBAAkB,QAA0B;AAClD,SAAK,sBAAsB,MAAM;AAC/B,YAAM,WAAW,KAAK,cAAc,oBAAoB;AACxD,UAAI,UAAU;AACZ,iBAAS,MAAM,KAAK,MAAM;AAC1B,aAAK,cAAc,oBAAoB,QAAQ;AAAA,MACjD;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEQ,0BAA0B,QAAgB,WAA0B;AAC1E,SAAK,sBAAsB,MAAM;AAC/B,YAAM,WAAW,KAAK,cAAc,oBAAoB;AACxD,UAAI,UAAU;AACZ,cAAM,aAAa,SAAS,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM;AAC7D,YAAI,YAAY;AACd,qBAAW,YAAY;AACvB,eAAK,cAAc,oBAAoB,QAAQ;AAAA,QACjD;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,eAAe,QAAgC;AAC7C,UAAM,WAA0B,CAAC;AACjC,eAAW,QAAQ,KAAK,MAAM,OAAO,GAAG;AACtC,UAAI,KAAK,UAAU,YAAa;AAChC,UAAI,UAAU,KAAK,OAAO,OAAQ;AAClC,UAAI,KAAK,KAAK,aAAa,KAAK,WAAW;AACzC,iBAAS,KAAK;AAAA,UACZ,WAAY,KAAK,KAAK,aAAa,KAAK;AAAA,UACxC,QAAQ,KAAK;AAAA,UACb,UAAU,KAAK;AAAA,UACf,OAAO,KAAK;AAAA,UACZ,WAAW,KAAK,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,UACpD,SAAS,KAAK,KAAK;AAAA,UACnB,gBAAgB,KAAK,KAAK;AAAA,UAC1B,OAAO,KAAK,KAAK;AAAA,QACnB,CAAC;AAAA,MACH;AAAA,IACF;AAEA,UAAM,WAAW,KAAK,cAAc,oBAAoB;AACxD,QAAI,UAAU;AACZ,iBAAW,MAAM,SAAS,OAAO;AAC/B,YAAI,GAAG,aAAa,CAAC,SAAS,KAAK,CAAC,MAAM,EAAE,cAAc,GAAG,SAAS,GAAG;AACvE,cAAI,UAAU,GAAG,OAAO,OAAQ;AAChC,mBAAS,KAAK;AAAA,YACZ,WAAW,GAAG;AAAA,YACd,QAAQ,GAAG;AAAA,YACX,UAAU,GAAG;AAAA,YACb,OAAO,GAAG;AAAA,YACV,WAAW;AAAA,UACb,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,qBAAqB,QAAsB;AACjD,SAAK,sBAAsB,MAAM;AAC/B,YAAM,WAAW,KAAK,cAAc,oBAAoB;AACxD,UAAI,UAAU;AACZ,iBAAS,QAAQ,SAAS,MAAM,OAAO,CAAC,MAAM,EAAE,OAAO,MAAM;AAC7D,aAAK,cAAc,oBAAoB,QAAQ;AAAA,MACjD;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,sBAAsB,IAAsB;AAClD,SAAK,kBAAkB,KAAK,gBAAgB,KAAK,MAAM;AACrD,UAAI;AACF,WAAG;AAAA,MACL,SAAS,KAAK;AACZ,gBAAQ,MAAM,2CAA2C,GAAG;AAAA,MAC9D;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,WAA0B;AAC9B,SAAK,WAAW,QAAQ;AACxB,SAAK,WAAW,QAAQ;AAExB,eAAW,CAAC,MAAM,KAAK,KAAK,oBAAoB;AAC9C,WAAK,mBAAmB,MAAM;AAAA,IAChC;AAAA,EACF;AACF;;;AC5jBA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,OAAOC,WAAU;AAGV,IAAM,mBAAN,MAAuB;AAAA,EACpB;AAAA,EACA,gBAAsD;AAAA,EAE9D,YAAY,YAAoB;AAC9B,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,OAA0B;AAC/B,QAAI,KAAK,cAAe,cAAa,KAAK,aAAa;AACvD,SAAK,gBAAgB,WAAW,MAAM;AACpC,WAAK,UAAU,KAAK;AAAA,IACtB,GAAG,GAAG;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAA0B;AAC9B,QAAI,KAAK,cAAe,cAAa,KAAK,aAAa;AACvD,SAAK,UAAU,KAAK;AAAA,EACtB;AAAA,EAEQ,UAAU,OAA0B;AAC1C,UAAM,WAAWD,MAAK,KAAK,KAAK,YAAY,QAAQ;AACpD,IAAAD,IAAG,UAAU,UAAU,EAAE,WAAW,KAAK,CAAC;AAG1C,UAAM,UAAU,MAAM,OAAO,CAAC,MAAM,EAAE,UAAU,WAAW;AAE3D,UAAM,OAAO;AAAA,MACX,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,MACnC,OAAO,QAAQ,IAAI,CAAC,MAAM;AACxB,cAAM,WAAY,EAAE,cAAc,cAAc,EAAE,eAC9C,EAAE,eACF,KAAK;AACT,eAAO;AAAA,UACL,IAAI,EAAE;AAAA,UACN,MAAM,EAAE;AAAA,UACR,OAAO,EAAE;AAAA,UACT,SAAS,EAAE;AAAA,UACX,KAAK,EAAE;AAAA,UACP,QAAQ,EAAE;AAAA,UACV,WAAW,EAAE,aAAa;AAAA,UAC1B,QAAQ,EAAE,UAAU;AAAA,UACpB,SAAS,EAAE,UACPC,MAAK,QAAQ,UAAU,EAAE,OAAO,IAChC;AAAA,UACJ,MAAM,EAAE,QAAQ;AAAA,UAChB,OAAO,EAAE,KAAK,SAAS;AAAA,UACvB,kBAAkB,EAAE,KAAK,kBAAkB;AAAA,UAC3C,UAAU,EAAE,KAAK,WAAW;AAAA,UAC5B,YAAY,EAAE,KAAK,aAAa;AAAA,UAChC,YAAY,EAAE,aAAa;AAAA,QAC7B;AAAA,MACF,CAAC;AAAA,IACH;AAEA,UAAM,WAAWA,MAAK,KAAK,UAAU,aAAa;AAClD,IAAAD,IAAG,cAAc,UAAUE,MAAK,KAAK,MAAM,EAAE,WAAW,GAAG,CAAC,CAAC;AAAA,EAC/D;AACF;;;ACrEA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,SAAAC,cAA6B;AAGtC,IAAM,eAAe,oBAAI,IAAI;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,gBAAgB,oBAAI,IAAI;AAAA,EAC5B;AAAA,EACA;AACF,CAAC;AAEM,IAAM,YAAN,MAAgB;AAAA,EACb;AAAA,EACA,UAA4B;AAAA,EAC5B,OAAmB,CAAC;AAAA,EACpB,gBAAsD;AAAA,EACtD,YAAY,oBAAI,IAAgC;AAAA,EAChD,sBAAsB,oBAAI,IAAsC;AAAA,EAChE,gBAAgB,oBAAI,IAAoB;AAAA;AAAA,EAEhD,YAAY,YAAoB;AAC9B,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,QAAc;AAEZ,SAAK,OAAO,KAAK,UAAU,KAAK,YAAY,CAAC;AAC7C,SAAK,gBAAgB;AAIrB,SAAK,UAAUA,OAAM,KAAK,YAAY;AAAA,MACpC,SAAS,CAAC,aAAqB;AAC7B,cAAM,WAAWD,MAAK,SAAS,QAAQ;AACvC,eAAO,aAAa,IAAI,QAAQ,KAAK,cAAc,IAAI,QAAQ;AAAA,MACjE;AAAA,MACA,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,OAAO;AAAA,IACT,CAAC;AAED,UAAM,kBAAkB,MAAM;AAC5B,UAAI,KAAK,cAAe,cAAa,KAAK,aAAa;AACvD,WAAK,gBAAgB,WAAW,MAAM;AACpC,cAAM,UAAU,KAAK,UAAU,KAAK,YAAY,CAAC;AAEjD,YAAI,KAAK,gBAAgB,OAAO,MAAM,KAAK,gBAAgB,KAAK,IAAI,EAAG;AACvE,aAAK,OAAO;AACZ,aAAK,gBAAgB;AAAA,MACvB,GAAG,GAAG;AAAA,IACR;AAGA,UAAM,iBAAiB,CAAC,WAAwC,aAAqB;AAEnF,YAAM,eAAeA,MAAK,SAAS,KAAK,YAAY,QAAQ;AAC5D,UAAI,CAAC,gBAAgB,aAAa,WAAW,IAAI,EAAG;AAEpD,UAAI,CAAC,cAAc,KAAKA,MAAK,SAAS,QAAQ,CAAC,EAAG;AAElD,YAAM,MAAM,KAAK,IAAI;AACrB,YAAM,aAAa,KAAK,cAAc,IAAI,YAAY;AACtD,UAAI,cAAc,MAAM,aAAa,IAAM;AAC3C,WAAK,cAAc,IAAI,cAAc,GAAG;AAExC,UAAI,KAAK,cAAc,OAAO,KAAK;AACjC,mBAAW,CAAC,KAAK,EAAE,KAAK,KAAK,eAAe;AAC1C,cAAI,MAAM,KAAK,IAAO,MAAK,cAAc,OAAO,GAAG;AAAA,QACrD;AAAA,MACF;AAEA,YAAM,YAAY,EAAE,KAAK,UAAmB,QAAQ,QAAiB,QAAQ,SAAkB;AAC/F,YAAM,WAAyB;AAAA,QAC7B,MAAM;AAAA,QACN,QAAQ,UAAU,SAAS;AAAA,QAC3B,WAAW;AAAA,MACb;AACA,iBAAW,YAAY,KAAK,qBAAqB;AAC/C,iBAAS,QAAQ;AAAA,MACnB;AAAA,IACF;AAEA,SAAK,QAAQ,GAAG,OAAO,CAAC,MAAM;AAAE,qBAAe,OAAO,CAAC;AAAG,sBAAgB;AAAA,IAAE,CAAC;AAC7E,SAAK,QAAQ,GAAG,UAAU,CAAC,MAAM;AAAE,qBAAe,UAAU,CAAC;AAAA,IAAE,CAAC;AAChE,SAAK,QAAQ,GAAG,UAAU,CAAC,MAAM;AAAE,qBAAe,UAAU,CAAC;AAAG,sBAAgB;AAAA,IAAE,CAAC;AACnF,SAAK,QAAQ,GAAG,UAAU,eAAe;AACzC,SAAK,QAAQ,GAAG,aAAa,eAAe;AAC5C,SAAK,QAAQ,GAAG,SAAS,MAAM;AAAA,IAG/B,CAAC;AAAA,EACH;AAAA,EAEA,UAAsB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,aAAa,UAAkD;AAC7D,SAAK,UAAU,IAAI,QAAQ;AAC3B,WAAO,MAAM,KAAK,UAAU,OAAO,QAAQ;AAAA,EAC7C;AAAA,EAEA,aAAa,UAAwD;AACnE,SAAK,oBAAoB,IAAI,QAAQ;AACrC,WAAO,MAAM,KAAK,oBAAoB,OAAO,QAAQ;AAAA,EACvD;AAAA,EAEA,QAAc;AACZ,QAAI,KAAK,cAAe,cAAa,KAAK,aAAa;AACvD,SAAK,SAAS,MAAM;AACpB,SAAK,UAAU;AAAA,EACjB;AAAA,EAEQ,kBAAwB;AAC9B,eAAW,YAAY,KAAK,WAAW;AACrC,eAAS,KAAK,IAAI;AAAA,IACpB;AAAA,EACF;AAAA,EAEQ,gBAAgB,MAA0B;AAEhD,UAAM,QAAkB,CAAC;AACzB,UAAM,OAAO,CAAC,UAAsB;AAClC,iBAAW,KAAK,OAAO;AACrB,cAAM,KAAK,EAAE,IAAI;AACjB,YAAI,EAAE,SAAU,MAAK,EAAE,QAAQ;AAAA,MACjC;AAAA,IACF;AACA,SAAK,IAAI;AACT,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AAAA,EAEQ,UAAU,SAAiB,OAA2B;AAC5D,QAAI,QAAQ,EAAG,QAAO,CAAC;AAEvB,QAAI;AACF,YAAM,UAAUD,IAAG,YAAY,SAAS,EAAE,eAAe,KAAK,CAAC;AAC/D,YAAM,QAAoB,CAAC;AAE3B,iBAAW,SAAS,SAAS;AAC3B,YAAI,aAAa,IAAI,MAAM,IAAI,KAAK,cAAc,IAAI,MAAM,IAAI,EAAG;AAEnE,cAAM,WAAWC,MAAK,KAAK,SAAS,MAAM,IAAI;AAC9C,cAAM,eAAeA,MAAK,SAAS,KAAK,YAAY,QAAQ;AAE5D,YAAI,MAAM,YAAY,GAAG;AACvB,gBAAM,KAAK;AAAA,YACT,MAAM,MAAM;AAAA,YACZ,MAAM;AAAA,YACN,MAAM;AAAA,YACN,UAAU,KAAK,UAAU,UAAU,QAAQ,CAAC;AAAA,UAC9C,CAAC;AAAA,QACH,WAAW,MAAM,OAAO,GAAG;AACzB,gBAAM,KAAK;AAAA,YACT,MAAM,MAAM;AAAA,YACZ,MAAM;AAAA,YACN,MAAM;AAAA,UACR,CAAC;AAAA,QACH;AAAA,MACF;AAGA,YAAM,KAAK,CAAC,GAAG,MAAM;AACnB,YAAI,EAAE,SAAS,EAAE,KAAM,QAAO,EAAE,SAAS,cAAc,KAAK;AAC5D,eAAO,EAAE,KAAK,cAAc,EAAE,IAAI;AAAA,MACpC,CAAC;AAED,aAAO;AAAA,IACT,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AACF;;;AChLO,SAAS,gBACd,QACA,kBACA,YACM;AACN,QAAM,OAAO,CAAC,UAAuB;AACnC,QAAI,OAAO,eAAe,OAAO,MAAM;AACrC,aAAO,KAAK,KAAK,UAAU,KAAK,CAAC;AAAA,IACnC;AAAA,EACF;AAGA,QAAM,QAAQ,iBAAiB,SAAS;AACxC,OAAK;AAAA,IACH,MAAM;AAAA,IACN;AAAA,EACF,CAAC;AAKD,QAAM,wBAAwB,MAAM;AACpC,QAAM,mBAAmB,YAAY;AACnC,eAAW,QAAQ,MAAM,OAAO;AAC9B,YAAM,aAAa,iBAAiB,cAAc,KAAK,EAAE;AACzD,UAAI,CAAC,WAAY;AACjB,UAAI,WAAW,UAAU,uBAAuB;AAC9C,aAAK,EAAE,MAAM,mBAAmB,QAAQ,KAAK,IAAI,MAAM,WAAW,CAAC;AAAA,MACrE,OAAO;AACL,iBAAS,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK,uBAAuB;AACjE,cAAI,OAAO,eAAe,OAAO,KAAM;AACvC,eAAK,EAAE,MAAM,mBAAmB,QAAQ,KAAK,IAAI,MAAM,WAAW,MAAM,GAAG,IAAI,qBAAqB,EAAE,CAAC;AAEvG,gBAAM,IAAI,QAAc,CAAC,YAAY,aAAa,OAAO,CAAC;AAAA,QAC5D;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,mBAAiB,EAAE,MAAM,MAAM;AAAA,EAA+B,CAAC;AAG/D,QAAM,YAAY,iBAAiB,aAAa;AAChD,aAAW,CAAC,QAAQ,KAAK,KAAK,WAAW;AACvC,QAAI,MAAM,SAAS,GAAG;AACpB,WAAK,EAAE,MAAM,aAAa,QAAQ,MAAM,CAAC;AAAA,IAC3C;AAAA,EACF;AAGA,cAAY,cAAc,EACvB,KAAK,CAAC,SAAS,KAAK,EAAE,MAAM,kBAAkB,GAAG,KAAK,CAAC,CAAC,EACxD,MAAM,MAAM;AAAA,EAAC,CAAC;AAGjB,QAAM,UAAU,iBAAiB,SAAS;AAAA,IACxC,gBAAgB,CAAC,QAAQ,SAAS;AAChC,WAAK,EAAE,MAAM,mBAAmB,QAAQ,KAAK,CAAC;AAAA,IAChD;AAAA,IACA,qBAAqB,CAAC,QAAQ,UAAU;AACtC,WAAK,EAAE,MAAM,sBAAsB,QAAQ,MAAM,CAAC;AAAA,IACpD;AAAA,IACA,cAAc,CAAC,QAAQ,WAAW;AAChC,WAAK,EAAE,MAAM,eAAe,QAAQ,OAAO,CAAC;AAAA,IAC9C;AAAA,IACA,YAAY,CAAC,QAAQ,SAAS;AAC5B,WAAK,EAAE,MAAM,aAAa,QAAQ,KAAK,CAAC;AAAA,IAC1C;AAAA,IACA,aAAa,CAAC,SAAS;AACrB,WAAK,EAAE,MAAM,cAAc,KAAK,CAAC;AAAA,IACnC;AAAA,IACA,eAAe,CAAC,WAAW;AACzB,WAAK,EAAE,MAAM,gBAAgB,OAAO,CAAC;AAAA,IACvC;AAAA,IACA,gBAAgB,CAAC,QAAQ,aAAa;AACpC,WAAK,EAAE,MAAM,iBAAiB,QAAQ,SAAS,CAAC;AAAA,IAClD;AAAA,IACA,gBAAgB,CAAC,aAAa;AAC5B,WAAK,EAAE,MAAM,iBAAiB,SAAS,CAAC;AAAA,IAC1C;AAAA,IACA,YAAY,CAAC,QAAQ,UAAU;AAC7B,WAAK,EAAE,MAAM,aAAa,QAAQ,MAAM,CAAC;AAAA,IAC3C;AAAA,IACA,YAAY,CAAC,SAAS;AACpB,WAAK,EAAE,MAAM,WAAW,KAAK,CAAC;AAAA,IAChC;AAAA,IACA,WAAW,CAAC,WAAW;AACrB,WAAK,EAAE,MAAM,YAAY,UAAU,OAAO,UAAU,QAAQ,OAAO,OAAO,CAAC;AAAA,IAC7E;AAAA,EACF,CAAC;AAGD,SAAO,GAAG,WAAW,CAAC,QAAgC;AACpD,QAAI;AACJ,QAAI;AACF,cAAQ,KAAK,MAAM,IAAI,SAAS,CAAC;AAAA,IACnC,QAAQ;AACN;AAAA,IACF;AAEA,YAAQ,MAAM,MAAM;AAAA,MAClB,KAAK;AACH,YAAI;AACF,2BAAiB,YAAY,MAAM,QAAQ,MAAM,IAAI;AAAA,QACvD,QAAQ;AAAA,QAER;AACA;AAAA,MAEF,KAAK;AACH,YAAI;AACF,2BAAiB,WAAW,MAAM,QAAQ,MAAM,MAAM,MAAM,IAAI;AAAA,QAClE,QAAQ;AAAA,QAER;AACA;AAAA,MAEF,KAAK;AACH,yBAAiB,uBAAuB,MAAM,QAAQ,MAAM,IAAI,EAAE,MAAM,CAAC,QAAQ;AAC/E,kBAAQ,MAAM,6BAA6B,GAAG;AAAA,QAChD,CAAC;AACD;AAAA,MAEF,KAAK;AACH,yBAAiB,WAAW,MAAM,MAAM,EAAE,MAAM,CAAC,QAAQ;AACvD,kBAAQ,MAAM,uBAAuB,GAAG;AAAA,QAC1C,CAAC;AACD;AAAA,MAEF,KAAK;AACH,yBAAiB,UAAU,MAAM,MAAM,EAAE,MAAM,CAAC,QAAQ;AACtD,kBAAQ,MAAM,sBAAsB,GAAG;AAAA,QACzC,CAAC;AACD;AAAA,MAEF,KAAK;AACH,yBAAiB,YAAY,MAAM,QAAQ,MAAM,MAAM,MAAM,SAAS;AACtE;AAAA,MAEF,KAAK;AACH,aAAK,EAAE,MAAM,gBAAgB,QAAQ,MAAM,QAAQ,UAAU,iBAAiB,eAAe,MAAM,MAAM,EAAE,CAAC;AAC5G;AAAA,MAEF,KAAK;AACH,oBAAY,QAAQ;AACpB;AAAA,MAEF,KAAK;AACH,oBAAY,WAAW,MAAM,IAAI,EAAE,MAAM,CAAC,QAAQ;AAChD,kBAAQ,MAAM,sBAAsB,GAAG;AAAA,QACzC,CAAC;AACD;AAAA,MAEF,KAAK;AACH,oBAAY,UAAU,EAAE,MAAM,CAAC,QAAQ;AACrC,kBAAQ,MAAM,0BAA0B,GAAG;AAAA,QAC7C,CAAC;AACD;AAAA,MAEF,KAAK;AACH,oBAAY,YAAY,MAAM,IAAI,EAAE,MAAM,CAAC,QAAQ;AACjD,kBAAQ,MAAM,uBAAuB,GAAG;AAAA,QAC1C,CAAC;AACD;AAAA,MAEF,KAAK;AACH,oBAAY,WAAW,EAAE,MAAM,CAAC,QAAQ;AACtC,kBAAQ,MAAM,2BAA2B,GAAG;AAAA,QAC9C,CAAC;AACD;AAAA,MAEF,KAAK;AACH,oBAAY,YAAY,MAAM,IAAI,EAAE,MAAM,CAAC,QAAQ;AACjD,kBAAQ,MAAM,uBAAuB,GAAG;AAAA,QAC1C,CAAC;AACD;AAAA,MAEF,KAAK;AACH,oBAAY,WAAW,EAAE,MAAM,CAAC,QAAQ;AACtC,kBAAQ,MAAM,2BAA2B,GAAG;AAAA,QAC9C,CAAC;AACD;AAAA,MAEF,KAAK;AACH,YAAI,YAAY;AACd,qBAAW,OAAO,MAAM,OAAO,EAC5B,KAAK,CAAC,YAAY;AACjB,iBAAK,EAAE,MAAM,cAAc,QAAQ,UAAU,SAAS,MAAM,SAAS,QAAQ,CAAC;AAE9E,mBAAO,WAAW,cAAc;AAAA,UAClC,CAAC,EACA,KAAK,CAAC,SAAS;AACd,iBAAK,EAAE,MAAM,kBAAkB,GAAG,KAAK,CAAC;AAAA,UAC1C,CAAC,EACA,MAAM,CAAC,QAAQ;AACd,iBAAK,EAAE,MAAM,cAAc,QAAQ,UAAU,SAAS,OAAO,SAAS,OAAO,GAAG,EAAE,CAAC;AAAA,UACrF,CAAC;AAAA,QACL;AACA;AAAA,MAEF,KAAK;AACH,YAAI,YAAY;AACd,qBAAW,KAAK,EACb,KAAK,CAAC,YAAY;AACjB,iBAAK,EAAE,MAAM,cAAc,QAAQ,QAAQ,SAAS,MAAM,SAAS,QAAQ,CAAC;AAC5E,mBAAO,WAAW,cAAc;AAAA,UAClC,CAAC,EACA,KAAK,CAAC,SAAS;AACd,iBAAK,EAAE,MAAM,kBAAkB,GAAG,KAAK,CAAC;AAAA,UAC1C,CAAC,EACA,MAAM,CAAC,QAAQ;AACd,iBAAK,EAAE,MAAM,cAAc,QAAQ,QAAQ,SAAS,OAAO,SAAS,OAAO,GAAG,EAAE,CAAC;AAAA,UACnF,CAAC;AAAA,QACL;AACA;AAAA,MAEF,KAAK;AACH,yBAAiB,cAAc,MAAM,MAAM,EACxC,KAAK,CAAC,WAAW;AAChB,eAAK,EAAE,MAAM,qBAAqB,QAAQ,MAAM,QAAQ,GAAG,OAAO,CAAC;AAEnE,sBAAY,QAAQ;AAAA,QACtB,CAAC,EACA,MAAM,CAAC,QAAQ;AACd,eAAK,EAAE,MAAM,qBAAqB,QAAQ,MAAM,QAAQ,SAAS,OAAO,SAAS,OAAO,GAAG,EAAE,CAAC;AAAA,QAChG,CAAC;AACH;AAAA,MAEF,KAAK;AACH,yBAAiB,gBAAgB,MAAM,MAAM,EAC1C,KAAK,CAAC,WAAW;AAChB,eAAK,EAAE,MAAM,qBAAqB,QAAQ,MAAM,QAAQ,GAAG,OAAO,CAAC;AACnE,sBAAY,QAAQ;AAAA,QACtB,CAAC,EACA,MAAM,CAAC,QAAQ;AACd,eAAK,EAAE,MAAM,qBAAqB,QAAQ,MAAM,QAAQ,SAAS,OAAO,SAAS,OAAO,GAAG,EAAE,CAAC;AAAA,QAChG,CAAC;AACH;AAAA,MAEF,KAAK;AACH,yBAAiB,gBAAgB,MAAM,MAAM;AAC7C;AAAA,MAEF,KAAK;AACH;AAAA,MAEF,KAAK,kBAAkB;AAErB,cAAM,EAAE,QAAQ,cAAc,QAAQ,IAAI;AAC1C,cAAM,aAAa,iBAAiB,SAAS,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,YAAY;AAChF,YAAI,cAAc,QAAQ,QAAQ,KAAK,GAAG;AACxC,gBAAM,MAAM;AAAA,YACV;AAAA,YACA,oBAAoB,QAAQ,IAAI,IAAI,QAAQ,IAAI;AAAA,YAChD,QAAQ,QAAQ,KAAK;AAAA,YACrB;AAAA,UACF,EAAE,KAAK,IAAI;AACX,2BAAiB,YAAY,cAAc,MAAM,IAAI;AAAA,QACvD;AACA;AAAA,MACF;AAAA,MAEA,KAAK;AAAA,MACL,KAAK;AAEH;AAAA,IACJ;AAAA,EACF,CAAC;AAED,SAAO,GAAG,SAAS,MAAM;AACvB,YAAQ;AAAA,EACV,CAAC;AACH;;;ACpRA,OAAOE,SAAQ;AACf,OAAOC,WAAU;AAiBjB,IAAM,iBAAiB;AAEvB,IAAM,iBAAiB;AAEvB,IAAM,aAAa;AAEnB,IAAM,oBAAoB;AAE1B,IAAM,mBAAmB,oBAAI,IAAI,CAAC,OAAO,QAAQ,OAAO,QAAQ,QAAQ,QAAQ,QAAQ,MAAM,CAAC;AAC/F,IAAM,qBAAqB,CAAC,OAAO,QAAQ,OAAO,QAAQ,QAAQ,QAAQ,IAAI,aAAa,cAAc,aAAa,YAAY;AAGlI,IAAM,YAAY,oBAAI,IAAI,CAAC,gBAAgB,QAAQ,QAAQ,SAAS,SAAS,SAAS,YAAY,UAAU,UAAU,QAAQ,CAAC;AAIxH,IAAM,qBAAN,MAAyB;AAAA,EACtB;AAAA,EAER,YAAY,YAAoB;AAC9B,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAoB;AAClB,UAAM,QAAQ,KAAK,aAAa,KAAK,UAAU;AAC/C,UAAM,QAAmB,CAAC;AAE1B,eAAW,WAAW,OAAO;AAC3B,YAAM,UAAUA,MAAK,SAAS,KAAK,YAAY,OAAO;AACtD,YAAM,UAAU,KAAK,eAAe,SAAS,OAAO;AACpD,YAAM,KAAK,EAAE,IAAI,SAAS,QAAQ,CAAC;AAAA,IACrC;AAEA,WAAO,EAAE,OAAO,MAAM,KAAK,WAAW;AAAA,EACxC;AAAA,EAEQ,aAAa,KAAa,QAAQ,GAAa;AACrD,QAAI,QAAQ,EAAG,QAAO,CAAC;AACvB,UAAM,QAAkB,CAAC;AAEzB,QAAI;AACJ,QAAI;AACF,gBAAUD,IAAG,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC;AAAA,IACvD,QAAQ;AACN,aAAO;AAAA,IACT;AAEA,eAAW,SAAS,SAAS;AAC3B,UAAI,MAAM,KAAK,WAAW,GAAG,KAAK,MAAM,SAAS,IAAK;AACtD,YAAM,WAAWC,MAAK,KAAK,KAAK,MAAM,IAAI;AAE1C,UAAI,MAAM,YAAY,GAAG;AACvB,YAAI,UAAU,IAAI,MAAM,IAAI,EAAG;AAC/B,cAAM,KAAK,GAAG,KAAK,aAAa,UAAU,QAAQ,CAAC,CAAC;AAAA,MACtD,WAAW,MAAM,OAAO,GAAG;AACzB,cAAM,MAAMA,MAAK,QAAQ,MAAM,IAAI;AACnC,YAAI,iBAAiB,IAAI,GAAG,GAAG;AAC7B,gBAAM,KAAK,QAAQ;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,eAAe,SAAiB,SAA2B;AACjE,QAAI;AACJ,QAAI;AACF,gBAAUD,IAAG,aAAa,SAAS,OAAO;AAAA,IAC5C,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,aAAa,oBAAI,IAAY;AACnC,UAAM,WAAW,CAAC,gBAAgB,gBAAgB,YAAY,iBAAiB;AAE/E,eAAW,WAAW,UAAU;AAC9B,cAAQ,YAAY;AACpB,UAAI;AACJ,cAAQ,QAAQ,QAAQ,KAAK,OAAO,OAAO,MAAM;AAC/C,cAAM,OAAO,MAAM,CAAC;AAEpB,YAAI,KAAK,WAAW,GAAG,GAAG;AACxB,qBAAW,IAAI,IAAI;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AAGA,UAAM,UAAoB,CAAC;AAC3B,UAAM,UAAUC,MAAK,QAAQ,OAAO;AAEpC,eAAW,QAAQ,YAAY;AAC7B,YAAM,WAAW,KAAK,iBAAiB,SAAS,IAAI;AACpD,UAAI,UAAU;AACZ,cAAM,cAAcA,MAAK,SAAS,KAAK,YAAY,QAAQ;AAC3D,gBAAQ,KAAK,WAAW;AAAA,MAC1B;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,iBAAiB,SAAiB,WAAkC;AAC1E,UAAM,OAAOA,MAAK,QAAQ,SAAS,SAAS;AAE5C,eAAW,OAAO,oBAAoB;AACpC,YAAM,YAAY,OAAO;AACzB,UAAI;AACF,YAAID,IAAG,SAAS,SAAS,EAAE,OAAO,GAAG;AACnC,iBAAO;AAAA,QACT;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACF;;;AC7IA,OAAOE,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,YAAAC,iBAAgB;AA2BzB,IAAM,cAAc;AACpB,IAAM,iBAAiB;AACvB,IAAM,oBAAoB;AAC1B,IAAM,8BAA8B,MAAM;AAC1C,IAAM,eAAe;AAYd,IAAM,kBAAN,MAAM,iBAAgB;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAc,oBAAI,IAAwB;AAAA;AAAA,EAC1C,cAAc;AAAA,EACd;AAAA,EAER,YAAY,YAAoB,aAAqB,gBAAgB,IAAI;AACvE,SAAK,aAAa;AAClB,UAAM,YAAY,KAAK,KAAK,IAAI,CAAC;AACjC,SAAK,aAAaD,MAAK,KAAK,YAAY,aAAa,SAAS;AAC9D,IAAAD,IAAG,UAAU,KAAK,YAAY,EAAE,WAAW,KAAK,CAAC;AAEjD,SAAK,gBAAgB;AAErB,SAAK,UAAU;AAAA,MACb,IAAI;AAAA,MACJ,WAAW,KAAK,IAAI;AAAA,MACpB,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA,OAAO,CAAC;AAAA,MACR,OAAO,CAAC;AAAA;AAAA,IACV;AAAA,EACF;AAAA;AAAA,EAIA,YAAY,MAAuB;AACjC,QAAI,KAAK,UAAU,YAAa;AAChC,UAAM,SAAS,KAAK,QAAQ,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,KAAK,EAAE;AAC9D,QAAI,CAAC,QAAQ;AACX,WAAK,QAAQ,MAAM,KAAK;AAAA,QACtB,IAAI,KAAK;AAAA,QACT,MAAM,KAAK;AAAA,QACX,OAAO,KAAK;AAAA,QACZ,MAAM,KAAK;AAAA,MACb,CAAC;AAAA,IACH;AAEA,QAAI,KAAK,WAAW,WAAW;AAC7B,WAAK,UAAU,KAAK,IAAI,KAAK,MAAM,KAAK,OAAO,KAAK,IAAI;AAAA,IAC1D;AAAA,EACF;AAAA,EAEA,cAAc,QAAsB;AAClC,SAAK,QAAQ,MAAM;AAAA,EACrB;AAAA,EAEA,aAAa,QAAgB,QAAoB,MAAwB;AACvE,QAAI,CAAC,QAAQ,KAAK,UAAU,YAAa;AAEzC,UAAM,SAAS,KAAK,YAAY,IAAI,MAAM;AAE1C,QAAI,WAAW,aAAa,CAAC,QAAQ;AAEnC,WAAK,UAAU,QAAQ,KAAK,MAAM,KAAK,OAAO,KAAK,IAAI;AAAA,IACzD,YAAY,WAAW,UAAU,WAAW,aAAa,WAAW,YAAY,QAAQ;AAEtF,WAAK,kBAAkB,QAAQ,MAAM;AACrC,WAAK,QAAQ,MAAM;AAAA,IACrB,WAAW,QAAQ;AAEjB,WAAK,kBAAkB,QAAQ,MAAM;AAAA,IACvC;AAAA,EACF;AAAA,EAEA,WAAW,QAAgB,MAAsB;AAC/C,UAAM,SAAS,KAAK,YAAY,IAAI,MAAM;AAC1C,QAAI,CAAC,OAAQ;AAEb,UAAM,QAAqB;AAAA,MACzB,GAAG,KAAK,IAAI,IAAI,OAAO,KAAK;AAAA,MAC5B,MAAM;AAAA,MACN;AAAA,MACA;AAAA,IACF;AACA,WAAO,KAAK,OAAO,KAAK,KAAK;AAAA,EAC/B;AAAA,EAEA,eAAe,QAAgB,MAAoB;AACjD,UAAM,SAAS,KAAK,YAAY,IAAI,MAAM;AAC1C,QAAI,CAAC,OAAQ;AAGb,QAAI,OAAO,iBAAiB,4BAA6B;AAEzD,WAAO,kBAAkB;AACzB,WAAO,iBAAiB,KAAK;AAG7B,QAAI,CAAC,OAAO,oBAAoB;AAC9B,aAAO,qBAAqB,WAAW,MAAM;AAC3C,aAAK,oBAAoB,MAAM;AAAA,MACjC,GAAG,iBAAiB;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,eAAe,QAAgB,UAA8B;AAC3D,UAAM,SAAS,KAAK,YAAY,IAAI,MAAM;AAC1C,QAAI,CAAC,OAAQ;AAEb,UAAM,QAAqB;AAAA,MACzB,GAAG,KAAK,IAAI,IAAI,OAAO,KAAK;AAAA,MAC5B,MAAM;AAAA,MACN;AAAA,MACA,UAAU,EAAE,GAAG,SAAS;AAAA,IAC1B;AACA,WAAO,KAAK,OAAO,KAAK,KAAK;AAG7B,YAAQ,SAAS,QAAQ;AAAA,MACvB,KAAK;AACH,eAAO,UAAU,IAAI,SAAS,IAAI;AAClC;AAAA,MACF,KAAK;AAAA,MACL,KAAK;AACH,eAAO,YAAY,IAAI,SAAS,IAAI;AACpC;AAAA,MACF,KAAK;AACH,eAAO,aAAa,IAAI,SAAS,IAAI;AACrC;AAAA,IACJ;AAGA,QAAI,SAAS,WAAW,UAAU,SAAS,WAAW,WAAW,SAAS,WAAW,UAAU;AAC7F,WAAK,YAAY,SAAS,IAAI,EAAE,KAAK,CAAC,SAAS;AAC7C,YAAI,MAAM;AACR,gBAAM,WAAW,EAAE,GAAG,MAAM,UAAW,KAAK;AAAA,QAC9C;AAAA,MACF,CAAC,EAAE,MAAM,MAAM;AAAA,MAAqC,CAAC;AAAA,IACvD;AAAA,EACF;AAAA;AAAA,EAGA,wBAAwB,UAA8B;AAEpD,QAAI,KAAK,YAAY,SAAS,EAAG;AAGjC,QAAI,KAAK,YAAY,SAAS,EAAG;AAEjC,UAAM,CAAC,QAAQ,MAAM,IAAI,CAAC,GAAG,KAAK,YAAY,QAAQ,CAAC,EAAE,CAAC;AAG1D,QAAI;AACJ,aAAS,IAAI,OAAO,KAAK,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK;AACvD,YAAM,IAAI,OAAO,KAAK,OAAO,CAAC;AAC9B,UAAI,EAAE,SAAS,cAAc,EAAE,UAAU,SAAS,SAAS,MAAM;AAC/D,yBAAiB;AACjB;AAAA,MACF;AAAA,IACF;AACA,QAAI,kBAAmB,KAAK,IAAI,IAAI,OAAO,KAAK,YAAY,eAAe,IAAK,IAAM;AAEtF,UAAM,QAAqB;AAAA,MACzB,GAAG,KAAK,IAAI,IAAI,OAAO,KAAK;AAAA,MAC5B,MAAM;AAAA,MACN;AAAA,MACA,UAAU,EAAE,GAAG,SAAS;AAAA,IAC1B;AACA,WAAO,KAAK,OAAO,KAAK,KAAK;AAG7B,QAAI,SAAS,WAAW,UAAU,SAAS,WAAW,UAAU;AAC9D,WAAK,YAAY,SAAS,IAAI,EAAE,KAAK,CAAC,SAAS;AAC7C,YAAI,MAAM;AACR,gBAAM,WAAW,EAAE,GAAG,MAAM,UAAW,KAAK;AAAA,QAC9C;AAAA,MACF,CAAC,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IACnB;AAAA,EACF;AAAA;AAAA;AAAA,EAKA,QAAc;AAEZ,eAAW,UAAU,CAAC,GAAG,KAAK,YAAY,KAAK,CAAC,GAAG;AACjD,WAAK,QAAQ,MAAM;AAAA,IACrB;AAEA,SAAK,QAAQ,UAAU,KAAK,IAAI;AAChC,SAAK,iBAAiB;AACtB,SAAK,oBAAoB;AAAA,EAC3B;AAAA;AAAA,EAIA,OAAO,aAAa,YAA4C;AAC9D,UAAM,YAAYC,MAAK,KAAK,YAAY,aAAa,cAAc;AACnE,QAAI,CAACD,IAAG,WAAW,SAAS,EAAG,QAAO,CAAC;AACvC,QAAI;AACF,YAAM,OAAO,KAAK,MAAMA,IAAG,aAAa,WAAW,OAAO,CAAC;AAC3D,aAAO,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAC;AAAA,IACvC,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA,EAEA,OAAO,WAAW,YAAoB,WAAyC;AAC7E,UAAM,cAAcC,MAAK,KAAK,YAAY,aAAa,WAAW,cAAc;AAChF,QAAI,CAACD,IAAG,WAAW,WAAW,EAAG,QAAO;AACxC,QAAI;AACF,aAAO,KAAK,MAAMA,IAAG,aAAa,aAAa,OAAO,CAAC;AAAA,IACzD,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,OAAO,QAAQ,YAAoB,WAAmB,QAAmC;AACvF,UAAM,WAAWC,MAAK,KAAK,YAAY,aAAa,WAAW,GAAG,MAAM,OAAO;AAC/E,QAAI,CAACD,IAAG,WAAW,QAAQ,EAAG,QAAO;AACrC,QAAI;AACF,aAAO,KAAK,MAAMA,IAAG,aAAa,UAAU,OAAO,CAAC;AAAA,IACtD,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA,EAGA,OAAO,cAAc,YAAoB,WAA4B;AAEnE,UAAM,aAAaC,MAAK,KAAK,YAAY,aAAa,SAAS;AAC/D,QAAID,IAAG,WAAW,UAAU,GAAG;AAC7B,MAAAA,IAAG,OAAO,YAAY,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,IACxD;AAGA,UAAM,YAAYC,MAAK,KAAK,YAAY,aAAa,cAAc;AACnE,QAAID,IAAG,WAAW,SAAS,GAAG;AAC5B,UAAI;AACF,YAAI,WAAmC,KAAK,MAAMA,IAAG,aAAa,WAAW,OAAO,CAAC;AACrF,cAAM,SAAS,SAAS;AACxB,mBAAW,SAAS,OAAO,OAAK,EAAE,OAAO,SAAS;AAClD,YAAI,SAAS,SAAS,QAAQ;AAC5B,UAAAA,IAAG,cAAc,WAAW,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAC7D,iBAAO;AAAA,QACT;AAAA,MACF,QAAQ;AAAA,MAAe;AAAA,IACzB;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,OAAO,kBAAkB,YAA4B;AACnD,UAAM,WAAW,iBAAgB,aAAa,UAAU;AACxD,QAAI,QAAQ;AACZ,eAAW,WAAW,UAAU;AAC9B,YAAM,aAAaC,MAAK,KAAK,YAAY,aAAa,QAAQ,EAAE;AAChE,UAAID,IAAG,WAAW,UAAU,GAAG;AAC7B,QAAAA,IAAG,OAAO,YAAY,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACtD;AAAA,MACF;AAAA,IACF;AAEA,UAAM,YAAYC,MAAK,KAAK,YAAY,aAAa,cAAc;AACnE,IAAAD,IAAG,cAAc,WAAW,KAAK,UAAU,CAAC,GAAG,MAAM,CAAC,CAAC;AACvD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,iBAAiB,YAAoB,eAA+B;AACzE,UAAM,YAAYC,MAAK,KAAK,YAAY,aAAa,cAAc;AACnE,QAAI,CAACD,IAAG,WAAW,SAAS,EAAG,QAAO;AAEtC,QAAI;AACJ,QAAI;AACF,iBAAW,KAAK,MAAMA,IAAG,aAAa,WAAW,OAAO,CAAC;AAAA,IAC3D,QAAQ;AAAE,aAAO;AAAA,IAAE;AAEnB,UAAM,SAAS,KAAK,IAAI,IAAI,gBAAgB,KAAK,KAAK,KAAK;AAC3D,UAAM,OAA+B,CAAC;AACtC,UAAM,SAAiC,CAAC;AAExC,eAAW,KAAK,UAAU;AACxB,UAAI,EAAE,YAAY,UAAU,KAAK,UAAU,cAAc;AACvD,eAAO,KAAK,CAAC;AAAA,MACf,OAAO;AACL,aAAK,KAAK,CAAC;AAAA,MACb;AAAA,IACF;AAEA,QAAI,OAAO,WAAW,EAAG,QAAO;AAGhC,eAAW,KAAK,QAAQ;AACtB,YAAM,aAAaC,MAAK,KAAK,YAAY,aAAa,EAAE,EAAE;AAC1D,UAAID,IAAG,WAAW,UAAU,GAAG;AAC7B,QAAAA,IAAG,OAAO,YAAY,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,MACxD;AAAA,IACF;AAEA,IAAAA,IAAG,cAAc,WAAW,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AACzD,WAAO,OAAO;AAAA,EAChB;AAAA;AAAA,EAIQ,UAAU,QAAgB,UAAkB,OAAkB,MAAqB;AAEzF,QAAI,KAAK,YAAY,IAAI,MAAM,GAAG;AAChC,WAAK,QAAQ,MAAM;AAAA,IACrB;AAEA,UAAM,SAAS,QAAQ,EAAE,KAAK,WAAW;AACzC,UAAM,OAAmB;AAAA,MACvB,IAAI;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW,KAAK,IAAI;AAAA,MACpB,SAAS;AAAA,MACT;AAAA,MACA,QAAQ,CAAC;AAAA,MACT,SAAS;AAAA,QACP,WAAW;AAAA,QACX,aAAa;AAAA,QACb,cAAc;AAAA,QACd,eAAe;AAAA,QACf,YAAY;AAAA,MACd;AAAA,IACF;AAEA,SAAK,YAAY,IAAI,QAAQ;AAAA,MAC3B;AAAA,MACA,gBAAgB;AAAA,MAChB,oBAAoB;AAAA,MACpB,eAAe;AAAA,MACf,WAAW,oBAAI,IAAI;AAAA,MACnB,aAAa,oBAAI,IAAI;AAAA,MACrB,cAAc,oBAAI,IAAI;AAAA,IACxB,CAAC;AAAA,EACH;AAAA,EAEQ,QAAQ,QAAsB;AACpC,UAAM,SAAS,KAAK,YAAY,IAAI,MAAM;AAC1C,QAAI,CAAC,OAAQ;AAGb,SAAK,oBAAoB,MAAM;AAE/B,UAAM,OAAO,OAAO;AACpB,SAAK,UAAU,KAAK,IAAI;AACxB,SAAK,UAAU;AAAA,MACb,WAAW,OAAO,UAAU;AAAA,MAC5B,aAAa,OAAO,YAAY;AAAA,MAChC,cAAc,OAAO,aAAa;AAAA,MAClC,eAAe,OAAO;AAAA,MACtB,YAAY,KAAK,UAAU,KAAK;AAAA,IAClC;AAGA,QAAI,KAAK,OAAO,SAAS,GAAG;AAC1B,WAAK,cAAc,IAAI;AAEvB,WAAK,QAAQ,MAAM,KAAK;AAAA,QACtB,GAAG;AAAA,QACH,QAAQ,CAAC;AAAA;AAAA,MACX,CAAC;AAAA,IACH;AAEA,SAAK,YAAY,OAAO,MAAM;AAAA,EAChC;AAAA,EAEQ,kBAAkB,QAAgB,QAA0B;AAClE,UAAM,SAAS,KAAK,YAAY,IAAI,MAAM;AAC1C,QAAI,CAAC,OAAQ;AACb,WAAO,KAAK,OAAO,KAAK;AAAA,MACtB,GAAG,KAAK,IAAI,IAAI,OAAO,KAAK;AAAA,MAC5B,MAAM;AAAA,MACN;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEQ,oBAAoB,QAAsB;AAChD,UAAM,SAAS,KAAK,YAAY,IAAI,MAAM;AAC1C,QAAI,CAAC,UAAU,CAAC,OAAO,eAAgB;AAEvC,QAAI,OAAO,oBAAoB;AAC7B,mBAAa,OAAO,kBAAkB;AACtC,aAAO,qBAAqB;AAAA,IAC9B;AAEA,WAAO,KAAK,OAAO,KAAK;AAAA,MACtB,GAAG,KAAK,IAAI,IAAI,OAAO,KAAK;AAAA,MAC5B,MAAM;AAAA,MACN;AAAA,MACA,MAAM,OAAO;AAAA,IACf,CAAC;AACD,WAAO,iBAAiB;AAAA,EAC1B;AAAA;AAAA,EAGQ,YAAY,MAAsC;AACxD,WAAO,IAAI,QAAQ,CAAC,YAAY;AAE9B,MAAAE,UAAS,OAAO,CAAC,QAAQ,cAAc,OAAO,MAAM,IAAI,GAAG;AAAA,QACzD,KAAK,KAAK;AAAA,QACV,SAAS;AAAA,QACT,WAAW,MAAM;AAAA,MACnB,GAAG,CAAC,KAAK,WAAW;AAClB,YAAI,UAAU,OAAO,KAAK,GAAG;AAC3B,kBAAQ,OAAO,KAAK,CAAC;AACrB;AAAA,QACF;AAEA,QAAAA,UAAS,OAAO,CAAC,QAAQ,cAAc,cAAc,aAAa,IAAI,GAAG;AAAA,UACvE,KAAK,KAAK;AAAA,UACV,SAAS;AAAA,UACT,WAAW,MAAM;AAAA,QACnB,GAAG,CAAC,OAAO,YAAY;AACrB,kBAAQ,SAAS,KAAK,KAAK,IAAI;AAAA,QACjC,CAAC;AAAA,MACH,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EAEQ,cAAc,MAAwB;AAC5C,UAAM,WAAWD,MAAK,KAAK,KAAK,YAAY,GAAG,KAAK,EAAE,OAAO;AAC7D,IAAAD,IAAG,cAAc,UAAU,KAAK,UAAU,IAAI,CAAC;AAAA,EACjD;AAAA,EAEQ,mBAAyB;AAC/B,UAAM,cAAcC,MAAK,KAAK,KAAK,YAAY,cAAc;AAC7D,IAAAD,IAAG,cAAc,aAAa,KAAK,UAAU,KAAK,SAAS,MAAM,CAAC,CAAC;AAAA,EACrE;AAAA,EAEQ,sBAA4B;AAClC,UAAM,YAAYC,MAAK,KAAK,KAAK,YAAY,aAAa,cAAc;AACxE,QAAI,WAAmC,CAAC;AAExC,QAAID,IAAG,WAAW,SAAS,GAAG;AAC5B,UAAI;AACF,mBAAW,KAAK,MAAMA,IAAG,aAAa,WAAW,OAAO,CAAC;AAAA,MAC3D,QAAQ;AAAA,MAAoB;AAAA,IAC9B;AAEA,UAAM,kBAAkB,KAAK,QAAQ,UACjC,KAAK,QAAQ,UAAU,KAAK,QAAQ,YACpC;AAEJ,aAAS,QAAQ;AAAA,MACf,IAAI,KAAK,QAAQ;AAAA,MACjB,WAAW,KAAK,QAAQ;AAAA,MACxB,SAAS,KAAK,QAAQ;AAAA,MACtB,aAAa,KAAK,QAAQ;AAAA,MAC1B,WAAW,KAAK,QAAQ,MAAM;AAAA,MAC9B,WAAW,KAAK,QAAQ,MAAM;AAAA,MAC9B;AAAA,IACF,CAAC;AAED,IAAAA,IAAG,cAAc,WAAW,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAG7D,UAAM,SAAS,iBAAgB,iBAAiB,KAAK,YAAY,KAAK,aAAa;AACnF,QAAI,SAAS,GAAG;AACd,cAAQ,IAAI,4BAA4B,MAAM,iBAAiB;AAAA,IACjE;AAAA,EACF;AACF;;;AC9fA,SAAS,YAAAG,iBAAgB;AACzB,SAAS,aAAAC,kBAAiB;AAG1B,IAAMC,iBAAgBD,WAAUD,SAAQ;AA0BxC,IAAM,YAAY;AAEX,IAAM,mBAAN,MAAuB;AAAA,EACpB;AAAA,EACA,QAA8D;AAAA,EAEtE,YAAY,eAA8B;AACxC,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEA,MAAM,aAAa,YAAY,cAA4C;AACzE,UAAM,MAAM,KAAK,IAAI;AACrB,QAAI,KAAK,SAAS,MAAM,KAAK,MAAM,KAAK,WAAW;AACjD,aAAO,KAAK,MAAM;AAAA,IACpB;AAEA,UAAM,WAAW,MAAM,KAAK,cAAc,SAAS;AACnD,SAAK,QAAQ,EAAE,UAAU,IAAI,IAAI;AACjC,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,cAAc,WAAiD;AAC3E,UAAM,WAAW,KAAK,cAAc,mBAAmB,SAAS;AAChE,QAAI,CAAC,YAAY,SAAS,QAAQ,UAAU;AAC1C,aAAO,CAAC;AAAA,IACV;AAEA,QAAI;AACF,YAAM,EAAE,OAAO,IAAI,MAAME,eAAc,SAAS,KAAK,CAAC,YAAY,QAAQ,YAAY,MAAM,GAAG;AAAA,QAC7F,SAAS;AAAA,QACT,KAAK,EAAE,GAAG,QAAQ,IAAI;AAAA,MACxB,CAAC;AAED,YAAM,SAAS,KAAK,MAAM,OAAO,KAAK,CAAC;AACvC,YAAM,QAAyB,MAAM,QAAQ,MAAM,IAAI,SAAU,OAAO,YAAY,CAAC;AAErF,aAAO,MAAM,IAAI,CAAC,OAAO;AAAA,QACvB,WAAW,EAAE;AAAA,QACb,SAAS,EAAE;AAAA,QACX,OAAO,EAAE;AAAA,QACT,SAAS,EAAE;AAAA,QACX,UAAU,EAAE;AAAA,QACZ,WAAW,EAAE;AAAA,QACb,WAAW,EAAE;AAAA,QACb,aAAa,EAAE;AAAA,QACf,QAAQ;AAAA,MACV,EAAE;AAAA,IACJ,SAAS,KAAK;AACZ,cAAQ,KAAK,+CAAgD,IAAc,OAAO;AAClF,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AACF;;;AhBhEA,IAAM,YAAYC,OAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AAE7D,eAAsB,YAAY,MAAc,YAAoB;AAClE,QAAM,UAAU,QAAQ,EAAE,QAAQ,MAAM,CAAC;AAGzC,QAAM,gBAAgB,IAAI,cAAc,UAAU;AAClD,gBAAc,iBAAiB;AAE/B,QAAM,mBAAmB,IAAI,iBAAiB,aAAa;AAC3D,QAAM,iBAAiB,KAAK;AAG5B,QAAM,eAAe,IAAI,iBAAiB,UAAU;AAEpD,mBAAiB,SAAS;AAAA,IACxB,aAAa,MAAM,aAAa,OAAO,iBAAiB,SAAS,CAAC;AAAA,IAClE,eAAe,MAAM,aAAa,OAAO,iBAAiB,SAAS,CAAC;AAAA,IACpE,cAAc,MAAM,aAAa,OAAO,iBAAiB,SAAS,CAAC;AAAA,IACnE,YAAY,MAAM,aAAa,OAAO,iBAAiB,SAAS,CAAC;AAAA,EACnE,CAAC;AAGD,QAAM,WAAW,cAAc,oBAAoB;AACnD,QAAM,eAAe,cAAc,iBAAiB;AACpD,QAAM,WAAW,IAAI,gBAAgB,YAAY,UAAU,QAAQ,SAAS,aAAa,SAAS,sBAAsB;AAExH,mBAAiB,SAAS;AAAA,IACxB,aAAa,CAAC,SAAS,SAAS,YAAY,IAAI;AAAA,IAChD,eAAe,CAAC,WAAW,SAAS,cAAc,MAAM;AAAA,IACxD,cAAc,CAAC,QAAQ,WAAW;AAChC,YAAM,QAAQ,iBAAiB,SAAS;AACxC,YAAM,OAAO,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM;AAC9C,eAAS,aAAa,QAAQ,QAAQ,IAAI;AAAA,IAC5C;AAAA,IACA,YAAY,CAAC,QAAQ,SAAS,SAAS,WAAW,QAAQ,IAAI;AAAA,IAC9D,gBAAgB,CAAC,QAAQ,SAAS,SAAS,eAAe,QAAQ,IAAI;AAAA,IACtE,gBAAgB,CAAC,QAAQ,aAAa,SAAS,eAAe,QAAQ,QAAQ;AAAA,EAChF,CAAC;AAGD,QAAM,YAAY,IAAI,UAAU,UAAU;AAC1C,YAAU,aAAa,CAAC,SAAS;AAC/B,qBAAiB,aAAa,IAAI;AAAA,EACpC,CAAC;AACD,YAAU,aAAa,CAAC,aAAa;AACnC,qBAAiB,iBAAiB,QAAQ;AAE1C,aAAS,wBAAwB,QAAQ;AAAA,EAC3C,CAAC;AACD,MAAI;AACF,cAAU,MAAM;AAAA,EAClB,SAAS,KAAK;AACZ,YAAQ,KAAK,6CAA8C,IAAc,OAAO;AAAA,EAClF;AAGA,QAAM,aAAa,IAAI,WAAW,UAAU;AAC5C,aAAW,aAAa,CAAC,WAAW;AAClC,qBAAiB,YAAY,MAAM;AAAA,EACrC,CAAC;AACD,MAAI;AACF,UAAM,WAAW,MAAM;AAAA,EACzB,SAAS,KAAK;AACZ,YAAQ,KAAK,6CAA8C,IAAc,OAAO;AAAA,EAClF;AAGA,QAAM,QAAQ,SAAS,gBAAgB;AAEvC,UAAQ,IAAI,aAAa,EAAE,WAAW,KAAK,GAAG,CAAC,QAAQ,QAAQ;AAC7D,YAAQ,IAAI,6BAA6B,IAAI,EAAE;AAC/C,QAAI;AACF,sBAAgB,QAAQ,kBAAkB,UAAU;AAGpD,YAAM,OAAO,UAAU,QAAQ;AAC/B,UAAI,KAAK,SAAS,GAAG;AACnB,eAAO,KAAK,KAAK,UAAU,EAAE,MAAM,WAAW,KAAK,CAAC,CAAC;AAAA,MACvD;AACA,YAAM,EAAE,UAAU,OAAO,IAAI,WAAW,gBAAgB;AACxD,UAAI,SAAS,SAAS,KAAK,OAAO,SAAS,GAAG;AAC5C,eAAO,KAAK,KAAK,UAAU,EAAE,MAAM,YAAY,UAAU,OAAO,CAAC,CAAC;AAAA,MACpE;AACA,cAAQ,IAAI,uBAAuB;AAEnC,aAAO,GAAG,SAAS,CAAC,MAAc,WAAmB;AACnD,gBAAQ,IAAI,kCAAkC,IAAI,WAAW,OAAO,SAAS,CAAC,EAAE;AAAA,MAClF,CAAC;AACD,aAAO,GAAG,SAAS,CAAC,QAAe;AACjC,gBAAQ,MAAM,sBAAsB,GAAG;AAAA,MACzC,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,cAAQ,MAAM,qCAAqC,GAAG;AAAA,IACxD;AAAA,EACF,CAAC;AAGD,UAAQ,IAAI,eAAe,YAAY;AACrC,WAAO,EAAE,QAAQ,KAAK;AAAA,EACxB,CAAC;AAGD,UAAQ,IAAI,eAAe,YAAY;AACrC,WAAO,MAAM,cAAc,uBAAuB;AAAA,EACpD,CAAC;AAGD,UAAQ,IAAI,eAAe,YAAY;AACrC,WAAO,cAAc,iBAAiB;AAAA,EACxC,CAAC;AAED,UAAQ,IAAI,eAAe,OAAO,SAAS,UAAU;AACnD,QAAI;AACF,YAAM,SAAS,QAAQ;AACvB,oBAAc,mBAAmB,MAAM;AACvC,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB,SAAS,KAAK;AACZ,YAAM,KAAK,GAAG;AACd,aAAO,EAAE,OAAO,iBAAiB;AAAA,IACnC;AAAA,EACF,CAAC;AAGD,QAAM,mBAAmB,IAAI,iBAAiB,aAAa;AAE3D,UAAQ,IAAI,iBAAiB,OAAO,YAAY;AAC9C,UAAM,EAAE,MAAM,IAAI,QAAQ;AAC1B,UAAM,WAAW,MAAM,iBAAiB,aAAa,SAAS,YAAY;AAE1E,UAAM,WAAW,iBAAiB,eAAe;AACjD,UAAM,OAAO,IAAI,IAAI,SAAS,IAAI,CAACC,OAAMA,GAAE,SAAS,CAAC;AACrD,UAAM,SAAS;AAAA,MACb,GAAG,SAAS,IAAI,CAACA,QAAO;AAAA,QACtB,WAAWA,GAAE;AAAA,QACb,SAASA,GAAE;AAAA,QACX,OAAOA,GAAE;AAAA,QACT,SAASA,GAAE;AAAA,QACX,UAAU;AAAA,QACV,WAAWA,GAAE;AAAA,QACb,WAAWA,GAAE;AAAA,QACb,aAAa;AAAA,QACb,QAAQ;AAAA,MACV,EAAE;AAAA,MACF,GAAG,SAAS,OAAO,CAACA,OAAM,CAAC,KAAK,IAAIA,GAAE,SAAS,CAAC;AAAA,IAClD;AACA,WAAO;AAAA,EACT,CAAC;AAGD,UAAQ,IAAI,wBAAwB,YAAY;AAC9C,WAAO,gBAAgB,aAAa,UAAU;AAAA,EAChD,CAAC;AAED,UAAQ,IAAI,mCAAmC,OAAO,SAAS,UAAU;AACvE,UAAM,EAAE,UAAU,IAAI,QAAQ;AAC9B,UAAM,UAAU,gBAAgB,WAAW,YAAY,SAAS;AAChE,QAAI,CAAC,SAAS;AAAE,YAAM,KAAK,GAAG;AAAG,aAAO,EAAE,OAAO,oBAAoB;AAAA,IAAE;AACvE,WAAO;AAAA,EACT,CAAC;AAED,UAAQ,IAAI,iDAAiD,OAAO,SAAS,UAAU;AACrF,UAAM,EAAE,WAAW,OAAO,IAAI,QAAQ;AACtC,UAAM,OAAO,gBAAgB,QAAQ,YAAY,WAAW,MAAM;AAClE,QAAI,CAAC,MAAM;AAAE,YAAM,KAAK,GAAG;AAAG,aAAO,EAAE,OAAO,iBAAiB;AAAA,IAAE;AACjE,WAAO;AAAA,EACT,CAAC;AAGD,UAAQ,OAAO,mCAAmC,OAAO,YAAY;AACnE,UAAM,EAAE,UAAU,IAAI,QAAQ;AAC9B,UAAM,UAAU,gBAAgB,cAAc,YAAY,SAAS;AACnE,WAAO,EAAE,SAAS,QAAQ;AAAA,EAC5B,CAAC;AAGD,UAAQ,OAAO,wBAAwB,YAAY;AACjD,UAAM,QAAQ,gBAAgB,kBAAkB,UAAU;AAC1D,WAAO,EAAE,SAAS,MAAM,SAAS,MAAM;AAAA,EACzC,CAAC;AAGD,MAAI,gBAAyF;AAC7F,QAAM,gBAAgB;AAEtB,UAAQ,IAAI,aAAa,YAAY;AACnC,UAAM,MAAM,KAAK,IAAI;AACrB,QAAI,iBAAiB,MAAM,cAAc,KAAK,eAAe;AAC3D,aAAO,cAAc;AAAA,IACvB;AACA,UAAM,WAAW,IAAI,mBAAmB,UAAU;AAClD,UAAM,QAAQ,SAAS,QAAQ;AAC/B,oBAAgB,EAAE,OAAO,IAAI,IAAI;AACjC,WAAO;AAAA,EACT,CAAC;AAGD,UAAQ,IAAI,aAAa,OAAO,SAAS,UAAU;AACjD,UAAM,EAAE,MAAM,SAAS,IAAI,QAAQ;AACnC,QAAI,CAAC,UAAU;AACb,YAAM,KAAK,GAAG;AACd,aAAO,EAAE,OAAO,yBAAyB;AAAA,IAC3C;AAGA,QAAI,SAAS,SAAS,IAAI,KAAKD,OAAK,WAAW,QAAQ,GAAG;AACxD,YAAM,KAAK,GAAG;AACd,aAAO,EAAE,OAAO,eAAe;AAAA,IACjC;AAEA,UAAM,WAAWA,OAAK,QAAQ,YAAY,QAAQ;AAGlD,QAAI,CAAC,SAAS,WAAW,UAAU,GAAG;AACpC,YAAM,KAAK,GAAG;AACd,aAAO,EAAE,OAAO,6BAA6B;AAAA,IAC/C;AAEA,QAAI;AACF,YAAM,UAAUE,IAAG,aAAa,UAAU,OAAO;AACjD,aAAO,EAAE,SAAS,MAAM,SAAS;AAAA,IACnC,QAAQ;AACN,YAAM,KAAK,GAAG;AACd,aAAO,EAAE,OAAO,iBAAiB;AAAA,IACnC;AAAA,EACF,CAAC;AAGD,UAAQ,IAAI,iBAAiB,OAAO,SAAS,UAAU;AACrD,UAAM,EAAE,MAAM,SAAS,IAAI,QAAQ;AACnC,QAAI,CAAC,UAAU;AACb,YAAM,KAAK,GAAG;AACd,aAAO,EAAE,OAAO,yBAAyB;AAAA,IAC3C;AACA,QAAI,SAAS,SAAS,IAAI,KAAKF,OAAK,WAAW,QAAQ,GAAG;AACxD,YAAM,KAAK,GAAG;AACd,aAAO,EAAE,OAAO,eAAe;AAAA,IACjC;AACA,UAAM,WAAWA,OAAK,QAAQ,YAAY,QAAQ;AAClD,QAAI,CAAC,SAAS,WAAW,UAAU,GAAG;AACpC,YAAM,KAAK,GAAG;AACd,aAAO,EAAE,OAAO,6BAA6B;AAAA,IAC/C;AACA,QAAI,CAACE,IAAG,WAAW,QAAQ,GAAG;AAC5B,YAAM,KAAK,GAAG;AACd,aAAO,EAAE,OAAO,iBAAiB;AAAA,IACnC;AACA,UAAM,MAAMF,OAAK,QAAQ,QAAQ,EAAE,YAAY;AAC/C,UAAM,UAAkC;AAAA,MACtC,QAAQ;AAAA,MAAa,QAAQ;AAAA,MAAc,SAAS;AAAA,MACpD,QAAQ;AAAA,MAAa,SAAS;AAAA,MAAc,QAAQ;AAAA,MACpD,QAAQ;AAAA,MAAa,SAAS;AAAA,MAC9B,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AACA,UAAM,OAAO,QAAQ,GAAG,KAAK;AAC7B,UAAM,SAASE,IAAG,iBAAiB,QAAQ;AAC3C,UAAM,KAAK,IAAI;AACf,WAAO,MAAM,KAAK,MAAM;AAAA,EAC1B,CAAC;AAGD,QAAM,YAAYF,OAAK,KAAK,YAAY,UAAU,YAAY;AAE9D,UAAQ,IAAI,cAAc,YAAY;AACpC,QAAI;AACF,YAAM,MAAME,IAAG,aAAa,WAAW,OAAO;AAC9C,YAAM,OAAOC,MAAK,KAAK,GAAG;AAC1B,aAAO,EAAE,OAAO,MAAM,SAAS,CAAC,EAAE;AAAA,IACpC,QAAQ;AACN,aAAO,EAAE,OAAO,CAAC,EAAE;AAAA,IACrB;AAAA,EACF,CAAC;AAED,UAAQ,IAAI,cAAc,OAAO,SAAS,UAAU;AAClD,QAAI;AACF,YAAM,EAAE,MAAM,IAAI,QAAQ;AAC1B,MAAAD,IAAG,UAAUF,OAAK,QAAQ,SAAS,GAAG,EAAE,WAAW,KAAK,CAAC;AACzD,MAAAE,IAAG,cAAc,WAAWC,MAAK,KAAK,EAAE,MAAM,GAAG,EAAE,WAAW,GAAG,CAAC,GAAG,OAAO;AAC5E,aAAO,EAAE,SAAS,KAAK;AAAA,IACzB,SAAS,KAAK;AACZ,YAAM,KAAK,GAAG;AACd,aAAO,EAAE,OAAO,uBAAuB;AAAA,IACzC;AAAA,EACF,CAAC;AAGD,QAAM,cAAcH,OAAK,QAAQ,WAAW,gBAAgB;AAC5D,MAAI,CAACE,IAAG,WAAW,WAAW,GAAG;AAC/B,YAAQ,KAAK,qCAAqC,WAAW,EAAE;AAC/D,YAAQ,KAAK,oEAAoE;AAAA,EACnF;AACA,MAAIA,IAAG,WAAW,WAAW,GAAG;AAC9B,UAAM,QAAQ,SAAS,eAAe;AAAA,MACpC,MAAM;AAAA,MACN,QAAQ;AAAA,IACV,CAAC;AAGD,YAAQ,mBAAmB,CAAC,MAAM,UAAU;AAC1C,YAAM,SAAS,YAAY;AAAA,IAC7B,CAAC;AAAA,EACH;AAGA,QAAM,WAAW,YAAY;AAC3B,YAAQ,IAAI,oBAAoB;AAChC,aAAS,MAAM;AACf,iBAAa,MAAM,iBAAiB,SAAS,CAAC;AAC9C,cAAU,MAAM;AAChB,eAAW,MAAM;AACjB,UAAM,iBAAiB,SAAS;AAChC,UAAM,QAAQ,MAAM;AACpB,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,GAAG,UAAU,QAAQ;AAC7B,UAAQ,GAAG,WAAW,QAAQ;AAE9B,MAAI;AACF,UAAM,QAAQ,OAAO,EAAE,MAAM,MAAM,UAAU,CAAC;AAAA,EAChD,SAAS,KAAc;AACrB,QAAK,IAA8B,SAAS,cAAc;AACxD,cAAQ,MAAM,QAAQ,IAAI,wEAAwE;AAClG,cAAQ,MAAM,4BAA4B;AAC1C,cAAQ,MAAM,kCAAkC,IAAI,EAAE;AACtD,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,UAAM;AAAA,EACR;AACA,UAAQ,IAAI,4CAA4C,IAAI,EAAE;AAC9D,UAAQ,IAAI,kBAAkB,UAAU,EAAE;AAC1C,UAAQ,IAAI,gBAAgB,UAAU,QAAQ,EAAE,MAAM,oBAAoB;AAC1E,QAAM,EAAE,UAAU,GAAG,QAAQ,EAAE,IAAI,WAAW,gBAAgB;AAC9D,UAAQ,IAAI,gBAAgB,EAAE,MAAM,cAAc,EAAE,MAAM,SAAS;AAEnE,SAAO,EAAE,SAAS,kBAAkB,cAAc;AACpD;;;AD9VA,IAAM,cAAc,SAAS,QAAQ,SAAS,KAAK,MAAM,GAAG,EAAE,CAAC,GAAG,EAAE;AACpE,IAAI,cAAc,IAAI;AACpB,UAAQ,MAAM,6DAA6D,QAAQ,SAAS,IAAI,EAAE;AAClG,UAAQ,MAAM,gDAAgD;AAC9D,UAAQ,KAAK,CAAC;AAChB;AAGA,OAAO,QAAQ,IAAI;AACnB,OAAO,QAAQ,IAAI;AACnB,OAAO,QAAQ,IAAI;AAEnB,IAAM,eAAe;AAErB,SAAS,aAAa;AACpB,UAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2CAa6B,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrD,QAAQ,CAAC;AACX;AAEA,SAAS,gBAAgB,UAA0B;AACjD,QAAM,OAAO,QAAQ,IAAI,QAAQ,QAAQ,IAAI,eAAe;AAK5D,MAAI,MAAM;AACV,MAAI,YAAY;AAEhB,SAAO,QAAQE,OAAK,QAAQ,GAAG,GAAG;AAChC,QAAIC,KAAG,WAAWD,OAAK,KAAK,KAAK,qBAAqB,CAAC,GAAG;AACxD,aAAO;AAAA,IACT;AACA,QACEC,KAAG,WAAWD,OAAK,KAAK,KAAK,MAAM,CAAC,KACpCC,KAAG,WAAWD,OAAK,KAAK,KAAK,QAAQ,CAAC,GACtC;AACA,kBAAY;AAAA,IACd;AACA,UAAM,SAASA,OAAK,QAAQ,GAAG;AAE/B,QAAI,QAAQ,WAAW,QAAQ,QAAQ,SAAU;AACjD,UAAM;AAAA,EACR;AAGA,MAAI,QAAQ,cAAc,QAAQ,aAAa,MAAM;AACnD,YAAQ,KAAK,6CAA6C,IAAI,IAAI;AAClE,YAAQ,KAAK,kCAAkC;AAAA,EACjD;AAEA,SAAO;AACT;AAEA,SAAS,kBAAkB,QAAyB;AAClD,MAAI,QAAQ,IAAI,mBAAmB;AACjC,WAAOA,OAAK,QAAQ,QAAQ,IAAI,iBAAiB;AAAA,EACnD;AACA,MAAI,QAAQ;AACV,UAAM,WAAWA,OAAK,QAAQ,MAAM;AACpC,QAAI,CAACC,KAAG,WAAW,QAAQ,GAAG;AAC5B,cAAQ,MAAM,oCAAoC,QAAQ,EAAE;AAC5D,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,QAAI,CAACA,KAAG,SAAS,QAAQ,EAAE,YAAY,GAAG;AACxC,cAAQ,MAAM,2BAA2B,QAAQ,EAAE;AACnD,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,WAAO;AAAA,EACT;AACA,SAAO,gBAAgB,QAAQ,IAAI,CAAC;AACtC;AAEA,IAAM,WAAW,oBAAI,IAAI,CAAC,SAAS,QAAQ,UAAU,QAAQ,MAAM,CAAC;AAEpE,eAAe,OAAO;AACpB,QAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AAIjC,MAAI;AACJ,MAAI;AAEJ,MAAI,KAAK,WAAW,GAAG;AACrB,cAAU;AAAA,EACZ,WAAW,KAAK,CAAC,MAAM,YAAY,KAAK,CAAC,MAAM,MAAM;AACnD,cAAU;AAAA,EACZ,WAAW,SAAS,IAAI,KAAK,CAAC,CAAC,GAAG;AAChC,cAAU,KAAK,CAAC;AAChB,aAAS,KAAK,CAAC;AAAA,EACjB,OAAO;AAEL,cAAU;AACV,aAAS,KAAK,CAAC;AAAA,EACjB;AAEA,MAAI,YAAY,QAAQ;AACtB,eAAW;AACX;AAAA,EACF;AAEA,QAAM,aAAa,kBAAkB,MAAM;AAE3C,UAAQ,SAAS;AAAA,IACf,KAAK,SAAS;AACZ,YAAM,OAAO,SAAS,QAAQ,IAAI,cAAc,OAAO,YAAY,GAAG,EAAE;AACxE,YAAM,YAAY,MAAM,UAAU;AAGlC,YAAM,MAAM,oBAAoB,IAAI;AACpC,aAAO,MAAM,EAAE,KAAK,CAAC,QAAQ,IAAI,QAAQ,GAAG,CAAC,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAG7D,YAAM,EAAE,eAAe,GAAG,IAAI,MAAM;AACpC,YAAM,KAAK,IAAI,GAAG,UAAU;AAC5B,SAAG,iBAAiB;AACpB,SAAG,uBAAuB,EAAE,KAAK,CAAC,iBAAiB;AACjD,cAAM,UAAU,OAAO,QAAQ,YAAY,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,SAAS;AAC3E,YAAI,QAAQ,SAAS,GAAG;AACtB,kBAAQ,IAAI,gCAAgC;AAC5C,qBAAW,CAAC,KAAK,IAAI,KAAK,SAAS;AACjC,oBAAQ,IAAI,cAAc,GAAG,KAAK,KAAK,GAAG,qBAAgB,KAAK,WAAW,EAAE;AAAA,UAC9E;AACA,kBAAQ,IAAI;AAAA,QACd;AAAA,MACF,CAAC,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AACjB;AAAA,IACF;AAAA,IAEA,KAAK,QAAQ;AACX,YAAM,EAAE,eAAAC,eAAc,IAAI,MAAM;AAChC,YAAM,gBAAgB,IAAIA,eAAc,UAAU;AAClD,oBAAc,iBAAiB;AAC/B,oBAAc,cAAc;AAC5B,cAAQ,IAAI,0BAA0B,UAAU,EAAE;AAClD;AAAA,IACF;AAAA,IAEA,KAAK,UAAU;AACb,YAAM,EAAE,eAAAA,eAAc,IAAI,MAAM;AAChC,YAAM,gBAAgB,IAAIA,eAAc,UAAU;AAClD,YAAM,WAAW,cAAc,oBAAoB;AACnD,UAAI,CAAC,UAAU;AACb,gBAAQ,IAAI,sDAAsD;AAClE;AAAA,MACF;AACA,cAAQ,IAAI,cAAc,SAAS,IAAI,EAAE;AACzC,cAAQ,IAAI,UAAU,SAAS,MAAM,MAAM,EAAE;AAC7C,iBAAW,QAAQ,SAAS,OAAO;AACjC,gBAAQ,IAAI,OAAO,KAAK,EAAE,KAAK,KAAK,KAAK,KAAK,KAAK,IAAI,GAAG,KAAK,OAAO,WAAM,KAAK,IAAI,KAAK,EAAE,EAAE;AAAA,MAChG;AACA;AAAA,IACF;AAAA,IAEA,KAAK,QAAQ;AACX,UAAI;AACF,cAAM,OAAO,SAAS,QAAQ,IAAI,cAAc,OAAO,YAAY,GAAG,EAAE;AACxE,cAAM,MAAM,MAAM,MAAM,oBAAoB,IAAI,aAAa;AAC7D,YAAI,IAAI,IAAI;AACV,kBAAQ,IAAI,4BAA4B;AACxC,kBAAQ,KAAK,QAAQ,KAAK,SAAS;AAAA,QACrC;AAAA,MACF,QAAQ;AACN,gBAAQ,IAAI,gCAAgC;AAAA,MAC9C;AACA;AAAA,IACF;AAAA,IAEA;AACE,cAAQ,MAAM,oBAAoB,OAAO,EAAE;AAC3C,iBAAW;AACX,cAAQ,KAAK,CAAC;AAAA,EAClB;AACF;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,UAAQ,MAAM,gBAAgB,GAAG;AACjC,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["path","fs","path","fs","yaml","fs","os","path","stripAnsi","MAX_BUFFER_SIZE","path","fs","os","spawn","fs","os","path","MAX_SCROLLBACK_BYTES","path","fs","path","simpleGit","fs","fs","path","yaml","fs","path","watch","fs","path","fs","path","execFile","execFile","promisify","execFileAsync","path","s","fs","yaml","path","fs","ConfigManager"]}
|
|
1
|
+
{"version":3,"sources":["../src/workspace/ConfigManager.ts","../src/cli.ts","../src/index.ts","../src/pty/PtyManager.ts","../src/comm/StatuslineParser.ts","../src/comm/ShellReadyDetector.ts","../src/comm/AgentReadyDetector.ts","../src/comm/OutputStateAnalyzer.ts","../src/pty/ActivityParser.ts","../src/runtime/AcpRuntime.ts","../src/git/WorktreeManager.ts","../src/git/GitService.ts","../src/workspace/WorkspaceManager.ts","../src/workspace/AgentsYamlWriter.ts","../src/fs/FsWatcher.ts","../src/ws/handlers.ts","../src/deps/DependencyAnalyzer.ts","../src/history/SessionRecorder.ts","../src/workspace/SessionDiscovery.ts"],"sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\nimport os from 'node:os'\nimport { execFile } from 'node:child_process'\nimport { promisify } from 'node:util'\nimport yaml from 'js-yaml'\nimport type { GlobalConfig, WorkspaceConfig, AgentDefinition, AgentAvailability } from '../types.ts'\n\nconst execFileAsync = promisify(execFile)\n\nconst GLOBAL_DIR = path.join(os.homedir(), '.nexus')\nconst GLOBAL_CONFIG_PATH = path.join(GLOBAL_DIR, 'config.yaml')\n\nconst DEFAULT_GLOBAL_CONFIG: GlobalConfig = {\n version: '1',\n defaults: {\n shell: process.env.SHELL || '/bin/bash',\n scrollback_lines: 5000,\n grid_columns: 2,\n history_retention_days: 30,\n theme: 'dark-ide',\n },\n agents: {\n claudecode: {\n bin: 'claude',\n continue_flag: '--continue',\n resume_flag: '--resume',\n yolo_flag: '--dangerously-skip-permissions',\n statusline: true,\n transport: 'pty',\n env: {},\n },\n codex: {\n bin: 'codex',\n continue_flag: '',\n resume_flag: '',\n yolo_flag: '',\n statusline: false,\n transport: 'pty',\n env: {},\n },\n opencode: {\n bin: 'opencode',\n continue_flag: '--continue',\n resume_flag: '',\n yolo_flag: '--yolo',\n statusline: false,\n transport: 'acp',\n env: {},\n },\n 'kimi-cli': {\n bin: 'kimi',\n continue_flag: '--continue',\n resume_flag: '',\n yolo_flag: '',\n statusline: false,\n transport: 'pty',\n env: {},\n },\n qodercli: {\n bin: 'qodercli',\n continue_flag: '-c',\n resume_flag: '-r',\n yolo_flag: '--yolo',\n statusline: false,\n transport: 'pty',\n env: {},\n },\n },\n}\n\nexport class ConfigManager {\n private globalConfig: GlobalConfig | null = null\n private workspaceConfig: WorkspaceConfig | null = null\n private projectDir: string\n\n constructor(projectDir: string) {\n this.projectDir = projectDir\n }\n\n loadGlobalConfig(): GlobalConfig {\n if (this.globalConfig) return this.globalConfig\n\n if (fs.existsSync(GLOBAL_CONFIG_PATH)) {\n const content = fs.readFileSync(GLOBAL_CONFIG_PATH, 'utf-8')\n this.globalConfig = yaml.load(content) as GlobalConfig\n // Merge in any default agents or missing fields from the saved config\n let updated = false\n for (const [key, def] of Object.entries(DEFAULT_GLOBAL_CONFIG.agents)) {\n if (!this.globalConfig.agents[key]) {\n this.globalConfig.agents[key] = def\n updated = true\n } else {\n // Merge missing fields from defaults into existing agent definition\n const existing = this.globalConfig.agents[key]\n for (const [field, value] of Object.entries(def)) {\n if (!(field in existing)) {\n (existing as Record<string, unknown>)[field] = value\n updated = true\n }\n }\n }\n }\n if (updated) {\n this.saveGlobalConfig(this.globalConfig)\n }\n } else {\n this.globalConfig = { ...DEFAULT_GLOBAL_CONFIG }\n // Agent detection is async now — save defaults first, detect in background\n this.saveGlobalConfig(this.globalConfig)\n this.detectAgentsAsync().then((detected) => {\n if (Object.keys(detected).length > 0 && this.globalConfig) {\n this.globalConfig.agents = { ...this.globalConfig.agents, ...detected }\n this.saveGlobalConfig(this.globalConfig)\n }\n }).catch(() => { /* ignore detection failure */ })\n }\n\n return this.globalConfig\n }\n\n private saveGlobalConfig(config: GlobalConfig): void {\n fs.mkdirSync(GLOBAL_DIR, { recursive: true })\n fs.writeFileSync(GLOBAL_CONFIG_PATH, yaml.dump(config, { lineWidth: -1 }))\n }\n\n loadWorkspaceConfig(): WorkspaceConfig | null {\n if (this.workspaceConfig) return this.workspaceConfig\n\n const configPath = path.join(this.projectDir, '.nexus', 'config.yaml')\n if (fs.existsSync(configPath)) {\n const content = fs.readFileSync(configPath, 'utf-8')\n const parsed = yaml.load(content) as WorkspaceConfig | null\n if (parsed) {\n if (!Array.isArray(parsed.panes)) parsed.panes = []\n this.workspaceConfig = parsed\n return this.workspaceConfig\n }\n }\n\n return null\n }\n\n saveWorkspaceConfig(config: WorkspaceConfig): void {\n const nexusDir = path.join(this.projectDir, '.nexus')\n fs.mkdirSync(nexusDir, { recursive: true })\n const configPath = path.join(nexusDir, 'config.yaml')\n fs.writeFileSync(configPath, yaml.dump(config, { lineWidth: -1 }))\n this.workspaceConfig = config\n }\n\n initWorkspace(): WorkspaceConfig {\n const existing = this.loadWorkspaceConfig()\n if (existing) return existing\n\n const dirName = path.basename(this.projectDir)\n const isGit = fs.existsSync(path.join(this.projectDir, '.git'))\n\n const config: WorkspaceConfig = {\n version: '1',\n name: dirName,\n description: '',\n repository: {\n path: '.',\n git: isGit,\n },\n panes: [],\n }\n\n this.saveWorkspaceConfig(config)\n return config\n }\n\n private async detectAgentsAsync(): Promise<Record<string, AgentDefinition>> {\n const agents: Record<string, AgentDefinition> = {}\n\n const agentBins: Array<{ key: string; bin: string; flag: string; statusline: boolean; transport: 'pty' | 'acp' }> = [\n { key: 'claudecode', bin: 'claude', flag: '--continue', statusline: true, transport: 'pty' },\n { key: 'codex', bin: 'codex', flag: '', statusline: false, transport: 'pty' },\n { key: 'opencode', bin: 'opencode', flag: '--continue', statusline: false, transport: 'acp' },\n { key: 'kimi-cli', bin: 'kimi', flag: '--continue', statusline: false, transport: 'pty' },\n { key: 'qodercli', bin: 'qodercli', flag: '-c', statusline: false, transport: 'pty' },\n ]\n\n const results = await Promise.allSettled(\n agentBins.map(async (agent) => {\n await execFileAsync('which', [agent.bin], { timeout: 3000 })\n return agent\n })\n )\n\n for (const result of results) {\n if (result.status === 'fulfilled') {\n const agent = result.value\n agents[agent.key] = {\n bin: agent.bin,\n continue_flag: agent.flag,\n statusline: agent.statusline,\n transport: agent.transport,\n env: {},\n }\n }\n }\n\n return agents\n }\n\n getAgentDefinition(agentType: string): AgentDefinition | undefined {\n const global = this.loadGlobalConfig()\n return global.agents[agentType]\n }\n\n getShell(): string {\n const global = this.loadGlobalConfig()\n const configured = global.defaults.shell\n // Prefer zsh > configured > $SHELL > /bin/sh\n // Include macOS Homebrew paths for Apple Silicon and Intel\n const candidates = [\n '/opt/homebrew/bin/zsh', // macOS Apple Silicon Homebrew\n '/usr/local/bin/zsh', // macOS Intel Homebrew\n '/usr/bin/zsh', // Linux\n '/bin/zsh', // macOS default / Linux\n configured,\n process.env.SHELL,\n '/bin/bash',\n '/bin/sh',\n ]\n for (const sh of candidates) {\n if (!sh) continue\n try {\n fs.accessSync(sh, fs.constants.X_OK)\n return sh\n } catch {\n // try next\n }\n }\n return '/bin/sh'\n }\n\n /**\n * Check which agents are available (installed) on the system.\n * Returns a record of agentType → { installed, bin, installHint }\n */\n async checkAgentAvailability(): Promise<Record<string, AgentAvailability>> {\n const global = this.loadGlobalConfig()\n const knownAgents: Array<{ key: string; bin: string; installHint: string }> = [\n { key: 'claudecode', bin: 'claude', installHint: 'npm install -g @anthropic-ai/claude-code' },\n { key: 'codex', bin: 'codex', installHint: 'npm install -g @openai/codex' },\n { key: 'opencode', bin: 'opencode', installHint: 'go install github.com/opencode-ai/opencode@latest' },\n { key: 'kimi-cli', bin: 'kimi', installHint: 'pip install kimi-cli' },\n { key: 'qodercli', bin: 'qodercli', installHint: 'See https://docs.qoder.com/zh/cli/using-cli' },\n ]\n\n const checks = await Promise.allSettled(\n knownAgents.map(async (agent) => {\n const def = global.agents[agent.key]\n const bin = def?.bin || agent.bin\n try {\n await execFileAsync('which', [bin], { timeout: 3000 })\n return { ...agent, bin, installed: true }\n } catch {\n return { ...agent, bin, installed: false }\n }\n })\n )\n\n const result: Record<string, AgentAvailability> = {}\n for (const check of checks) {\n if (check.status === 'fulfilled') {\n const { key, bin, installHint, installed } = check.value\n result[key] = { installed, bin, installHint }\n }\n }\n\n return result\n }\n\n updateGlobalConfig(config: GlobalConfig): void {\n this.globalConfig = config\n this.saveGlobalConfig(config)\n }\n\n getProjectDir(): string {\n return this.projectDir\n }\n}\n","import path from 'node:path'\nimport fs from 'node:fs'\nimport { startServer } from './index.ts'\n\n// Check Node.js version — node-pty requires Node 22+\nconst nodeVersion = parseInt(process.versions.node.split('.')[0], 10)\nif (nodeVersion < 22) {\n console.error(`Error: Nexus requires Node.js >= 22, but you are running v${process.versions.node}`)\n console.error(` Please upgrade: nvm install 22 && nvm use 22`)\n process.exit(1)\n}\n\n// Clean up parent session env so spawned PTYs don't detect nesting\ndelete process.env.CLAUDECODE\ndelete process.env.CLAUDE_CODE\ndelete process.env.CLAUDE_CODE_ENTRYPOINT\n\nconst DEFAULT_PORT = 7700\n\nfunction printUsage() {\n console.log(`\n Usage: nexus [command] [directory]\n\n Commands:\n start [dir] Start the Nexus server (default)\n init [dir] Initialize .nexus/ config in a project\n status [dir] Show workspace status\n stop Stop the running server\n\n Arguments:\n dir Path to the project directory (defaults to cwd)\n\n Environment:\n NEXUS_PORT Server port (default: ${DEFAULT_PORT})\n\n Examples:\n nexus # Start in current directory\n nexus ~/projects/my-app # Start with a specific project\n nexus start ~/projects/app # Explicit start command\n nexus init . # Initialize config in cwd\n`.trimEnd())\n}\n\nfunction findProjectRoot(startDir: string): string {\n const home = process.env.HOME || process.env.USERPROFILE || ''\n\n // Walk up from startDir, prefer the highest-level match\n // (monorepo root, not a nested package)\n // Stop at HOME — never go above it\n let dir = startDir\n let bestMatch = startDir\n\n while (dir !== path.dirname(dir)) {\n if (fs.existsSync(path.join(dir, 'pnpm-workspace.yaml'))) {\n return dir // pnpm monorepo root is definitive\n }\n if (\n fs.existsSync(path.join(dir, '.git')) ||\n fs.existsSync(path.join(dir, '.nexus'))\n ) {\n bestMatch = dir\n }\n const parent = path.dirname(dir)\n // Don't traverse above HOME directory\n if (home && parent === home && dir !== startDir) break\n dir = parent\n }\n\n // Warn if resolved to HOME — likely a mistake\n if (home && bestMatch === home && startDir === home) {\n console.warn(`Warning: Running Nexus in HOME directory (${home}).`)\n console.warn(` Consider: nexus <project-path>`)\n }\n\n return bestMatch\n}\n\nfunction resolveProjectDir(dirArg?: string): string {\n if (process.env.NEXUS_PROJECT_DIR) {\n return path.resolve(process.env.NEXUS_PROJECT_DIR)\n }\n if (dirArg) {\n const resolved = path.resolve(dirArg)\n if (!fs.existsSync(resolved)) {\n console.error(`Error: directory does not exist: ${resolved}`)\n process.exit(1)\n }\n if (!fs.statSync(resolved).isDirectory()) {\n console.error(`Error: not a directory: ${resolved}`)\n process.exit(1)\n }\n return resolved\n }\n return findProjectRoot(process.cwd())\n}\n\nconst COMMANDS = new Set(['start', 'init', 'status', 'stop', 'help'])\n\nasync function main() {\n const args = process.argv.slice(2)\n\n // Parse command and directory argument\n // Support: nexus <dir>, nexus <cmd> <dir>, nexus <cmd>\n let command: string\n let dirArg: string | undefined\n\n if (args.length === 0) {\n command = 'start'\n } else if (args[0] === '--help' || args[0] === '-h') {\n command = 'help'\n } else if (COMMANDS.has(args[0])) {\n command = args[0]\n dirArg = args[1]\n } else {\n // First arg is not a known command — treat it as a directory\n command = 'start'\n dirArg = args[0]\n }\n\n if (command === 'help') {\n printUsage()\n return\n }\n\n const projectDir = resolveProjectDir(dirArg)\n\n switch (command) {\n case 'start': {\n const port = parseInt(process.env.NEXUS_PORT || String(DEFAULT_PORT), 10)\n await startServer(port, projectDir)\n\n // Auto-open browser (non-blocking, failure is ok)\n const url = `http://localhost:${port}`\n import('open').then((mod) => mod.default(url)).catch(() => {})\n\n // Check agent availability after server is up (non-blocking)\n const { ConfigManager: CM } = await import('./workspace/ConfigManager.ts')\n const cm = new CM(projectDir)\n cm.loadGlobalConfig()\n cm.checkAgentAvailability().then((availability) => {\n const missing = Object.entries(availability).filter(([, a]) => !a.installed)\n if (missing.length > 0) {\n console.log('\\n Optional agents not found:')\n for (const [key, info] of missing) {\n console.log(` \\u26A0 ${key} (${info.bin}) — install: ${info.installHint}`)\n }\n console.log()\n }\n }).catch(() => {})\n break\n }\n\n case 'init': {\n const { ConfigManager } = await import('./workspace/ConfigManager.ts')\n const configManager = new ConfigManager(projectDir)\n configManager.loadGlobalConfig()\n configManager.initWorkspace()\n console.log(`Initialized .nexus/ in ${projectDir}`)\n break\n }\n\n case 'status': {\n const { ConfigManager } = await import('./workspace/ConfigManager.ts')\n const configManager = new ConfigManager(projectDir)\n const wsConfig = configManager.loadWorkspaceConfig()\n if (!wsConfig) {\n console.log('No .nexus/config.yaml found. Run `nexus init` first.')\n break\n }\n console.log(`Workspace: ${wsConfig.name}`)\n console.log(`Panes: ${wsConfig.panes.length}`)\n for (const pane of wsConfig.panes) {\n console.log(` - ${pane.id} [${pane.agent}] ${pane.name}${pane.task ? ` — ${pane.task}` : ''}`)\n }\n break\n }\n\n case 'stop': {\n try {\n const port = parseInt(process.env.NEXUS_PORT || String(DEFAULT_PORT), 10)\n const res = await fetch(`http://localhost:${port}/api/health`)\n if (res.ok) {\n console.log('Sending shutdown signal...')\n process.kill(process.pid, 'SIGTERM')\n }\n } catch {\n console.log('No running Nexus server found.')\n }\n break\n }\n\n default:\n console.error(`Unknown command: ${command}`)\n printUsage()\n process.exit(1)\n }\n}\n\nmain().catch((err) => {\n console.error('Fatal error:', err)\n process.exit(1)\n})\n","import Fastify from 'fastify'\nimport fastifyWebsocket from '@fastify/websocket'\nimport fastifyStatic from '@fastify/static'\nimport path from 'node:path'\nimport fs from 'node:fs'\nimport yaml from 'js-yaml'\nimport { fileURLToPath } from 'node:url'\nimport { ConfigManager } from './workspace/ConfigManager.ts'\nimport { WorkspaceManager } from './workspace/WorkspaceManager.ts'\nimport { AgentsYamlWriter } from './workspace/AgentsYamlWriter.ts'\nimport { FsWatcher } from './fs/FsWatcher.ts'\nimport { GitService } from './git/GitService.ts'\nimport { setupWsHandlers } from './ws/handlers.ts'\nimport { DependencyAnalyzer } from './deps/DependencyAnalyzer.ts'\nimport { SessionRecorder } from './history/SessionRecorder.ts'\nimport { SessionDiscovery } from './workspace/SessionDiscovery.ts'\nimport type { GlobalConfig } from './types.ts'\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url))\n\nexport async function startServer(port: number, projectDir: string) {\n const fastify = Fastify({ logger: false })\n\n // Managers\n const configManager = new ConfigManager(projectDir)\n configManager.loadGlobalConfig()\n\n const workspaceManager = new WorkspaceManager(configManager)\n await workspaceManager.init()\n\n // agents.yaml writer — updates on pane state changes\n const agentsWriter = new AgentsYamlWriter(projectDir)\n\n workspaceManager.onEvents({\n onPaneAdded: () => agentsWriter.update(workspaceManager.getPanes()),\n onPaneRemoved: () => agentsWriter.update(workspaceManager.getPanes()),\n onPaneStatus: () => agentsWriter.update(workspaceManager.getPanes()),\n onPaneMeta: () => agentsWriter.update(workspaceManager.getPanes()),\n })\n\n // Session recorder — records replay history\n const wsConfig = configManager.loadWorkspaceConfig()\n const globalConfig = configManager.loadGlobalConfig()\n const recorder = new SessionRecorder(projectDir, wsConfig?.name || 'Nexus', globalConfig.defaults.history_retention_days)\n\n workspaceManager.onEvents({\n onPaneAdded: (pane) => recorder.onPaneAdded(pane),\n onPaneRemoved: (paneId) => recorder.onPaneRemoved(paneId),\n onPaneStatus: (paneId, status) => {\n const panes = workspaceManager.getPanes()\n const pane = panes.find((p) => p.id === paneId)\n recorder.onPaneStatus(paneId, status, pane)\n },\n onPaneMeta: (paneId, meta) => recorder.onPaneMeta(paneId, meta),\n onTerminalData: (paneId, data) => recorder.onTerminalData(paneId, data),\n onPaneActivity: (paneId, activity) => recorder.onPaneActivity(paneId, activity),\n })\n\n // File system watcher\n const fsWatcher = new FsWatcher(projectDir)\n fsWatcher.onTreeChange((tree) => {\n workspaceManager.emitFileTree(tree)\n })\n fsWatcher.onFileChange((activity) => {\n workspaceManager.emitFileActivity(activity)\n // Also feed file changes to session recorder for diff capture\n recorder.onFileActivityForReplay(activity)\n })\n try {\n fsWatcher.start()\n } catch (err) {\n console.warn('[FsWatcher] Failed to start file watcher:', (err as Error).message)\n }\n\n // Git service\n const gitService = new GitService(projectDir)\n gitService.onDiffChange((result) => {\n workspaceManager.emitGitDiff(result)\n })\n try {\n await gitService.start()\n } catch (err) {\n console.warn('[GitService] Failed to start git service:', (err as Error).message)\n }\n\n // WebSocket\n await fastify.register(fastifyWebsocket)\n\n fastify.get('/nexus-ws', { websocket: true }, (socket, req) => {\n console.log('[WS] Upgrade request from', req.ip)\n try {\n setupWsHandlers(socket, workspaceManager, gitService)\n\n // Send initial file tree and git diffs to new client\n const tree = fsWatcher.getTree()\n if (tree.length > 0) {\n socket.send(JSON.stringify({ type: 'fs.tree', tree }))\n }\n const { unstaged, staged } = gitService.getCurrentDiffs()\n if (unstaged.length > 0 || staged.length > 0) {\n socket.send(JSON.stringify({ type: 'git.diff', unstaged, staged }))\n }\n console.log('[WS] Client connected')\n\n socket.on('close', (code: number, reason: Buffer) => {\n console.log(`[WS] Client disconnected: code=${code} reason=${reason.toString()}`)\n })\n socket.on('error', (err: Error) => {\n console.error('[WS] Socket error:', err)\n })\n } catch (err) {\n console.error('[WS] Error in connection handler:', err)\n }\n })\n\n // Health check\n fastify.get('/api/health', async () => {\n return { status: 'ok' }\n })\n\n // Agent availability endpoint\n fastify.get('/api/agents', async () => {\n return await configManager.checkAgentAvailability()\n })\n\n // Global config endpoints\n fastify.get('/api/config', async () => {\n return configManager.loadGlobalConfig()\n })\n\n fastify.put('/api/config', async (request, reply) => {\n try {\n const config = request.body as GlobalConfig\n configManager.updateGlobalConfig(config)\n return { success: true }\n } catch (err) {\n reply.code(400)\n return { error: 'Invalid config' }\n }\n })\n\n // Session discovery (claude sessions list)\n const sessionDiscovery = new SessionDiscovery(configManager)\n\n fastify.get('/api/sessions', async (request) => {\n const { agent } = request.query as { agent?: string }\n const external = await sessionDiscovery.listSessions(agent || 'claudecode')\n // Merge with Nexus internal sessions, dedup by sessionId\n const internal = workspaceManager.getSessionList()\n const seen = new Set(internal.map((s) => s.sessionId))\n const merged = [\n ...internal.map((s) => ({\n sessionId: s.sessionId,\n summary: s.paneName,\n model: s.model,\n costUsd: s.costUsd,\n numTurns: undefined as number | undefined,\n createdAt: s.timestamp,\n updatedAt: s.timestamp,\n projectPath: undefined as string | undefined,\n source: 'nexus' as const,\n })),\n ...external.filter((s) => !seen.has(s.sessionId)),\n ]\n return merged\n })\n\n // Replay history endpoints\n fastify.get('/api/replay/sessions', async () => {\n return SessionRecorder.listSessions(projectDir)\n })\n\n fastify.get('/api/replay/sessions/:sessionId', async (request, reply) => {\n const { sessionId } = request.params as { sessionId: string }\n const session = SessionRecorder.getSession(projectDir, sessionId)\n if (!session) { reply.code(404); return { error: 'Session not found' } }\n return session\n })\n\n fastify.get('/api/replay/sessions/:sessionId/turns/:turnId', async (request, reply) => {\n const { sessionId, turnId } = request.params as { sessionId: string; turnId: string }\n const turn = SessionRecorder.getTurn(projectDir, sessionId, turnId)\n if (!turn) { reply.code(404); return { error: 'Turn not found' } }\n return turn\n })\n\n // Delete a single replay session\n fastify.delete('/api/replay/sessions/:sessionId', async (request) => {\n const { sessionId } = request.params as { sessionId: string }\n const deleted = SessionRecorder.deleteSession(projectDir, sessionId)\n return { success: deleted }\n })\n\n // Delete all replay sessions\n fastify.delete('/api/replay/sessions', async () => {\n const count = SessionRecorder.deleteAllSessions(projectDir)\n return { success: true, deleted: count }\n })\n\n // Dependency graph endpoint — cached with TTL to avoid repeated full-scan\n let depGraphCache: { graph: ReturnType<DependencyAnalyzer['analyze']>; ts: number } | null = null\n const DEP_CACHE_TTL = 30_000 // 30s\n\n fastify.get('/api/deps', async () => {\n const now = Date.now()\n if (depGraphCache && now - depGraphCache.ts < DEP_CACHE_TTL) {\n return depGraphCache.graph\n }\n const analyzer = new DependencyAnalyzer(projectDir)\n const graph = analyzer.analyze()\n depGraphCache = { graph, ts: now }\n return graph\n })\n\n // File read endpoint\n fastify.get('/api/file', async (request, reply) => {\n const { path: filePath } = request.query as { path?: string }\n if (!filePath) {\n reply.code(400)\n return { error: 'Missing path parameter' }\n }\n\n // Security: reject paths with .. or absolute paths\n if (filePath.includes('..') || path.isAbsolute(filePath)) {\n reply.code(403)\n return { error: 'Invalid path' }\n }\n\n const fullPath = path.resolve(projectDir, filePath)\n\n // Ensure resolved path is within projectDir\n if (!fullPath.startsWith(projectDir)) {\n reply.code(403)\n return { error: 'Path traversal not allowed' }\n }\n\n try {\n const content = fs.readFileSync(fullPath, 'utf-8')\n return { content, path: filePath }\n } catch {\n reply.code(404)\n return { error: 'File not found' }\n }\n })\n\n // Raw file endpoint — serves binary files with correct MIME type\n fastify.get('/api/file/raw', async (request, reply) => {\n const { path: filePath } = request.query as { path?: string }\n if (!filePath) {\n reply.code(400)\n return { error: 'Missing path parameter' }\n }\n if (filePath.includes('..') || path.isAbsolute(filePath)) {\n reply.code(403)\n return { error: 'Invalid path' }\n }\n const fullPath = path.resolve(projectDir, filePath)\n if (!fullPath.startsWith(projectDir)) {\n reply.code(403)\n return { error: 'Path traversal not allowed' }\n }\n if (!fs.existsSync(fullPath)) {\n reply.code(404)\n return { error: 'File not found' }\n }\n const ext = path.extname(fullPath).toLowerCase()\n const mimeMap: Record<string, string> = {\n '.png': 'image/png', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg',\n '.gif': 'image/gif', '.webp': 'image/webp', '.ico': 'image/x-icon',\n '.bmp': 'image/bmp', '.avif': 'image/avif',\n '.pdf': 'application/pdf',\n '.svg': 'image/svg+xml',\n }\n const mime = mimeMap[ext] || 'application/octet-stream'\n const stream = fs.createReadStream(fullPath)\n reply.type(mime)\n return reply.send(stream)\n })\n\n // Notes CRUD — persisted to .nexus/notes.yaml\n const notesPath = path.join(projectDir, '.nexus', 'notes.yaml')\n\n fastify.get('/api/notes', async () => {\n try {\n const raw = fs.readFileSync(notesPath, 'utf-8')\n const data = yaml.load(raw) as { notes?: unknown[] }\n return { notes: data?.notes || [] }\n } catch {\n return { notes: [] }\n }\n })\n\n fastify.put('/api/notes', async (request, reply) => {\n try {\n const { notes } = request.body as { notes: unknown[] }\n fs.mkdirSync(path.dirname(notesPath), { recursive: true })\n fs.writeFileSync(notesPath, yaml.dump({ notes }, { lineWidth: -1 }), 'utf-8')\n return { success: true }\n } catch (err) {\n reply.code(400)\n return { error: 'Failed to save notes' }\n }\n })\n\n // Serve static frontend in production\n const webDistPath = path.resolve(__dirname, '../../web/dist')\n if (!fs.existsSync(webDistPath)) {\n console.warn(` [Warning] Frontend not found at ${webDistPath}`)\n console.warn(` Run 'pnpm run build:web' to build the frontend, or use dev mode.`)\n }\n if (fs.existsSync(webDistPath)) {\n await fastify.register(fastifyStatic, {\n root: webDistPath,\n prefix: '/',\n })\n\n // SPA fallback for client-side routing\n fastify.setNotFoundHandler((_req, reply) => {\n reply.sendFile('index.html')\n })\n }\n\n // Graceful shutdown\n const shutdown = async () => {\n console.log('\\nShutting down...')\n recorder.flush()\n agentsWriter.flush(workspaceManager.getPanes())\n fsWatcher.close()\n gitService.close()\n await workspaceManager.shutdown()\n await fastify.close()\n process.exit(0)\n }\n\n process.on('SIGINT', shutdown)\n process.on('SIGTERM', shutdown)\n\n try {\n await fastify.listen({ port, host: '0.0.0.0' })\n } catch (err: unknown) {\n if ((err as NodeJS.ErrnoException).code === 'EADDRINUSE') {\n console.error(`Port ${port} is already in use. Kill the existing process or use a different port:`)\n console.error(` NEXUS_PORT=7800 pnpm dev`)\n console.error(` # or find and kill: lsof -i :${port}`)\n process.exit(1)\n }\n throw err\n }\n console.log(`Nexus server running at http://localhost:${port}`)\n console.log(` Project dir: ${projectDir}`)\n console.log(` File tree: ${fsWatcher.getTree().length} top-level entries`)\n const { unstaged: u, staged: s } = gitService.getCurrentDiffs()\n console.log(` Git diffs: ${u.length} unstaged, ${s.length} staged`)\n\n return { fastify, workspaceManager, configManager }\n}\n","import * as pty from 'node-pty'\nimport fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport type { PaneConfig, PaneStatus, PaneMeta, AgentDefinition, FileActivity } from '../types.ts'\nimport { StatuslineParser } from '../comm/StatuslineParser.ts'\nimport { ShellReadyDetector } from '../comm/ShellReadyDetector.ts'\nimport { AgentReadyDetector } from '../comm/AgentReadyDetector.ts'\nimport { OutputStateAnalyzer } from '../comm/OutputStateAnalyzer.ts'\nimport { ActivityParser } from './ActivityParser.ts'\nimport type { ConfigManager } from '../workspace/ConfigManager.ts'\n\nconst MAX_SCROLLBACK_BYTES = 512 * 1024 // 512KB per pane\n\ninterface PtyEntry {\n pty: pty.IPty\n config: PaneConfig\n status: PaneStatus\n meta: PaneMeta\n parser: StatuslineParser\n activityParser: ActivityParser\n stateAnalyzer: OutputStateAnalyzer\n shellDetector: ShellReadyDetector | null\n agentDetector: AgentReadyDetector | null\n scrollback: string[]\n scrollbackBytes: number\n onDataCallbacks: Array<(data: string) => void>\n onStatusCallbacks: Array<(status: PaneStatus) => void>\n onMetaCallbacks: Array<(meta: PaneMeta) => void>\n onActivityCallbacks: Array<(activity: FileActivity) => void>\n}\n\nexport class PtyManager {\n private entries = new Map<string, PtyEntry>()\n private configManager: ConfigManager\n\n constructor(configManager: ConfigManager) {\n this.configManager = configManager\n }\n\n spawn(paneId: string, config: PaneConfig, cols = 80, rows = 24): number {\n if (this.entries.has(paneId)) {\n this.kill(paneId)\n }\n\n const shell = this.configManager.getShell()\n console.log(`[PTY] Using shell: ${shell} for pane ${paneId}`)\n const projectDir = this.configManager.getProjectDir()\n // Worktree panes use worktreePath as base; shared panes use projectDir\n const basePath = (config.isolation === 'worktree' && config.worktreePath)\n ? config.worktreePath\n : projectDir\n let cwd = config.workdir\n ? path.resolve(basePath, config.workdir)\n : basePath\n\n // Validate cwd exists — posix_spawnp fails if cwd is invalid\n if (!fs.existsSync(cwd)) {\n console.warn(`[PTY] cwd does not exist: ${cwd}, falling back to ${projectDir}`)\n cwd = fs.existsSync(projectDir) ? projectDir : os.homedir()\n }\n\n // Validate shell binary exists, fall back gracefully\n let resolvedShell = shell\n if (!fs.existsSync(resolvedShell)) {\n const fallbacks = ['/bin/zsh', '/bin/bash', '/bin/sh']\n const found = fallbacks.find(s => fs.existsSync(s))\n console.error(`[PTY] Shell binary not found: ${resolvedShell}, falling back to ${found || '/bin/sh'}`)\n resolvedShell = found || '/bin/sh'\n }\n\n const agentDef = this.configManager.getAgentDefinition(config.agent)\n const isAgent = agentDef && config.agent !== '__shell__'\n\n // Build environment from agent definition\n // Filter out all Claude-related env vars to prevent nested session detection\n const env: Record<string, string> = {}\n for (const [key, value] of Object.entries(process.env)) {\n if (value !== undefined && !key.startsWith('CLAUDE') && key !== 'CLAUDECODE') {\n env[key] = value\n }\n }\n if (agentDef?.env) {\n // Block dangerous env vars that could be used for injection\n const BLOCKED_ENV_KEYS = new Set([\n 'PATH', 'LD_PRELOAD', 'LD_LIBRARY_PATH',\n 'DYLD_INSERT_LIBRARIES', 'DYLD_LIBRARY_PATH', 'DYLD_FRAMEWORK_PATH',\n ])\n for (const [key, value] of Object.entries(agentDef.env)) {\n if (BLOCKED_ENV_KEYS.has(key)) {\n console.warn(`[PTY] Ignoring blocked env var from agent config: ${key}`)\n continue\n }\n // Resolve ${VAR} references from process.env\n const resolved = value.replace(/\\$\\{(\\w+)\\}/g, (_, varName: string) => {\n return process.env[varName] || ''\n })\n if (resolved) env[key] = resolved\n }\n }\n if (agentDef?.bin === 'claude' && !env.CLAUDE_CODE_NO_FLICKER) {\n env.CLAUDE_CODE_NO_FLICKER = '1'\n }\n\n // Ensure PATH is set — on some systems (e.g. macOS launchd) it may be missing\n if (!env.PATH) {\n env.PATH = '/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin'\n if (process.platform === 'darwin') {\n env.PATH = '/opt/homebrew/bin:/opt/homebrew/sbin:' + env.PATH\n }\n }\n\n console.log(`[PTY] Spawning pane ${paneId}: shell=${resolvedShell}, cwd=${cwd}`)\n\n const term = pty.spawn(resolvedShell, [], {\n name: 'xterm-256color',\n cols,\n rows,\n cwd,\n env,\n })\n\n // Create communication components\n const shellDetector = isAgent\n ? new ShellReadyDetector(paneId, { stripSentinel: true })\n : null\n\n const stateAnalyzer = new OutputStateAnalyzer({\n idleThresholdMs: 5000,\n onStatusChange: (status) => {\n const e = this.entries.get(paneId)\n if (e) {\n e.status = status\n for (const cb of e.onStatusCallbacks) {\n cb(status)\n }\n }\n },\n })\n\n const entry: PtyEntry = {\n pty: term,\n config,\n status: 'running',\n meta: {},\n parser: new StatuslineParser(),\n activityParser: new ActivityParser(),\n stateAnalyzer,\n shellDetector,\n agentDetector: null, // Created after shell is ready\n scrollback: [],\n scrollbackBytes: 0,\n onDataCallbacks: [],\n onStatusCallbacks: [],\n onMetaCallbacks: [],\n onActivityCallbacks: [],\n }\n\n this.entries.set(paneId, entry)\n\n // Handle PTY output\n term.onData((data: string) => {\n // Feed shell ready detector (strips sentinel from output)\n let processedData = data\n if (entry.shellDetector && !entry.shellDetector.isDone) {\n processedData = entry.shellDetector.feed(data)\n }\n\n // Feed agent ready detector\n if (entry.agentDetector && !entry.agentDetector.isDone) {\n entry.agentDetector.feed(processedData)\n }\n\n const { cleanData, meta } = entry.parser.parse(processedData)\n\n if (cleanData) {\n // Feed state analyzer (hot path — just timestamp + timer reset)\n entry.stateAnalyzer.onOutput()\n\n // Buffer for scrollback replay\n entry.scrollback.push(cleanData)\n entry.scrollbackBytes += cleanData.length\n // Trim if over budget — batch splice instead of shift() loop to avoid O(n²)\n if (entry.scrollbackBytes > MAX_SCROLLBACK_BYTES) {\n let bytesToRemove = entry.scrollbackBytes - MAX_SCROLLBACK_BYTES\n let removeCount = 0\n while (removeCount < entry.scrollback.length - 1 && bytesToRemove > 0) {\n bytesToRemove -= entry.scrollback[removeCount].length\n entry.scrollbackBytes -= entry.scrollback[removeCount].length\n removeCount++\n }\n if (removeCount > 0) {\n entry.scrollback.splice(0, removeCount)\n }\n }\n\n for (const cb of entry.onDataCallbacks) {\n cb(cleanData)\n }\n }\n\n if (meta) {\n entry.meta = { ...entry.meta, ...meta }\n\n // Feed to state analyzer and agent ready detector\n entry.stateAnalyzer.onMeta(meta)\n if (entry.agentDetector && !entry.agentDetector.isDone) {\n entry.agentDetector.onMeta(meta)\n }\n\n for (const cb of entry.onMetaCallbacks) {\n cb(entry.meta)\n }\n }\n\n // Parse file activity from PTY output (attributed to this pane)\n if (config.agent !== '__shell__') {\n const activity = entry.activityParser.parse(data)\n if (activity) {\n for (const cb of entry.onActivityCallbacks) {\n cb(activity)\n }\n }\n }\n })\n\n // Handle PTY exit\n term.onExit(({ exitCode }) => {\n const e = this.entries.get(paneId)\n if (e) {\n e.stateAnalyzer.onExit(exitCode)\n // Dispose detectors\n e.shellDetector?.dispose()\n e.agentDetector?.dispose()\n }\n })\n\n // Shell ready → Agent command → Agent ready → Task\n if (isAgent && shellDetector) {\n this.startAgentSequence(paneId, config, agentDef!, shellDetector)\n }\n\n return term.pid\n }\n\n /**\n * Orchestrates the shell → agent → task startup sequence using\n * event-driven detectors instead of hardcoded setTimeout delays.\n */\n private async startAgentSequence(\n paneId: string,\n config: PaneConfig,\n agentDef: AgentDefinition,\n shellDetector: ShellReadyDetector,\n ): Promise<void> {\n const entry = this.entries.get(paneId)\n if (!entry) return\n\n // Step 1: Wait for shell to be ready\n const shellResult = await shellDetector.start(entry.pty)\n if (!this.entries.has(paneId)) return // pane was killed while waiting\n\n console.log(`[PTY] Shell ready for ${paneId}: detected=${shellResult.detected} (${shellResult.elapsedMs}ms)`)\n\n // Step 2: Send agent command\n this.sendAgentCommand(paneId, config, agentDef)\n\n // Step 3: If there's a task, wait for agent to be ready before sending\n if (config.task && config.restore !== 'manual') {\n const agentDetector = new AgentReadyDetector({\n quiescenceMs: 3000,\n hardTimeoutMs: 15000,\n })\n entry.agentDetector = agentDetector\n\n const agentResult = await agentDetector.start()\n if (!this.entries.has(paneId)) return // pane was killed while waiting\n\n console.log(`[PTY] Agent ready for ${paneId}: reason=${agentResult.reason} (${agentResult.elapsedMs}ms)`)\n\n // Send the task\n entry.pty.write(config.task + '\\r')\n }\n }\n\n private sendAgentCommand(paneId: string, config: PaneConfig, agentDef: AgentDefinition): void {\n const entry = this.entries.get(paneId)\n if (!entry) return\n\n let cmd = agentDef.bin\n\n // Add resume flag with specific session ID\n if (config.restore === 'resume' && config.sessionId && agentDef.resume_flag) {\n cmd += ` ${agentDef.resume_flag} ${config.sessionId}`\n } else if (config.restore === 'continue' && agentDef.continue_flag) {\n // Add continue flag to resume latest session\n cmd += ` ${agentDef.continue_flag}`\n }\n\n // Add yolo flag if enabled\n if (config.yolo && agentDef.yolo_flag) {\n cmd += ` ${agentDef.yolo_flag}`\n }\n\n // Send the command to start the agent\n entry.pty.write(cmd + '\\r')\n }\n\n write(paneId: string, data: string): void {\n const entry = this.entries.get(paneId)\n if (entry) {\n entry.pty.write(data)\n }\n }\n\n resize(paneId: string, cols: number, rows: number): void {\n const entry = this.entries.get(paneId)\n if (entry) {\n try {\n entry.pty.resize(cols, rows)\n } catch {\n // PTY may not be ready yet (ENOTTY), ignore\n }\n }\n }\n\n kill(paneId: string): void {\n const entry = this.entries.get(paneId)\n if (entry) {\n // Clean up comm components\n entry.stateAnalyzer.dispose()\n entry.shellDetector?.dispose()\n entry.agentDetector?.dispose()\n entry.parser.reset()\n\n // Clear callback arrays to break closure references and prevent leaks\n entry.onDataCallbacks.length = 0\n entry.onStatusCallbacks.length = 0\n entry.onMetaCallbacks.length = 0\n entry.onActivityCallbacks.length = 0\n\n try {\n entry.pty.kill()\n } catch {\n // Process may already be dead\n }\n this.entries.delete(paneId)\n }\n }\n\n killAll(): void {\n for (const [paneId] of this.entries) {\n this.kill(paneId)\n }\n }\n\n getStatus(paneId: string): PaneStatus {\n return this.entries.get(paneId)?.status || 'stopped'\n }\n\n getMeta(paneId: string): PaneMeta {\n return this.entries.get(paneId)?.meta || {}\n }\n\n getPid(paneId: string): number | undefined {\n return this.entries.get(paneId)?.pty.pid\n }\n\n onData(paneId: string, callback: (data: string) => void): void {\n const entry = this.entries.get(paneId)\n if (entry) {\n entry.onDataCallbacks.push(callback)\n }\n }\n\n onStatus(paneId: string, callback: (status: PaneStatus) => void): void {\n const entry = this.entries.get(paneId)\n if (entry) {\n entry.onStatusCallbacks.push(callback)\n }\n }\n\n onMeta(paneId: string, callback: (meta: PaneMeta) => void): void {\n const entry = this.entries.get(paneId)\n if (entry) {\n entry.onMetaCallbacks.push(callback)\n }\n }\n\n onActivity(paneId: string, callback: (activity: FileActivity) => void): void {\n const entry = this.entries.get(paneId)\n if (entry) {\n entry.onActivityCallbacks.push(callback)\n }\n }\n\n getScrollback(paneId: string): string {\n const entry = this.entries.get(paneId)\n if (!entry) return ''\n return entry.scrollback.join('')\n }\n\n has(paneId: string): boolean {\n return this.entries.has(paneId)\n }\n}\n","import type { PaneMeta } from '../types.ts'\n\n/**\n * Parses Claude Code statusline JSON from PTY output.\n *\n * Hardened version with multi-layer validation:\n * 1. Line must parse as valid JSON\n * 2. Must contain at least 2 known statusline fields (eliminates random JSON)\n * 3. Field types are strictly validated\n *\n * Performance:\n * - Fast-path: lines that don't start with '{' are skipped with zero overhead.\n * - Buffer is only used for incomplete lines; complete lines are processed inline.\n * - JSON.parse is only attempted on candidate lines, not all output.\n */\n\n// The known statusline field names and their expected types\nconst KNOWN_FIELDS: Record<string, string> = {\n model: 'string',\n session_id: 'string',\n cost_usd: 'number',\n context_used_pct: 'number',\n cwd: 'string',\n tool_name: 'string',\n // Claude Code may add more fields — add them here as discovered\n}\n\n// Minimum number of known fields required to classify as statusline\nconst MIN_KNOWN_FIELDS = 2\n\n// Max buffer size — if a line exceeds this without a newline, discard buffer\nconst MAX_BUFFER_SIZE = 64 * 1024 // 64KB\n\nexport class StatuslineParser {\n private buffer = ''\n\n /**\n * Process raw PTY output data.\n * Returns { cleanData, meta } where cleanData has statusline JSON stripped\n * and meta contains parsed metadata (if any was found).\n */\n parse(data: string): { cleanData: string; meta: PaneMeta | null } {\n let meta: PaneMeta | null = null\n\n // Fast path: no newline means partial chunk (keystroke echo, prompt).\n // Buffer it but pass through immediately.\n if (!data.includes('\\n')) {\n this.buffer += data\n // Prevent unbounded buffer growth (e.g., binary output without newlines)\n if (this.buffer.length > MAX_BUFFER_SIZE) {\n this.buffer = ''\n }\n return { cleanData: data, meta: null }\n }\n\n const combined = this.buffer + data\n this.buffer = ''\n\n const lines = combined.split('\\n')\n\n // Last element is trailing content (empty if data ended with \\n)\n const trailing = lines.pop() || ''\n if (trailing) {\n this.buffer = trailing\n }\n\n const cleanLines: string[] = []\n\n for (const line of lines) {\n const trimmed = line.trim()\n\n // Fast reject: not a JSON candidate\n if (trimmed.length < 10 || trimmed.charCodeAt(0) !== 0x7B /* '{' */) {\n cleanLines.push(line)\n continue\n }\n\n // Must end with '}'\n if (trimmed.charCodeAt(trimmed.length - 1) !== 0x7D /* '}' */) {\n cleanLines.push(line)\n continue\n }\n\n // Attempt JSON parse\n let parsed: Record<string, unknown>\n try {\n parsed = JSON.parse(trimmed)\n } catch {\n cleanLines.push(line)\n continue\n }\n\n // Validate: must be a plain object with enough known fields\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n cleanLines.push(line)\n continue\n }\n\n if (this.isStatuslineJson(parsed)) {\n meta = this.extractMeta(parsed)\n // Strip this line from terminal output\n continue\n }\n\n // Valid JSON but not a statusline — pass through\n cleanLines.push(line)\n }\n\n // Reconstruct output\n let cleanData = cleanLines.join('\\n')\n if (cleanLines.length > 0) {\n cleanData += '\\n'\n }\n\n return { cleanData, meta }\n }\n\n /**\n * Reset internal buffer state. Useful when restarting a pane.\n */\n reset(): void {\n this.buffer = ''\n }\n\n private isStatuslineJson(obj: Record<string, unknown>): boolean {\n let matchCount = 0\n for (const [field, expectedType] of Object.entries(KNOWN_FIELDS)) {\n if (field in obj) {\n // Type must also match\n if (typeof obj[field] === expectedType) {\n matchCount++\n }\n }\n }\n return matchCount >= MIN_KNOWN_FIELDS\n }\n\n private extractMeta(obj: Record<string, unknown>): PaneMeta {\n const meta: PaneMeta = {}\n\n if (typeof obj.model === 'string') {\n meta.model = obj.model\n }\n if (typeof obj.context_used_pct === 'number') {\n meta.contextUsedPct = obj.context_used_pct\n }\n if (typeof obj.cost_usd === 'number') {\n meta.costUsd = obj.cost_usd\n }\n if (typeof obj.session_id === 'string') {\n meta.sessionId = obj.session_id\n }\n if (typeof obj.cwd === 'string') {\n meta.cwd = obj.cwd\n }\n\n return meta\n }\n}\n","import type { IPty } from 'node-pty'\n\n/**\n * Detects when a shell process is ready to receive commands.\n *\n * Strategy: write an echo sentinel command into the PTY immediately after spawn.\n * The sentinel queues behind .bashrc/.zshrc sourcing and executes only when\n * the shell is interactive and ready. We watch the PTY output for the sentinel\n * value and resolve the promise.\n *\n * Performance notes:\n * - The sentinel is a single small write; no polling loop.\n * - The onData listener is removed as soon as the sentinel is found or the\n * timeout fires, so there is zero ongoing overhead.\n * - The sentinel string includes paneId to avoid cross-pane collisions.\n */\n\nconst FALLBACK_TIMEOUT_MS = 8000\n\nexport interface ShellReadyOptions {\n /** Milliseconds before giving up and resolving anyway. Default 8000. */\n timeoutMs?: number\n /** If true, suppress the sentinel echo from reaching downstream consumers. */\n stripSentinel?: boolean\n}\n\nexport interface ShellReadyResult {\n /** Whether the sentinel was detected (true) or we timed out (false). */\n detected: boolean\n /** Milliseconds elapsed from injection to detection/timeout. */\n elapsedMs: number\n}\n\nexport class ShellReadyDetector {\n private sentinel: string\n private resolve!: (result: ShellReadyResult) => void\n private promise: Promise<ShellReadyResult>\n private startTime: number\n private timer: ReturnType<typeof setTimeout> | null = null\n private disposed = false\n\n // Exposed for testing — accumulated raw output chunks\n private chunks: string[] = []\n\n constructor(\n private paneId: string,\n private options: ShellReadyOptions = {},\n ) {\n // Use a unique, unlikely-to-collide sentinel value\n this.sentinel = `__NEXUS_RDY_${paneId}_${Date.now().toString(36)}__`\n this.startTime = Date.now()\n\n this.promise = new Promise<ShellReadyResult>((resolve) => {\n this.resolve = resolve\n })\n }\n\n /**\n * Inject the sentinel into the shell and start watching.\n * Call this immediately after pty.spawn().\n *\n * Returns a promise that resolves when the shell is ready.\n * The caller should await this before sending any agent command.\n */\n start(term: IPty): Promise<ShellReadyResult> {\n const timeoutMs = this.options.timeoutMs ?? FALLBACK_TIMEOUT_MS\n\n // Inject sentinel echo — the shell will execute this after .bashrc finishes\n term.write(`echo ${this.sentinel}\\r`)\n\n // Set up fallback timeout\n this.timer = setTimeout(() => {\n if (!this.disposed) {\n this.disposed = true\n this.resolve({\n detected: false,\n elapsedMs: Date.now() - this.startTime,\n })\n }\n }, timeoutMs)\n\n return this.promise\n }\n\n /**\n * Feed PTY output data into the detector.\n * Call this from the PTY onData handler.\n *\n * Returns the data with the sentinel line stripped if `stripSentinel` is true\n * and the sentinel was found in this chunk. Otherwise returns the data as-is.\n */\n feed(data: string): string {\n if (this.disposed) return data\n\n this.chunks.push(data)\n\n // Check if sentinel appears in accumulated data\n // We check chunks to handle the case where sentinel spans two chunks\n const recent = this.chunks.length <= 3\n ? this.chunks.join('')\n : this.chunks.slice(-3).join('')\n\n if (recent.includes(this.sentinel)) {\n this.disposed = true\n if (this.timer) {\n clearTimeout(this.timer)\n this.timer = null\n }\n this.resolve({\n detected: true,\n elapsedMs: Date.now() - this.startTime,\n })\n // Free reference to accumulated chunks\n this.chunks = []\n\n if (this.options.stripSentinel) {\n return this.stripSentinelFromData(data)\n }\n }\n\n return data\n }\n\n /**\n * Whether the detector has finished (either by detection or timeout).\n */\n get isDone(): boolean {\n return this.disposed\n }\n\n /**\n * Clean up without resolving (e.g., if the PTY is killed before ready).\n */\n dispose(): void {\n if (!this.disposed) {\n this.disposed = true\n if (this.timer) {\n clearTimeout(this.timer)\n this.timer = null\n }\n this.resolve({\n detected: false,\n elapsedMs: Date.now() - this.startTime,\n })\n }\n this.chunks = []\n }\n\n private stripSentinelFromData(data: string): string {\n // Remove the sentinel line and surrounding echo command artifacts\n // The echo command produces: `echo __NEXUS_RDY_...__\\r\\n__NEXUS_RDY_...__\\r\\n`\n // We want to strip both the command echo and the output\n const lines = data.split('\\n')\n const filtered = lines.filter((line) => !line.includes(this.sentinel))\n return filtered.join('\\n')\n }\n}\n","import type { PaneMeta } from '../types.ts'\n\n/**\n * Detects when an Agent process has finished initializing and is ready\n * to receive user input (tasks, review comments, etc.).\n *\n * Strategy (layered, first match wins):\n * 1. Statusline detection — if the StatuslineParser emits a meta event with\n * a session_id, the agent is live and ready.\n * 2. Prompt pattern — detect known agent prompt patterns in terminal output\n * (e.g., Claude Code's `❯` or `>` prompt after init banner).\n * 3. Output quiescence — if the agent stops producing output for a\n * configurable interval, assume it's waiting for input.\n * 4. Hard timeout — resolve regardless after a maximum wait.\n *\n * Performance:\n * - No polling; purely event-driven via feed() / onMeta() calls.\n * - Single timer for quiescence; re-armed on each output chunk.\n * - All listeners removed on resolve.\n */\n\nconst DEFAULT_QUIESCENCE_MS = 3000\nconst DEFAULT_HARD_TIMEOUT_MS = 15000\n\n// Known agent prompt patterns (after ANSI stripping)\nconst PROMPT_PATTERNS = [\n /❯\\s*$/, // Claude Code prompt\n />\\s*$/, // Generic prompt\n /\\$\\s*$/, // Shell-style prompt (some agents)\n /waiting for input/i,\n]\n\nexport interface AgentReadyOptions {\n /** Ms of output silence before assuming ready. Default 3000. */\n quiescenceMs?: number\n /** Hard timeout ms. Default 15000. */\n hardTimeoutMs?: number\n /** Additional prompt regex patterns for custom agents. */\n extraPromptPatterns?: RegExp[]\n}\n\nexport type AgentReadyReason = 'statusline' | 'prompt' | 'quiescence' | 'timeout'\n\nexport interface AgentReadyResult {\n reason: AgentReadyReason\n elapsedMs: number\n}\n\nexport class AgentReadyDetector {\n private resolve!: (result: AgentReadyResult) => void\n private promise: Promise<AgentReadyResult>\n private startTime: number\n private disposed = false\n\n private quiescenceTimer: ReturnType<typeof setTimeout> | null = null\n private hardTimer: ReturnType<typeof setTimeout> | null = null\n\n private quiescenceMs: number\n private promptPatterns: RegExp[]\n\n constructor(private options: AgentReadyOptions = {}) {\n this.startTime = Date.now()\n this.quiescenceMs = options.quiescenceMs ?? DEFAULT_QUIESCENCE_MS\n this.promptPatterns = [\n ...PROMPT_PATTERNS,\n ...(options.extraPromptPatterns || []),\n ]\n\n this.promise = new Promise<AgentReadyResult>((resolve) => {\n this.resolve = resolve\n })\n }\n\n /**\n * Start the detection timers. Returns a promise that resolves when the\n * agent is deemed ready.\n */\n start(): Promise<AgentReadyResult> {\n const hardTimeoutMs = this.options.hardTimeoutMs ?? DEFAULT_HARD_TIMEOUT_MS\n\n // Hard timeout\n this.hardTimer = setTimeout(() => {\n this.finish('timeout')\n }, hardTimeoutMs)\n\n // Start initial quiescence timer (agent may not produce any output\n // if it's immediately ready)\n this.resetQuiescence()\n\n return this.promise\n }\n\n /**\n * Feed terminal output from the agent. Resets quiescence timer and\n * checks for prompt patterns.\n */\n feed(data: string): void {\n if (this.disposed) return\n\n // Reset quiescence timer on any output\n this.resetQuiescence()\n\n // Check for prompt patterns (strip ANSI first)\n const clean = stripAnsi(data)\n // Only check the last portion — prompt appears at end of output\n const tail = clean.slice(-200)\n\n for (const pattern of this.promptPatterns) {\n if (pattern.test(tail)) {\n this.finish('prompt')\n return\n }\n }\n }\n\n /**\n * Called when a statusline meta event is received. If it contains a\n * session_id, the agent is definitely ready.\n */\n onMeta(meta: PaneMeta): void {\n if (this.disposed) return\n\n if (meta.sessionId) {\n this.finish('statusline')\n }\n }\n\n get isDone(): boolean {\n return this.disposed\n }\n\n dispose(): void {\n if (!this.disposed) {\n this.disposed = true\n this.clearTimers()\n this.resolve({\n reason: 'timeout',\n elapsedMs: Date.now() - this.startTime,\n })\n }\n }\n\n private finish(reason: AgentReadyReason): void {\n if (this.disposed) return\n this.disposed = true\n this.clearTimers()\n this.resolve({\n reason,\n elapsedMs: Date.now() - this.startTime,\n })\n }\n\n private resetQuiescence(): void {\n if (this.quiescenceTimer) {\n clearTimeout(this.quiescenceTimer)\n }\n this.quiescenceTimer = setTimeout(() => {\n this.finish('quiescence')\n }, this.quiescenceMs)\n }\n\n private clearTimers(): void {\n if (this.quiescenceTimer) {\n clearTimeout(this.quiescenceTimer)\n this.quiescenceTimer = null\n }\n if (this.hardTimer) {\n clearTimeout(this.hardTimer)\n this.hardTimer = null\n }\n }\n}\n\n// Lightweight ANSI stripper — only needs to handle enough for prompt detection\nfunction stripAnsi(str: string): string {\n return str\n .replace(/\\x1b\\][^\\x07]*(?:\\x07|\\x1b\\\\)/g, '') // OSC\n .replace(/\\x1b\\[[0-9;]*[a-zA-Z]/g, '') // CSI\n .replace(/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f]/g, '') // control chars\n}\n","import type { PaneMeta, PaneStatus } from '../types.ts'\n\n/**\n * Infers Agent behavioral state from PTY output patterns and statusline metadata.\n *\n * State machine:\n * running — Agent is producing output (actively working)\n * waiting — Agent has stopped producing output for `idleThresholdMs`\n * (likely waiting for user input or confirmation)\n * idle — Extended silence (`idleThresholdMs * 3`), process still alive\n * stopped — Process exited normally\n * error — Process exited with non-zero code\n *\n * The stopped/error states are set externally (from PTY exit handler),\n * not by this analyzer.\n *\n * Performance:\n * - Single setTimeout for idle detection; re-armed per output chunk.\n * - onOutput() is called on every PTY data event, so it must be fast:\n * just a timestamp update + timer reset.\n * - Meta changes are infrequent and cheap to process.\n * - No string inspection on the hot path (prompt detection is in AgentReadyDetector).\n */\n\nconst DEFAULT_IDLE_THRESHOLD_MS = 5000\n\nexport interface OutputStateOptions {\n /** Ms of silence before transitioning running→waiting. Default 5000. */\n idleThresholdMs?: number\n /** Callback when inferred status changes. */\n onStatusChange?: (status: PaneStatus) => void\n}\n\nexport class OutputStateAnalyzer {\n private currentStatus: PaneStatus = 'running'\n private lastOutputTime = 0\n private lastContextPct: number | null = null\n private idleTimer: ReturnType<typeof setTimeout> | null = null\n private extendedIdleTimer: ReturnType<typeof setTimeout> | null = null\n\n private idleThresholdMs: number\n private onStatusChange?: (status: PaneStatus) => void\n\n constructor(options: OutputStateOptions = {}) {\n this.idleThresholdMs = options.idleThresholdMs ?? DEFAULT_IDLE_THRESHOLD_MS\n this.onStatusChange = options.onStatusChange\n this.lastOutputTime = Date.now()\n }\n\n /**\n * Call on every PTY output chunk. Must be fast — hot path.\n */\n onOutput(): void {\n this.lastOutputTime = Date.now()\n\n // If we were waiting/idle, transition back to running\n if (this.currentStatus === 'waiting' || this.currentStatus === 'idle') {\n this.setStatus('running')\n }\n\n this.resetIdleTimers()\n }\n\n /**\n * Call when a statusline meta event is received.\n * Context usage changes confirm the agent is actively working.\n */\n onMeta(meta: PaneMeta): void {\n if (meta.contextUsedPct !== undefined) {\n if (this.lastContextPct !== null && meta.contextUsedPct > this.lastContextPct) {\n // Context grew — agent is definitely working\n if (this.currentStatus !== 'running') {\n this.setStatus('running')\n }\n this.resetIdleTimers()\n }\n this.lastContextPct = meta.contextUsedPct\n }\n }\n\n /**\n * Call when the PTY process exits. Overrides any inferred state.\n */\n onExit(exitCode: number): void {\n this.clearTimers()\n this.setStatus(exitCode === 0 ? 'stopped' : 'error')\n }\n\n /**\n * Get the current inferred status.\n */\n getStatus(): PaneStatus {\n return this.currentStatus\n }\n\n /**\n * Milliseconds since last output.\n */\n getSilenceMs(): number {\n return Date.now() - this.lastOutputTime\n }\n\n /**\n * Clean up timers.\n */\n dispose(): void {\n this.clearTimers()\n }\n\n private setStatus(status: PaneStatus): void {\n if (status === this.currentStatus) return\n this.currentStatus = status\n this.onStatusChange?.(status)\n }\n\n private resetIdleTimers(): void {\n this.clearTimers()\n\n // Stage 1: running → waiting\n this.idleTimer = setTimeout(() => {\n if (this.currentStatus === 'running') {\n this.setStatus('waiting')\n }\n\n // Stage 2: waiting → idle (3x threshold)\n this.extendedIdleTimer = setTimeout(() => {\n if (this.currentStatus === 'waiting') {\n this.setStatus('idle')\n }\n }, this.idleThresholdMs * 2)\n }, this.idleThresholdMs)\n }\n\n private clearTimers(): void {\n if (this.idleTimer) {\n clearTimeout(this.idleTimer)\n this.idleTimer = null\n }\n if (this.extendedIdleTimer) {\n clearTimeout(this.extendedIdleTimer)\n this.extendedIdleTimer = null\n }\n }\n}\n","export type FileAction = 'read' | 'edit' | 'write' | 'create' | 'delete' | 'bash'\n\nexport interface FileActivity {\n file: string\n action: FileAction\n timestamp: number\n}\n\n// More complete ANSI stripping — handles OSC sequences, cursor movement, etc.\nfunction stripAnsi(str: string): string {\n return str\n .replace(/\\x1b\\][^\\x07]*(?:\\x07|\\x1b\\\\)/g, '') // OSC sequences\n .replace(/\\x1b\\[[0-9;]*[a-zA-Z]/g, '') // CSI sequences\n .replace(/\\x1b[()][AB012]/g, '') // Character set selection\n .replace(/\\x1b[>=<]/g, '') // Keypad/cursor mode\n .replace(/\\x0f|\\x0e/g, '') // SI/SO\n .replace(/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f]/g, '') // Other control chars\n}\n\n/**\n * Parses Claude Code PTY output to detect file operations.\n * Claude Code outputs tool usage with various ANSI-styled formats.\n * This parser strips ANSI codes and matches known patterns.\n */\nconst MAX_BUFFER_SIZE = 64 * 1024 // 64KB — same as StatuslineParser\n\nexport class ActivityParser {\n private buffer = ''\n private lastFile = ''\n private lastTime = 0\n private readonly DEDUP_MS = 2000 // Ignore same file within 2s\n\n parse(data: string): FileActivity | null {\n if (!data.includes('\\n')) {\n this.buffer += data\n // Prevent unbounded buffer growth (e.g., binary output without newlines)\n if (this.buffer.length > MAX_BUFFER_SIZE) {\n this.buffer = ''\n }\n return null\n }\n\n const lines = (this.buffer + data).split('\\n')\n this.buffer = ''\n\n const trailing = lines.pop() || ''\n if (trailing) {\n this.buffer = trailing\n }\n\n // Check all lines, return first match\n for (const line of lines) {\n const activity = this.parseLine(line)\n if (activity) {\n // Dedup: skip if same file within DEDUP_MS\n if (activity.file === this.lastFile && activity.timestamp - this.lastTime < this.DEDUP_MS) {\n continue\n }\n this.lastFile = activity.file\n this.lastTime = activity.timestamp\n return activity\n }\n }\n\n return null\n }\n\n private parseLine(line: string): FileActivity | null {\n const clean = stripAnsi(line).trim()\n if (!clean || clean.length < 5) return null\n\n // ── Claude Code specific patterns ──\n\n // Pattern: \"⎿ Read file_path\" or \"⎿ Edit file_path\" (Claude Code tool result markers)\n const toolResultMatch = clean.match(\n /^[⎿│├└┌┐┘┤┬┴┼╭╮╰╯─━]?\\s*(Read|Edit|Write|MultiEdit|Create|Delete|Glob|Grep|Bash)\\s+(.+)/i,\n )\n if (toolResultMatch) {\n return this.buildActivity(toolResultMatch[1], toolResultMatch[2])\n }\n\n // Pattern: Tool name at start of line followed by path — \"Read src/foo.ts\"\n // Must be exact tool name, not part of a sentence\n const toolStartMatch = clean.match(\n /^(Read|Edit|Write|MultiEdit|Create|Delete)\\s+([^\\s(][^\\s]*\\.\\w{1,10})\\b/,\n )\n if (toolStartMatch) {\n return this.buildActivity(toolStartMatch[1], toolStartMatch[2])\n }\n\n // Pattern: Tool name with parenthesized path — \"Read(src/foo.ts)\" or \"Edit(file_path=...)\"\n const parenMatch = clean.match(\n /\\b(Read|Edit|Write|MultiEdit|Create|Delete)\\((?:file_path\\s*[:=]\\s*)?[\"']?([^\"')]+\\.\\w{1,10})[\"']?\\)/i,\n )\n if (parenMatch) {\n return this.buildActivity(parenMatch[1], parenMatch[2])\n }\n\n // Pattern: \"file_path\": \"src/foo.ts\" (JSON-like in tool output)\n const jsonFieldMatch = clean.match(\n /[\"']?file_path[\"']?\\s*[:=]\\s*[\"']([^\"']+\\.\\w{1,10})[\"']/i,\n )\n if (jsonFieldMatch) {\n const action = this.inferActionFromContext(clean)\n return this.buildActivity(action, jsonFieldMatch[1])\n }\n\n // Pattern: \"── Read: src/foo.ts\" or \"Read: src/foo.ts\"\n const colonMatch = clean.match(\n /(?:─+\\s*)?(Read|Edit|Write|MultiEdit|Create|Delete)\\s*:\\s*(.+?)(?:\\s*─+)?$/i,\n )\n if (colonMatch) {\n return this.buildActivity(colonMatch[1], colonMatch[2])\n }\n\n // Pattern: Spinner chars + tool — \"⠿ Edit src/foo.ts\" / \"✓ Write src/bar.ts\"\n const spinnerMatch = clean.match(\n /[⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏⠿✓✗✔✘●◉▶▸►◆◇■□▪▫★☆○◎]\\s*(Read|Edit|Write|MultiEdit|Create|Delete)\\s+(.+)/i,\n )\n if (spinnerMatch) {\n return this.buildActivity(spinnerMatch[1], spinnerMatch[2])\n }\n\n // Pattern: Indented path after tool header (continuation line)\n // e.g., \" /relative/path/file.ts\" or \" path/to/file.ts\"\n // Only if line is just a path with leading whitespace\n const indentedPathMatch = clean.match(\n /^([a-zA-Z0-9_][a-zA-Z0-9_./\\-]*\\.\\w{1,10})$/,\n )\n if (indentedPathMatch && line.startsWith(' ')) {\n return this.buildActivity('Read', indentedPathMatch[1])\n }\n\n return null\n }\n\n private buildActivity(toolName: string, rawPath: string): FileActivity | null {\n const file = this.cleanPath(rawPath)\n if (!file || !this.isValidPath(file)) return null\n\n const action = this.toolToAction(toolName)\n return { file, action, timestamp: Date.now() }\n }\n\n private toolToAction(tool: string): FileAction {\n switch (tool.toLowerCase()) {\n case 'read':\n case 'glob':\n case 'grep':\n return 'read'\n case 'edit':\n case 'multiedit':\n return 'edit'\n case 'write':\n return 'write'\n case 'create':\n return 'create'\n case 'delete':\n return 'delete'\n case 'bash':\n return 'bash'\n default:\n return 'read'\n }\n }\n\n private inferActionFromContext(line: string): string {\n const lower = line.toLowerCase()\n if (lower.includes('edit') || lower.includes('old_string') || lower.includes('new_string')) return 'Edit'\n if (lower.includes('write') || lower.includes('content')) return 'Write'\n if (lower.includes('delete') || lower.includes('remove')) return 'Delete'\n return 'Read'\n }\n\n private cleanPath(raw: string): string {\n return raw\n .trim()\n .replace(/^['\"`]+|['\"`]+$/g, '')\n .replace(/^\\.\\//, '')\n .replace(/\\s+.*$/, '') // Remove anything after whitespace\n .replace(/[,;:)]+$/, '') // Remove trailing punctuation\n .replace(/^\\(/, '') // Remove leading paren\n }\n\n // Paths under these prefixes are Nexus internals or noise — ignore them\n private static IGNORED_PREFIXES = ['.nexus/', 'node_modules/', '.git/']\n\n private isValidPath(file: string): boolean {\n if (!file || file.length < 3) return false\n // Must have a file extension\n if (!/\\.\\w{1,10}$/.test(file)) return false\n // Must not be absolute path or URL\n if (file.startsWith('/') || file.includes('://')) return false\n // Skip Nexus internal and noise paths\n for (const prefix of ActivityParser.IGNORED_PREFIXES) {\n if (file.startsWith(prefix)) return false\n }\n // No suspicious chars\n if (/[<>|&$`\\\\{}[\\]]/.test(file)) return false\n // Reasonable length\n const parts = file.split('/')\n if (parts.length > 15) return false\n for (const part of parts) {\n if (part.length > 100 || part.length === 0) return false\n }\n return true\n }\n}\n","import { spawn, type ChildProcessWithoutNullStreams } from 'node:child_process'\nimport fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport type {\n AgentDefinition,\n ConversationEvent,\n FileActivity,\n PaneConfig,\n PaneMeta,\n PaneStatus,\n} from '../types.ts'\nimport type { ConfigManager } from '../workspace/ConfigManager.ts'\n\nconst MAX_SCROLLBACK_BYTES = 512 * 1024\n\ninterface PendingRequest {\n resolve: (value: unknown) => void\n reject: (error: Error) => void\n}\n\ninterface AcpEntry {\n proc: ChildProcessWithoutNullStreams\n config: PaneConfig\n status: PaneStatus\n meta: PaneMeta\n nextRequestId: number\n nextMessageId: number\n nextToolId: number\n pending: Map<number, PendingRequest>\n stdoutBuffer: string\n scrollback: string[]\n scrollbackBytes: number\n onDataCallbacks: Array<(data: string) => void>\n onStatusCallbacks: Array<(status: PaneStatus) => void>\n onMetaCallbacks: Array<(meta: PaneMeta) => void>\n onConversationCallbacks: Array<(event: ConversationEvent) => void>\n onActivityCallbacks: Array<(activity: FileActivity) => void>\n}\n\nfunction resolveAgentEnv(agentDef: AgentDefinition | undefined): Record<string, string> {\n const env: Record<string, string> = {}\n for (const [key, value] of Object.entries(process.env)) {\n if (value !== undefined && !key.startsWith('CLAUDE') && key !== 'CLAUDECODE') {\n env[key] = value\n }\n }\n\n if (agentDef?.env) {\n const blocked = new Set([\n 'PATH', 'LD_PRELOAD', 'LD_LIBRARY_PATH',\n 'DYLD_INSERT_LIBRARIES', 'DYLD_LIBRARY_PATH', 'DYLD_FRAMEWORK_PATH',\n ])\n for (const [key, value] of Object.entries(agentDef.env)) {\n if (blocked.has(key)) continue\n env[key] = value.replace(/\\$\\{(\\w+)\\}/g, (_, name: string) => process.env[name] || '')\n }\n }\n\n if (!env.PATH) {\n env.PATH = '/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin'\n if (process.platform === 'darwin') {\n env.PATH = `/opt/homebrew/bin:/opt/homebrew/sbin:${env.PATH}`\n }\n }\n\n return env\n}\n\nexport class AcpRuntime {\n private entries = new Map<string, AcpEntry>()\n private configManager: ConfigManager\n\n constructor(configManager: ConfigManager) {\n this.configManager = configManager\n }\n\n spawn(paneId: string, config: PaneConfig): number | undefined {\n if (this.entries.has(paneId)) {\n this.kill(paneId)\n }\n\n const projectDir = this.configManager.getProjectDir()\n const basePath = (config.isolation === 'worktree' && config.worktreePath)\n ? config.worktreePath\n : projectDir\n let cwd = config.workdir\n ? path.resolve(basePath, config.workdir)\n : basePath\n\n if (!fs.existsSync(cwd)) {\n cwd = fs.existsSync(projectDir) ? projectDir : os.homedir()\n }\n\n const agentDef = this.configManager.getAgentDefinition(config.agent)\n if (!agentDef) {\n throw new Error(`Missing agent definition for ${config.agent}`)\n }\n\n const env = resolveAgentEnv(agentDef)\n const proc = spawn(agentDef.bin, ['acp'], {\n cwd,\n env,\n stdio: ['pipe', 'pipe', 'pipe'],\n })\n\n const entry: AcpEntry = {\n proc,\n config,\n status: 'running',\n meta: { cwd },\n nextRequestId: 1,\n nextMessageId: 1,\n nextToolId: 1,\n pending: new Map(),\n stdoutBuffer: '',\n scrollback: [],\n scrollbackBytes: 0,\n onDataCallbacks: [],\n onStatusCallbacks: [],\n onMetaCallbacks: [],\n onConversationCallbacks: [],\n onActivityCallbacks: [],\n }\n\n this.entries.set(paneId, entry)\n\n proc.stdout.setEncoding('utf8')\n proc.stderr.setEncoding('utf8')\n\n proc.stdout.on('data', (chunk: string) => this.handleStdout(paneId, chunk))\n proc.stderr.on('data', (chunk: string) => {\n this.emitTerminal(paneId, `[acp stderr] ${chunk}`)\n })\n proc.on('exit', (code, signal) => {\n const e = this.entries.get(paneId)\n if (!e) return\n for (const pending of e.pending.values()) {\n pending.reject(new Error(`ACP process exited (${code ?? 'null'}${signal ? `, ${signal}` : ''})`))\n }\n e.pending.clear()\n this.setStatus(paneId, code === 0 ? 'stopped' : 'error')\n })\n\n this.bootstrap(paneId, cwd, config).catch((err) => {\n this.emitTerminal(paneId, `[acp error] ${(err as Error).message}\\n`)\n this.setStatus(paneId, 'error')\n })\n\n return proc.pid\n }\n\n private async bootstrap(paneId: string, cwd: string, config: PaneConfig): Promise<void> {\n const initResult = await this.request(paneId, 'initialize', {\n protocolVersion: 1,\n clientInfo: { name: 'nexus', version: '0.1.0' },\n clientCapabilities: {},\n })\n\n const loadedSessionId = config.restore === 'resume' && config.sessionId\n ? await this.tryLoadSession(paneId, config.sessionId)\n : null\n\n const sessionResult = loadedSessionId\n ? { sessionId: loadedSessionId }\n : await this.request(paneId, 'session/new', {\n cwd,\n })\n\n const sessionId = this.extractSessionId(sessionResult) || this.extractSessionId(initResult) || config.sessionId\n if (sessionId) {\n this.updateMeta(paneId, { sessionId, cwd })\n } else {\n this.updateMeta(paneId, { cwd })\n }\n\n this.emitConversation(paneId, { type: 'status', status: 'idle' })\n this.setStatus(paneId, 'idle')\n\n if (config.task && config.restore !== 'manual') {\n await this.sendPrompt(paneId, config.task)\n }\n }\n\n private async tryLoadSession(paneId: string, sessionId: string): Promise<string | null> {\n try {\n const result = await this.request(paneId, 'session/load', { sessionId })\n return this.extractSessionId(result) || sessionId\n } catch {\n return null\n }\n }\n\n async sendPrompt(paneId: string, text: string): Promise<void> {\n const entry = this.entries.get(paneId)\n if (!entry) return\n\n const sessionId = entry.meta.sessionId || entry.config.sessionId\n const messageId = `user-${entry.nextMessageId++}`\n this.emitConversation(paneId, { type: 'message', messageId, role: 'user', text })\n this.emitTerminal(paneId, `\\n> ${text}\\n\\n`)\n this.setStatus(paneId, 'running')\n this.emitConversation(paneId, { type: 'status', status: 'running' })\n\n const params: Record<string, unknown> = {\n prompt: [{ type: 'text', text }],\n }\n if (sessionId) params.sessionId = sessionId\n\n await this.request(paneId, 'session/prompt', params)\n\n // Some ACP servers stream updates but do not send an explicit \"idle\" event.\n // We leave the pane in running until an update or request completion arrives.\n }\n\n onData(paneId: string, cb: (data: string) => void): void {\n const entry = this.entries.get(paneId)\n if (entry) entry.onDataCallbacks.push(cb)\n }\n\n onStatus(paneId: string, cb: (status: PaneStatus) => void): void {\n const entry = this.entries.get(paneId)\n if (entry) entry.onStatusCallbacks.push(cb)\n }\n\n onMeta(paneId: string, cb: (meta: PaneMeta) => void): void {\n const entry = this.entries.get(paneId)\n if (entry) entry.onMetaCallbacks.push(cb)\n }\n\n onConversation(paneId: string, cb: (event: ConversationEvent) => void): void {\n const entry = this.entries.get(paneId)\n if (entry) entry.onConversationCallbacks.push(cb)\n }\n\n onActivity(paneId: string, cb: (activity: FileActivity) => void): void {\n const entry = this.entries.get(paneId)\n if (entry) entry.onActivityCallbacks.push(cb)\n }\n\n write(_paneId: string, _data: string): void {\n // ACP-backed panes do not accept raw terminal input on the primary session.\n }\n\n resize(_paneId: string, _cols: number, _rows: number): void {\n // No-op for the initial minimal ACP path.\n }\n\n getScrollback(paneId: string): string {\n const entry = this.entries.get(paneId)\n return entry ? entry.scrollback.join('') : ''\n }\n\n kill(paneId: string): void {\n const entry = this.entries.get(paneId)\n if (!entry) return\n entry.proc.kill()\n this.entries.delete(paneId)\n }\n\n killAll(): void {\n for (const paneId of this.entries.keys()) {\n this.kill(paneId)\n }\n }\n\n private handleStdout(paneId: string, chunk: string): void {\n const entry = this.entries.get(paneId)\n if (!entry) return\n\n entry.stdoutBuffer += chunk\n while (true) {\n const newline = entry.stdoutBuffer.indexOf('\\n')\n if (newline === -1) break\n const line = entry.stdoutBuffer.slice(0, newline).trim()\n entry.stdoutBuffer = entry.stdoutBuffer.slice(newline + 1)\n if (!line) continue\n\n try {\n const message = JSON.parse(line) as Record<string, unknown>\n this.handleMessage(paneId, message)\n } catch {\n this.emitTerminal(paneId, line + '\\n')\n }\n }\n }\n\n private handleMessage(paneId: string, message: Record<string, unknown>): void {\n const entry = this.entries.get(paneId)\n if (!entry) return\n\n if (typeof message.id === 'number') {\n const pending = entry.pending.get(message.id)\n if (pending) {\n entry.pending.delete(message.id)\n if ('error' in message && message.error) {\n const err = message.error as { message?: string }\n pending.reject(new Error(err?.message || 'ACP request failed'))\n } else {\n pending.resolve(message.result)\n }\n }\n return\n }\n\n if (message.method === 'session/update') {\n const params = (message.params || {}) as Record<string, unknown>\n this.handleSessionUpdate(paneId, params)\n return\n }\n }\n\n private handleSessionUpdate(paneId: string, params: Record<string, unknown>): void {\n const sessionId = this.extractSessionId(params)\n if (sessionId) {\n this.updateMeta(paneId, { sessionId })\n }\n\n const rawUpdate = params.update || params.delta || params.event || params\n const updates = Array.isArray(rawUpdate) ? rawUpdate : [rawUpdate]\n\n for (const update of updates) {\n if (!update || typeof update !== 'object') continue\n const record = update as Record<string, unknown>\n const kind = String(record.type || record.kind || '')\n const content = this.extractText(record)\n\n if (kind.includes('agent_message')) {\n const messageId = `assistant-${this.entries.get(paneId)?.nextMessageId ?? 1}`\n this.emitConversation(paneId, {\n type: 'message',\n messageId,\n role: 'assistant',\n text: content,\n append: true,\n })\n if (content) {\n this.emitTerminal(paneId, content)\n }\n this.setStatus(paneId, 'running')\n } else if (kind.includes('tool_call')) {\n const toolCallId = `tool-${this.entries.get(paneId)?.nextToolId ?? 1}`\n this.emitConversation(paneId, {\n type: 'tool',\n toolCallId,\n title: String(record.title || record.name || 'tool'),\n status: kind.includes('update') ? 'in_progress' : 'pending',\n text: content || undefined,\n })\n if (content) {\n this.emitTerminal(paneId, `\\n[tool] ${content}\\n`)\n }\n } else if (kind.includes('turn') || kind.includes('done') || kind.includes('completed')) {\n this.setStatus(paneId, 'idle')\n this.emitConversation(paneId, { type: 'status', status: 'idle' })\n }\n }\n }\n\n private extractText(record: Record<string, unknown>): string {\n const direct = record.text || record.delta || record.content\n if (typeof direct === 'string') return direct\n if (Array.isArray(direct)) {\n return direct\n .map((item) => {\n if (typeof item === 'string') return item\n if (item && typeof item === 'object' && typeof (item as Record<string, unknown>).text === 'string') {\n return String((item as Record<string, unknown>).text)\n }\n return ''\n })\n .join('')\n }\n if (direct && typeof direct === 'object' && typeof (direct as Record<string, unknown>).text === 'string') {\n return String((direct as Record<string, unknown>).text)\n }\n return ''\n }\n\n private request(paneId: string, method: string, params: Record<string, unknown>): Promise<unknown> {\n const entry = this.entries.get(paneId)\n if (!entry) {\n return Promise.reject(new Error(`Missing ACP entry for ${paneId}`))\n }\n\n const id = entry.nextRequestId++\n const payload = JSON.stringify({ jsonrpc: '2.0', id, method, params }) + '\\n'\n entry.proc.stdin.write(payload)\n\n return new Promise((resolve, reject) => {\n entry.pending.set(id, { resolve, reject })\n })\n }\n\n private extractSessionId(result: unknown): string | undefined {\n if (!result || typeof result !== 'object') return undefined\n const record = result as Record<string, unknown>\n if (typeof record.sessionId === 'string') return record.sessionId\n if (typeof record.session_id === 'string') return record.session_id\n if (record.session && typeof record.session === 'object') {\n const nested = record.session as Record<string, unknown>\n if (typeof nested.id === 'string') return nested.id\n if (typeof nested.sessionId === 'string') return nested.sessionId\n }\n return undefined\n }\n\n private emitTerminal(paneId: string, data: string): void {\n const entry = this.entries.get(paneId)\n if (!entry || !data) return\n\n entry.scrollback.push(data)\n entry.scrollbackBytes += data.length\n if (entry.scrollbackBytes > MAX_SCROLLBACK_BYTES) {\n let bytesToRemove = entry.scrollbackBytes - MAX_SCROLLBACK_BYTES\n let removeCount = 0\n while (removeCount < entry.scrollback.length - 1 && bytesToRemove > 0) {\n bytesToRemove -= entry.scrollback[removeCount].length\n entry.scrollbackBytes -= entry.scrollback[removeCount].length\n removeCount++\n }\n if (removeCount > 0) entry.scrollback.splice(0, removeCount)\n }\n\n for (const cb of entry.onDataCallbacks) {\n cb(data)\n }\n }\n\n private setStatus(paneId: string, status: PaneStatus): void {\n const entry = this.entries.get(paneId)\n if (!entry || entry.status === status) return\n entry.status = status\n for (const cb of entry.onStatusCallbacks) {\n cb(status)\n }\n }\n\n private updateMeta(paneId: string, meta: PaneMeta): void {\n const entry = this.entries.get(paneId)\n if (!entry) return\n entry.meta = { ...entry.meta, ...meta }\n for (const cb of entry.onMetaCallbacks) {\n cb(entry.meta)\n }\n }\n\n private emitConversation(paneId: string, event: ConversationEvent): void {\n const entry = this.entries.get(paneId)\n if (!entry) return\n for (const cb of entry.onConversationCallbacks) {\n cb(event)\n }\n }\n}\n","import path from 'node:path'\nimport fs from 'node:fs'\nimport { simpleGit, type SimpleGit } from 'simple-git'\n\ninterface WorktreeEntry {\n path: string\n branch: string\n baseBranch: string\n}\n\nexport class WorktreeManager {\n private projectDir: string\n private git: SimpleGit\n private worktrees = new Map<string, WorktreeEntry>()\n\n constructor(projectDir: string) {\n this.projectDir = projectDir\n this.git = simpleGit(projectDir)\n }\n\n /**\n * Create a git worktree + branch for a pane.\n * Returns the worktree disk path and branch name.\n */\n async create(paneId: string, paneName: string): Promise<{ worktreePath: string; branch: string }> {\n const baseBranch = await this.getCurrentBranch()\n const slug = this.slugify(paneName)\n const branch = `nexus/${paneId}-${slug}`\n const worktreePath = path.join(this.projectDir, '.nexus', 'worktrees', paneId)\n\n // Clean up if leftover from previous session\n if (fs.existsSync(worktreePath)) {\n await this.forceRemoveWorktree(worktreePath)\n }\n\n // Delete branch if it already exists (stale from previous session)\n try {\n await this.git.raw(['branch', '-D', branch])\n } catch {\n // Branch doesn't exist, fine\n }\n\n fs.mkdirSync(path.dirname(worktreePath), { recursive: true })\n await this.git.raw(['worktree', 'add', '-b', branch, worktreePath, baseBranch])\n\n const entry: WorktreeEntry = { path: worktreePath, branch, baseBranch }\n this.worktrees.set(paneId, entry)\n\n return { worktreePath, branch }\n }\n\n /**\n * Restore a worktree from a previous session.\n * If the worktree directory still exists, re-register it.\n * If not, recreate it from the existing branch.\n * Returns false if the branch no longer exists (stale config).\n */\n async restore(paneId: string, branch: string, worktreePath: string): Promise<boolean> {\n // Determine base branch\n const baseBranch = await this.getCurrentBranch()\n\n // Check if branch exists\n try {\n await this.git.raw(['rev-parse', '--verify', branch])\n } catch {\n // Branch doesn't exist — stale config, can't restore\n return false\n }\n\n if (fs.existsSync(worktreePath)) {\n // Worktree directory still exists (non-graceful shutdown) — just re-register\n this.worktrees.set(paneId, { path: worktreePath, branch, baseBranch })\n return true\n }\n\n // Recreate worktree from existing branch\n try {\n // Clean up any stale git worktree metadata\n await this.git.raw(['worktree', 'prune']).catch(() => {})\n fs.mkdirSync(path.dirname(worktreePath), { recursive: true })\n await this.git.raw(['worktree', 'add', worktreePath, branch])\n this.worktrees.set(paneId, { path: worktreePath, branch, baseBranch })\n return true\n } catch (err) {\n console.warn(`[WorktreeManager] Failed to restore worktree for ${paneId}:`, (err as Error).message)\n return false\n }\n }\n\n /**\n * Remove a worktree. Branch is kept for later merge/PR.\n */\n async remove(paneId: string): Promise<void> {\n const entry = this.worktrees.get(paneId)\n if (!entry) return\n\n await this.forceRemoveWorktree(entry.path)\n this.worktrees.delete(paneId)\n }\n\n /**\n * Remove worktree and also delete the branch.\n */\n async removeWithBranch(paneId: string): Promise<void> {\n const entry = this.worktrees.get(paneId)\n if (!entry) return\n\n await this.forceRemoveWorktree(entry.path)\n\n try {\n await this.git.raw(['branch', '-D', entry.branch])\n } catch {\n // Branch may not exist\n }\n\n this.worktrees.delete(paneId)\n }\n\n /**\n * Get diffs for a worktree pane relative to its base branch.\n */\n async getDiffs(paneId: string): Promise<{ file: string; status: string; hunks: string }[]> {\n const entry = this.worktrees.get(paneId)\n if (!entry) return []\n\n const wtGit = simpleGit(entry.path)\n const diffs: { file: string; status: string; hunks: string }[] = []\n\n try {\n // Get status in the worktree (uncommitted changes)\n const status = await wtGit.status()\n\n // Also get committed changes vs base branch\n const committedDiff = await wtGit.diff([`${entry.baseBranch}...HEAD`]).catch(() => '')\n const uncommittedDiff = await wtGit.diff()\n const stagedDiff = await wtGit.diff(['--cached'])\n const combinedDiff = [committedDiff, uncommittedDiff, stagedDiff].filter(Boolean).join('\\n')\n\n // Collect all changed files\n const allFiles = new Set<string>()\n const fileStatuses = new Map<string, string>()\n\n // From committed diff vs base\n if (committedDiff) {\n const parsed = this.parseFileDiffs(committedDiff)\n for (const [file] of parsed) {\n allFiles.add(file)\n fileStatuses.set(file, 'modified')\n }\n }\n\n // From working tree status\n for (const file of status.created) {\n allFiles.add(file)\n fileStatuses.set(file, 'added')\n }\n for (const file of status.modified) {\n allFiles.add(file)\n if (!fileStatuses.has(file)) fileStatuses.set(file, 'modified')\n }\n for (const file of status.deleted) {\n allFiles.add(file)\n fileStatuses.set(file, 'deleted')\n }\n for (const file of status.renamed) {\n allFiles.add(file.to)\n fileStatuses.set(file.to, 'renamed')\n }\n for (const file of status.staged) {\n if (!allFiles.has(file)) {\n allFiles.add(file)\n fileStatuses.set(file, 'modified')\n }\n }\n\n // Parse hunks\n const hunkMap = combinedDiff ? this.parseFileDiffs(combinedDiff) : new Map<string, string>()\n\n for (const file of allFiles) {\n diffs.push({\n file,\n status: fileStatuses.get(file) || 'modified',\n hunks: hunkMap.get(file) || '',\n })\n }\n\n const fs = await import('node:fs/promises')\n for (const diff of diffs) {\n if (diff.status === 'added' && !diff.hunks) {\n try {\n const fullPath = path.join(entry.path, diff.file)\n const stat = await fs.stat(fullPath).catch(() => null)\n if (!stat || !stat.isFile()) continue\n if (stat.size > 256 * 1024) {\n diff.hunks = `--- /dev/null\\n+++ b/${diff.file}\\n@@ -0,0 +0,0 @@\\n Binary or large file (${Math.round(stat.size / 1024)}KB)`\n continue\n }\n const content = await fs.readFile(fullPath, 'utf-8')\n const lines = content.split('\\n')\n const plusLines = lines.map((line) => `+${line}`).join('\\n')\n diff.hunks = `--- /dev/null\\n+++ b/${diff.file}\\n@@ -0,0 +1,${lines.length} @@\\n${plusLines}`\n } catch {\n // Skip unreadable files.\n }\n }\n }\n } catch (err) {\n console.warn(`[WorktreeManager] getDiffs failed for ${paneId}:`, (err as Error).message)\n }\n\n return diffs\n }\n\n /**\n * Merge the worktree branch into the base branch (e.g. main).\n * First commits any uncommitted changes in the worktree, then merges.\n */\n async merge(paneId: string): Promise<{ success: boolean; message: string }> {\n const entry = this.worktrees.get(paneId)\n if (!entry) {\n return { success: false, message: 'Worktree not found for this pane' }\n }\n\n const wtGit = simpleGit(entry.path)\n\n try {\n // Auto-commit any uncommitted changes in the worktree\n const status = await wtGit.status()\n const hasChanges = status.modified.length > 0 || status.created.length > 0\n || status.deleted.length > 0 || status.staged.length > 0\n || status.not_added.length > 0\n\n if (hasChanges) {\n await wtGit.add('-A')\n await wtGit.commit(`nexus: auto-commit before merge (${entry.branch})`)\n }\n\n // Check if there are any commits to merge\n const log = await wtGit.log([`${entry.baseBranch}..${entry.branch}`])\n if (log.total === 0) {\n return { success: false, message: 'No changes to merge' }\n }\n\n // Merge from main repo (not worktree) to avoid \"can't merge into checked-out branch\" issue\n await this.git.merge([entry.branch])\n\n return {\n success: true,\n message: `Merged ${log.total} commit${log.total !== 1 ? 's' : ''} from ${entry.branch} into ${entry.baseBranch}`,\n }\n } catch (err) {\n // If merge failed due to conflict, abort it\n try {\n await this.git.merge(['--abort'])\n } catch {\n // ignore abort failure\n }\n return {\n success: false,\n message: `Merge conflict: ${(err as Error).message}`,\n }\n }\n }\n\n /**\n * Discard all changes: remove worktree and delete the branch.\n */\n async discard(paneId: string): Promise<{ success: boolean; message: string }> {\n const entry = this.worktrees.get(paneId)\n if (!entry) {\n return { success: false, message: 'Worktree not found for this pane' }\n }\n\n const branch = entry.branch\n await this.forceRemoveWorktree(entry.path)\n\n try {\n await this.git.raw(['branch', '-D', branch])\n } catch {\n // Branch may not exist\n }\n\n this.worktrees.delete(paneId)\n return { success: true, message: `Discarded branch ${branch}` }\n }\n\n getWorktreePath(paneId: string): string | undefined {\n return this.worktrees.get(paneId)?.path\n }\n\n getBranch(paneId: string): string | undefined {\n return this.worktrees.get(paneId)?.branch\n }\n\n getBaseBranch(paneId: string): string | undefined {\n return this.worktrees.get(paneId)?.baseBranch\n }\n\n has(paneId: string): boolean {\n return this.worktrees.has(paneId)\n }\n\n /**\n * Clean up all worktrees on shutdown.\n */\n async removeAll(): Promise<void> {\n for (const [paneId] of this.worktrees) {\n await this.remove(paneId)\n }\n }\n\n private async getCurrentBranch(): Promise<string> {\n try {\n const branch = await this.git.revparse(['--abbrev-ref', 'HEAD'])\n return branch.trim() || 'HEAD'\n } catch {\n return 'HEAD'\n }\n }\n\n private slugify(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9\\u4e00-\\u9fff]+/g, '-')\n .replace(/^-|-$/g, '')\n .slice(0, 30)\n }\n\n private async forceRemoveWorktree(wtPath: string): Promise<void> {\n try {\n await this.git.raw(['worktree', 'remove', '--force', wtPath])\n } catch {\n // Worktree may already be gone; clean up directory manually\n try {\n fs.rmSync(wtPath, { recursive: true, force: true })\n await this.git.raw(['worktree', 'prune'])\n } catch {\n // Best effort\n }\n }\n }\n\n private parseFileDiffs(diffText: string): Map<string, string> {\n const result = new Map<string, string>()\n const fileSections = diffText.split(/^diff --git /m).filter(Boolean)\n\n for (const section of fileSections) {\n const headerMatch = section.match(/^a\\/(.+?) b\\/(.+)/)\n if (!headerMatch) continue\n const filename = headerMatch[2]\n result.set(filename, `diff --git ${section}`)\n }\n\n return result\n }\n}\n","import path from 'node:path'\nimport { simpleGit, type SimpleGit } from 'simple-git'\nimport { watch, type FSWatcher } from 'chokidar'\nimport type { FileDiff } from '../types.ts'\n\nexport interface GitDiffResult {\n unstaged: FileDiff[]\n staged: FileDiff[]\n}\n\nexport class GitService {\n private git: SimpleGit\n private projectDir: string\n private gitWatcher: FSWatcher | null = null\n private workWatcher: FSWatcher | null = null\n private debounceTimer: ReturnType<typeof setTimeout> | null = null\n private workDebounceTimer: ReturnType<typeof setTimeout> | null = null\n private listeners = new Set<(result: GitDiffResult) => void>()\n private currentResult: GitDiffResult = { unstaged: [], staged: [] }\n\n constructor(projectDir: string) {\n this.projectDir = projectDir\n this.git = simpleGit(projectDir)\n }\n\n async start(): Promise<void> {\n const isRepo = await this.git.checkIsRepo()\n if (!isRepo) return\n\n await this.refresh()\n\n const scheduleRefresh = () => {\n if (this.debounceTimer) clearTimeout(this.debounceTimer)\n this.debounceTimer = setTimeout(() => {\n this.refresh()\n }, 1000)\n }\n\n const gitDir = path.join(this.projectDir, '.git')\n this.gitWatcher = watch([\n path.join(gitDir, 'index'),\n path.join(gitDir, 'HEAD'),\n path.join(gitDir, 'refs'),\n ], {\n persistent: true,\n ignoreInitial: true,\n })\n this.gitWatcher.on('all', scheduleRefresh)\n\n // Working tree watcher — uses a longer debounce to avoid flooding\n // git diff on every keystroke when agents are writing files\n const scheduleWorkRefresh = () => {\n if (this.workDebounceTimer) clearTimeout(this.workDebounceTimer)\n this.workDebounceTimer = setTimeout(() => {\n this.refresh()\n }, 3000)\n }\n\n this.workWatcher = watch(this.projectDir, {\n ignored: (filePath: string) => {\n const basename = path.basename(filePath)\n return basename === '.git' || basename === 'node_modules' || basename === '.nexus' || basename === 'dist'\n },\n persistent: true,\n ignoreInitial: true,\n depth: 5,\n })\n this.workWatcher.on('all', scheduleWorkRefresh)\n }\n\n async refresh(): Promise<void> {\n try {\n const result = await Promise.race([\n this.getDiffs(),\n new Promise<never>((_, reject) =>\n setTimeout(() => reject(new Error('git diff timeout')), 15000)\n ),\n ])\n this.currentResult = result\n this.notifyListeners()\n } catch (err) {\n if ((err as Error).message === 'git diff timeout') {\n console.warn('[GitService] git diff timed out (15s), using cached result')\n }\n // Other git failures also silently use cached result\n }\n }\n\n getCurrentDiffs(): GitDiffResult {\n return this.currentResult\n }\n\n onDiffChange(callback: (result: GitDiffResult) => void): () => void {\n this.listeners.add(callback)\n return () => this.listeners.delete(callback)\n }\n\n // ─── Stage / Unstage ─────────────────────────────────────\n\n async acceptFile(file: string): Promise<void> {\n await this.git.add(file)\n await this.refresh()\n }\n\n async acceptAll(): Promise<void> {\n await this.git.add('-A')\n await this.refresh()\n }\n\n async unstageFile(file: string): Promise<void> {\n await this.git.reset(['HEAD', '--', file])\n await this.refresh()\n }\n\n async unstageAll(): Promise<void> {\n await this.git.reset(['HEAD'])\n await this.refresh()\n }\n\n // ─── Discard ──────────────────────────────────────────────\n\n async discardFile(file: string): Promise<void> {\n const status = await this.git.status()\n const isUntracked = status.not_added.includes(file) || status.created.includes(file)\n\n if (isUntracked) {\n const fullPath = path.join(this.projectDir, file)\n const fs = await import('node:fs')\n if (fs.existsSync(fullPath)) {\n fs.unlinkSync(fullPath)\n }\n } else {\n await this.git.checkout(['--', file])\n try {\n await this.git.reset(['HEAD', '--', file])\n } catch {\n // May not be staged, ignore\n }\n }\n await this.refresh()\n }\n\n async discardAll(): Promise<void> {\n await this.git.checkout(['--', '.'])\n await this.git.clean('f', ['-d'])\n await this.refresh()\n }\n\n // ─── Commit / Push ────────────────────────────────────────\n\n async commit(message: string): Promise<string> {\n const result = await this.git.commit(message)\n await this.refresh()\n const summary = result.summary\n return `${summary.changes} file${summary.changes !== 1 ? 's' : ''}, +${summary.insertions} -${summary.deletions}`\n }\n\n async push(): Promise<string> {\n await this.git.push()\n await this.refresh()\n return 'Pushed successfully'\n }\n\n async getBranchInfo(): Promise<{ branch: string; remote?: string; ahead: number; behind: number }> {\n const status = await this.git.status()\n return {\n branch: status.current || 'HEAD',\n remote: status.tracking || undefined,\n ahead: status.ahead,\n behind: status.behind,\n }\n }\n\n // ─── Cleanup ──────────────────────────────────────────────\n\n close(): void {\n if (this.debounceTimer) clearTimeout(this.debounceTimer)\n if (this.workDebounceTimer) clearTimeout(this.workDebounceTimer)\n this.gitWatcher?.close()\n this.gitWatcher = null\n this.workWatcher?.close()\n this.workWatcher = null\n }\n\n // ─── Internal ─────────────────────────────────────────────\n\n private async getDiffs(): Promise<GitDiffResult> {\n const status = await this.git.status()\n const unstaged: FileDiff[] = []\n const staged: FileDiff[] = []\n\n // Get unified diffs\n const [unstagedDiffText, stagedDiffText] = await Promise.all([\n this.git.diff(),\n this.git.diff(['--cached']),\n ])\n\n const unstagedHunks = this.parseFileDiffs(unstagedDiffText)\n const stagedHunks = this.parseFileDiffs(stagedDiffText)\n\n const stagedFiles = new Set<string>(status.staged)\n\n // ─── Unstaged changes ───────────────────────────────────\n for (const file of status.not_added) {\n unstaged.push({ file, status: 'added', hunks: '' })\n }\n for (const file of status.created) {\n if (!stagedFiles.has(file)) {\n unstaged.push({ file, status: 'added', hunks: '' })\n }\n }\n for (const file of status.deleted) {\n if (!stagedFiles.has(file)) {\n unstaged.push({ file, status: 'deleted', hunks: '' })\n }\n }\n for (const file of status.modified) {\n unstaged.push({ file, status: 'modified', hunks: unstagedHunks.get(file) || '' })\n }\n for (const file of status.renamed) {\n if (!stagedFiles.has(file.to)) {\n unstaged.push({ file: file.to, status: 'renamed', hunks: '' })\n }\n }\n\n // Attach hunks to unstaged entries that don't have them yet\n for (const diff of unstaged) {\n if (!diff.hunks && unstagedHunks.has(diff.file)) {\n diff.hunks = unstagedHunks.get(diff.file)!\n }\n }\n\n // For untracked/new files without hunks, read file content to generate a synthetic diff.\n for (const diff of unstaged) {\n if (diff.status === 'added' && !diff.hunks) {\n try {\n const fs = await import('node:fs/promises')\n const fullPath = path.join(this.projectDir, diff.file)\n const stat = await fs.stat(fullPath).catch(() => null)\n if (!stat || !stat.isFile()) continue\n if (stat.size > 256 * 1024) {\n diff.hunks = `--- /dev/null\\n+++ b/${diff.file}\\n@@ -0,0 +0,0 @@\\n Binary or large file (${Math.round(stat.size / 1024)}KB)`\n continue\n }\n const content = await fs.readFile(fullPath, 'utf-8')\n const lines = content.split('\\n')\n const plusLines = lines.map((line) => `+${line}`).join('\\n')\n diff.hunks = `--- /dev/null\\n+++ b/${diff.file}\\n@@ -0,0 +1,${lines.length} @@\\n${plusLines}`\n } catch {\n // Skip unreadable files.\n }\n }\n }\n\n // ─── Staged changes ─────────────────────────────────────\n // Use status.files for accurate staged file detection\n for (const fileResult of status.files) {\n const indexStatus = fileResult.index\n if (!indexStatus || indexStatus === '?' || indexStatus === ' ') continue\n\n const file = fileResult.path\n let diffStatus: FileDiff['status'] = 'modified'\n if (indexStatus === 'A') diffStatus = 'added'\n else if (indexStatus === 'D') diffStatus = 'deleted'\n else if (indexStatus === 'R') diffStatus = 'renamed'\n\n staged.push({\n file,\n status: diffStatus,\n hunks: stagedHunks.get(file) || '',\n })\n }\n\n return { unstaged, staged }\n }\n\n private parseFileDiffs(diffText: string): Map<string, string> {\n const result = new Map<string, string>()\n if (!diffText) return result\n const fileSections = diffText.split(/^diff --git /m).filter(Boolean)\n\n for (const section of fileSections) {\n const headerMatch = section.match(/^a\\/(.+?) b\\/(.+)/)\n if (!headerMatch) continue\n const filename = headerMatch[2]\n result.set(filename, `diff --git ${section}`)\n }\n\n return result\n }\n\n private notifyListeners(): void {\n for (const listener of this.listeners) {\n listener(this.currentResult)\n }\n }\n}\n","import type {\n ConversationEvent,\n PaneConfig,\n PaneState,\n PaneCreateConfig,\n WorkspaceState,\n RestoreMode,\n PaneStatus,\n PaneMeta,\n FileNode,\n FileDiff,\n FileActivity,\n SessionInfo,\n} from '../types.ts'\nimport type { GitDiffResult } from '../git/GitService.ts'\nimport { PtyManager } from '../pty/PtyManager.ts'\nimport { AcpRuntime } from '../runtime/AcpRuntime.ts'\nimport { ConfigManager } from './ConfigManager.ts'\nimport { WorktreeManager } from '../git/WorktreeManager.ts'\nimport { GitService } from '../git/GitService.ts'\n\nlet paneCounter = 0\n\nfunction nextPaneId(): string {\n return `pane-${++paneCounter}`\n}\n\nexport interface EventHandlers {\n onPaneAdded?: (pane: PaneState) => void\n onPaneRemoved?: (paneId: string) => void\n onConversationEvent?: (paneId: string, event: ConversationEvent) => void\n onPaneStatus?: (paneId: string, status: PaneStatus) => void\n onPaneMeta?: (paneId: string, meta: PaneMeta) => void\n onTerminalData?: (paneId: string, data: string) => void\n onPaneActivity?: (paneId: string, activity: FileActivity) => void\n onFileActivity?: (activity: FileActivity) => void\n onFileTree?: (tree: FileNode[]) => void\n onGitDiff?: (result: GitDiffResult) => void\n onPaneDiff?: (paneId: string, diffs: FileDiff[]) => void\n}\n\ntype ListenerKey = keyof EventHandlers\n\nexport class WorkspaceManager {\n private panes = new Map<string, PaneState>()\n private ptyManager: PtyManager\n private acpRuntime: AcpRuntime\n private configManager: ConfigManager\n private worktreeManager: WorktreeManager\n private perPaneGitServices = new Map<string, GitService>()\n private wsName = ''\n private wsDescription = ''\n\n // Serialize config writes to prevent race conditions when closing multiple panes\n private configWriteLock: Promise<void> = Promise.resolve()\n\n // Multi-client event listener sets\n private listeners: { [K in ListenerKey]: Set<NonNullable<EventHandlers[K]>> } = {\n onPaneAdded: new Set(),\n onPaneRemoved: new Set(),\n onConversationEvent: new Set(),\n onPaneStatus: new Set(),\n onPaneMeta: new Set(),\n onTerminalData: new Set(),\n onPaneActivity: new Set(),\n onFileActivity: new Set(),\n onFileTree: new Set(),\n onGitDiff: new Set(),\n onPaneDiff: new Set(),\n }\n\n constructor(configManager: ConfigManager) {\n this.configManager = configManager\n this.ptyManager = new PtyManager(configManager)\n this.acpRuntime = new AcpRuntime(configManager)\n this.worktreeManager = new WorktreeManager(configManager.getProjectDir())\n }\n\n async init(): Promise<void> {\n const wsConfig = this.configManager.initWorkspace()\n this.wsName = wsConfig.name\n this.wsDescription = wsConfig.description || ''\n if (!Array.isArray(wsConfig.panes)) wsConfig.panes = []\n\n // Sync paneCounter to avoid id collisions with restored panes\n for (const p of wsConfig.panes) {\n const match = p.id.match(/^pane-(\\d+)$/)\n if (match) {\n const num = parseInt(match[1], 10)\n if (num >= paneCounter) paneCounter = num\n }\n }\n\n // Restore panes from config (skip failures — stale panes from previous sessions)\n // Auto-resume: if a pane has a saved sessionId, always use --resume regardless of original restore mode\n let failCount = 0\n for (const paneConfig of wsConfig.panes) {\n if (paneConfig.sessionId && paneConfig.agent !== '__shell__') {\n paneConfig.restore = 'resume'\n }\n\n // Restore worktree if needed\n if (paneConfig.isolation === 'worktree' && paneConfig.branch && paneConfig.worktreePath) {\n try {\n const restored = await this.worktreeManager.restore(paneConfig.id, paneConfig.branch, paneConfig.worktreePath)\n if (!restored) {\n console.warn(`Skipping worktree pane ${paneConfig.id} (${paneConfig.name}): branch no longer exists`)\n failCount++\n continue\n }\n } catch (err) {\n console.warn(`Skipping worktree pane ${paneConfig.id} (${paneConfig.name}): restore failed:`, (err as Error).message)\n failCount++\n continue\n }\n }\n\n try {\n this.spawnPane(paneConfig)\n\n // Start per-pane git service for worktree panes\n if (paneConfig.isolation === 'worktree' && paneConfig.worktreePath) {\n await this.startPaneGitService(paneConfig.id, paneConfig.worktreePath)\n }\n } catch (err) {\n console.warn(`Skipping stale pane ${paneConfig.id} (${paneConfig.name}):`, (err as Error).message)\n failCount++\n }\n }\n // Clean stale panes from config if any failed\n if (failCount > 0) {\n wsConfig.panes = wsConfig.panes.filter((p) => this.panes.has(p.id))\n this.configManager.saveWorkspaceConfig(wsConfig)\n }\n }\n\n getState(): WorkspaceState {\n return {\n name: this.wsName,\n description: this.wsDescription,\n projectDir: this.configManager.getProjectDir(),\n panes: Array.from(this.panes.values()),\n }\n }\n\n getPanes(): PaneState[] {\n return Array.from(this.panes.values())\n }\n\n async createPane(createConfig: PaneCreateConfig): Promise<PaneState> {\n const isShell = createConfig.agent === '__shell__'\n const id = isShell ? '__shell__' : nextPaneId()\n const isolation = createConfig.isolation || 'shared'\n\n // Extract cols/rows (transient, not persisted in PaneConfig)\n const { cols, rows, ...rest } = createConfig\n\n const config: PaneConfig = {\n id,\n ...rest,\n yolo: rest.yolo || false,\n isolation,\n sessionId: rest.sessionId,\n }\n\n // Create worktree if requested\n if (isolation === 'worktree' && !isShell) {\n try {\n const { worktreePath, branch } = await this.worktreeManager.create(id, createConfig.name)\n config.worktreePath = worktreePath\n config.branch = branch\n } catch (err) {\n console.error(`Failed to create worktree for pane ${id}:`, err)\n throw err\n }\n }\n\n try {\n const pane = this.spawnPane(config, cols, rows)\n\n // Start per-pane git service for worktree panes\n if (isolation === 'worktree' && config.worktreePath) {\n await this.startPaneGitService(id, config.worktreePath)\n }\n\n // Don't persist the bottom shell pane to workspace config\n if (!isShell) {\n this.persistPaneConfig(config)\n }\n return pane\n } catch (err) {\n // Clean up worktree on spawn failure\n if (isolation === 'worktree') {\n await this.worktreeManager.removeWithBranch(id)\n }\n console.error(`Failed to create pane ${id}:`, err)\n throw err\n }\n }\n\n async closePane(paneId: string): Promise<void> {\n const pane = this.panes.get(paneId)\n if (pane?.runtime === 'acp') {\n this.acpRuntime.kill(paneId)\n } else {\n this.ptyManager.kill(paneId)\n }\n\n // Clean up worktree resources\n if (pane?.isolation === 'worktree') {\n this.stopPaneGitService(paneId)\n await this.worktreeManager.remove(paneId)\n }\n\n this.panes.delete(paneId)\n this.emit('onPaneRemoved', paneId)\n this.removePaneFromConfig(paneId)\n }\n\n restartPane(paneId: string, mode: RestoreMode, sessionId?: string): void {\n const existingState = this.panes.get(paneId)\n if (!existingState) return\n\n if (existingState.runtime === 'acp') {\n this.acpRuntime.kill(paneId)\n } else {\n this.ptyManager.kill(paneId)\n }\n\n // For resume mode, use the provided sessionId or fall back to the last known one\n const resolvedSessionId = mode === 'resume'\n ? (sessionId || existingState.sessionId || existingState.meta.sessionId)\n : undefined\n\n const config: PaneConfig = {\n id: paneId,\n name: existingState.name,\n agent: existingState.agent,\n workdir: existingState.workdir,\n task: existingState.task,\n restore: mode,\n isolation: existingState.isolation,\n yolo: existingState.yolo || false,\n worktreePath: existingState.worktreePath,\n branch: existingState.branch,\n sessionId: resolvedSessionId,\n }\n\n this.spawnPane(config)\n this.updatePaneConfigSessionId(paneId, resolvedSessionId)\n }\n\n async mergeWorktree(paneId: string): Promise<{ success: boolean; message: string }> {\n const pane = this.panes.get(paneId)\n if (!pane || pane.isolation !== 'worktree') {\n return { success: false, message: 'Pane is not a worktree pane' }\n }\n return this.worktreeManager.merge(paneId)\n }\n\n async discardWorktree(paneId: string): Promise<{ success: boolean; message: string }> {\n const pane = this.panes.get(paneId)\n if (!pane || pane.isolation !== 'worktree') {\n return { success: false, message: 'Pane is not a worktree pane' }\n }\n\n // Stop per-pane git service\n this.stopPaneGitService(paneId)\n\n // Discard worktree and branch\n const result = await this.worktreeManager.discard(paneId)\n\n if (result.success) {\n // Clear worktree info from pane state (pane stays open but no longer isolated)\n pane.isolation = 'shared'\n pane.worktreePath = undefined\n pane.branch = undefined\n // Emit empty diffs to clear the UI\n this.emit('onPaneDiff', paneId, [])\n }\n\n return result\n }\n\n writeToPane(paneId: string, data: string): void {\n const pane = this.panes.get(paneId)\n if (!pane) return\n if (pane.runtime === 'acp') {\n this.acpRuntime.write(paneId, data)\n return\n }\n this.ptyManager.write(paneId, data)\n }\n\n sendConversationToPane(paneId: string, text: string): Promise<void> {\n const pane = this.panes.get(paneId)\n if (!pane) return Promise.resolve()\n if (pane.runtime === 'acp') {\n return this.acpRuntime.sendPrompt(paneId, text)\n }\n this.ptyManager.write(paneId, text + '\\r')\n return Promise.resolve()\n }\n\n resizePane(paneId: string, cols: number, rows: number): void {\n const pane = this.panes.get(paneId)\n if (!pane) return\n if (pane.runtime === 'acp') {\n this.acpRuntime.resize(paneId, cols, rows)\n return\n }\n this.ptyManager.resize(paneId, cols, rows)\n }\n\n getScrollback(paneId: string): string {\n const pane = this.panes.get(paneId)\n if (!pane) return ''\n return pane.runtime === 'acp'\n ? this.acpRuntime.getScrollback(paneId)\n : this.ptyManager.getScrollback(paneId)\n }\n\n // ─── Event Registration (multi-client safe) ────────────────\n\n /**\n * Register event handlers for a client. Returns a cleanup function\n * that removes only this client's handlers.\n */\n onEvents(handlers: EventHandlers): () => void {\n const cleanups: Array<() => void> = []\n\n for (const key of Object.keys(handlers) as ListenerKey[]) {\n const handler = handlers[key]\n if (handler) {\n const set = this.listeners[key] as Set<typeof handler>\n set.add(handler)\n cleanups.push(() => set.delete(handler))\n }\n }\n\n return () => {\n for (const cleanup of cleanups) {\n cleanup()\n }\n }\n }\n\n // Broadcast events (called by services)\n emitFileTree(tree: FileNode[]): void {\n this.emit('onFileTree', tree)\n }\n\n emitGitDiff(result: GitDiffResult): void {\n this.emit('onGitDiff', result)\n }\n\n emitFileActivity(activity: FileActivity): void {\n this.emit('onFileActivity', activity)\n }\n\n async refreshPaneDiff(paneId: string): Promise<void> {\n const gitService = this.perPaneGitServices.get(paneId)\n if (gitService) {\n await gitService.refresh()\n }\n }\n\n /**\n * Get current per-pane diffs (for initial sync on WS connect).\n */\n getPaneDiffs(): Map<string, FileDiff[]> {\n const result = new Map<string, FileDiff[]>()\n for (const [paneId, gitService] of this.perPaneGitServices) {\n result.set(paneId, gitService.getCurrentDiffs().unstaged)\n }\n return result\n }\n\n // ─── Internal ─────────────────────────────────────────────\n\n private emit<K extends ListenerKey>(key: K, ...args: Parameters<NonNullable<EventHandlers[K]>>): void {\n const set = this.listeners[key] as Set<(...a: typeof args) => void>\n for (const listener of set) {\n listener(...args)\n }\n }\n\n private spawnPane(config: PaneConfig, cols?: number, rows?: number): PaneState {\n const runtime = this.resolveRuntime(config.agent)\n const pid = runtime === 'acp'\n ? this.acpRuntime.spawn(config.id, config)\n : this.ptyManager.spawn(config.id, config, cols || 80, rows || 24)\n\n const pane: PaneState = {\n id: config.id,\n name: config.name,\n agent: config.agent,\n workdir: config.workdir,\n task: config.task,\n restore: config.restore,\n isolation: config.isolation || 'shared',\n yolo: config.yolo || false,\n branch: config.branch,\n worktreePath: config.worktreePath,\n sessionId: config.sessionId,\n runtime,\n status: 'running',\n pid,\n meta: {},\n startedAt: new Date().toISOString(),\n }\n\n this.panes.set(config.id, pane)\n this.emit('onPaneAdded', pane)\n\n const runtimeAdapter = runtime === 'acp' ? this.acpRuntime : this.ptyManager\n\n runtimeAdapter.onData(config.id, (data) => {\n this.emit('onTerminalData', config.id, data)\n })\n\n runtimeAdapter.onStatus(config.id, (status) => {\n const p = this.panes.get(config.id)\n if (p) {\n p.status = status\n this.emit('onPaneStatus', config.id, status)\n }\n })\n\n runtimeAdapter.onMeta(config.id, (meta) => {\n const p = this.panes.get(config.id)\n if (p) {\n p.meta = meta\n // Persist sessionId from statusline to PaneState and config.yaml for auto-resume\n if (meta.sessionId && meta.sessionId !== p.sessionId) {\n p.sessionId = meta.sessionId\n this.updatePaneConfigSessionId(config.id, meta.sessionId)\n }\n this.emit('onPaneMeta', config.id, meta)\n }\n })\n\n runtimeAdapter.onActivity(config.id, (activity) => {\n this.emit('onPaneActivity', config.id, activity)\n })\n\n if (runtime === 'acp') {\n this.acpRuntime.onConversation(config.id, (event) => {\n this.emit('onConversationEvent', config.id, event)\n })\n }\n\n return pane\n }\n\n private resolveRuntime(agentType: PaneState['agent']): PaneState['runtime'] {\n if (agentType === '__shell__') return 'pty'\n const def = this.configManager.getAgentDefinition(agentType)\n return def?.transport || 'pty'\n }\n\n private async startPaneGitService(paneId: string, worktreePath: string): Promise<void> {\n const gitService = new GitService(worktreePath)\n gitService.onDiffChange((result) => {\n // Tag each unstaged diff with the paneId (worktree panes show unstaged only)\n const tagged = result.unstaged.map((d) => ({ ...d, paneId }))\n this.emit('onPaneDiff', paneId, tagged)\n })\n await gitService.start()\n this.perPaneGitServices.set(paneId, gitService)\n }\n\n private stopPaneGitService(paneId: string): void {\n const gitService = this.perPaneGitServices.get(paneId)\n if (gitService) {\n gitService.close()\n this.perPaneGitServices.delete(paneId)\n }\n }\n\n private persistPaneConfig(config: PaneConfig): void {\n this.serializedConfigWrite(() => {\n const wsConfig = this.configManager.loadWorkspaceConfig()\n if (wsConfig) {\n wsConfig.panes.push(config)\n this.configManager.saveWorkspaceConfig(wsConfig)\n }\n })\n }\n\n private updatePaneConfigSessionId(paneId: string, sessionId?: string): void {\n this.serializedConfigWrite(() => {\n const wsConfig = this.configManager.loadWorkspaceConfig()\n if (wsConfig) {\n const paneConfig = wsConfig.panes.find((p) => p.id === paneId)\n if (paneConfig) {\n paneConfig.sessionId = sessionId\n this.configManager.saveWorkspaceConfig(wsConfig)\n }\n }\n })\n }\n\n getSessionList(paneId?: string): SessionInfo[] {\n const sessions: SessionInfo[] = []\n for (const pane of this.panes.values()) {\n if (pane.agent === '__shell__') continue\n if (paneId && pane.id !== paneId) continue\n if (pane.meta.sessionId || pane.sessionId) {\n sessions.push({\n sessionId: (pane.meta.sessionId || pane.sessionId)!,\n paneId: pane.id,\n paneName: pane.name,\n agent: pane.agent,\n timestamp: pane.startedAt || new Date().toISOString(),\n costUsd: pane.meta.costUsd,\n contextUsedPct: pane.meta.contextUsedPct,\n model: pane.meta.model,\n })\n }\n }\n // Also include sessions from config that aren't currently running\n const wsConfig = this.configManager.loadWorkspaceConfig()\n if (wsConfig) {\n for (const pc of wsConfig.panes) {\n if (pc.sessionId && !sessions.find((s) => s.sessionId === pc.sessionId)) {\n if (paneId && pc.id !== paneId) continue\n sessions.push({\n sessionId: pc.sessionId,\n paneId: pc.id,\n paneName: pc.name,\n agent: pc.agent,\n timestamp: '',\n })\n }\n }\n }\n return sessions\n }\n\n private removePaneFromConfig(paneId: string): void {\n this.serializedConfigWrite(() => {\n const wsConfig = this.configManager.loadWorkspaceConfig()\n if (wsConfig) {\n wsConfig.panes = wsConfig.panes.filter((p) => p.id !== paneId)\n this.configManager.saveWorkspaceConfig(wsConfig)\n }\n })\n }\n\n /**\n * Serialize config file writes to prevent race conditions\n * when multiple panes are created/closed simultaneously.\n */\n private serializedConfigWrite(fn: () => void): void {\n this.configWriteLock = this.configWriteLock.then(() => {\n try {\n fn()\n } catch (err) {\n console.error('[WorkspaceManager] Config write failed:', err)\n }\n })\n }\n\n async shutdown(): Promise<void> {\n this.ptyManager.killAll()\n this.acpRuntime.killAll()\n // Close per-pane git services (worktree directories are preserved for restore)\n for (const [paneId] of this.perPaneGitServices) {\n this.stopPaneGitService(paneId)\n }\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport yaml from 'js-yaml'\nimport type { PaneState } from '../types.ts'\n\nexport class AgentsYamlWriter {\n private projectDir: string\n private debounceTimer: ReturnType<typeof setTimeout> | null = null\n\n constructor(projectDir: string) {\n this.projectDir = projectDir\n }\n\n /**\n * Write agents.yaml with current pane states. Debounced to avoid excessive writes.\n */\n update(panes: PaneState[]): void {\n if (this.debounceTimer) clearTimeout(this.debounceTimer)\n this.debounceTimer = setTimeout(() => {\n this.writeFile(panes)\n }, 500)\n }\n\n /**\n * Write immediately without debouncing.\n */\n flush(panes: PaneState[]): void {\n if (this.debounceTimer) clearTimeout(this.debounceTimer)\n this.writeFile(panes)\n }\n\n private writeFile(panes: PaneState[]): void {\n const nexusDir = path.join(this.projectDir, '.nexus')\n fs.mkdirSync(nexusDir, { recursive: true })\n\n // Filter out the bottom shell pane\n const visible = panes.filter((p) => p.agent !== '__shell__')\n\n const data = {\n updated_at: new Date().toISOString(),\n panes: visible.map((p) => {\n const basePath = (p.isolation === 'worktree' && p.worktreePath)\n ? p.worktreePath\n : this.projectDir\n return {\n id: p.id,\n name: p.name,\n agent: p.agent,\n runtime: p.runtime,\n pid: p.pid,\n status: p.status,\n isolation: p.isolation || 'shared',\n branch: p.branch || undefined,\n workdir: p.workdir\n ? path.resolve(basePath, p.workdir)\n : basePath,\n task: p.task || undefined,\n model: p.meta.model || undefined,\n context_used_pct: p.meta.contextUsedPct ?? undefined,\n cost_usd: p.meta.costUsd ?? undefined,\n session_id: p.meta.sessionId || undefined,\n started_at: p.startedAt || undefined,\n }\n }),\n }\n\n const filePath = path.join(nexusDir, 'agents.yaml')\n fs.writeFileSync(filePath, yaml.dump(data, { lineWidth: -1 }))\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { watch, type FSWatcher } from 'chokidar'\nimport type { FileNode, FileActivity } from '../types.ts'\n\nconst IGNORED_DIRS = new Set([\n 'node_modules',\n '.git',\n '.nexus',\n 'dist',\n '.cache',\n '.turbo',\n '__pycache__',\n])\n\nconst IGNORED_FILES = new Set([\n '.DS_Store',\n 'Thumbs.db',\n])\n\nexport class FsWatcher {\n private projectDir: string\n private watcher: FSWatcher | null = null\n private tree: FileNode[] = []\n private debounceTimer: ReturnType<typeof setTimeout> | null = null\n private listeners = new Set<(tree: FileNode[]) => void>()\n private fileChangeListeners = new Set<(activity: FileActivity) => void>()\n private recentChanges = new Map<string, number>() // path → timestamp for dedup\n\n constructor(projectDir: string) {\n this.projectDir = projectDir\n }\n\n start(): void {\n // Build initial tree synchronously\n this.tree = this.buildTree(this.projectDir, 0)\n this.notifyListeners()\n\n // Watch top-level directory only (depth 0) for structural changes\n // Use function-based ignored to reliably filter out heavy directories\n this.watcher = watch(this.projectDir, {\n ignored: (filePath: string) => {\n const basename = path.basename(filePath)\n return IGNORED_DIRS.has(basename) || IGNORED_FILES.has(basename)\n },\n persistent: true,\n ignoreInitial: true,\n depth: 5,\n })\n\n const scheduleRebuild = () => {\n if (this.debounceTimer) clearTimeout(this.debounceTimer)\n this.debounceTimer = setTimeout(() => {\n const newTree = this.buildTree(this.projectDir, 0)\n // Skip broadcast if tree hasn't structurally changed\n if (this.treeFingerprint(newTree) === this.treeFingerprint(this.tree)) return\n this.tree = newTree\n this.notifyListeners()\n }, 300)\n }\n\n // Emit individual file change events for activity tracking\n const emitFileChange = (eventType: 'add' | 'change' | 'unlink', filePath: string) => {\n // Only emit for files, not directories\n const relativePath = path.relative(this.projectDir, filePath)\n if (!relativePath || relativePath.startsWith('..')) return\n // Skip files without extension (likely directories or special files)\n if (!/\\.\\w{1,10}$/.test(path.basename(filePath))) return\n // Dedup: skip if same file changed within 1s\n const now = Date.now()\n const lastChange = this.recentChanges.get(relativePath)\n if (lastChange && now - lastChange < 1000) return\n this.recentChanges.set(relativePath, now)\n // Clean old entries periodically\n if (this.recentChanges.size > 200) {\n for (const [key, ts] of this.recentChanges) {\n if (now - ts > 10000) this.recentChanges.delete(key)\n }\n }\n\n const actionMap = { add: 'create' as const, change: 'edit' as const, unlink: 'delete' as const }\n const activity: FileActivity = {\n file: relativePath,\n action: actionMap[eventType],\n timestamp: now,\n }\n for (const listener of this.fileChangeListeners) {\n listener(activity)\n }\n }\n\n this.watcher.on('add', (p) => { emitFileChange('add', p); scheduleRebuild() })\n this.watcher.on('change', (p) => { emitFileChange('change', p) })\n this.watcher.on('unlink', (p) => { emitFileChange('unlink', p); scheduleRebuild() })\n this.watcher.on('addDir', scheduleRebuild)\n this.watcher.on('unlinkDir', scheduleRebuild)\n this.watcher.on('error', () => {\n // Silently handle watcher errors (e.g., ENOSPC)\n // Tree is still built synchronously, just won't auto-update\n })\n }\n\n getTree(): FileNode[] {\n return this.tree\n }\n\n onTreeChange(callback: (tree: FileNode[]) => void): () => void {\n this.listeners.add(callback)\n return () => this.listeners.delete(callback)\n }\n\n onFileChange(callback: (activity: FileActivity) => void): () => void {\n this.fileChangeListeners.add(callback)\n return () => this.fileChangeListeners.delete(callback)\n }\n\n close(): void {\n if (this.debounceTimer) clearTimeout(this.debounceTimer)\n this.watcher?.close()\n this.watcher = null\n }\n\n private notifyListeners(): void {\n for (const listener of this.listeners) {\n listener(this.tree)\n }\n }\n\n private treeFingerprint(tree: FileNode[]): string {\n // Fast structural fingerprint: concatenate paths and types\n const parts: string[] = []\n const walk = (nodes: FileNode[]) => {\n for (const n of nodes) {\n parts.push(n.path)\n if (n.children) walk(n.children)\n }\n }\n walk(tree)\n return parts.join('\\n')\n }\n\n private buildTree(dirPath: string, depth: number): FileNode[] {\n if (depth > 5) return [] // Match chokidar watch depth\n\n try {\n const entries = fs.readdirSync(dirPath, { withFileTypes: true })\n const nodes: FileNode[] = []\n\n for (const entry of entries) {\n if (IGNORED_DIRS.has(entry.name) || IGNORED_FILES.has(entry.name)) continue\n\n const fullPath = path.join(dirPath, entry.name)\n const relativePath = path.relative(this.projectDir, fullPath)\n\n if (entry.isDirectory()) {\n nodes.push({\n name: entry.name,\n path: relativePath,\n type: 'directory',\n children: this.buildTree(fullPath, depth + 1),\n })\n } else if (entry.isFile()) {\n nodes.push({\n name: entry.name,\n path: relativePath,\n type: 'file',\n })\n }\n }\n\n // Sort: directories first, then files, alphabetical within each group\n nodes.sort((a, b) => {\n if (a.type !== b.type) return a.type === 'directory' ? -1 : 1\n return a.name.localeCompare(b.name)\n })\n\n return nodes\n } catch {\n return []\n }\n }\n}\n","import type { WebSocket } from '@fastify/websocket'\nimport type { ClientEvent, ServerEvent } from '../types.ts'\nimport type { WorkspaceManager } from '../workspace/WorkspaceManager.ts'\nimport type { GitService } from '../git/GitService.ts'\n\nexport function setupWsHandlers(\n socket: WebSocket,\n workspaceManager: WorkspaceManager,\n gitService?: GitService,\n): void {\n const send = (event: ServerEvent) => {\n if (socket.readyState === socket.OPEN) {\n socket.send(JSON.stringify(event))\n }\n }\n\n // Send initial workspace state\n const state = workspaceManager.getState()\n send({\n type: 'workspace.state',\n state,\n })\n\n // Replay terminal scrollback for each pane asynchronously.\n // Uses setImmediate to yield between panes and between chunks,\n // preventing event loop starvation with 10+ panes × 512KB scrollback.\n const SCROLLBACK_CHUNK_SIZE = 512 * 1024 // 512KB per message — matches server-side scrollback limit\n const replayScrollback = async () => {\n for (const pane of state.panes) {\n const scrollback = workspaceManager.getScrollback(pane.id)\n if (!scrollback) continue\n if (scrollback.length <= SCROLLBACK_CHUNK_SIZE) {\n send({ type: 'terminal.output', paneId: pane.id, data: scrollback })\n } else {\n for (let i = 0; i < scrollback.length; i += SCROLLBACK_CHUNK_SIZE) {\n if (socket.readyState !== socket.OPEN) return // bail if disconnected\n send({ type: 'terminal.output', paneId: pane.id, data: scrollback.slice(i, i + SCROLLBACK_CHUNK_SIZE) })\n // Yield to event loop between chunks\n await new Promise<void>((resolve) => setImmediate(resolve))\n }\n }\n }\n }\n replayScrollback().catch(() => { /* socket may have closed */ })\n\n // Send initial per-pane diffs for worktree panes\n const paneDiffs = workspaceManager.getPaneDiffs()\n for (const [paneId, diffs] of paneDiffs) {\n if (diffs.length > 0) {\n send({ type: 'pane.diff', paneId, diffs })\n }\n }\n\n // Send initial branch info\n gitService?.getBranchInfo()\n .then((info) => send({ type: 'git.branchInfo', ...info }))\n .catch(() => {})\n\n // Register event handlers for this client (multi-client safe)\n const cleanup = workspaceManager.onEvents({\n onTerminalData: (paneId, data) => {\n send({ type: 'terminal.output', paneId, data })\n },\n onConversationEvent: (paneId, event) => {\n send({ type: 'conversation.event', paneId, event })\n },\n onPaneStatus: (paneId, status) => {\n send({ type: 'pane.status', paneId, status })\n },\n onPaneMeta: (paneId, meta) => {\n send({ type: 'pane.meta', paneId, meta })\n },\n onPaneAdded: (pane) => {\n send({ type: 'pane.added', pane })\n },\n onPaneRemoved: (paneId) => {\n send({ type: 'pane.removed', paneId })\n },\n onPaneActivity: (paneId, activity) => {\n send({ type: 'pane.activity', paneId, activity })\n },\n onFileActivity: (activity) => {\n send({ type: 'file.activity', activity })\n },\n onPaneDiff: (paneId, diffs) => {\n send({ type: 'pane.diff', paneId, diffs })\n },\n onFileTree: (tree) => {\n send({ type: 'fs.tree', tree })\n },\n onGitDiff: (result) => {\n send({ type: 'git.diff', unstaged: result.unstaged, staged: result.staged })\n },\n })\n\n // Handle incoming messages from client\n socket.on('message', (raw: { toString(): string }) => {\n let event: ClientEvent\n try {\n event = JSON.parse(raw.toString()) as ClientEvent\n } catch {\n return\n }\n\n switch (event.type) {\n case 'terminal.input':\n try {\n workspaceManager.writeToPane(event.paneId, event.data)\n } catch {\n // Pane may have been closed between events — silently ignore\n }\n break\n\n case 'terminal.resize':\n try {\n workspaceManager.resizePane(event.paneId, event.cols, event.rows)\n } catch {\n // Pane may have been closed — ignore\n }\n break\n\n case 'conversation.send':\n workspaceManager.sendConversationToPane(event.paneId, event.text).catch((err) => {\n console.error('conversation.send failed:', err)\n })\n break\n\n case 'pane.create':\n workspaceManager.createPane(event.config).catch((err) => {\n console.error('pane.create failed:', err)\n })\n break\n\n case 'pane.close':\n workspaceManager.closePane(event.paneId).catch((err) => {\n console.error('pane.close failed:', err)\n })\n break\n\n case 'pane.restart':\n workspaceManager.restartPane(event.paneId, event.mode, event.sessionId)\n break\n\n case 'session.list':\n send({ type: 'session.list', paneId: event.paneId, sessions: workspaceManager.getSessionList(event.paneId) })\n break\n\n case 'git.refresh':\n gitService?.refresh()\n break\n\n case 'git.accept':\n gitService?.acceptFile(event.file).catch((err) => {\n console.error('git.accept failed:', err)\n })\n break\n\n case 'git.accept.all':\n gitService?.acceptAll().catch((err) => {\n console.error('git.accept.all failed:', err)\n })\n break\n\n case 'git.discard':\n gitService?.discardFile(event.file).catch((err) => {\n console.error('git.discard failed:', err)\n })\n break\n\n case 'git.discard.all':\n gitService?.discardAll().catch((err) => {\n console.error('git.discard.all failed:', err)\n })\n break\n\n case 'git.unstage':\n gitService?.unstageFile(event.file).catch((err) => {\n console.error('git.unstage failed:', err)\n })\n break\n\n case 'git.unstage.all':\n gitService?.unstageAll().catch((err) => {\n console.error('git.unstage.all failed:', err)\n })\n break\n\n case 'git.commit':\n if (gitService) {\n gitService.commit(event.message)\n .then((summary) => {\n send({ type: 'git.result', action: 'commit', success: true, message: summary })\n // Also refresh branch info after commit\n return gitService.getBranchInfo()\n })\n .then((info) => {\n send({ type: 'git.branchInfo', ...info })\n })\n .catch((err) => {\n send({ type: 'git.result', action: 'commit', success: false, message: String(err) })\n })\n }\n break\n\n case 'git.push':\n if (gitService) {\n gitService.push()\n .then((summary) => {\n send({ type: 'git.result', action: 'push', success: true, message: summary })\n return gitService.getBranchInfo()\n })\n .then((info) => {\n send({ type: 'git.branchInfo', ...info })\n })\n .catch((err) => {\n send({ type: 'git.result', action: 'push', success: false, message: String(err) })\n })\n }\n break\n\n case 'pane.merge':\n workspaceManager.mergeWorktree(event.paneId)\n .then((result) => {\n send({ type: 'pane.merge.result', paneId: event.paneId, ...result })\n // Refresh global git diff after merge\n gitService?.refresh()\n })\n .catch((err) => {\n send({ type: 'pane.merge.result', paneId: event.paneId, success: false, message: String(err) })\n })\n break\n\n case 'pane.discard':\n workspaceManager.discardWorktree(event.paneId)\n .then((result) => {\n send({ type: 'pane.merge.result', paneId: event.paneId, ...result })\n gitService?.refresh()\n })\n .catch((err) => {\n send({ type: 'pane.merge.result', paneId: event.paneId, success: false, message: String(err) })\n })\n break\n\n case 'pane.diff.refresh':\n workspaceManager.refreshPaneDiff(event.paneId)\n break\n\n case 'workspace.save':\n break\n\n case 'review.comment': {\n // Send review comment to agent pane as terminal input\n const { paneId: targetPaneId, comment } = event\n const targetPane = workspaceManager.getPanes().find((p) => p.id === targetPaneId)\n if (targetPane && comment.content.trim()) {\n const msg = [\n '',\n `[Review Comment] ${comment.file}:${comment.line}`,\n comment.content.trim(),\n '',\n ].join('\\n')\n workspaceManager.writeToPane(targetPaneId, msg + '\\n')\n }\n break\n }\n\n case 'broadcast.send':\n case 'task.dispatch':\n // P2 features — no-op for now\n break\n }\n })\n\n socket.on('close', () => {\n cleanup()\n })\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\n\n// ─── Types ───────────────────────────────────────────────────\n\nexport interface DepNode {\n id: string // relative file path (e.g., \"src/index.ts\")\n imports: string[] // resolved relative paths this file imports\n}\n\nexport interface DepGraph {\n nodes: DepNode[]\n root: string // project root (absolute)\n}\n\n// ─── Import regex patterns ───────────────────────────────────\n\n// Matches: import ... from 'specifier' or import 'specifier'\nconst IMPORT_FROM_RE = /import\\s+(?:[\\s\\S]*?\\s+from\\s+)?['\"]([^'\"]+)['\"]/g\n// Matches: export ... from 'specifier'\nconst EXPORT_FROM_RE = /export\\s+(?:[\\s\\S]*?\\s+from\\s+)?['\"]([^'\"]+)['\"]/g\n// Matches: require('specifier')\nconst REQUIRE_RE = /require\\s*\\(\\s*['\"]([^'\"]+)['\"]\\s*\\)/g\n// Matches: import('specifier') — dynamic import\nconst DYNAMIC_IMPORT_RE = /import\\s*\\(\\s*['\"]([^'\"]+)['\"]\\s*\\)/g\n\nconst JS_TS_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx', '.mjs', '.mts', '.cjs', '.cts'])\nconst RESOLVE_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.mts', '', '/index.ts', '/index.tsx', '/index.js', '/index.jsx']\n\n// Directories to skip\nconst SKIP_DIRS = new Set(['node_modules', '.git', 'dist', 'build', '.next', '.nuxt', 'coverage', '.nexus', '.turbo', '.cache'])\n\n// ─── DependencyAnalyzer ─────────────────────────────────────\n\nexport class DependencyAnalyzer {\n private projectDir: string\n\n constructor(projectDir: string) {\n this.projectDir = projectDir\n }\n\n /**\n * Scan the project directory and build a dependency graph.\n * Only analyzes JS/TS files with relative imports.\n */\n analyze(): DepGraph {\n const files = this.collectFiles(this.projectDir)\n const nodes: DepNode[] = []\n\n for (const absPath of files) {\n const relPath = path.relative(this.projectDir, absPath)\n const imports = this.extractImports(absPath, relPath)\n nodes.push({ id: relPath, imports })\n }\n\n return { nodes, root: this.projectDir }\n }\n\n private collectFiles(dir: string, depth = 0): string[] {\n if (depth > 8) return [] // safety limit\n const files: string[] = []\n\n let entries: fs.Dirent[]\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true })\n } catch {\n return files\n }\n\n for (const entry of entries) {\n if (entry.name.startsWith('.') && entry.name !== '.') continue\n const fullPath = path.join(dir, entry.name)\n\n if (entry.isDirectory()) {\n if (SKIP_DIRS.has(entry.name)) continue\n files.push(...this.collectFiles(fullPath, depth + 1))\n } else if (entry.isFile()) {\n const ext = path.extname(entry.name)\n if (JS_TS_EXTENSIONS.has(ext)) {\n files.push(fullPath)\n }\n }\n }\n\n return files\n }\n\n private extractImports(absPath: string, relPath: string): string[] {\n let content: string\n try {\n content = fs.readFileSync(absPath, 'utf-8')\n } catch {\n return []\n }\n\n const specifiers = new Set<string>()\n const patterns = [IMPORT_FROM_RE, EXPORT_FROM_RE, REQUIRE_RE, DYNAMIC_IMPORT_RE]\n\n for (const pattern of patterns) {\n pattern.lastIndex = 0\n let match: RegExpExecArray | null\n while ((match = pattern.exec(content)) !== null) {\n const spec = match[1]\n // Only resolve relative imports (skip node_modules / bare specifiers)\n if (spec.startsWith('.')) {\n specifiers.add(spec)\n }\n }\n }\n\n // Resolve specifiers to relative file paths\n const imports: string[] = []\n const fileDir = path.dirname(absPath)\n\n for (const spec of specifiers) {\n const resolved = this.resolveSpecifier(fileDir, spec)\n if (resolved) {\n const resolvedRel = path.relative(this.projectDir, resolved)\n imports.push(resolvedRel)\n }\n }\n\n return imports\n }\n\n private resolveSpecifier(fromDir: string, specifier: string): string | null {\n const base = path.resolve(fromDir, specifier)\n\n for (const ext of RESOLVE_EXTENSIONS) {\n const candidate = base + ext\n try {\n if (fs.statSync(candidate).isFile()) {\n return candidate\n }\n } catch {\n // not found, try next\n }\n }\n\n return null\n }\n}\n","import fs from 'node:fs'\nimport path from 'node:path'\nimport { execFile } from 'node:child_process'\nimport type {\n PaneState,\n PaneStatus,\n PaneMeta,\n FileActivity,\n AgentType,\n ReplayEvent,\n ReplayTurn,\n ReplaySession,\n ReplaySessionSummary,\n} from '../types.ts'\n\n/**\n * SessionRecorder records workspace events into Turn-based replay files.\n *\n * Structure:\n * .nexus/history/\n * sessions.json — array of session summaries (index)\n * session-<id>/\n * session.json — full session metadata (panes, timing)\n * turn-<id>.json — one file per turn (events array)\n *\n * A \"Turn\" is one idle→running→idle cycle of an agent pane.\n * Terminal output is sampled (batched per 200ms) to keep file sizes sane.\n */\n\nconst HISTORY_DIR = '.nexus/history'\nconst SESSIONS_INDEX = 'sessions.json'\nconst TERMINAL_BATCH_MS = 200\nconst MAX_TERMINAL_BYTES_PER_TURN = 256 * 1024 // 256KB cap per turn\nconst MAX_SESSIONS = 50\n\ninterface ActiveTurn {\n turn: ReplayTurn\n terminalBuffer: string\n terminalFlushTimer: ReturnType<typeof setTimeout> | null\n terminalBytes: number\n filesRead: Set<string>\n filesEdited: Set<string>\n filesCreated: Set<string>\n}\n\nexport class SessionRecorder {\n private projectDir: string\n private session: ReplaySession\n private sessionDir: string\n private activeTurns = new Map<string, ActiveTurn>() // paneId -> current turn\n private turnCounter = 0\n private retentionDays: number\n\n constructor(projectDir: string, projectName: string, retentionDays = 30) {\n this.projectDir = projectDir\n const sessionId = `s-${Date.now()}`\n this.sessionDir = path.join(projectDir, HISTORY_DIR, sessionId)\n fs.mkdirSync(this.sessionDir, { recursive: true })\n\n this.retentionDays = retentionDays\n\n this.session = {\n id: sessionId,\n startedAt: Date.now(),\n endedAt: null,\n projectDir,\n projectName,\n panes: [],\n turns: [], // lightweight refs only — full data in turn files\n }\n }\n\n // ─── Event Hooks (called by WorkspaceManager wiring) ─────\n\n onPaneAdded(pane: PaneState): void {\n if (pane.agent === '__shell__') return\n const exists = this.session.panes.find((p) => p.id === pane.id)\n if (!exists) {\n this.session.panes.push({\n id: pane.id,\n name: pane.name,\n agent: pane.agent,\n task: pane.task,\n })\n }\n // A new pane in 'running' state starts a turn immediately\n if (pane.status === 'running') {\n this.startTurn(pane.id, pane.name, pane.agent, pane.task)\n }\n }\n\n onPaneRemoved(paneId: string): void {\n this.endTurn(paneId)\n }\n\n onPaneStatus(paneId: string, status: PaneStatus, pane?: PaneState): void {\n if (!pane || pane.agent === '__shell__') return\n\n const active = this.activeTurns.get(paneId)\n\n if (status === 'running' && !active) {\n // idle → running: start a new turn\n this.startTurn(paneId, pane.name, pane.agent, pane.task)\n } else if ((status === 'idle' || status === 'stopped' || status === 'error') && active) {\n // running → idle/stopped/error: end the turn\n this.recordStatusEvent(paneId, status)\n this.endTurn(paneId)\n } else if (active) {\n // intermediate status change (e.g. running → waiting → running)\n this.recordStatusEvent(paneId, status)\n }\n }\n\n onPaneMeta(paneId: string, meta: PaneMeta): void {\n const active = this.activeTurns.get(paneId)\n if (!active) return\n\n const event: ReplayEvent = {\n t: Date.now() - active.turn.startedAt,\n type: 'meta',\n paneId,\n meta,\n }\n active.turn.events.push(event)\n }\n\n onTerminalData(paneId: string, data: string): void {\n const active = this.activeTurns.get(paneId)\n if (!active) return\n\n // Cap terminal data per turn\n if (active.terminalBytes >= MAX_TERMINAL_BYTES_PER_TURN) return\n\n active.terminalBuffer += data\n active.terminalBytes += data.length\n\n // Batch terminal writes to reduce event count\n if (!active.terminalFlushTimer) {\n active.terminalFlushTimer = setTimeout(() => {\n this.flushTerminalBuffer(paneId)\n }, TERMINAL_BATCH_MS)\n }\n }\n\n onPaneActivity(paneId: string, activity: FileActivity): void {\n const active = this.activeTurns.get(paneId)\n if (!active) return\n\n const event: ReplayEvent = {\n t: Date.now() - active.turn.startedAt,\n type: 'activity',\n paneId,\n activity: { ...activity },\n }\n active.turn.events.push(event)\n\n // Track summary\n switch (activity.action) {\n case 'read':\n active.filesRead.add(activity.file)\n break\n case 'edit':\n case 'write':\n active.filesEdited.add(activity.file)\n break\n case 'create':\n active.filesCreated.add(activity.file)\n break\n }\n\n // Async capture diff for write operations\n if (activity.action === 'edit' || activity.action === 'write' || activity.action === 'create') {\n this.captureDiff(activity.file).then((diff) => {\n if (diff) {\n event.activity = { ...event.activity!, diff }\n }\n }).catch(() => { /* ignore diff capture failures */ })\n }\n }\n\n /** Also accept file-level activity (from FsWatcher) attributed to the most recently active pane */\n onFileActivityForReplay(activity: FileActivity): void {\n // Try to attribute to any active turn (prefer most recent)\n if (this.activeTurns.size === 0) return\n\n // If only one active turn, attribute to it; otherwise skip (ambiguous)\n if (this.activeTurns.size !== 1) return\n\n const [paneId, active] = [...this.activeTurns.entries()][0]\n\n // Skip if this file was already recorded by pane activity within 2s\n let recentActivity: ReplayEvent | undefined\n for (let i = active.turn.events.length - 1; i >= 0; i--) {\n const e = active.turn.events[i]\n if (e.type === 'activity' && e.activity?.file === activity.file) {\n recentActivity = e\n break\n }\n }\n if (recentActivity && (Date.now() - active.turn.startedAt - recentActivity.t) < 2000) return\n\n const event: ReplayEvent = {\n t: Date.now() - active.turn.startedAt,\n type: 'activity',\n paneId,\n activity: { ...activity },\n }\n active.turn.events.push(event)\n\n // Capture diff\n if (activity.action === 'edit' || activity.action === 'create') {\n this.captureDiff(activity.file).then((diff) => {\n if (diff) {\n event.activity = { ...event.activity!, diff }\n }\n }).catch(() => {})\n }\n }\n\n // ─── Session Lifecycle ────────────────────────────────────\n\n /** Flush all active turns and write session index. Called on shutdown. */\n flush(): void {\n // End all active turns\n for (const paneId of [...this.activeTurns.keys()]) {\n this.endTurn(paneId)\n }\n\n this.session.endedAt = Date.now()\n this.writeSessionFile()\n this.updateSessionsIndex()\n }\n\n // ─── Query API ────────────────────────────────────────────\n\n static listSessions(projectDir: string): ReplaySessionSummary[] {\n const indexPath = path.join(projectDir, HISTORY_DIR, SESSIONS_INDEX)\n if (!fs.existsSync(indexPath)) return []\n try {\n const data = JSON.parse(fs.readFileSync(indexPath, 'utf-8'))\n return Array.isArray(data) ? data : []\n } catch {\n return []\n }\n }\n\n static getSession(projectDir: string, sessionId: string): ReplaySession | null {\n const sessionPath = path.join(projectDir, HISTORY_DIR, sessionId, 'session.json')\n if (!fs.existsSync(sessionPath)) return null\n try {\n return JSON.parse(fs.readFileSync(sessionPath, 'utf-8'))\n } catch {\n return null\n }\n }\n\n static getTurn(projectDir: string, sessionId: string, turnId: string): ReplayTurn | null {\n const turnPath = path.join(projectDir, HISTORY_DIR, sessionId, `${turnId}.json`)\n if (!fs.existsSync(turnPath)) return null\n try {\n return JSON.parse(fs.readFileSync(turnPath, 'utf-8'))\n } catch {\n return null\n }\n }\n\n /** Delete a single session and its directory. Returns true if deleted. */\n static deleteSession(projectDir: string, sessionId: string): boolean {\n // Remove session directory\n const sessionDir = path.join(projectDir, HISTORY_DIR, sessionId)\n if (fs.existsSync(sessionDir)) {\n fs.rmSync(sessionDir, { recursive: true, force: true })\n }\n\n // Remove from index\n const indexPath = path.join(projectDir, HISTORY_DIR, SESSIONS_INDEX)\n if (fs.existsSync(indexPath)) {\n try {\n let sessions: ReplaySessionSummary[] = JSON.parse(fs.readFileSync(indexPath, 'utf-8'))\n const before = sessions.length\n sessions = sessions.filter(s => s.id !== sessionId)\n if (sessions.length < before) {\n fs.writeFileSync(indexPath, JSON.stringify(sessions, null, 2))\n return true\n }\n } catch { /* ignore */ }\n }\n return false\n }\n\n /** Delete all sessions. Returns the number of sessions deleted. */\n static deleteAllSessions(projectDir: string): number {\n const sessions = SessionRecorder.listSessions(projectDir)\n let count = 0\n for (const session of sessions) {\n const sessionDir = path.join(projectDir, HISTORY_DIR, session.id)\n if (fs.existsSync(sessionDir)) {\n fs.rmSync(sessionDir, { recursive: true, force: true })\n count++\n }\n }\n // Reset index\n const indexPath = path.join(projectDir, HISTORY_DIR, SESSIONS_INDEX)\n fs.writeFileSync(indexPath, JSON.stringify([], null, 2))\n return count\n }\n\n /**\n * Passive cleanup: prune sessions exceeding max count or older than retentionDays.\n * Called automatically when saving a new session.\n */\n static pruneOldSessions(projectDir: string, retentionDays: number): number {\n const indexPath = path.join(projectDir, HISTORY_DIR, SESSIONS_INDEX)\n if (!fs.existsSync(indexPath)) return 0\n\n let sessions: ReplaySessionSummary[]\n try {\n sessions = JSON.parse(fs.readFileSync(indexPath, 'utf-8'))\n } catch { return 0 }\n\n const cutoff = Date.now() - retentionDays * 24 * 60 * 60 * 1000\n const keep: ReplaySessionSummary[] = []\n const remove: ReplaySessionSummary[] = []\n\n for (const s of sessions) {\n if (s.startedAt < cutoff || keep.length >= MAX_SESSIONS) {\n remove.push(s)\n } else {\n keep.push(s)\n }\n }\n\n if (remove.length === 0) return 0\n\n // Delete session directories\n for (const s of remove) {\n const sessionDir = path.join(projectDir, HISTORY_DIR, s.id)\n if (fs.existsSync(sessionDir)) {\n fs.rmSync(sessionDir, { recursive: true, force: true })\n }\n }\n\n fs.writeFileSync(indexPath, JSON.stringify(keep, null, 2))\n return remove.length\n }\n\n // ─── Internal ─────────────────────────────────────────────\n\n private startTurn(paneId: string, paneName: string, agent: AgentType, task?: string): void {\n // End any existing turn for this pane first\n if (this.activeTurns.has(paneId)) {\n this.endTurn(paneId)\n }\n\n const turnId = `turn-${++this.turnCounter}`\n const turn: ReplayTurn = {\n id: turnId,\n paneId,\n paneName,\n agent,\n startedAt: Date.now(),\n endedAt: null,\n task,\n events: [],\n summary: {\n filesRead: 0,\n filesEdited: 0,\n filesCreated: 0,\n terminalBytes: 0,\n durationMs: 0,\n },\n }\n\n this.activeTurns.set(paneId, {\n turn,\n terminalBuffer: '',\n terminalFlushTimer: null,\n terminalBytes: 0,\n filesRead: new Set(),\n filesEdited: new Set(),\n filesCreated: new Set(),\n })\n }\n\n private endTurn(paneId: string): void {\n const active = this.activeTurns.get(paneId)\n if (!active) return\n\n // Flush any remaining terminal buffer\n this.flushTerminalBuffer(paneId)\n\n const turn = active.turn\n turn.endedAt = Date.now()\n turn.summary = {\n filesRead: active.filesRead.size,\n filesEdited: active.filesEdited.size,\n filesCreated: active.filesCreated.size,\n terminalBytes: active.terminalBytes,\n durationMs: turn.endedAt - turn.startedAt,\n }\n\n // Only save turns with meaningful content\n if (turn.events.length > 0) {\n this.writeTurnFile(turn)\n // Store lightweight ref in session (without events)\n this.session.turns.push({\n ...turn,\n events: [], // don't duplicate events in session file\n })\n }\n\n this.activeTurns.delete(paneId)\n }\n\n private recordStatusEvent(paneId: string, status: PaneStatus): void {\n const active = this.activeTurns.get(paneId)\n if (!active) return\n active.turn.events.push({\n t: Date.now() - active.turn.startedAt,\n type: 'status',\n paneId,\n status,\n })\n }\n\n private flushTerminalBuffer(paneId: string): void {\n const active = this.activeTurns.get(paneId)\n if (!active || !active.terminalBuffer) return\n\n if (active.terminalFlushTimer) {\n clearTimeout(active.terminalFlushTimer)\n active.terminalFlushTimer = null\n }\n\n active.turn.events.push({\n t: Date.now() - active.turn.startedAt,\n type: 'terminal',\n paneId,\n data: active.terminalBuffer,\n })\n active.terminalBuffer = ''\n }\n\n /** Capture git diff for a single file. Returns unified diff string or null. */\n private captureDiff(file: string): Promise<string | null> {\n return new Promise((resolve) => {\n // Try git diff first (for tracked files), fall back to git diff --no-index for new files\n execFile('git', ['diff', '--no-color', '-U3', '--', file], {\n cwd: this.projectDir,\n timeout: 3000,\n maxBuffer: 128 * 1024,\n }, (err, stdout) => {\n if (stdout && stdout.trim()) {\n resolve(stdout.trim())\n return\n }\n // For untracked (new) files, show full content as diff\n execFile('git', ['diff', '--no-color', '--no-index', '/dev/null', file], {\n cwd: this.projectDir,\n timeout: 3000,\n maxBuffer: 128 * 1024,\n }, (_err2, stdout2) => {\n resolve(stdout2?.trim() || null)\n })\n })\n })\n }\n\n private writeTurnFile(turn: ReplayTurn): void {\n const turnPath = path.join(this.sessionDir, `${turn.id}.json`)\n fs.writeFileSync(turnPath, JSON.stringify(turn))\n }\n\n private writeSessionFile(): void {\n const sessionPath = path.join(this.sessionDir, 'session.json')\n fs.writeFileSync(sessionPath, JSON.stringify(this.session, null, 2))\n }\n\n private updateSessionsIndex(): void {\n const indexPath = path.join(this.projectDir, HISTORY_DIR, SESSIONS_INDEX)\n let sessions: ReplaySessionSummary[] = []\n\n if (fs.existsSync(indexPath)) {\n try {\n sessions = JSON.parse(fs.readFileSync(indexPath, 'utf-8'))\n } catch { /* start fresh */ }\n }\n\n const totalDurationMs = this.session.endedAt\n ? this.session.endedAt - this.session.startedAt\n : 0\n\n sessions.unshift({\n id: this.session.id,\n startedAt: this.session.startedAt,\n endedAt: this.session.endedAt,\n projectName: this.session.projectName,\n turnCount: this.session.turns.length,\n paneCount: this.session.panes.length,\n totalDurationMs,\n })\n\n fs.writeFileSync(indexPath, JSON.stringify(sessions, null, 2))\n\n // Passive cleanup: prune sessions exceeding retention or max count\n const pruned = SessionRecorder.pruneOldSessions(this.projectDir, this.retentionDays)\n if (pruned > 0) {\n console.log(`[SessionRecorder] Pruned ${pruned} old session(s)`)\n }\n }\n}\n","import { execFile } from 'node:child_process'\nimport { promisify } from 'node:util'\nimport type { ConfigManager } from './ConfigManager.ts'\n\nconst execFileAsync = promisify(execFile)\n\nexport interface ClaudeSession {\n session_id: string\n project_path?: string\n model?: string\n cost_usd?: number\n duration_ms?: number\n created_at?: string\n updated_at?: string\n summary?: string\n num_turns?: number\n}\n\nexport interface DiscoveredSession {\n sessionId: string\n summary?: string\n model?: string\n costUsd?: number\n numTurns?: number\n createdAt?: string\n updatedAt?: string\n projectPath?: string\n source: 'nexus' | 'external'\n}\n\nconst CACHE_TTL = 30_000 // 30s\n\nexport class SessionDiscovery {\n private configManager: ConfigManager\n private cache: { sessions: DiscoveredSession[]; ts: number } | null = null\n\n constructor(configManager: ConfigManager) {\n this.configManager = configManager\n }\n\n async listSessions(agentType = 'claudecode'): Promise<DiscoveredSession[]> {\n const now = Date.now()\n if (this.cache && now - this.cache.ts < CACHE_TTL) {\n return this.cache.sessions\n }\n\n const sessions = await this.fetchSessions(agentType)\n this.cache = { sessions, ts: now }\n return sessions\n }\n\n private async fetchSessions(agentType: string): Promise<DiscoveredSession[]> {\n const agentDef = this.configManager.getAgentDefinition(agentType)\n if (!agentDef || agentDef.bin !== 'claude') {\n return []\n }\n\n try {\n const { stdout } = await execFileAsync(agentDef.bin, ['sessions', 'list', '--output', 'json'], {\n timeout: 10_000,\n env: { ...process.env },\n })\n\n const parsed = JSON.parse(stdout.trim())\n const items: ClaudeSession[] = Array.isArray(parsed) ? parsed : (parsed.sessions || [])\n\n return items.map((s) => ({\n sessionId: s.session_id,\n summary: s.summary,\n model: s.model,\n costUsd: s.cost_usd,\n numTurns: s.num_turns,\n createdAt: s.created_at,\n updatedAt: s.updated_at,\n projectPath: s.project_path,\n source: 'external' as const,\n }))\n } catch (err) {\n console.warn('[SessionDiscovery] Failed to list sessions:', (err as Error).message)\n return []\n }\n }\n}\n"],"mappings":"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","names":["path","fs","path","fs","yaml","fs","os","path","stripAnsi","MAX_BUFFER_SIZE","path","fs","os","spawn","fs","os","path","MAX_SCROLLBACK_BYTES","path","fs","path","simpleGit","fs","fs","path","yaml","fs","path","watch","fs","path","fs","path","execFile","execFile","promisify","execFileAsync","path","s","fs","yaml","path","fs","ConfigManager"]}
|