open-coleslaw 0.3.2 → 0.4.0

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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/server.ts","../src/tools/start-meeting.ts","../src/orchestrator/orchestrator.ts","../src/storage/agent-store.ts","../src/storage/meeting-store.ts","../src/storage/worker-store.ts","../src/storage/mention-store.ts","../src/storage/minutes-store.ts","../src/storage/task-store.ts","../src/types/agent.ts","../src/agents/departments.ts","../src/orchestrator/event-bus.ts","../src/utils/logger.ts","../src/orchestrator/leader-pool.ts","../src/tools/get-meeting-status.ts","../src/tools/get-minutes.ts","../src/tools/compact-minutes.ts","../src/meeting/compactor.ts","../src/tools/execute-tasks.ts","../src/tools/get-agent-tree.ts","../src/tools/respond-to-mention.ts","../src/tools/get-mentions.ts","../src/tools/cancel-meeting.ts","../src/tools/list-meetings.ts","../src/tools/get-task-report.ts","../src/tools/create-capability.ts","../src/extension/capability-registry.ts","../src/utils/config.ts","../src/extension/generator.ts","../src/extension/guide-updater.ts","../src/extension/extension-manager.ts","../src/tools/get-cost-summary.ts","../src/utils/cost-tracker.ts","../src/tools/chain-meeting.ts","../src/tools/add-transcript.ts","../src/orchestrator/meeting-runner.ts","../src/tools/generate-minutes.ts","../src/dashboard/server.ts","../src/dashboard/html.ts","../src/dashboard/state-bridge.ts","../src/dashboard/client.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { createServer } from './server.js';\nimport { ensureDataDirs } from './utils/config.js';\nimport { startDashboard } from './dashboard/server.js';\n\nasync function main() {\n ensureDataDirs();\n\n // Only start dashboard if not explicitly disabled\n const isBareSubprocess = process.env['CLAUDE_CODE_SIMPLE'] === '1';\n\n if (!isBareSubprocess) {\n const sessionId = randomUUID();\n const projectPath = process.cwd();\n const projectName = projectPath.split('/').pop() ?? 'unknown';\n startDashboard({ sessionId, projectPath, projectName }).catch(() => {});\n }\n\n const server = createServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\nmain().catch((error) => {\n console.error('Fatal error:', error);\n process.exit(1);\n});\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport {\n startMeetingSchema,\n startMeetingHandler,\n getMeetingStatusSchema,\n getMeetingStatusHandler,\n getMinutesSchema,\n getMinutesHandler,\n compactMinutesSchema,\n compactMinutesHandler,\n executeTasksSchema,\n executeTasksHandler,\n getAgentTreeHandler,\n respondToMentionSchema,\n respondToMentionHandler,\n getMentionsSchema,\n getMentionsHandler,\n cancelMeetingSchema,\n cancelMeetingHandler,\n listMeetingsSchema,\n listMeetingsHandler,\n getTaskReportSchema,\n getTaskReportHandler,\n createCapabilitySchema,\n createCapabilityHandler,\n getCostSummarySchema,\n getCostSummaryHandler,\n chainMeetingSchema,\n chainMeetingHandler,\n addTranscriptSchema,\n addTranscriptHandler,\n generateMinutesSchema,\n generateMinutesHandler,\n} from './tools/index.js';\n\nexport function createServer(): McpServer {\n const server = new McpServer({\n name: 'open-coleslaw',\n version: '0.1.0',\n });\n\n // 1. start-meeting\n server.tool(\n 'start-meeting',\n 'Create a new meeting record with topic and agenda. Returns meetingId and recommended departments. Does NOT run the meeting.',\n startMeetingSchema,\n startMeetingHandler,\n );\n\n // 2. get-meeting-status\n server.tool(\n 'get-meeting-status',\n 'Get the status of a specific meeting or all active meetings',\n getMeetingStatusSchema,\n getMeetingStatusHandler,\n );\n\n // 3. get-minutes\n server.tool(\n 'get-minutes',\n 'Retrieve meeting minutes in full, summary, or tasks-only format',\n getMinutesSchema,\n getMinutesHandler,\n );\n\n // 4. compact-minutes\n server.tool(\n 'compact-minutes',\n 'Compact meeting minutes into a structured, department-assigned task list',\n compactMinutesSchema,\n compactMinutesHandler,\n );\n\n // 5. execute-tasks\n server.tool(\n 'execute-tasks',\n 'Get the task list from compacted minutes for agent dispatch. Does NOT spawn workers.',\n executeTasksSchema,\n executeTasksHandler,\n );\n\n // 6. get-agent-tree\n server.tool(\n 'get-agent-tree',\n 'Return the full agent hierarchy tree',\n getAgentTreeHandler,\n );\n\n // 7. respond-to-mention\n server.tool(\n 'respond-to-mention',\n 'Respond to a pending @mention with a decision',\n respondToMentionSchema,\n respondToMentionHandler,\n );\n\n // 8. get-mentions\n server.tool(\n 'get-mentions',\n 'List @mentions filtered by status and/or meeting',\n getMentionsSchema,\n getMentionsHandler,\n );\n\n // 9. cancel-meeting\n server.tool(\n 'cancel-meeting',\n 'Cancel an active meeting and clean up its agents and workers',\n cancelMeetingSchema,\n cancelMeetingHandler,\n );\n\n // 10. list-meetings\n server.tool(\n 'list-meetings',\n 'List meetings with optional status filter and pagination',\n listMeetingsSchema,\n listMeetingsHandler,\n );\n\n // 11. get-task-report\n server.tool(\n 'get-task-report',\n 'Generate a task execution report for a meeting with per-department breakdown',\n getTaskReportSchema,\n getTaskReportHandler,\n );\n\n // 12. create-capability\n server.tool(\n 'create-capability',\n 'Create a new extension capability (hook, skill, command, asset, or loop)',\n createCapabilitySchema,\n createCapabilityHandler,\n );\n\n // 13. get-cost-summary\n server.tool(\n 'get-cost-summary',\n 'Get cost summary for a specific meeting or overall across all meetings',\n getCostSummarySchema,\n getCostSummaryHandler,\n );\n\n // 14. chain-meeting\n server.tool(\n 'chain-meeting',\n 'Create a new meeting chained from a previous meeting, using its minutes as context. Does NOT run the meeting.',\n chainMeetingSchema,\n chainMeetingHandler,\n );\n\n // 15. add-transcript\n server.tool(\n 'add-transcript',\n 'Add a transcript entry to a meeting. Used to record speaker contributions during meeting phases.',\n addTranscriptSchema,\n addTranscriptHandler,\n );\n\n // 16. generate-minutes\n server.tool(\n 'generate-minutes',\n 'Generate PRD minutes from all stored transcripts for a meeting. Marks the meeting as completed.',\n generateMinutesSchema,\n generateMinutesHandler,\n );\n\n return server;\n}\n","import { z } from 'zod';\nimport { Orchestrator } from '../orchestrator/orchestrator.js';\nimport type { Department } from '../types/index.js';\n\nexport const startMeetingSchema = {\n topic: z.string().describe('Meeting topic'),\n agenda: z.array(z.string()).describe('Agenda items'),\n departments: z\n .array(z.string())\n .optional()\n .describe('Specific departments to invite'),\n};\n\nexport async function startMeetingHandler({\n topic,\n agenda,\n departments,\n}: {\n topic: string;\n agenda: string[];\n departments?: string[];\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const orchestrator = new Orchestrator();\n const result = orchestrator.startMeeting({\n topic,\n agenda,\n departments: departments as Department[] | undefined,\n });\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import { v4 as uuidv4 } from 'uuid';\nimport type {\n Department,\n Meeting,\n MentionRecord,\n} from '../types/index.js';\nimport {\n createMeeting,\n updateMeeting,\n getMeeting,\n listMeetings,\n listPendingMentions,\n getAgentTree,\n getMinutesByMeeting,\n} from '../storage/index.js';\nimport type { AgentTreeNode } from '../storage/index.js';\nimport { LeaderPool } from './leader-pool.js';\nimport { logger } from '../utils/logger.js';\n\n// ---------------------------------------------------------------------------\n// Keyword maps for leader selection heuristics\n// ---------------------------------------------------------------------------\n\nconst DEPARTMENT_KEYWORDS: Record<Department, string[]> = {\n architecture: [\n 'architecture', 'design', 'schema', 'api', 'data model', 'module',\n 'interface', 'contract', 'coupling', 'dependency graph', 'adr',\n 'system design', 'blueprint', 'data flow',\n ],\n engineering: [\n 'code', 'implement', 'build', 'feature', 'bug', 'fix', 'refactor',\n 'develop', 'function', 'class', 'module', 'write', 'create',\n 'modify', 'update', 'delete', 'crud', 'endpoint', 'migration',\n ],\n qa: [\n 'test', 'quality', 'security', 'performance', 'audit', 'coverage',\n 'regression', 'benchmark', 'vulnerability', 'pen test', 'lint',\n 'assertion', 'e2e', 'integration test', 'unit test',\n ],\n product: [\n 'requirements', 'user', 'story', 'priority', 'acceptance criteria',\n 'user flow', 'stakeholder', 'roadmap', 'scope', 'use case',\n 'persona', 'mvp', 'specification',\n ],\n research: [\n 'research', 'explore', 'investigate', 'search', 'analyze', 'find',\n 'discover', 'benchmark', 'compare', 'survey', 'documentation',\n 'reference', 'existing code',\n ],\n};\n\n// ---------------------------------------------------------------------------\n// StartMeeting options & result\n// ---------------------------------------------------------------------------\n\nexport interface StartMeetingOptions {\n topic: string;\n agenda: string[];\n departments?: Department[];\n previousMeetingId?: string | null;\n}\n\nexport interface StartMeetingResult {\n meetingId: string;\n departments: Department[];\n agenda: string[];\n topic: string;\n}\n\n// ---------------------------------------------------------------------------\n// Orchestrator status\n// ---------------------------------------------------------------------------\n\nexport interface OrchestratorStatus {\n activeMeetings: Meeting[];\n pendingMentions: MentionRecord[];\n agentTree: AgentTreeNode | null;\n}\n\n// ---------------------------------------------------------------------------\n// Orchestrator — creates meeting records and selects leaders\n//\n// No longer runs meetings itself. Meetings are orchestrated by Claude Code's\n// Agent tool via skill/agent markdown files.\n// ---------------------------------------------------------------------------\n\nexport class Orchestrator {\n private readonly leaderPool = new LeaderPool();\n\n /**\n * Internal ID for the orchestrator \"agent\". Used as the meeting initiator\n * and as the root of the agent tree.\n */\n private readonly orchestratorId: string;\n\n constructor(orchestratorId?: string) {\n this.orchestratorId = orchestratorId ?? 'orchestrator-root';\n }\n\n // ---- leader selection ---------------------------------------------------\n\n /**\n * Analyse a topic and agenda to determine which department leaders should\n * be convened for a meeting.\n *\n * Uses keyword-based heuristics:\n * - Matches topic + agenda text against per-department keyword lists.\n * - Scores each department by the number of keyword hits.\n * - Selects departments with at least one hit.\n * - Falls back to engineering + architecture for complex topics (multiple\n * agenda items) or engineering alone for simple ones.\n */\n selectLeaders(topic: string, agenda: string[]): Department[] {\n const corpus = [topic, ...agenda].join(' ').toLowerCase();\n\n const scores = new Map<Department, number>();\n\n for (const [dept, keywords] of Object.entries(DEPARTMENT_KEYWORDS) as [Department, string[]][]) {\n let score = 0;\n for (const kw of keywords) {\n if (corpus.includes(kw)) {\n score++;\n }\n }\n if (score > 0) {\n scores.set(dept, score);\n }\n }\n\n if (scores.size === 0) {\n // Fallback: complex topics (3+ agenda items) get architecture + engineering;\n // simple ones get engineering only.\n if (agenda.length >= 3) {\n logger.debug('No keyword matches; defaulting to architecture + engineering (complex topic)', {\n meetingId: topic,\n });\n return ['architecture', 'engineering'];\n }\n logger.debug('No keyword matches; defaulting to engineering only (simple topic)', {\n meetingId: topic,\n });\n return ['engineering'];\n }\n\n // Sort by score descending and take all with hits\n const selected = [...scores.entries()]\n .sort((a, b) => b[1] - a[1])\n .map(([dept]) => dept);\n\n logger.debug(`Selected departments: ${selected.join(', ')}`, { meetingId: topic });\n\n return selected;\n }\n\n // ---- start meeting ------------------------------------------------------\n\n /**\n * Create a new meeting record and return meeting info + recommended leaders.\n *\n * Does NOT run the meeting. The calling agent (via skill markdown) is\n * responsible for orchestrating the meeting phases using add-transcript\n * and generate-minutes MCP tools.\n */\n startMeeting(opts: StartMeetingOptions): StartMeetingResult {\n const { topic, agenda } = opts;\n const departments = opts.departments ?? this.selectLeaders(topic, agenda);\n\n logger.info(`Creating meeting: \"${topic}\" with departments: [${departments.join(', ')}]`);\n\n // Create the meeting record\n const meetingId = uuidv4();\n createMeeting({\n id: meetingId,\n topic,\n agenda,\n participantIds: departments.map((d) => `${d}-leader`),\n initiatedBy: this.orchestratorId,\n status: 'pending',\n phase: 'orchestrator-phase',\n startedAt: Date.now(),\n previousMeetingId: opts.previousMeetingId ?? null,\n });\n\n return {\n meetingId,\n departments,\n agenda,\n topic,\n };\n }\n\n // ---- chain meeting -------------------------------------------------------\n\n /**\n * Create a new meeting chained from a previous meeting.\n *\n * Loads minutes from the previous meeting and includes them as context for\n * the new meeting topic. The new meeting's `previousMeetingId` is set for\n * traceability.\n *\n * Does NOT run the meeting (same as startMeeting).\n */\n chainMeeting(opts: {\n previousMeetingId: string;\n topic: string;\n agenda: string[];\n departments?: Department[];\n }): StartMeetingResult {\n const previousMeeting = getMeeting(opts.previousMeetingId);\n if (!previousMeeting) {\n throw new Error(`Previous meeting not found: ${opts.previousMeetingId}`);\n }\n\n const previousMinutes = getMinutesByMeeting(opts.previousMeetingId);\n if (!previousMinutes) {\n throw new Error(`No minutes found for previous meeting: ${opts.previousMeetingId}`);\n }\n\n // Prepend the previous meeting context to the topic\n const contextPrefix =\n `[Chained from meeting \"${previousMeeting.topic}\" (${opts.previousMeetingId})]\\n\\n` +\n `--- Previous Meeting Minutes ---\\n${previousMinutes.content}\\n--- End Previous Minutes ---\\n\\n`;\n\n const enrichedTopic = contextPrefix + opts.topic;\n\n logger.info(\n `Chaining meeting from \"${previousMeeting.topic}\" -> \"${opts.topic}\"`,\n { meetingId: opts.previousMeetingId },\n );\n\n return this.startMeeting({\n topic: enrichedTopic,\n agenda: opts.agenda,\n departments: opts.departments,\n previousMeetingId: opts.previousMeetingId,\n });\n }\n\n // ---- status -------------------------------------------------------------\n\n /**\n * Return a summary of all active meetings, pending @mentions, and the\n * current agent tree.\n */\n getStatus(): OrchestratorStatus {\n // Active meetings: anything not completed/cancelled/failed\n const allMeetings = listMeetings();\n const activeMeetings = allMeetings.filter(\n (m) => !['completed', 'cancelled', 'failed', 'reported', 'compacted'].includes(m.status),\n );\n\n // Pending @mentions across all meetings\n const pendingMentions = listPendingMentions();\n\n // Agent tree rooted at the orchestrator (may be null if no agents yet)\n const agentTree = getAgentTree(this.orchestratorId);\n\n return {\n activeMeetings,\n pendingMentions,\n agentTree,\n };\n }\n\n // ---- accessors ----------------------------------------------------------\n\n /** The leader pool used by this orchestrator instance. */\n getLeaderPool(): LeaderPool {\n return this.leaderPool;\n }\n\n /** The orchestrator's agent ID. */\n getId(): string {\n return this.orchestratorId;\n }\n}\n","import { v4 as uuidv4 } from 'uuid';\nimport { getDb } from './db.js';\nimport type { AgentNode, AgentTier, AgentStatus, Department } from '../types/index.js';\n\ninterface AgentRow {\n id: string;\n tier: string;\n role: string;\n department: string;\n parent_id: string | null;\n meeting_id: string | null;\n status: string;\n current_task: string | null;\n session_id: string | null;\n spawned_at: number;\n completed_at: number | null;\n cost_usd: number;\n}\n\nfunction rowToAgent(row: AgentRow): AgentNode {\n return {\n id: row.id,\n tier: row.tier as AgentTier,\n role: row.role,\n department: row.department as Department,\n parentId: row.parent_id,\n meetingId: row.meeting_id,\n status: row.status as AgentStatus,\n currentTask: row.current_task,\n sessionId: row.session_id,\n spawnedAt: row.spawned_at,\n completedAt: row.completed_at,\n costUsd: row.cost_usd,\n };\n}\n\nexport function createAgent(\n agent: Omit<AgentNode, 'id' | 'spawnedAt' | 'completedAt' | 'costUsd'> & {\n id?: string;\n spawnedAt?: number;\n completedAt?: number | null;\n costUsd?: number;\n }\n): AgentNode {\n const db = getDb();\n const id = agent.id ?? uuidv4();\n const spawnedAt = agent.spawnedAt ?? Date.now();\n const completedAt = agent.completedAt ?? null;\n const costUsd = agent.costUsd ?? 0;\n\n db.prepare(\n `INSERT INTO agents (id, tier, role, department, parent_id, meeting_id, status, current_task, session_id, spawned_at, completed_at, cost_usd)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`\n ).run(\n id,\n agent.tier,\n agent.role,\n agent.department,\n agent.parentId,\n agent.meetingId,\n agent.status,\n agent.currentTask,\n agent.sessionId,\n spawnedAt,\n completedAt,\n costUsd\n );\n\n return {\n id,\n tier: agent.tier,\n role: agent.role,\n department: agent.department,\n parentId: agent.parentId,\n meetingId: agent.meetingId,\n status: agent.status,\n currentTask: agent.currentTask,\n sessionId: agent.sessionId,\n spawnedAt,\n completedAt,\n costUsd,\n };\n}\n\nexport function getAgent(id: string): AgentNode | null {\n const db = getDb();\n const row = db.prepare('SELECT * FROM agents WHERE id = ?').get(id) as AgentRow | undefined;\n return row ? rowToAgent(row) : null;\n}\n\nexport function updateAgent(\n id: string,\n updates: Partial<Omit<AgentNode, 'id'>>\n): AgentNode | null {\n const db = getDb();\n const existing = getAgent(id);\n if (!existing) return null;\n\n const fields: string[] = [];\n const values: unknown[] = [];\n\n if (updates.tier !== undefined) { fields.push('tier = ?'); values.push(updates.tier); }\n if (updates.role !== undefined) { fields.push('role = ?'); values.push(updates.role); }\n if (updates.department !== undefined) { fields.push('department = ?'); values.push(updates.department); }\n if (updates.parentId !== undefined) { fields.push('parent_id = ?'); values.push(updates.parentId); }\n if (updates.meetingId !== undefined) { fields.push('meeting_id = ?'); values.push(updates.meetingId); }\n if (updates.status !== undefined) { fields.push('status = ?'); values.push(updates.status); }\n if (updates.currentTask !== undefined) { fields.push('current_task = ?'); values.push(updates.currentTask); }\n if (updates.sessionId !== undefined) { fields.push('session_id = ?'); values.push(updates.sessionId); }\n if (updates.spawnedAt !== undefined) { fields.push('spawned_at = ?'); values.push(updates.spawnedAt); }\n if (updates.completedAt !== undefined) { fields.push('completed_at = ?'); values.push(updates.completedAt); }\n if (updates.costUsd !== undefined) { fields.push('cost_usd = ?'); values.push(updates.costUsd); }\n\n if (fields.length === 0) return existing;\n\n values.push(id);\n db.prepare(`UPDATE agents SET ${fields.join(', ')} WHERE id = ?`).run(...values);\n\n return getAgent(id);\n}\n\nexport function listAgentsByMeeting(meetingId: string): AgentNode[] {\n const db = getDb();\n const rows = db\n .prepare('SELECT * FROM agents WHERE meeting_id = ?')\n .all(meetingId) as AgentRow[];\n return rows.map(rowToAgent);\n}\n\nexport function listAgentsByParent(parentId: string): AgentNode[] {\n const db = getDb();\n const rows = db\n .prepare('SELECT * FROM agents WHERE parent_id = ?')\n .all(parentId) as AgentRow[];\n return rows.map(rowToAgent);\n}\n\nexport interface AgentTreeNode extends AgentNode {\n children: AgentTreeNode[];\n}\n\nexport function getAgentTree(rootId: string): AgentTreeNode | null {\n const agent = getAgent(rootId);\n if (!agent) return null;\n\n const children = listAgentsByParent(rootId);\n const treeNode: AgentTreeNode = {\n ...agent,\n children: children\n .map((child) => getAgentTree(child.id))\n .filter((node): node is AgentTreeNode => node !== null),\n };\n\n return treeNode;\n}\n","import { v4 as uuidv4 } from 'uuid';\nimport { getDb } from './db.js';\nimport type { Meeting, MeetingStatus, MeetingPhase } from '../types/index.js';\n\ninterface MeetingRow {\n id: string;\n topic: string;\n agenda: string;\n participant_ids: string;\n status: string;\n phase: string;\n started_at: number | null;\n completed_at: number | null;\n initiated_by: string;\n previous_meeting_id?: string | null;\n}\n\n/** Ensure the previous_meeting_id column exists (backward-compat migration). */\nfunction ensurePreviousMeetingIdColumn(): void {\n const db = getDb();\n // PRAGMA table_info returns rows for each column; check if the column exists.\n const cols = db.prepare(\"PRAGMA table_info('meetings')\").all() as Array<{ name: string }>;\n const hasColumn = cols.some((c) => c.name === 'previous_meeting_id');\n if (!hasColumn) {\n db.exec('ALTER TABLE meetings ADD COLUMN previous_meeting_id TEXT DEFAULT NULL');\n }\n}\n\nlet columnChecked = false;\n\nfunction rowToMeeting(row: MeetingRow): Meeting {\n return {\n id: row.id,\n topic: row.topic,\n agenda: JSON.parse(row.agenda) as string[],\n participantIds: JSON.parse(row.participant_ids) as string[],\n status: row.status as MeetingStatus,\n phase: row.phase as MeetingPhase,\n startedAt: row.started_at,\n completedAt: row.completed_at,\n initiatedBy: row.initiated_by,\n previousMeetingId: row.previous_meeting_id ?? null,\n };\n}\n\nexport function createMeeting(\n meeting: Omit<Meeting, 'id' | 'status' | 'phase' | 'startedAt' | 'completedAt' | 'previousMeetingId'> & {\n id?: string;\n status?: MeetingStatus;\n phase?: MeetingPhase;\n startedAt?: number | null;\n completedAt?: number | null;\n previousMeetingId?: string | null;\n }\n): Meeting {\n if (!columnChecked) {\n ensurePreviousMeetingIdColumn();\n columnChecked = true;\n }\n\n const db = getDb();\n const id = meeting.id ?? uuidv4();\n const status = meeting.status ?? 'pending';\n const phase = meeting.phase ?? 'orchestrator-phase';\n const startedAt = meeting.startedAt ?? null;\n const completedAt = meeting.completedAt ?? null;\n const previousMeetingId = meeting.previousMeetingId ?? null;\n\n db.prepare(\n `INSERT INTO meetings (id, topic, agenda, participant_ids, status, phase, started_at, completed_at, initiated_by, previous_meeting_id)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`\n ).run(\n id,\n meeting.topic,\n JSON.stringify(meeting.agenda),\n JSON.stringify(meeting.participantIds),\n status,\n phase,\n startedAt,\n completedAt,\n meeting.initiatedBy,\n previousMeetingId\n );\n\n return {\n id,\n topic: meeting.topic,\n agenda: meeting.agenda,\n participantIds: meeting.participantIds,\n status,\n phase,\n startedAt,\n completedAt,\n initiatedBy: meeting.initiatedBy,\n previousMeetingId,\n };\n}\n\nexport function getMeeting(id: string): Meeting | null {\n if (!columnChecked) {\n ensurePreviousMeetingIdColumn();\n columnChecked = true;\n }\n\n const db = getDb();\n const row = db.prepare('SELECT * FROM meetings WHERE id = ?').get(id) as MeetingRow | undefined;\n return row ? rowToMeeting(row) : null;\n}\n\nexport function updateMeeting(\n id: string,\n updates: Partial<Omit<Meeting, 'id'>>\n): Meeting | null {\n const db = getDb();\n const existing = getMeeting(id);\n if (!existing) return null;\n\n const fields: string[] = [];\n const values: unknown[] = [];\n\n if (updates.topic !== undefined) { fields.push('topic = ?'); values.push(updates.topic); }\n if (updates.agenda !== undefined) { fields.push('agenda = ?'); values.push(JSON.stringify(updates.agenda)); }\n if (updates.participantIds !== undefined) { fields.push('participant_ids = ?'); values.push(JSON.stringify(updates.participantIds)); }\n if (updates.status !== undefined) { fields.push('status = ?'); values.push(updates.status); }\n if (updates.phase !== undefined) { fields.push('phase = ?'); values.push(updates.phase); }\n if (updates.startedAt !== undefined) { fields.push('started_at = ?'); values.push(updates.startedAt); }\n if (updates.completedAt !== undefined) { fields.push('completed_at = ?'); values.push(updates.completedAt); }\n if (updates.initiatedBy !== undefined) { fields.push('initiated_by = ?'); values.push(updates.initiatedBy); }\n if (updates.previousMeetingId !== undefined) { fields.push('previous_meeting_id = ?'); values.push(updates.previousMeetingId); }\n\n if (fields.length === 0) return existing;\n\n values.push(id);\n db.prepare(`UPDATE meetings SET ${fields.join(', ')} WHERE id = ?`).run(...values);\n\n return getMeeting(id);\n}\n\nexport function listMeetings(statusFilter?: MeetingStatus): Meeting[] {\n if (!columnChecked) {\n ensurePreviousMeetingIdColumn();\n columnChecked = true;\n }\n\n const db = getDb();\n let rows: MeetingRow[];\n\n if (statusFilter) {\n rows = db\n .prepare('SELECT * FROM meetings WHERE status = ? ORDER BY started_at DESC')\n .all(statusFilter) as MeetingRow[];\n } else {\n rows = db\n .prepare('SELECT * FROM meetings ORDER BY started_at DESC')\n .all() as MeetingRow[];\n }\n\n return rows.map(rowToMeeting);\n}\n","import { v4 as uuidv4 } from 'uuid';\nimport { getDb } from './db.js';\nimport type { WorkerRecord, WorkerStatus, TaskType } from '../types/index.js';\n\ninterface WorkerRow {\n id: string;\n leader_id: string;\n meeting_id: string;\n task_description: string;\n task_type: string | null;\n status: string;\n input_context: string | null;\n output_result: string | null;\n error_message: string | null;\n dependencies: string;\n spawned_at: number;\n completed_at: number | null;\n cost_usd: number;\n}\n\nfunction rowToWorker(row: WorkerRow): WorkerRecord {\n return {\n id: row.id,\n leaderId: row.leader_id,\n meetingId: row.meeting_id,\n taskDescription: row.task_description,\n taskType: row.task_type as TaskType | null,\n status: row.status as WorkerStatus,\n inputContext: row.input_context,\n outputResult: row.output_result,\n errorMessage: row.error_message,\n dependencies: JSON.parse(row.dependencies) as string[],\n spawnedAt: row.spawned_at,\n completedAt: row.completed_at,\n costUsd: row.cost_usd,\n };\n}\n\nexport function createWorker(\n worker: Omit<WorkerRecord, 'id' | 'status' | 'spawnedAt' | 'completedAt' | 'costUsd'> & {\n id?: string;\n status?: WorkerStatus;\n spawnedAt?: number;\n completedAt?: number | null;\n costUsd?: number;\n }\n): WorkerRecord {\n const db = getDb();\n const id = worker.id ?? uuidv4();\n const status = worker.status ?? 'pending';\n const spawnedAt = worker.spawnedAt ?? Date.now();\n const completedAt = worker.completedAt ?? null;\n const costUsd = worker.costUsd ?? 0;\n\n db.prepare(\n `INSERT INTO workers (id, leader_id, meeting_id, task_description, task_type, status, input_context, output_result, error_message, dependencies, spawned_at, completed_at, cost_usd)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`\n ).run(\n id,\n worker.leaderId,\n worker.meetingId,\n worker.taskDescription,\n worker.taskType,\n status,\n worker.inputContext,\n worker.outputResult,\n worker.errorMessage,\n JSON.stringify(worker.dependencies),\n spawnedAt,\n completedAt,\n costUsd\n );\n\n return {\n id,\n leaderId: worker.leaderId,\n meetingId: worker.meetingId,\n taskDescription: worker.taskDescription,\n taskType: worker.taskType,\n status,\n inputContext: worker.inputContext,\n outputResult: worker.outputResult,\n errorMessage: worker.errorMessage,\n dependencies: worker.dependencies,\n spawnedAt,\n completedAt,\n costUsd,\n };\n}\n\nexport function getWorker(id: string): WorkerRecord | null {\n const db = getDb();\n const row = db.prepare('SELECT * FROM workers WHERE id = ?').get(id) as WorkerRow | undefined;\n return row ? rowToWorker(row) : null;\n}\n\nexport function updateWorker(\n id: string,\n updates: Partial<Omit<WorkerRecord, 'id'>>\n): WorkerRecord | null {\n const db = getDb();\n const existing = getWorker(id);\n if (!existing) return null;\n\n const fields: string[] = [];\n const values: unknown[] = [];\n\n if (updates.leaderId !== undefined) { fields.push('leader_id = ?'); values.push(updates.leaderId); }\n if (updates.meetingId !== undefined) { fields.push('meeting_id = ?'); values.push(updates.meetingId); }\n if (updates.taskDescription !== undefined) { fields.push('task_description = ?'); values.push(updates.taskDescription); }\n if (updates.taskType !== undefined) { fields.push('task_type = ?'); values.push(updates.taskType); }\n if (updates.status !== undefined) { fields.push('status = ?'); values.push(updates.status); }\n if (updates.inputContext !== undefined) { fields.push('input_context = ?'); values.push(updates.inputContext); }\n if (updates.outputResult !== undefined) { fields.push('output_result = ?'); values.push(updates.outputResult); }\n if (updates.errorMessage !== undefined) { fields.push('error_message = ?'); values.push(updates.errorMessage); }\n if (updates.dependencies !== undefined) { fields.push('dependencies = ?'); values.push(JSON.stringify(updates.dependencies)); }\n if (updates.spawnedAt !== undefined) { fields.push('spawned_at = ?'); values.push(updates.spawnedAt); }\n if (updates.completedAt !== undefined) { fields.push('completed_at = ?'); values.push(updates.completedAt); }\n if (updates.costUsd !== undefined) { fields.push('cost_usd = ?'); values.push(updates.costUsd); }\n\n if (fields.length === 0) return existing;\n\n values.push(id);\n db.prepare(`UPDATE workers SET ${fields.join(', ')} WHERE id = ?`).run(...values);\n\n return getWorker(id);\n}\n\nexport function listWorkersByLeader(leaderId: string): WorkerRecord[] {\n const db = getDb();\n const rows = db\n .prepare('SELECT * FROM workers WHERE leader_id = ? ORDER BY spawned_at ASC')\n .all(leaderId) as WorkerRow[];\n return rows.map(rowToWorker);\n}\n","import { v4 as uuidv4 } from 'uuid';\nimport { getDb } from './db.js';\nimport type { MentionRecord, MentionUrgency, MentionStatus, MentionOption } from '../types/index.js';\n\ninterface MentionRow {\n id: string;\n meeting_id: string;\n agenda_item: string | null;\n summary: string;\n options: string;\n urgency: string;\n status: string;\n user_decision: string | null;\n user_reasoning: string | null;\n created_at: number;\n resolved_at: number | null;\n}\n\nfunction rowToMention(row: MentionRow): MentionRecord {\n return {\n id: row.id,\n meetingId: row.meeting_id,\n agendaItem: row.agenda_item,\n summary: row.summary,\n options: JSON.parse(row.options) as MentionOption[],\n urgency: row.urgency as MentionUrgency,\n status: row.status as MentionStatus,\n userDecision: row.user_decision,\n userReasoning: row.user_reasoning,\n createdAt: row.created_at,\n resolvedAt: row.resolved_at,\n };\n}\n\nexport function createMention(\n mention: Omit<MentionRecord, 'id' | 'status' | 'createdAt' | 'resolvedAt'> & {\n id?: string;\n status?: MentionStatus;\n createdAt?: number;\n resolvedAt?: number | null;\n }\n): MentionRecord {\n const db = getDb();\n const id = mention.id ?? uuidv4();\n const status = mention.status ?? 'pending';\n const createdAt = mention.createdAt ?? Date.now();\n const resolvedAt = mention.resolvedAt ?? null;\n\n db.prepare(\n `INSERT INTO mentions (id, meeting_id, agenda_item, summary, options, urgency, status, user_decision, user_reasoning, created_at, resolved_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`\n ).run(\n id,\n mention.meetingId,\n mention.agendaItem,\n mention.summary,\n JSON.stringify(mention.options),\n mention.urgency,\n status,\n mention.userDecision,\n mention.userReasoning,\n createdAt,\n resolvedAt\n );\n\n return {\n id,\n meetingId: mention.meetingId,\n agendaItem: mention.agendaItem,\n summary: mention.summary,\n options: mention.options,\n urgency: mention.urgency,\n status,\n userDecision: mention.userDecision,\n userReasoning: mention.userReasoning,\n createdAt,\n resolvedAt,\n };\n}\n\nexport function getMention(id: string): MentionRecord | null {\n const db = getDb();\n const row = db.prepare('SELECT * FROM mentions WHERE id = ?').get(id) as MentionRow | undefined;\n return row ? rowToMention(row) : null;\n}\n\nexport function updateMention(\n id: string,\n updates: Partial<Omit<MentionRecord, 'id'>>\n): MentionRecord | null {\n const db = getDb();\n const existing = getMention(id);\n if (!existing) return null;\n\n const fields: string[] = [];\n const values: unknown[] = [];\n\n if (updates.meetingId !== undefined) { fields.push('meeting_id = ?'); values.push(updates.meetingId); }\n if (updates.agendaItem !== undefined) { fields.push('agenda_item = ?'); values.push(updates.agendaItem); }\n if (updates.summary !== undefined) { fields.push('summary = ?'); values.push(updates.summary); }\n if (updates.options !== undefined) { fields.push('options = ?'); values.push(JSON.stringify(updates.options)); }\n if (updates.urgency !== undefined) { fields.push('urgency = ?'); values.push(updates.urgency); }\n if (updates.status !== undefined) { fields.push('status = ?'); values.push(updates.status); }\n if (updates.userDecision !== undefined) { fields.push('user_decision = ?'); values.push(updates.userDecision); }\n if (updates.userReasoning !== undefined) { fields.push('user_reasoning = ?'); values.push(updates.userReasoning); }\n if (updates.createdAt !== undefined) { fields.push('created_at = ?'); values.push(updates.createdAt); }\n if (updates.resolvedAt !== undefined) { fields.push('resolved_at = ?'); values.push(updates.resolvedAt); }\n\n if (fields.length === 0) return existing;\n\n values.push(id);\n db.prepare(`UPDATE mentions SET ${fields.join(', ')} WHERE id = ?`).run(...values);\n\n return getMention(id);\n}\n\nexport function listPendingMentions(): MentionRecord[] {\n const db = getDb();\n const rows = db\n .prepare(\"SELECT * FROM mentions WHERE status = 'pending' ORDER BY created_at ASC\")\n .all() as MentionRow[];\n return rows.map(rowToMention);\n}\n\nexport function listMentionsByMeeting(meetingId: string): MentionRecord[] {\n const db = getDb();\n const rows = db\n .prepare('SELECT * FROM mentions WHERE meeting_id = ? ORDER BY created_at ASC')\n .all(meetingId) as MentionRow[];\n return rows.map(rowToMention);\n}\n","import { v4 as uuidv4 } from 'uuid';\nimport { getDb } from './db.js';\nimport type { MinutesRecord, MinutesFormat, ActionItem } from '../types/index.js';\n\ninterface MinutesRow {\n id: string;\n meeting_id: string;\n format: string;\n content: string;\n action_items: string;\n created_at: number;\n}\n\nfunction rowToMinutes(row: MinutesRow): MinutesRecord {\n return {\n id: row.id,\n meetingId: row.meeting_id,\n format: row.format as MinutesFormat,\n content: row.content,\n actionItems: JSON.parse(row.action_items) as ActionItem[],\n createdAt: row.created_at,\n };\n}\n\nexport function createMinutes(\n minutes: Omit<MinutesRecord, 'id' | 'createdAt'> & {\n id?: string;\n createdAt?: number;\n }\n): MinutesRecord {\n const db = getDb();\n const id = minutes.id ?? uuidv4();\n const createdAt = minutes.createdAt ?? Date.now();\n\n db.prepare(\n `INSERT INTO minutes (id, meeting_id, format, content, action_items, created_at)\n VALUES (?, ?, ?, ?, ?, ?)`\n ).run(\n id,\n minutes.meetingId,\n minutes.format,\n minutes.content,\n JSON.stringify(minutes.actionItems),\n createdAt\n );\n\n return {\n id,\n meetingId: minutes.meetingId,\n format: minutes.format,\n content: minutes.content,\n actionItems: minutes.actionItems,\n createdAt,\n };\n}\n\nexport function getMinutesByMeeting(meetingId: string): MinutesRecord | null {\n const db = getDb();\n const row = db\n .prepare('SELECT * FROM minutes WHERE meeting_id = ?')\n .get(meetingId) as MinutesRow | undefined;\n return row ? rowToMinutes(row) : null;\n}\n","import { getDb } from './db.js';\nimport type { ActionItem } from '../types/index.js';\n\ninterface MinutesRow {\n id: string;\n meeting_id: string;\n action_items: string;\n}\n\nexport function getTasksFromMinutes(meetingId: string): ActionItem[] {\n const db = getDb();\n const row = db\n .prepare('SELECT action_items FROM minutes WHERE meeting_id = ?')\n .get(meetingId) as Pick<MinutesRow, 'action_items'> | undefined;\n\n if (!row) return [];\n\n return JSON.parse(row.action_items) as ActionItem[];\n}\n\nexport function updateTaskInMinutes(\n meetingId: string,\n taskId: string,\n updates: Partial<Omit<ActionItem, 'id'>>\n): ActionItem | null {\n const db = getDb();\n const row = db\n .prepare('SELECT id, action_items FROM minutes WHERE meeting_id = ?')\n .get(meetingId) as Pick<MinutesRow, 'id' | 'action_items'> | undefined;\n\n if (!row) return null;\n\n const actionItems = JSON.parse(row.action_items) as ActionItem[];\n const index = actionItems.findIndex((item) => item.id === taskId);\n\n if (index === -1) return null;\n\n const updated: ActionItem = { ...actionItems[index], ...updates, id: taskId };\n actionItems[index] = updated;\n\n db.prepare('UPDATE minutes SET action_items = ? WHERE id = ?').run(\n JSON.stringify(actionItems),\n row.id\n );\n\n return updated;\n}\n","export type AgentTier = 'orchestrator' | 'leader' | 'worker';\n\nexport type AgentStatus =\n | 'idle'\n | 'in-meeting'\n | 'working'\n | 'spawning-workers'\n | 'aggregating'\n | 'waiting-for-user'\n | 'completed'\n | 'failed';\n\nexport type Department =\n | 'architecture'\n | 'engineering'\n | 'qa'\n | 'product'\n | 'research';\n\nexport type LeaderRole =\n | 'arch-leader'\n | 'eng-leader'\n | 'qa-leader'\n | 'pm-leader'\n | 'research-leader';\n\nexport type WorkerType =\n | 'schema-designer'\n | 'api-designer'\n | 'dependency-analyzer'\n | 'feature-dev'\n | 'bug-fixer'\n | 'refactorer'\n | 'test-writer'\n | 'test-runner'\n | 'security-auditor'\n | 'perf-tester'\n | 'requirements-analyzer'\n | 'user-flow-mapper'\n | 'code-explorer'\n | 'doc-searcher'\n | 'benchmark-runner'\n | 'minutes-writer'\n | 'compactor';\n\nexport interface AgentNode {\n id: string;\n tier: AgentTier;\n role: string;\n department: Department;\n parentId: string | null;\n meetingId: string | null;\n status: AgentStatus;\n currentTask: string | null;\n sessionId: string | null;\n spawnedAt: number;\n completedAt: number | null;\n costUsd: number;\n}\n\nexport interface AgentConfig {\n model: string;\n maxTurns: number;\n\n allowedTools: string[];\n}\n\nexport const TIER_CONFIGS: Record<AgentTier, Omit<AgentConfig, 'allowedTools'>> = {\n orchestrator: {\n model: 'claude-opus-4-6',\n maxTurns: 10,\n },\n leader: {\n model: 'claude-sonnet-4-6',\n maxTurns: 20,\n },\n worker: {\n model: 'claude-sonnet-4-6',\n maxTurns: 30,\n },\n};\n\nexport const DEPARTMENT_TOOLS: Record<Department, string[]> = {\n architecture: ['Read', 'Grep', 'Glob'],\n engineering: ['Read', 'Grep', 'Glob', 'Write', 'Edit', 'Bash'],\n qa: ['Read', 'Grep', 'Glob', 'Bash'],\n product: ['Read'],\n research: ['Read', 'Grep', 'Glob', 'WebSearch'],\n};\n","import type { Department, LeaderRole, WorkerType } from '../types/index.js';\nimport { DEPARTMENT_TOOLS } from '../types/index.js';\n\n/** Full metadata for a department. */\nexport interface DepartmentInfo {\n name: Department;\n description: string;\n leaderRole: LeaderRole;\n workerTypes: WorkerType[];\n allowedTools: string[];\n}\n\nconst DEPARTMENT_REGISTRY: ReadonlyMap<Department, DepartmentInfo> = new Map<Department, DepartmentInfo>([\n [\n 'architecture',\n {\n name: 'architecture',\n description:\n 'Responsible for system design, schema definitions, API surface design, and dependency analysis. ' +\n 'The architecture department plans before code is written — it produces blueprints, not implementations.',\n leaderRole: 'arch-leader',\n workerTypes: ['schema-designer', 'api-designer', 'dependency-analyzer'],\n allowedTools: DEPARTMENT_TOOLS.architecture,\n },\n ],\n [\n 'engineering',\n {\n name: 'engineering',\n description:\n 'Responsible for writing, modifying, and refactoring production code. ' +\n 'Engineering owns feature development, bug fixes, and code quality improvements.',\n leaderRole: 'eng-leader',\n workerTypes: ['feature-dev', 'bug-fixer', 'refactorer'],\n allowedTools: DEPARTMENT_TOOLS.engineering,\n },\n ],\n [\n 'qa',\n {\n name: 'qa',\n description:\n 'Responsible for test creation, test execution, security auditing, and performance testing. ' +\n 'QA ensures deliverables meet acceptance criteria and do not introduce regressions.',\n leaderRole: 'qa-leader',\n workerTypes: ['test-writer', 'test-runner', 'security-auditor', 'perf-tester'],\n allowedTools: DEPARTMENT_TOOLS.qa,\n },\n ],\n [\n 'product',\n {\n name: 'product',\n description:\n 'Responsible for requirements analysis, user-flow mapping, and stakeholder alignment. ' +\n 'Product translates user intent into well-scoped, actionable requirements for other departments.',\n leaderRole: 'pm-leader',\n workerTypes: ['requirements-analyzer', 'user-flow-mapper'],\n allowedTools: DEPARTMENT_TOOLS.product,\n },\n ],\n [\n 'research',\n {\n name: 'research',\n description:\n 'Responsible for codebase exploration, documentation search, benchmarking, and knowledge gathering. ' +\n 'Research produces facts and context that inform decisions made by other departments.',\n leaderRole: 'research-leader',\n workerTypes: ['code-explorer', 'doc-searcher', 'benchmark-runner'],\n allowedTools: DEPARTMENT_TOOLS.research,\n },\n ],\n]);\n\n/** Reverse lookup: leader role → department. */\nconst ROLE_TO_DEPARTMENT: ReadonlyMap<LeaderRole, Department> = new Map<LeaderRole, Department>(\n [...DEPARTMENT_REGISTRY.values()].map((d) => [d.leaderRole, d.name]),\n);\n\n/**\n * Get the full metadata for a single department.\n * Throws if the department key is unknown.\n */\nexport function getDepartment(dept: Department): DepartmentInfo {\n const info = DEPARTMENT_REGISTRY.get(dept);\n if (!info) {\n throw new Error(`Unknown department: ${dept}`);\n }\n return info;\n}\n\n/**\n * Return metadata for every registered department.\n */\nexport function getAllDepartments(): DepartmentInfo[] {\n return [...DEPARTMENT_REGISTRY.values()];\n}\n\n/**\n * Resolve a leader role back to its owning department.\n * Throws if the role is unknown.\n */\nexport function getDepartmentForRole(role: LeaderRole): Department {\n const dept = ROLE_TO_DEPARTMENT.get(role);\n if (dept === undefined) {\n throw new Error(`Unknown leader role: ${role}`);\n }\n return dept;\n}\n","import { EventEmitter } from 'node:events';\nimport type { AgentEvent, DashboardEvent } from '../types/index.js';\n\n// ---------------------------------------------------------------------------\n// Typed event map\n// ---------------------------------------------------------------------------\n\n/**\n * Events emitted by the internal event bus.\n *\n * - `agent_event` — individual agent lifecycle events (spawned, destroyed, state change, etc.)\n * - `dashboard` — full dashboard payloads (snapshot or delta) intended for the WebSocket dashboard.\n */\nexport interface EventBusEvents {\n agent_event: [event: AgentEvent];\n dashboard: [event: DashboardEvent];\n}\n\n// ---------------------------------------------------------------------------\n// EventBus class\n// ---------------------------------------------------------------------------\n\nclass EventBus {\n private readonly emitter = new EventEmitter();\n\n constructor() {\n // Allow a reasonable number of listeners (leaders + dashboard + internal consumers)\n this.emitter.setMaxListeners(50);\n }\n\n // ---- emit ---------------------------------------------------------------\n\n /**\n * Emit a single agent lifecycle event.\n *\n * The event is:\n * 1. Broadcast to all `agent_event` listeners.\n * 2. Wrapped in a `delta` dashboard event and broadcast to `dashboard` listeners.\n * 3. (Planned) Persisted to SQLite via the storage layer.\n */\n emitAgentEvent(event: AgentEvent): void {\n this.emitter.emit('agent_event', event);\n\n // Wrap in a delta for the dashboard\n const delta: DashboardEvent = {\n type: 'delta',\n timestamp: Date.now(),\n events: [event],\n };\n this.emitter.emit('dashboard', delta);\n\n // TODO: persist to SQLite once the storage layer is implemented\n // import { eventStore } from '../storage/event-store.js';\n // eventStore.persist(event);\n }\n\n /**\n * Emit a full dashboard snapshot (used on initial WebSocket connection).\n */\n emitDashboardSnapshot(snapshot: DashboardEvent): void {\n this.emitter.emit('dashboard', snapshot);\n }\n\n // ---- subscribe ----------------------------------------------------------\n\n on<K extends keyof EventBusEvents>(event: K, listener: (...args: EventBusEvents[K]) => void): void {\n this.emitter.on(event, listener as (...args: unknown[]) => void);\n }\n\n off<K extends keyof EventBusEvents>(event: K, listener: (...args: EventBusEvents[K]) => void): void {\n this.emitter.off(event, listener as (...args: unknown[]) => void);\n }\n\n once<K extends keyof EventBusEvents>(event: K, listener: (...args: EventBusEvents[K]) => void): void {\n this.emitter.once(event, listener as (...args: unknown[]) => void);\n }\n\n // ---- utility ------------------------------------------------------------\n\n removeAllListeners(event?: keyof EventBusEvents): void {\n if (event) {\n this.emitter.removeAllListeners(event);\n } else {\n this.emitter.removeAllListeners();\n }\n }\n\n listenerCount(event: keyof EventBusEvents): number {\n return this.emitter.listenerCount(event);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Singleton export\n// ---------------------------------------------------------------------------\n\n/** Global event bus singleton for internal inter-agent communication. */\nexport const eventBus = new EventBus();\n","/**\n * Structured logger that writes to stderr.\n *\n * stdout is reserved for the MCP stdio transport, so all diagnostic output\n * goes to stderr to avoid corrupting the JSON-RPC stream.\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\nexport interface LogContext {\n meetingId?: string;\n agentId?: string;\n department?: string;\n [key: string]: unknown;\n}\n\ninterface LogEntry {\n timestamp: string;\n level: LogLevel;\n message: string;\n context?: LogContext;\n}\n\n// ---------------------------------------------------------------------------\n// Level ordering\n// ---------------------------------------------------------------------------\n\nconst LEVEL_PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\n// ---------------------------------------------------------------------------\n// Logger class\n// ---------------------------------------------------------------------------\n\nclass Logger {\n private minLevel: LogLevel = 'info';\n\n /**\n * Set the minimum log level. Messages below this level are silently dropped.\n * Defaults to 'info'. Set to 'debug' for verbose output.\n */\n setLevel(level: LogLevel): void {\n this.minLevel = level;\n }\n\n getLevel(): LogLevel {\n return this.minLevel;\n }\n\n debug(message: string, context?: LogContext): void {\n this.log('debug', message, context);\n }\n\n info(message: string, context?: LogContext): void {\n this.log('info', message, context);\n }\n\n warn(message: string, context?: LogContext): void {\n this.log('warn', message, context);\n }\n\n error(message: string, context?: LogContext): void {\n this.log('error', message, context);\n }\n\n // -----------------------------------------------------------------------\n // Internal\n // -----------------------------------------------------------------------\n\n private log(level: LogLevel, message: string, context?: LogContext): void {\n if (LEVEL_PRIORITY[level] < LEVEL_PRIORITY[this.minLevel]) {\n return;\n }\n\n const entry: LogEntry = {\n timestamp: new Date().toISOString(),\n level,\n message,\n };\n\n if (context && Object.keys(context).length > 0) {\n entry.context = context;\n }\n\n // Write to stderr as a single JSON line for easy parsing\n process.stderr.write(JSON.stringify(entry) + '\\n');\n }\n}\n\n// ---------------------------------------------------------------------------\n// Singleton export\n// ---------------------------------------------------------------------------\n\n/** Global structured logger — writes to stderr to keep stdout clean for MCP. */\nexport const logger = new Logger();\n","import { v4 as uuidv4 } from 'uuid';\nimport type { AgentNode, Department } from '../types/index.js';\nimport { createAgent, updateAgent, listAgentsByMeeting } from '../storage/index.js';\nimport { getDepartment } from '../agents/departments.js';\nimport { eventBus } from './event-bus.js';\nimport { logger } from '../utils/logger.js';\n\n// ---------------------------------------------------------------------------\n// LeaderPool — manages leader agent lifecycles\n// ---------------------------------------------------------------------------\n\nexport class LeaderPool {\n /**\n * Active leaders keyed by their agent ID.\n * This is a fast in-memory index; the source of truth is SQLite.\n */\n private readonly activeLeaders = new Map<string, AgentNode>();\n\n // ---- spawn --------------------------------------------------------------\n\n /**\n * Spawn a new leader agent for the given department and meeting.\n *\n * Persists the agent to SQLite and emits an `agent_spawned` event on the\n * event bus.\n */\n spawnLeader(department: Department, meetingId: string): AgentNode {\n const deptInfo = getDepartment(department);\n\n const agent = createAgent({\n tier: 'leader',\n role: deptInfo.leaderRole,\n department,\n parentId: null, // The orchestrator is implicit; no stored orchestrator agent row yet.\n meetingId,\n status: 'in-meeting',\n currentTask: null,\n sessionId: null,\n });\n\n this.activeLeaders.set(agent.id, agent);\n\n logger.info(`Spawned leader: ${deptInfo.leaderRole}`, {\n agentId: agent.id,\n department,\n meetingId,\n });\n\n eventBus.emitAgentEvent({\n kind: 'agent_spawned',\n agentId: agent.id,\n agentType: 'leader',\n parentId: null,\n label: deptInfo.leaderRole,\n department,\n });\n\n return agent;\n }\n\n // ---- query --------------------------------------------------------------\n\n /**\n * Return all currently-active leaders assigned to a given meeting.\n *\n * Falls back to a SQLite query filtered by status so that leaders which were\n * deactivated out-of-band are excluded.\n */\n getLeadersForMeeting(meetingId: string): AgentNode[] {\n // Fast path: filter in-memory cache\n const fromCache = [...this.activeLeaders.values()].filter(\n (a) => a.meetingId === meetingId,\n );\n\n if (fromCache.length > 0) {\n return fromCache;\n }\n\n // Slow path: query storage (e.g. after a server restart)\n return listAgentsByMeeting(meetingId).filter(\n (a) => a.tier === 'leader' && a.status !== 'completed' && a.status !== 'failed',\n );\n }\n\n // ---- deactivate ---------------------------------------------------------\n\n /**\n * Mark a leader as completed and remove it from the in-memory cache.\n */\n deactivateLeader(leaderId: string): void {\n const leader = this.activeLeaders.get(leaderId);\n\n updateAgent(leaderId, {\n status: 'completed',\n completedAt: Date.now(),\n });\n\n this.activeLeaders.delete(leaderId);\n\n logger.info(`Deactivated leader: ${leaderId}`, {\n agentId: leaderId,\n department: leader?.department,\n });\n\n eventBus.emitAgentEvent({\n kind: 'agent_destroyed',\n agentId: leaderId,\n });\n }\n}\n","import { z } from 'zod';\nimport {\n getMeeting,\n listMeetings,\n listAgentsByMeeting,\n listWorkersByLeader,\n} from '../storage/index.js';\n\nexport const getMeetingStatusSchema = {\n meetingId: z\n .string()\n .optional()\n .describe('Specific meeting ID, or omit for all active'),\n};\n\nexport async function getMeetingStatusHandler({\n meetingId,\n}: {\n meetingId?: string;\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n if (meetingId) {\n const meeting = getMeeting(meetingId);\n if (!meeting) {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n { error: `Meeting not found: ${meetingId}` },\n null,\n 2,\n ),\n },\n ],\n isError: true,\n };\n }\n\n const agents = listAgentsByMeeting(meetingId);\n const workers = agents.flatMap((agent) =>\n listWorkersByLeader(agent.id),\n );\n\n const result = {\n meeting,\n agents,\n workers,\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n }\n\n // Return all active meetings summary\n const allMeetings = listMeetings();\n const activeMeetings = allMeetings.filter(\n (m) =>\n !['completed', 'cancelled', 'failed', 'reported', 'compacted'].includes(\n m.status,\n ),\n );\n\n const result = {\n totalMeetings: allMeetings.length,\n activeMeetings: activeMeetings.map((m) => ({\n id: m.id,\n topic: m.topic,\n status: m.status,\n phase: m.phase,\n startedAt: m.startedAt,\n })),\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import { z } from 'zod';\nimport { getMinutesByMeeting } from '../storage/index.js';\n\nexport const getMinutesSchema = {\n meetingId: z.string().describe('Meeting ID'),\n format: z\n .enum(['full', 'summary', 'tasks_only'])\n .default('full')\n .optional()\n .describe('Output format'),\n};\n\nexport async function getMinutesHandler({\n meetingId,\n format,\n}: {\n meetingId: string;\n format?: 'full' | 'summary' | 'tasks_only';\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const minutes = getMinutesByMeeting(meetingId);\n if (!minutes) {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n { error: `No minutes found for meeting: ${meetingId}` },\n null,\n 2,\n ),\n },\n ],\n isError: true,\n };\n }\n\n const effectiveFormat = format ?? 'full';\n\n let result: unknown;\n\n switch (effectiveFormat) {\n case 'full':\n result = {\n id: minutes.id,\n meetingId: minutes.meetingId,\n format: minutes.format,\n content: minutes.content,\n actionItems: minutes.actionItems,\n createdAt: minutes.createdAt,\n };\n break;\n\n case 'summary': {\n // Extract a summary: first 500 chars of content + action item count\n const summaryContent =\n minutes.content.length > 500\n ? minutes.content.slice(0, 500) + '...'\n : minutes.content;\n result = {\n id: minutes.id,\n meetingId: minutes.meetingId,\n summary: summaryContent,\n actionItemCount: minutes.actionItems.length,\n createdAt: minutes.createdAt,\n };\n break;\n }\n\n case 'tasks_only':\n result = {\n meetingId: minutes.meetingId,\n actionItems: minutes.actionItems,\n totalTasks: minutes.actionItems.length,\n };\n break;\n }\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import { z } from 'zod';\nimport { Compactor } from '../meeting/compactor.js';\n\nexport const compactMinutesSchema = {\n meetingId: z.string().describe('Meeting ID'),\n additionalInstructions: z\n .string()\n .optional()\n .describe('Additional instructions for compaction'),\n};\n\nexport async function compactMinutesHandler({\n meetingId,\n additionalInstructions,\n}: {\n meetingId: string;\n additionalInstructions?: string;\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const compactor = new Compactor();\n const tasks = await compactor.compactMinutes(\n meetingId,\n additionalInstructions,\n );\n\n const result = {\n meetingId,\n tasksGenerated: tasks.length,\n tasks,\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","/**\n * Compacts meeting minutes into a structured task list per department.\n *\n * Assigns departments and priorities based on keyword analysis.\n */\n\nimport { v4 as uuidv4 } from 'uuid';\nimport { getMinutesByMeeting, createMinutes } from '../storage/index.js';\nimport { getDb } from '../storage/db.js';\nimport type { ActionItem, Department, MinutesRecord } from '../types/index.js';\nimport { logger } from '../utils/logger.js';\n\n// ---------------------------------------------------------------------------\n// Keyword → department mapping\n// ---------------------------------------------------------------------------\n\nconst DEPARTMENT_KEYWORDS: Record<Department, string[]> = {\n architecture: [\n 'schema', 'design', 'architecture', 'blueprint', 'dependency',\n 'api design', 'system design', '아키텍처', '설계',\n ],\n engineering: [\n 'implement', 'code', 'develop', 'build', 'refactor', 'fix',\n 'feature', 'module', '구현', '개발', '코드',\n ],\n qa: [\n 'test', 'quality', 'coverage', 'security', 'audit', 'performance',\n 'regression', 'validation', '테스트', '검증', '품질',\n ],\n product: [\n 'requirement', 'user story', 'acceptance criteria', 'stakeholder',\n 'priority', 'roadmap', 'scope', '요구사항', '사용자',\n ],\n research: [\n 'research', 'explore', 'investigate', 'benchmark', 'compare',\n 'evaluate', 'poc', 'prototype', '조사', '탐색',\n ],\n};\n\n// ---------------------------------------------------------------------------\n// Keyword → priority mapping\n// ---------------------------------------------------------------------------\n\nconst PRIORITY_KEYWORDS: Record<ActionItem['priority'], string[]> = {\n critical: [\n 'critical', 'urgent', 'blocker', 'blocking', 'asap', 'immediately',\n '긴급', '즉시', 'p0',\n ],\n high: [\n 'high priority', 'important', 'must', 'required', 'essential',\n '중요', '필수', 'p1',\n ],\n medium: [\n 'medium', 'should', 'moderate', '보통', 'p2',\n ],\n low: [\n 'low priority', 'nice to have', 'optional', 'consider',\n '낮음', '선택', 'p3',\n ],\n};\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction detectDepartment(text: string): Department {\n const lower = text.toLowerCase();\n let bestDept: Department = 'engineering';\n let bestScore = 0;\n\n for (const [dept, keywords] of Object.entries(DEPARTMENT_KEYWORDS) as [Department, string[]][]) {\n const score = keywords.reduce(\n (acc, kw) => acc + (lower.includes(kw.toLowerCase()) ? 1 : 0),\n 0,\n );\n if (score > bestScore) {\n bestScore = score;\n bestDept = dept;\n }\n }\n\n return bestDept;\n}\n\nfunction detectPriority(text: string): ActionItem['priority'] {\n const lower = text.toLowerCase();\n\n // Check from highest to lowest — first match wins\n for (const priority of ['critical', 'high', 'medium', 'low'] as const) {\n const keywords = PRIORITY_KEYWORDS[priority];\n if (keywords.some((kw) => lower.includes(kw.toLowerCase()))) {\n return priority;\n }\n }\n\n return 'medium';\n}\n\nconst LEADER_ROLE_FOR_DEPT: Record<Department, string> = {\n architecture: 'arch-leader',\n engineering: 'eng-leader',\n qa: 'qa-leader',\n product: 'pm-leader',\n research: 'research-leader',\n};\n\n// ---------------------------------------------------------------------------\n// Compactor\n// ---------------------------------------------------------------------------\n\nexport class Compactor {\n /**\n * Compact minutes into actionable, department-assigned tasks.\n *\n * 1. Load minutes for the meeting\n * 2. Parse action items from the minutes content\n * 3. Assign each to a department based on keywords\n * 4. Set priorities based on keywords\n * 5. Save updated action items to minutes record\n * 6. Return the structured task list\n */\n async compactMinutes(\n meetingId: string,\n additionalInstructions?: string,\n ): Promise<ActionItem[]> {\n logger.info('Compacting minutes', { meetingId });\n\n // 1. Load existing minutes\n const minutes = getMinutesByMeeting(meetingId);\n if (!minutes) {\n throw new Error(`No minutes found for meeting: ${meetingId}`);\n }\n\n // 2–4. Refine existing action items with department + priority detection\n const refinedItems: ActionItem[] = minutes.actionItems.map((item) => {\n const fullText = `${item.title} ${item.description} ${additionalInstructions ?? ''}`;\n const department = detectDepartment(fullText);\n const priority = detectPriority(fullText);\n\n return {\n ...item,\n assignedDepartment: department,\n assignedRole: LEADER_ROLE_FOR_DEPT[department],\n priority,\n };\n });\n\n // If there are no existing action items, try to extract from minutes content\n if (refinedItems.length === 0) {\n const extracted = this.extractFromContent(minutes.content);\n refinedItems.push(...extracted);\n }\n\n // 5. Update the minutes record in the DB\n const db = getDb();\n db.prepare('UPDATE minutes SET action_items = ? WHERE id = ?').run(\n JSON.stringify(refinedItems),\n minutes.id,\n );\n\n logger.info('Minutes compacted', {\n meetingId,\n actionItemCount: refinedItems.length,\n } as Record<string, unknown>);\n\n // 6. Return the structured task list\n return refinedItems;\n }\n\n // -------------------------------------------------------------------------\n // Fallback extraction from raw minutes content\n // -------------------------------------------------------------------------\n\n private extractFromContent(content: string): ActionItem[] {\n const items: ActionItem[] = [];\n const lines = content.split('\\n');\n\n for (const line of lines) {\n const trimmed = line.trim();\n // Look for lines that start with \"- \" or numbered items under action sections\n if (\n trimmed.startsWith('- ') &&\n trimmed.length > 5 &&\n trimmed !== '- None' &&\n trimmed !== '- None recorded' &&\n trimmed !== '- No action items identified' &&\n trimmed !== '- No action items recorded'\n ) {\n const text = trimmed.slice(2);\n const department = detectDepartment(text);\n const priority = detectPriority(text);\n\n items.push({\n id: uuidv4(),\n title: text.slice(0, 80),\n description: text,\n assignedDepartment: department,\n assignedRole: LEADER_ROLE_FOR_DEPT[department],\n priority,\n dependencies: [],\n acceptanceCriteria: [],\n });\n }\n }\n\n return items;\n }\n}\n","import { z } from 'zod';\nimport { getTasksFromMinutes } from '../storage/index.js';\n\nexport const executeTasksSchema = {\n meetingId: z.string().describe('Meeting ID'),\n taskIds: z\n .array(z.string())\n .optional()\n .describe('Specific tasks to execute, or all'),\n};\n\nexport async function executeTasksHandler({\n meetingId,\n taskIds,\n}: {\n meetingId: string;\n taskIds?: string[];\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const allTasks = getTasksFromMinutes(meetingId);\n\n if (allTasks.length === 0) {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n error: `No tasks found for meeting: ${meetingId}. Run compact-minutes first.`,\n },\n null,\n 2,\n ),\n },\n ],\n isError: true,\n };\n }\n\n // Filter tasks if specific IDs provided\n const tasksToExecute = taskIds\n ? allTasks.filter((t) => taskIds.includes(t.id))\n : allTasks;\n\n if (tasksToExecute.length === 0) {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n { error: 'No matching tasks found for the provided task IDs.' },\n null,\n 2,\n ),\n },\n ],\n isError: true,\n };\n }\n\n // Group tasks by department for the caller\n const tasksByDepartment = new Map<string, typeof tasksToExecute>();\n for (const task of tasksToExecute) {\n const dept = task.assignedDepartment;\n if (!tasksByDepartment.has(dept)) {\n tasksByDepartment.set(dept, []);\n }\n tasksByDepartment.get(dept)!.push(task);\n }\n\n const departments: Array<{\n department: string;\n tasks: typeof tasksToExecute;\n }> = [];\n\n for (const [department, tasks] of tasksByDepartment) {\n departments.push({ department, tasks });\n }\n\n const result = {\n meetingId,\n totalTasks: tasksToExecute.length,\n departments,\n instructions:\n 'These tasks should be dispatched to implementer agents. ' +\n 'The orchestrator agent will use Claude Code Agent tool to run each task.',\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import { getAgentTree } from '../storage/index.js';\n\nexport async function getAgentTreeHandler(): Promise<{\n content: { type: 'text'; text: string }[];\n isError?: boolean;\n}> {\n try {\n const tree = getAgentTree('orchestrator-root');\n\n const result = {\n root: tree,\n hasAgents: tree !== null,\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import { z } from 'zod';\nimport { getMention, updateMention } from '../storage/index.js';\nimport { eventBus } from '../orchestrator/event-bus.js';\n\nexport const respondToMentionSchema = {\n mentionId: z.string().describe('ID of the mention to respond to'),\n decision: z.string().describe('The decision made by the user'),\n reasoning: z.string().optional().describe('Optional reasoning for the decision'),\n};\n\nexport async function respondToMentionHandler({\n mentionId,\n decision,\n reasoning,\n}: {\n mentionId: string;\n decision: string;\n reasoning?: string;\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const mention = getMention(mentionId);\n\n if (!mention) {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n { error: `Mention not found: ${mentionId}` },\n null,\n 2,\n ),\n },\n ],\n isError: true,\n };\n }\n\n if (mention.status === 'resolved') {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n { error: `Mention already resolved: ${mentionId}` },\n null,\n 2,\n ),\n },\n ],\n isError: true,\n };\n }\n\n const resolved = updateMention(mentionId, {\n status: 'resolved',\n userDecision: decision,\n userReasoning: reasoning ?? null,\n resolvedAt: Date.now(),\n });\n\n eventBus.emitAgentEvent({\n kind: 'mention_resolved',\n mentionId,\n decision,\n });\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n { success: true, mention: resolved },\n null,\n 2,\n ),\n },\n ],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import { z } from 'zod';\nimport {\n listPendingMentions,\n listMentionsByMeeting,\n} from '../storage/index.js';\nimport type { MentionRecord } from '../types/index.js';\n\nexport const getMentionsSchema = {\n status: z\n .enum(['pending', 'resolved', 'all'])\n .default('pending')\n .optional()\n .describe('Filter mentions by status'),\n meetingId: z\n .string()\n .optional()\n .describe('Filter mentions by meeting ID'),\n};\n\nexport async function getMentionsHandler({\n status,\n meetingId,\n}: {\n status?: 'pending' | 'resolved' | 'all';\n meetingId?: string;\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const effectiveStatus = status ?? 'pending';\n let mentions: MentionRecord[];\n\n if (meetingId) {\n // Get all mentions for this meeting, then filter by status\n const allForMeeting = listMentionsByMeeting(meetingId);\n if (effectiveStatus === 'all') {\n mentions = allForMeeting;\n } else {\n mentions = allForMeeting.filter((m) => m.status === effectiveStatus);\n }\n } else if (effectiveStatus === 'pending') {\n mentions = listPendingMentions();\n } else if (effectiveStatus === 'resolved') {\n // listPendingMentions only returns pending; for resolved we need to\n // get all and filter. Since there is no dedicated storage function for\n // resolved mentions, we use listMentionsByMeeting with no meetingId —\n // but that requires a meetingId. Instead we get pending and note the\n // limitation, or we query directly.\n // For a clean approach, list all meetings' mentions by getting pending\n // and noting this is a filtered view.\n // Actually, we can use the DB directly through the existing functions.\n // The simplest correct approach: get all pending and return empty since\n // we want resolved. But that's wrong. Let's just get all mentions.\n // Since there's no listAllMentions, we'll import getDb and query directly.\n const { getDb } = await import('../storage/db.js');\n const db = getDb();\n interface MentionRow {\n id: string;\n meeting_id: string;\n agenda_item: string | null;\n summary: string;\n options: string;\n urgency: string;\n status: string;\n user_decision: string | null;\n user_reasoning: string | null;\n created_at: number;\n resolved_at: number | null;\n }\n const rows = db\n .prepare(\"SELECT * FROM mentions WHERE status = 'resolved' ORDER BY created_at ASC\")\n .all() as MentionRow[];\n mentions = rows.map((row) => ({\n id: row.id,\n meetingId: row.meeting_id,\n agendaItem: row.agenda_item,\n summary: row.summary,\n options: JSON.parse(row.options),\n urgency: row.urgency as MentionRecord['urgency'],\n status: row.status as MentionRecord['status'],\n userDecision: row.user_decision,\n userReasoning: row.user_reasoning,\n createdAt: row.created_at,\n resolvedAt: row.resolved_at,\n }));\n } else {\n // 'all'\n const { getDb } = await import('../storage/db.js');\n const db = getDb();\n interface MentionRow {\n id: string;\n meeting_id: string;\n agenda_item: string | null;\n summary: string;\n options: string;\n urgency: string;\n status: string;\n user_decision: string | null;\n user_reasoning: string | null;\n created_at: number;\n resolved_at: number | null;\n }\n const rows = db\n .prepare('SELECT * FROM mentions ORDER BY created_at ASC')\n .all() as MentionRow[];\n mentions = rows.map((row) => ({\n id: row.id,\n meetingId: row.meeting_id,\n agendaItem: row.agenda_item,\n summary: row.summary,\n options: JSON.parse(row.options),\n urgency: row.urgency as MentionRecord['urgency'],\n status: row.status as MentionRecord['status'],\n userDecision: row.user_decision,\n userReasoning: row.user_reasoning,\n createdAt: row.created_at,\n resolvedAt: row.resolved_at,\n }));\n }\n\n const result = {\n count: mentions.length,\n status: effectiveStatus,\n ...(meetingId ? { meetingId } : {}),\n mentions,\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import { z } from 'zod';\nimport {\n getMeeting,\n updateMeeting,\n listAgentsByMeeting,\n updateAgent,\n listWorkersByLeader,\n updateWorker,\n} from '../storage/index.js';\nimport { eventBus } from '../orchestrator/event-bus.js';\n\nexport const cancelMeetingSchema = {\n meetingId: z.string().describe('ID of the meeting to cancel'),\n reason: z.string().optional().describe('Reason for cancellation'),\n};\n\nexport async function cancelMeetingHandler({\n meetingId,\n reason,\n}: {\n meetingId: string;\n reason?: string;\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const meeting = getMeeting(meetingId);\n\n if (!meeting) {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n { error: `Meeting not found: ${meetingId}` },\n null,\n 2,\n ),\n },\n ],\n isError: true,\n };\n }\n\n if (meeting.status === 'completed' || meeting.status === 'cancelled') {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n error: `Meeting cannot be cancelled: current status is '${meeting.status}'`,\n },\n null,\n 2,\n ),\n },\n ],\n isError: true,\n };\n }\n\n // Update meeting status to cancelled\n updateMeeting(meetingId, { status: 'cancelled', completedAt: Date.now() });\n\n // Find all agents for this meeting and mark them as completed\n const agents = listAgentsByMeeting(meetingId);\n let agentsCancelled = 0;\n let workersFailed = 0;\n\n for (const agent of agents) {\n if (agent.status !== 'completed' && agent.status !== 'failed') {\n updateAgent(agent.id, { status: 'completed', completedAt: Date.now() });\n agentsCancelled++;\n\n eventBus.emitAgentEvent({\n kind: 'state_changed',\n agentId: agent.id,\n from: agent.status,\n to: 'completed',\n });\n }\n\n // Find all workers for this agent (leader) and mark them as failed\n const workers = listWorkersByLeader(agent.id);\n for (const worker of workers) {\n if (worker.status !== 'completed' && worker.status !== 'failed') {\n updateWorker(worker.id, {\n status: 'failed',\n errorMessage: reason ?? 'Meeting cancelled',\n completedAt: Date.now(),\n });\n workersFailed++;\n\n eventBus.emitAgentEvent({\n kind: 'task_completed',\n agentId: worker.id,\n result: 'failure',\n });\n }\n }\n }\n\n const result = {\n success: true,\n meetingId,\n previousStatus: meeting.status,\n reason: reason ?? 'No reason provided',\n agentsCancelled,\n workersFailed,\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import { z } from 'zod';\nimport { listMeetings } from '../storage/index.js';\nimport type { MeetingStatus } from '../types/index.js';\n\nexport const listMeetingsSchema = {\n status: z\n .enum(['pending', 'running', 'completed', 'cancelled', 'failed', 'all'])\n .default('all')\n .optional()\n .describe('Filter meetings by status'),\n limit: z\n .number()\n .default(20)\n .optional()\n .describe('Maximum number of meetings to return'),\n};\n\n// Map the user-facing \"running\" status to the internal statuses that represent\n// an active/running meeting.\nconst RUNNING_STATUSES: MeetingStatus[] = [\n 'convening',\n 'opening',\n 'discussion',\n 'synthesis',\n 'minutes-generation',\n 'executing',\n 'aggregation',\n 'waiting-for-user',\n];\n\nexport async function listMeetingsHandler({\n status,\n limit,\n}: {\n status?: 'pending' | 'running' | 'completed' | 'cancelled' | 'failed' | 'all';\n limit?: number;\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const effectiveStatus = status ?? 'all';\n const effectiveLimit = limit ?? 20;\n\n let meetings;\n\n if (effectiveStatus === 'all') {\n meetings = listMeetings();\n } else if (effectiveStatus === 'running') {\n // \"running\" maps to multiple internal statuses\n const all = listMeetings();\n meetings = all.filter((m) => RUNNING_STATUSES.includes(m.status));\n } else {\n meetings = listMeetings(effectiveStatus as MeetingStatus);\n }\n\n // Apply limit\n const limited = meetings.slice(0, effectiveLimit);\n\n const result = {\n total: meetings.length,\n returned: limited.length,\n status: effectiveStatus,\n meetings: limited.map((m) => ({\n id: m.id,\n topic: m.topic,\n status: m.status,\n phase: m.phase,\n participantCount: m.participantIds.length,\n startedAt: m.startedAt,\n })),\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import { z } from 'zod';\nimport {\n getMeeting,\n getMinutesByMeeting,\n listAgentsByMeeting,\n listWorkersByLeader,\n} from '../storage/index.js';\n\nexport const getTaskReportSchema = {\n meetingId: z.string().describe('ID of the meeting to generate a report for'),\n};\n\nexport async function getTaskReportHandler({\n meetingId,\n}: {\n meetingId: string;\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const meeting = getMeeting(meetingId);\n if (!meeting) {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n { error: `Meeting not found: ${meetingId}` },\n null,\n 2,\n ),\n },\n ],\n isError: true,\n };\n }\n\n const minutes = getMinutesByMeeting(meetingId);\n const agents = listAgentsByMeeting(meetingId);\n\n // Collect all workers grouped by leader/department\n const departmentBreakdowns: Array<{\n department: string;\n leaderId: string;\n leaderRole: string;\n workers: Array<{\n id: string;\n taskDescription: string;\n status: string;\n costUsd: number;\n errorMessage: string | null;\n }>;\n completed: number;\n failed: number;\n pending: number;\n totalCost: number;\n }> = [];\n\n let totalCompleted = 0;\n let totalFailed = 0;\n let totalPending = 0;\n let totalCost = 0;\n\n for (const agent of agents) {\n const workers = listWorkersByLeader(agent.id);\n\n const completed = workers.filter((w) => w.status === 'completed').length;\n const failed = workers.filter((w) => w.status === 'failed').length;\n const pending = workers.filter(\n (w) => w.status === 'pending' || w.status === 'running',\n ).length;\n const deptCost = workers.reduce((acc, w) => acc + w.costUsd, 0);\n\n totalCompleted += completed;\n totalFailed += failed;\n totalPending += pending;\n totalCost += deptCost;\n\n if (workers.length > 0) {\n departmentBreakdowns.push({\n department: agent.department,\n leaderId: agent.id,\n leaderRole: agent.role,\n workers: workers.map((w) => ({\n id: w.id,\n taskDescription: w.taskDescription,\n status: w.status,\n costUsd: w.costUsd,\n errorMessage: w.errorMessage,\n })),\n completed,\n failed,\n pending,\n totalCost: deptCost,\n });\n }\n }\n\n const result = {\n meetingId,\n topic: meeting.topic,\n status: meeting.status,\n actionItemCount: minutes?.actionItems.length ?? 0,\n summary: {\n totalWorkers: totalCompleted + totalFailed + totalPending,\n completed: totalCompleted,\n failed: totalFailed,\n pending: totalPending,\n totalCost,\n },\n departments: departmentBreakdowns,\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import { z } from 'zod';\nimport { ExtensionManager } from '../extension/extension-manager.js';\nimport type { CapabilityType } from '../extension/capability-registry.js';\nimport type { GenerateRequest } from '../extension/generator.js';\n\nexport const createCapabilitySchema = {\n type: z\n .enum(['hook', 'skill', 'command', 'asset', 'loop'])\n .describe('Type of capability to create'),\n name: z.string().describe('Name for the new capability'),\n description: z.string().describe('What the capability does'),\n trigger: z.string().describe('When the capability should be triggered'),\n userRequest: z\n .string()\n .optional()\n .describe('Original user request that triggered creation'),\n};\n\nexport async function createCapabilityHandler({\n type,\n name,\n description,\n trigger,\n userRequest,\n}: {\n type: 'hook' | 'skill' | 'command' | 'asset' | 'loop';\n name: string;\n description: string;\n trigger: string;\n userRequest?: string;\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const manager = new ExtensionManager();\n await manager.init();\n\n const request: GenerateRequest = {\n type: type as CapabilityType,\n name,\n description,\n trigger,\n userRequest: userRequest ?? description,\n };\n\n const result = await manager.createCapability(request);\n\n const output = {\n status: 'created',\n capability: {\n type: result.capability.type,\n name: result.capability.name,\n description: result.capability.description,\n trigger: result.capability.trigger,\n isBuiltIn: result.capability.isBuiltIn,\n },\n filePath: result.filePath,\n summary: result.summary,\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","/**\n * capability-registry.ts — Tracks all registered capabilities (built-in + custom).\n *\n * The registry is persisted to ~/.open-coleslaw/registry.json.\n * Built-in capabilities (the 6 hooks + 6 skills that ship with the project) are\n * hardcoded; custom capabilities are added/removed dynamically at runtime.\n */\n\nimport { readFileSync, writeFileSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { getConfig } from '../utils/config.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type CapabilityType = 'hook' | 'skill' | 'command' | 'asset' | 'loop';\n\nexport interface Capability {\n type: CapabilityType;\n name: string;\n description: string;\n trigger: string;\n createdAt: number;\n isBuiltIn: boolean;\n filePath: string;\n}\n\n// ---------------------------------------------------------------------------\n// Built-in capability definitions\n// ---------------------------------------------------------------------------\n\nconst BUILT_IN_HOOKS: Omit<Capability, 'createdAt'>[] = [\n {\n type: 'hook',\n name: 'pre-read',\n description: 'Loads rules + plugin guide + CLAUDE.md/README before execution',\n trigger: 'Before every execution',\n isBuiltIn: true,\n filePath: 'src/hooks/pre-read.ts',\n },\n {\n type: 'hook',\n name: 'auto-route',\n description: 'Analyzes user prompts and auto-routes to appropriate skill/agent',\n trigger: 'On every user prompt',\n isBuiltIn: true,\n filePath: 'src/hooks/auto-route.ts',\n },\n {\n type: 'hook',\n name: 'auto-commit',\n description: 'Creates conventional commits after task completion',\n trigger: 'After task completion when git is connected',\n isBuiltIn: true,\n filePath: 'src/hooks/auto-commit.ts',\n },\n {\n type: 'hook',\n name: 'doc-update',\n description: 'Updates CLAUDE.md/README.md after process completion',\n trigger: 'After process completion',\n isBuiltIn: true,\n filePath: 'src/hooks/doc-update.ts',\n },\n {\n type: 'hook',\n name: 'flow-verify',\n description: 'Verifies PRD user flows after development',\n trigger: 'After development phase completes',\n isBuiltIn: true,\n filePath: 'src/hooks/flow-verify.ts',\n },\n {\n type: 'hook',\n name: 'mvp-cycle',\n description: 'Triggers re-meeting on verification failure',\n trigger: 'When flow-verify reports failure',\n isBuiltIn: true,\n filePath: 'src/hooks/mvp-cycle.ts',\n },\n];\n\nconst BUILT_IN_SKILLS: Omit<Capability, 'createdAt'>[] = [\n {\n type: 'skill',\n name: 'meeting',\n description: 'Start a meeting (auto-selects leaders if topic given)',\n trigger: '/meeting [topic]',\n isBuiltIn: true,\n filePath: 'src/skills/meeting.ts',\n },\n {\n type: 'skill',\n name: 'status',\n description: 'Show current meetings, agents, and pending mentions',\n trigger: '/status',\n isBuiltIn: true,\n filePath: 'src/skills/status.ts',\n },\n {\n type: 'skill',\n name: 'dashboard',\n description: 'Open web dashboard at http://localhost:35143',\n trigger: '/dashboard',\n isBuiltIn: true,\n filePath: 'src/skills/dashboard.ts',\n },\n {\n type: 'skill',\n name: 'mention',\n description: 'View and respond to pending @mentions',\n trigger: '/mention',\n isBuiltIn: true,\n filePath: 'src/skills/mention.ts',\n },\n {\n type: 'skill',\n name: 'agents',\n description: 'Show full agent hierarchy tree',\n trigger: '/agents',\n isBuiltIn: true,\n filePath: 'src/skills/agents.ts',\n },\n {\n type: 'skill',\n name: 'minutes',\n description: 'View meeting minutes',\n trigger: '/minutes [meetingId]',\n isBuiltIn: true,\n filePath: 'src/skills/minutes.ts',\n },\n];\n\n// ---------------------------------------------------------------------------\n// Registry class\n// ---------------------------------------------------------------------------\n\nexport class CapabilityRegistry {\n private capabilities: Capability[] = [];\n private registryPath: string;\n\n constructor() {\n const { DATA_DIR } = getConfig();\n this.registryPath = join(DATA_DIR, 'registry.json');\n }\n\n /**\n * Load all capabilities: built-in (hardcoded) + custom (from registry.json).\n */\n async loadAll(): Promise<Capability[]> {\n // Start with built-in capabilities (timestamp 0 — they always existed)\n const builtIns: Capability[] = [\n ...BUILT_IN_HOOKS,\n ...BUILT_IN_SKILLS,\n ].map((cap) => ({ ...cap, createdAt: 0 }));\n\n // Merge in custom capabilities from persistent storage\n const custom = this.readCustomEntries();\n this.capabilities = [...builtIns, ...custom];\n return this.capabilities;\n }\n\n /**\n * Register a new custom capability and persist.\n */\n async register(cap: Omit<Capability, 'createdAt'>): Promise<void> {\n const entry: Capability = { ...cap, createdAt: Date.now() };\n\n // Remove any existing entry with the same name to avoid duplicates\n const custom = this.readCustomEntries().filter((c) => c.name !== cap.name);\n custom.push(entry);\n this.writeCustomEntries(custom);\n\n // Refresh in-memory list\n await this.loadAll();\n }\n\n /**\n * Unregister a custom capability and persist.\n */\n async unregister(type: CapabilityType, name: string): Promise<void> {\n const custom = this.readCustomEntries().filter(\n (c) => !(c.type === type && c.name === name),\n );\n this.writeCustomEntries(custom);\n\n // Refresh in-memory list\n await this.loadAll();\n }\n\n /**\n * Find capabilities by type.\n */\n findByType(type: CapabilityType): Capability[] {\n return this.capabilities.filter((c) => c.type === type);\n }\n\n /**\n * Find a capability by name.\n */\n findByName(name: string): Capability | undefined {\n return this.capabilities.find((c) => c.name === name);\n }\n\n /**\n * Check whether a capability with the given name exists.\n */\n has(name: string): boolean {\n return this.capabilities.some((c) => c.name === name);\n }\n\n /**\n * Format all capabilities as a human-readable list suitable for plugin-guide.md.\n */\n formatForGuide(): string {\n const sections: string[] = [];\n\n const types: CapabilityType[] = ['hook', 'skill', 'command', 'asset', 'loop'];\n for (const type of types) {\n const caps = this.findByType(type);\n if (caps.length === 0) continue;\n\n const label = type.charAt(0).toUpperCase() + type.slice(1) + 's';\n const lines = caps.map((c) => {\n const tag = c.isBuiltIn ? '' : ' [custom]';\n return `- **${c.name}**${tag} — ${c.description} (trigger: ${c.trigger})`;\n });\n sections.push(`### ${label}\\n${lines.join('\\n')}`);\n }\n\n return sections.join('\\n\\n');\n }\n\n // -------------------------------------------------------------------------\n // Private helpers\n // -------------------------------------------------------------------------\n\n private readCustomEntries(): Capability[] {\n if (!existsSync(this.registryPath)) {\n return [];\n }\n try {\n const raw = readFileSync(this.registryPath, 'utf-8');\n const parsed: unknown = JSON.parse(raw);\n if (!Array.isArray(parsed)) return [];\n return parsed as Capability[];\n } catch {\n return [];\n }\n }\n\n private writeCustomEntries(entries: Capability[]): void {\n writeFileSync(this.registryPath, JSON.stringify(entries, null, 2), 'utf-8');\n }\n}\n","import { mkdirSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface AppConfig {\n /** Root data directory: ~/.open-coleslaw/ */\n DATA_DIR: string;\n /** SQLite database path: ~/.open-coleslaw/data.db */\n DB_PATH: string;\n /** Directory for meeting minutes files: ~/.open-coleslaw/minutes/ */\n MINUTES_DIR: string;\n /** WebSocket dashboard port */\n DASHBOARD_PORT: number;\n}\n\n// ---------------------------------------------------------------------------\n// Defaults\n// ---------------------------------------------------------------------------\n\nfunction buildConfig(): AppConfig {\n const DATA_DIR = join(homedir(), '.open-coleslaw');\n return {\n DATA_DIR,\n DB_PATH: join(DATA_DIR, 'data.db'),\n MINUTES_DIR: join(DATA_DIR, 'minutes'),\n DASHBOARD_PORT: 35143,\n };\n}\n\n// Singleton — computed once, reused thereafter.\nlet _config: AppConfig | null = null;\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Return the runtime configuration.\n *\n * Values are derived from well-known paths under `~/.open-coleslaw/`.\n * The config object is created once and cached for the lifetime of the process.\n */\nexport function getConfig(): AppConfig {\n if (!_config) {\n _config = buildConfig();\n }\n return _config;\n}\n\n/**\n * Ensure all required data directories exist (creates them recursively if missing).\n *\n * Call this once during server startup before any storage or file I/O.\n */\nexport function ensureDataDirs(): void {\n const config = getConfig();\n mkdirSync(config.DATA_DIR, { recursive: true });\n mkdirSync(config.MINUTES_DIR, { recursive: true });\n}\n","/**\n * generator.ts — Generates code for new capabilities.\n *\n * Each capability type has a template that produces a standalone file.\n * Generated files are placed in ~/.open-coleslaw/custom-{type}s/.\n */\n\nimport { mkdirSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { getConfig } from '../utils/config.js';\nimport type { CapabilityType, Capability } from './capability-registry.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface GenerateRequest {\n type: CapabilityType;\n name: string;\n description: string;\n trigger: string;\n userRequest: string;\n}\n\nexport interface GenerateResult {\n filePath: string;\n code: string;\n registryEntry: Omit<Capability, 'createdAt'>;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction sanitizeName(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n}\n\nfunction header(request: GenerateRequest): string {\n const now = new Date().toISOString();\n return [\n `// Auto-generated by open-coleslaw extension system`,\n `// Name: ${request.name}`,\n `// Description: ${request.description}`,\n `// Trigger: ${request.trigger}`,\n `// Created: ${now}`,\n '',\n ].join('\\n');\n}\n\nfunction customDir(type: CapabilityType): string {\n const { DATA_DIR } = getConfig();\n const dir = join(DATA_DIR, `custom-${type}s`);\n mkdirSync(dir, { recursive: true });\n return dir;\n}\n\n// ---------------------------------------------------------------------------\n// Templates per capability type\n// ---------------------------------------------------------------------------\n\nfunction generateHook(request: GenerateRequest): string {\n return [\n header(request),\n `/**`,\n ` * Custom hook: ${request.name}`,\n ` * ${request.description}`,\n ` *`,\n ` * Trigger: ${request.trigger}`,\n ` * Original request: ${request.userRequest}`,\n ` *`,\n ` * Usage:`,\n ` * node custom-hooks/${sanitizeName(request.name)}.js`,\n ` */`,\n ``,\n `function main() {`,\n ` // Read input from stdin or environment if needed`,\n ` const input = process.env.HOOK_INPUT ?? '';`,\n ``,\n ` // TODO: Implement hook logic for \"${request.description}\"`,\n ` const result = {`,\n ` hook: '${request.name}',`,\n ` status: 'executed',`,\n ` input,`,\n ` timestamp: new Date().toISOString(),`,\n ` };`,\n ``,\n ` process.stdout.write(JSON.stringify(result));`,\n `}`,\n ``,\n `main();`,\n ``,\n ].join('\\n');\n}\n\nfunction generateSkill(request: GenerateRequest): string {\n return [\n header(request),\n `/**`,\n ` * Custom skill: ${request.name}`,\n ` * ${request.description}`,\n ` *`,\n ` * Trigger: ${request.trigger}`,\n ` * Original request: ${request.userRequest}`,\n ` */`,\n ``,\n `export function get${toPascalCase(request.name)}SkillPrompt(args) {`,\n ` const input = args?.trim() ?? '';`,\n ``,\n ` return [`,\n ` '<command-name>${request.name}</command-name>',`,\n ` '',`,\n ` '## ${request.name} Skill',`,\n ` '',`,\n ` '${request.description}',`,\n ` '',`,\n ` input ? \\`User input: \\${input}\\` : 'No input provided.',`,\n ` '',`,\n ` 'Instructions:',`,\n ` '1. Analyze the user request',`,\n ` '2. Perform the action described above',`,\n ` '3. Report the result to the user',`,\n ` ].join('\\\\n');`,\n `}`,\n ``,\n ].join('\\n');\n}\n\nfunction generateCommand(request: GenerateRequest): string {\n return [\n header(request),\n `/**`,\n ` * Custom command: ${request.name}`,\n ` * ${request.description}`,\n ` *`,\n ` * Trigger: ${request.trigger}`,\n ` * Original request: ${request.userRequest}`,\n ` *`,\n ` * Usage:`,\n ` * node custom-commands/${sanitizeName(request.name)}.js [action] [args...]`,\n ` */`,\n ``,\n `function main() {`,\n ` const args = process.argv.slice(2);`,\n ` const action = args[0] ?? 'default';`,\n ` const rest = args.slice(1);`,\n ``,\n ` const handlers = {`,\n ` default: () => ({`,\n ` command: '${request.name}',`,\n ` description: '${request.description}',`,\n ` usage: '${request.name}:action [args]',`,\n ` }),`,\n ` run: () => {`,\n ` // TODO: Implement the primary command action`,\n ` return {`,\n ` command: '${request.name}',`,\n ` action: 'run',`,\n ` args: rest,`,\n ` status: 'executed',`,\n ` timestamp: new Date().toISOString(),`,\n ` };`,\n ` },`,\n ` };`,\n ``,\n ` const handler = handlers[action] ?? handlers.default;`,\n ` const result = handler();`,\n ` process.stdout.write(JSON.stringify(result, null, 2));`,\n `}`,\n ``,\n `main();`,\n ``,\n ].join('\\n');\n}\n\nfunction generateAsset(request: GenerateRequest): string {\n // Assets can be JSON or Markdown. Default to JSON for configs, Markdown for docs.\n const isMarkdown =\n /template|guide|doc|readme|note/i.test(request.name) ||\n /template|guide|doc|readme|note/i.test(request.description);\n\n if (isMarkdown) {\n return [\n `<!-- Auto-generated by open-coleslaw extension system -->`,\n `<!-- Name: ${request.name} -->`,\n `<!-- Description: ${request.description} -->`,\n `<!-- Trigger: ${request.trigger} -->`,\n `<!-- Created: ${new Date().toISOString()} -->`,\n ``,\n `# ${request.name}`,\n ``,\n `${request.description}`,\n ``,\n `## Details`,\n ``,\n `> Original request: ${request.userRequest}`,\n ``,\n `<!-- TODO: Fill in content -->`,\n ``,\n ].join('\\n');\n }\n\n const data = {\n _meta: {\n generatedBy: 'open-coleslaw extension system',\n name: request.name,\n description: request.description,\n trigger: request.trigger,\n created: new Date().toISOString(),\n userRequest: request.userRequest,\n },\n config: {},\n };\n\n return JSON.stringify(data, null, 2) + '\\n';\n}\n\nfunction generateLoop(request: GenerateRequest): string {\n return [\n header(request),\n `/**`,\n ` * Custom loop: ${request.name}`,\n ` * ${request.description}`,\n ` *`,\n ` * Trigger: ${request.trigger}`,\n ` * Original request: ${request.userRequest}`,\n ` *`,\n ` * Usage:`,\n ` * node custom-loops/${sanitizeName(request.name)}.js`,\n ` */`,\n ``,\n `const INTERVAL_MS = 30000; // 30 seconds`,\n `const MAX_ITERATIONS = 100;`,\n ``,\n `async function check() {`,\n ` // TODO: Implement the condition check for \"${request.description}\"`,\n ` const result = {`,\n ` loop: '${request.name}',`,\n ` iteration: 0,`,\n ` timestamp: new Date().toISOString(),`,\n ` conditionMet: false,`,\n ` };`,\n ` return result;`,\n `}`,\n ``,\n `async function main() {`,\n ` let iteration = 0;`,\n ``,\n ` while (iteration < MAX_ITERATIONS) {`,\n ` iteration++;`,\n ` const result = await check();`,\n ` result.iteration = iteration;`,\n ``,\n ` process.stdout.write(JSON.stringify(result) + '\\\\n');`,\n ``,\n ` if (result.conditionMet) {`,\n ` process.stdout.write(JSON.stringify({`,\n ` loop: '${request.name}',`,\n ` status: 'completed',`,\n ` totalIterations: iteration,`,\n ` }) + '\\\\n');`,\n ` break;`,\n ` }`,\n ``,\n ` await new Promise((resolve) => setTimeout(resolve, INTERVAL_MS));`,\n ` }`,\n `}`,\n ``,\n `main().catch((err) => {`,\n ` process.stderr.write(String(err));`,\n ` process.exit(1);`,\n `});`,\n ``,\n ].join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction toPascalCase(str: string): string {\n return str\n .split(/[-_\\s]+/)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join('');\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Generate code for a new capability.\n *\n * Returns the file path where the code was written, the code itself,\n * and the registry entry to persist.\n */\nexport function generateCapability(request: GenerateRequest): GenerateResult {\n const safeName = sanitizeName(request.name);\n\n // Determine file extension based on type\n const isAssetMarkdown =\n request.type === 'asset' &&\n (/template|guide|doc|readme|note/i.test(request.name) ||\n /template|guide|doc|readme|note/i.test(request.description));\n\n let ext: string;\n if (request.type === 'asset') {\n ext = isAssetMarkdown ? '.md' : '.json';\n } else {\n ext = '.js';\n }\n\n const dir = customDir(request.type);\n const filePath = join(dir, `${safeName}${ext}`);\n\n // Generate the code\n let code: string;\n switch (request.type) {\n case 'hook':\n code = generateHook(request);\n break;\n case 'skill':\n code = generateSkill(request);\n break;\n case 'command':\n code = generateCommand(request);\n break;\n case 'asset':\n code = generateAsset(request);\n break;\n case 'loop':\n code = generateLoop(request);\n break;\n }\n\n // Write the file\n writeFileSync(filePath, code, 'utf-8');\n\n return {\n filePath,\n code,\n registryEntry: {\n type: request.type,\n name: request.name,\n description: request.description,\n trigger: request.trigger,\n isBuiltIn: false,\n filePath,\n },\n };\n}\n","/**\n * guide-updater.ts — Updates plugin-guide.md and rules.md when capabilities change.\n *\n * Regenerates plugin-guide.md with the current set of capabilities.\n * For rules.md, only appends custom rules — never removes base rules.\n */\n\nimport { readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { getConfig } from '../utils/config.js';\nimport type { CapabilityRegistry } from './capability-registry.js';\n\n// ---------------------------------------------------------------------------\n// Plugin guide\n// ---------------------------------------------------------------------------\n\n/**\n * Regenerate plugin-guide.md with the current set of registered capabilities.\n *\n * The guide is written to ~/.open-coleslaw/plugin-guide.md where the pre-read\n * hook picks it up.\n */\nexport async function updatePluginGuide(\n registry: CapabilityRegistry,\n): Promise<void> {\n const { DATA_DIR } = getConfig();\n const guidePath = join(DATA_DIR, 'plugin-guide.md');\n\n const capSection = registry.formatForGuide();\n\n const guide = [\n '# Open-Coleslaw Plugin Guide',\n '',\n '## Overview',\n 'Multi-agent orchestrator for Claude Code. Hierarchical agent system:',\n 'Orchestrator (proxy) -> Part Leaders (team leads) -> Workers (executors)',\n '',\n '## Registered Capabilities',\n '',\n capSection,\n '',\n '## Agent Tiers',\n '| Tier | Model | Role |',\n '|------|-------|------|',\n '| Orchestrator | claude-opus-4-6 (1M) | Full-picture routing, delegation |',\n '| Leader | claude-sonnet-4-6 | Meetings, technical decisions |',\n '| Worker (impl) | claude-sonnet-4-6 | Code, implementation |',\n '| Worker (research) | claude-haiku-4-5 | Quick lookups |',\n '',\n '## Departments',\n '- Architecture: system design, API, schema',\n '- Engineering: implementation, code quality',\n '- QA: testing, security, performance',\n '- Product: requirements, user stories',\n '- Research: codebase exploration, docs',\n '',\n '## Meeting Minutes',\n 'Saved to: ~/.open-coleslaw/minutes/',\n 'Index: ~/.open-coleslaw/minutes/INDEX.md',\n 'Format: PRD with frontmatter metadata + tags',\n '',\n '## Extension System',\n 'Custom capabilities are stored in ~/.open-coleslaw/custom-{type}s/.',\n 'Use the `create-capability` MCP tool to add new hooks, skills, commands, assets, or loops.',\n 'Registry: ~/.open-coleslaw/registry.json',\n '',\n ].join('\\n');\n\n writeFileSync(guidePath, guide, 'utf-8');\n}\n\n// ---------------------------------------------------------------------------\n// Rules\n// ---------------------------------------------------------------------------\n\n/** Sentinel that marks the beginning of the custom-rules block. */\nconst CUSTOM_RULES_START = '## Custom Rules';\nconst CUSTOM_RULES_END = '<!-- /custom-rules -->';\n\n/**\n * Append custom rules to rules.md without removing any base rules.\n *\n * Custom rules are bracketed between a `## Custom Rules` heading and\n * a closing HTML comment so they can be cleanly replaced on subsequent calls.\n */\nexport async function updateRulesIfNeeded(\n customRules: string[],\n): Promise<void> {\n if (customRules.length === 0) return;\n\n const { DATA_DIR } = getConfig();\n const rulesPath = join(DATA_DIR, 'rules.md');\n\n let existing: string;\n try {\n existing = readFileSync(rulesPath, 'utf-8');\n } catch {\n // If no rules.md yet, start from an empty document\n existing = '';\n }\n\n // Strip any previous custom-rules block\n const startIdx = existing.indexOf(CUSTOM_RULES_START);\n const endIdx = existing.indexOf(CUSTOM_RULES_END);\n let base: string;\n if (startIdx !== -1 && endIdx !== -1) {\n base =\n existing.slice(0, startIdx).trimEnd() +\n '\\n' +\n existing.slice(endIdx + CUSTOM_RULES_END.length).trimStart();\n } else if (startIdx !== -1) {\n base = existing.slice(0, startIdx).trimEnd();\n } else {\n base = existing;\n }\n\n // Build the new custom-rules section\n const rulesBlock = [\n '',\n CUSTOM_RULES_START,\n ...customRules.map((r) => `- ${r}`),\n CUSTOM_RULES_END,\n ].join('\\n');\n\n const updated = base.trimEnd() + '\\n' + rulesBlock + '\\n';\n writeFileSync(rulesPath, updated, 'utf-8');\n}\n","/**\n * extension-manager.ts — Top-level orchestrator for the extension system.\n *\n * Coordinates the CapabilityRegistry, code generator, and guide updater\n * so that the rest of the system has a single entry-point for extension\n * operations.\n */\n\nimport { CapabilityRegistry } from './capability-registry.js';\nimport type {\n CapabilityType,\n Capability,\n} from './capability-registry.js';\nimport { generateCapability } from './generator.js';\nimport type { GenerateRequest } from './generator.js';\nimport { updatePluginGuide } from './guide-updater.js';\n\n// ---------------------------------------------------------------------------\n// Analysis result\n// ---------------------------------------------------------------------------\n\nexport interface AnalysisResult {\n needsNewCapability: boolean;\n suggestedType?: CapabilityType;\n suggestedName?: string;\n suggestedDescription?: string;\n suggestedTrigger?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Creation result\n// ---------------------------------------------------------------------------\n\nexport interface CreateResult {\n capability: Capability;\n filePath: string;\n summary: string;\n}\n\n// ---------------------------------------------------------------------------\n// Keyword patterns for request analysis\n// ---------------------------------------------------------------------------\n\ninterface KeywordRule {\n type: CapabilityType;\n patterns: RegExp[];\n}\n\nconst KEYWORD_RULES: KeywordRule[] = [\n {\n type: 'hook',\n patterns: [\n /\\bevery\\s+time\\b/i,\n /\\balways\\b/i,\n /\\bbefore\\s+\\w+/i,\n /\\bafter\\s+\\w+/i,\n /\\bwhen\\s+\\w+/i,\n /\\bon\\s+(every|each)\\b/i,\n ],\n },\n {\n type: 'skill',\n patterns: [\n /\\/\\w+/,\n /\\bslash\\s+command\\b/i,\n /\\bshortcut\\b/i,\n /\\bskill\\b/i,\n ],\n },\n {\n type: 'asset',\n patterns: [\n /\\btemplate\\b/i,\n /\\bconfig\\b/i,\n /\\bsettings\\b/i,\n /\\bconfiguration\\b/i,\n ],\n },\n {\n type: 'loop',\n patterns: [\n /\\bcheck\\s+every\\b/i,\n /\\bpoll\\b/i,\n /\\bwatch\\b/i,\n /\\bmonitor\\b/i,\n /\\brepeatedly\\b/i,\n /\\bperiodically\\b/i,\n ],\n },\n];\n\n// ---------------------------------------------------------------------------\n// ExtensionManager\n// ---------------------------------------------------------------------------\n\nexport class ExtensionManager {\n private registry: CapabilityRegistry;\n\n constructor() {\n this.registry = new CapabilityRegistry();\n }\n\n /**\n * Initialize: load the registry from disk.\n */\n async init(): Promise<void> {\n await this.registry.loadAll();\n }\n\n /**\n * Analyze a user request to decide whether a new capability is needed.\n *\n * Uses keyword matching to suggest the capability type. Returns\n * `needsNewCapability: false` when the request matches an existing\n * capability name.\n */\n async analyzeRequest(request: string): Promise<AnalysisResult> {\n // If a capability with a matching name already exists, no creation needed\n const normalized = request.toLowerCase().trim();\n\n for (const cap of await this.registry.loadAll()) {\n if (normalized.includes(cap.name.toLowerCase())) {\n return { needsNewCapability: false };\n }\n }\n\n // Try to match keyword rules\n for (const rule of KEYWORD_RULES) {\n for (const pattern of rule.patterns) {\n if (pattern.test(request)) {\n const nameCandidate = extractName(request);\n return {\n needsNewCapability: true,\n suggestedType: rule.type,\n suggestedName: nameCandidate,\n suggestedDescription: request.slice(0, 120),\n suggestedTrigger: extractTrigger(request, rule.type),\n };\n }\n }\n }\n\n // Default: treat as a generic command\n return {\n needsNewCapability: true,\n suggestedType: 'command',\n suggestedName: extractName(request),\n suggestedDescription: request.slice(0, 120),\n suggestedTrigger: 'On user invocation',\n };\n }\n\n /**\n * Create a new capability, persist it, and update the plugin guide.\n */\n async createCapability(request: GenerateRequest): Promise<CreateResult> {\n // Generate the code file\n const result = generateCapability(request);\n\n // Register in the capability registry\n await this.registry.register(result.registryEntry);\n\n // Refresh the plugin guide so pre-read picks it up\n await updatePluginGuide(this.registry);\n\n // Build the full Capability object to return\n const capability: Capability = {\n ...result.registryEntry,\n createdAt: Date.now(),\n };\n\n const summary =\n `Created ${request.type} \"${request.name}\": ${request.description}. ` +\n `File: ${result.filePath}`;\n\n return { capability, filePath: result.filePath, summary };\n }\n\n /**\n * List all capabilities (built-in + custom).\n */\n async listCapabilities(): Promise<Capability[]> {\n return this.registry.loadAll();\n }\n\n /**\n * Remove a custom capability by name.\n *\n * Built-in capabilities cannot be removed.\n */\n async removeCapability(name: string): Promise<void> {\n const cap = this.registry.findByName(name);\n if (!cap) {\n throw new Error(`Capability not found: ${name}`);\n }\n if (cap.isBuiltIn) {\n throw new Error(`Cannot remove built-in capability: ${name}`);\n }\n\n await this.registry.unregister(cap.type, name);\n\n // Refresh the plugin guide\n await updatePluginGuide(this.registry);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Extract a reasonable short name from a user request string.\n */\nfunction extractName(request: string): string {\n // Try to pull out a slash-command name like /foo\n const slashMatch = request.match(/\\/(\\w[\\w-]*)/);\n if (slashMatch) return slashMatch[1];\n\n // Otherwise, take the first few meaningful words\n const words = request\n .replace(/[^a-zA-Z0-9\\s-]/g, '')\n .split(/\\s+/)\n .filter((w) => w.length > 2)\n .slice(0, 3);\n\n return words.join('-').toLowerCase() || 'unnamed';\n}\n\n/**\n * Generate a trigger description from the request and inferred type.\n */\nfunction extractTrigger(request: string, type: CapabilityType): string {\n switch (type) {\n case 'hook': {\n const beforeMatch = request.match(/before\\s+(\\w[\\w\\s]{0,30})/i);\n if (beforeMatch) return `Before ${beforeMatch[1].trim()}`;\n const afterMatch = request.match(/after\\s+(\\w[\\w\\s]{0,30})/i);\n if (afterMatch) return `After ${afterMatch[1].trim()}`;\n const whenMatch = request.match(/when\\s+(\\w[\\w\\s]{0,30})/i);\n if (whenMatch) return `When ${whenMatch[1].trim()}`;\n return 'On configured trigger';\n }\n case 'skill':\n return `/${extractName(request)}`;\n case 'loop': {\n const everyMatch = request.match(/every\\s+([\\w\\s]+)/i);\n if (everyMatch) return `Every ${everyMatch[1].trim()}`;\n return 'On interval';\n }\n case 'asset':\n return 'When referenced';\n case 'command':\n return 'On user invocation';\n }\n}\n","import { z } from 'zod';\nimport { costTracker } from '../utils/cost-tracker.js';\n\nexport const getCostSummarySchema = {\n meetingId: z.string().optional().describe('Optional meeting ID to filter costs'),\n};\n\nexport async function getCostSummaryHandler({\n meetingId,\n}: {\n meetingId?: string;\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const summary = costTracker.getSummary(meetingId);\n const budgetWarning = costTracker.checkBudget();\n\n const result: Record<string, unknown> = {\n ...summary,\n };\n\n if (budgetWarning) {\n result.budgetWarning = budgetWarning;\n }\n\n if (meetingId) {\n result.filteredByMeeting = meetingId;\n }\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import { getDb } from '../storage/db.js';\n\n// ---------------------------------------------------------------------------\n// Cost summary\n// ---------------------------------------------------------------------------\n\nexport interface CostSummary {\n totalUsd: number;\n byMeeting: Record<string, number>;\n byDepartment: Record<string, number>;\n byTier: Record<string, number>;\n budgetLimit: number | null;\n budgetRemaining: number | null;\n}\n\n// ---------------------------------------------------------------------------\n// In-memory cost entry\n// ---------------------------------------------------------------------------\n\ninterface CostEntry {\n agentId: string;\n meetingId: string;\n costUsd: number;\n recordedAt: number;\n}\n\n// ---------------------------------------------------------------------------\n// CostTracker\n// ---------------------------------------------------------------------------\n\nexport class CostTracker {\n private budgetLimitUsd: number | null = null;\n private entries: CostEntry[] = [];\n\n /** Set a budget limit in USD. */\n setBudget(limitUsd: number): void {\n this.budgetLimitUsd = limitUsd;\n }\n\n /** Record a cost for an agent action. */\n recordCost(agentId: string, meetingId: string, costUsd: number): void {\n this.entries.push({\n agentId,\n meetingId,\n costUsd,\n recordedAt: Date.now(),\n });\n }\n\n /** Get the current cost summary, combining in-memory entries with DB data. */\n getSummary(meetingId?: string): CostSummary {\n const byMeeting: Record<string, number> = {};\n const byDepartment: Record<string, number> = {};\n const byTier: Record<string, number> = {};\n let totalUsd = 0;\n\n // 1. Aggregate from the agents table in the DB\n try {\n const db = getDb();\n\n interface AgentCostRow {\n meeting_id: string | null;\n department: string;\n tier: string;\n cost_usd: number;\n }\n\n let agentRows: AgentCostRow[];\n if (meetingId) {\n agentRows = db\n .prepare('SELECT meeting_id, department, tier, cost_usd FROM agents WHERE meeting_id = ?')\n .all(meetingId) as AgentCostRow[];\n } else {\n agentRows = db\n .prepare('SELECT meeting_id, department, tier, cost_usd FROM agents')\n .all() as AgentCostRow[];\n }\n\n for (const row of agentRows) {\n const cost = row.cost_usd ?? 0;\n if (cost === 0) continue;\n\n totalUsd += cost;\n const mid = row.meeting_id ?? 'unknown';\n byMeeting[mid] = (byMeeting[mid] ?? 0) + cost;\n byDepartment[row.department] = (byDepartment[row.department] ?? 0) + cost;\n byTier[row.tier] = (byTier[row.tier] ?? 0) + cost;\n }\n\n // 2. Aggregate from the workers table\n interface WorkerCostRow {\n meeting_id: string;\n cost_usd: number;\n leader_id: string;\n }\n\n let workerRows: WorkerCostRow[];\n if (meetingId) {\n workerRows = db\n .prepare('SELECT meeting_id, cost_usd, leader_id FROM workers WHERE meeting_id = ?')\n .all(meetingId) as WorkerCostRow[];\n } else {\n workerRows = db\n .prepare('SELECT meeting_id, cost_usd, leader_id FROM workers')\n .all() as WorkerCostRow[];\n }\n\n for (const row of workerRows) {\n const cost = row.cost_usd ?? 0;\n if (cost === 0) continue;\n\n totalUsd += cost;\n byMeeting[row.meeting_id] = (byMeeting[row.meeting_id] ?? 0) + cost;\n byTier['worker'] = (byTier['worker'] ?? 0) + cost;\n\n // Look up the leader's department for the worker\n interface LeaderDeptRow { department: string }\n const leader = db\n .prepare('SELECT department FROM agents WHERE id = ?')\n .get(row.leader_id) as LeaderDeptRow | undefined;\n if (leader) {\n byDepartment[leader.department] = (byDepartment[leader.department] ?? 0) + cost;\n }\n }\n } catch {\n // DB might not be initialised yet; fall through to in-memory only\n }\n\n // 3. Aggregate in-memory entries\n const filteredEntries = meetingId\n ? this.entries.filter((e) => e.meetingId === meetingId)\n : this.entries;\n\n for (const entry of filteredEntries) {\n totalUsd += entry.costUsd;\n byMeeting[entry.meetingId] = (byMeeting[entry.meetingId] ?? 0) + entry.costUsd;\n }\n\n return {\n totalUsd,\n byMeeting,\n byDepartment,\n byTier,\n budgetLimit: this.budgetLimitUsd,\n budgetRemaining: this.budgetLimitUsd !== null ? this.budgetLimitUsd - totalUsd : null,\n };\n }\n\n /** Check if over budget. Returns a warning message or null. */\n checkBudget(): string | null {\n if (this.budgetLimitUsd === null) return null;\n\n const summary = this.getSummary();\n if (summary.totalUsd >= this.budgetLimitUsd) {\n return `Budget exceeded: $${summary.totalUsd.toFixed(4)} spent of $${this.budgetLimitUsd.toFixed(4)} limit`;\n }\n\n const remaining = this.budgetLimitUsd - summary.totalUsd;\n if (remaining < this.budgetLimitUsd * 0.1) {\n return `Budget warning: $${summary.totalUsd.toFixed(4)} spent, only $${remaining.toFixed(4)} remaining of $${this.budgetLimitUsd.toFixed(4)} limit`;\n }\n\n return null;\n }\n}\n\n/** Shared singleton instance. */\nexport const costTracker = new CostTracker();\n","import { z } from 'zod';\nimport { Orchestrator } from '../orchestrator/orchestrator.js';\nimport type { Department } from '../types/index.js';\n\nexport const chainMeetingSchema = {\n previousMeetingId: z.string().describe('ID of the previous meeting to chain from'),\n topic: z.string().describe('Topic for the new chained meeting'),\n agenda: z.array(z.string()).describe('Agenda items for the new meeting'),\n departments: z\n .array(z.string())\n .optional()\n .describe('Specific departments to invite'),\n};\n\nexport async function chainMeetingHandler({\n previousMeetingId,\n topic,\n agenda,\n departments,\n}: {\n previousMeetingId: string;\n topic: string;\n agenda: string[];\n departments?: string[];\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const orchestrator = new Orchestrator();\n const result = orchestrator.chainMeeting({\n previousMeetingId,\n topic,\n agenda,\n departments: departments as Department[] | undefined,\n });\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import { z } from 'zod';\nimport { MeetingRunner } from '../orchestrator/meeting-runner.js';\n\nexport const addTranscriptSchema = {\n meetingId: z.string().describe('Meeting ID'),\n speakerRole: z.string().describe('Role of the speaker (e.g. \"Architecture Lead\", \"Engineering Lead\")'),\n agendaItemIndex: z\n .number()\n .describe('Agenda item index (0-based). Use -1 for opening statements, -2 for synthesis'),\n roundNumber: z.number().describe('Discussion round number (0 for opening/synthesis)'),\n content: z.string().describe('The transcript content from the speaker'),\n};\n\nexport async function addTranscriptHandler({\n meetingId,\n speakerRole,\n agendaItemIndex,\n roundNumber,\n content,\n}: {\n meetingId: string;\n speakerRole: string;\n agendaItemIndex: number;\n roundNumber: number;\n content: string;\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const runner = new MeetingRunner(meetingId);\n const entry = runner.addTranscript(speakerRole, agendaItemIndex, roundNumber, content);\n\n const result = {\n success: true,\n entryId: entry.id,\n meetingId,\n speakerRole,\n agendaItemIndex,\n roundNumber,\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import type {\n TranscriptEntry,\n MeetingStatus,\n MeetingPhase,\n ActionItem,\n} from '../types/index.js';\nimport {\n getMeeting,\n updateMeeting,\n createMinutes,\n getMinutesByMeeting,\n} from '../storage/index.js';\nimport { getDb } from '../storage/db.js';\nimport { logger } from '../utils/logger.js';\n\n// ---------------------------------------------------------------------------\n// Transcript helpers (direct DB access since there is no transcript store)\n// ---------------------------------------------------------------------------\n\nfunction insertTranscriptEntry(\n meetingId: string,\n speakerId: string,\n speakerRole: string,\n agendaItemIndex: number,\n roundNumber: number,\n content: string,\n): TranscriptEntry {\n const db = getDb();\n const now = Date.now();\n const tokenCount = Math.ceil(content.length / 4); // rough approximation\n\n const result = db\n .prepare(\n `INSERT INTO transcript_entries\n (meeting_id, speaker_id, speaker_role, agenda_item_index, round_number, content, token_count, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(meetingId, speakerId, speakerRole, agendaItemIndex, roundNumber, content, tokenCount, now);\n\n return {\n id: Number(result.lastInsertRowid),\n meetingId,\n speakerId,\n speakerRole,\n agendaItemIndex,\n roundNumber,\n content,\n tokenCount,\n createdAt: now,\n };\n}\n\nfunction getTranscript(meetingId: string): TranscriptEntry[] {\n const db = getDb();\n interface TranscriptRow {\n id: number;\n meeting_id: string;\n speaker_id: string;\n speaker_role: string;\n agenda_item_index: number;\n round_number: number;\n content: string;\n token_count: number;\n created_at: number;\n }\n const rows = db\n .prepare('SELECT * FROM transcript_entries WHERE meeting_id = ? ORDER BY created_at ASC')\n .all(meetingId) as TranscriptRow[];\n\n return rows.map((r) => ({\n id: r.id,\n meetingId: r.meeting_id,\n speakerId: r.speaker_id,\n speakerRole: r.speaker_role,\n agendaItemIndex: r.agenda_item_index,\n roundNumber: r.round_number,\n content: r.content,\n tokenCount: r.token_count,\n createdAt: r.created_at,\n }));\n}\n\n// ---------------------------------------------------------------------------\n// MeetingRunner — data-only utility (no agent invocation)\n//\n// Stores transcript entries and generates minutes from stored transcripts.\n// Actual agent dispatch is handled by Claude Code's Agent tool, orchestrated\n// by skill/agent markdown files.\n// ---------------------------------------------------------------------------\n\nexport class MeetingRunner {\n private readonly meetingId: string;\n\n constructor(meetingId: string) {\n this.meetingId = meetingId;\n }\n\n // ---- Add transcript entry (called by MCP tool add-transcript) -----------\n\n /**\n * Add a transcript entry for this meeting.\n * Returns the created TranscriptEntry.\n */\n addTranscript(\n speakerRole: string,\n agendaItemIndex: number,\n roundNumber: number,\n content: string,\n ): TranscriptEntry {\n const meeting = getMeeting(this.meetingId);\n if (!meeting) {\n throw new Error(`Meeting not found: ${this.meetingId}`);\n }\n\n // Use speakerRole as speakerId since we no longer manage agent nodes here\n const entry = insertTranscriptEntry(\n this.meetingId,\n speakerRole,\n speakerRole,\n agendaItemIndex,\n roundNumber,\n content,\n );\n\n logger.debug(`Transcript added: ${speakerRole} (item ${agendaItemIndex}, round ${roundNumber})`, {\n meetingId: this.meetingId,\n });\n\n return entry;\n }\n\n // ---- Generate minutes from all transcripts ------------------------------\n\n /**\n * Generate meeting minutes by formatting all stored transcript entries.\n * Returns the minutesId of the created minutes record.\n */\n async generateMinutes(): Promise<string> {\n const meeting = getMeeting(this.meetingId);\n if (!meeting) {\n throw new Error(`Meeting not found: ${this.meetingId}`);\n }\n\n // Update phase\n updateMeeting(this.meetingId, {\n phase: 'minutes-generation' as MeetingPhase,\n status: 'minutes-generation' as MeetingStatus,\n });\n\n const transcript = getTranscript(this.meetingId);\n\n // --- Build the minutes content ---\n\n const sections: string[] = [];\n\n // Collect unique speaker roles from transcript\n const speakerRoles = [...new Set(transcript.map((e) => e.speakerRole))];\n\n sections.push(`# Meeting Minutes`);\n sections.push(`## Topic: ${meeting.topic}`);\n sections.push(`## Date: ${new Date().toISOString()}`);\n sections.push(`## Participants: ${speakerRoles.join(', ')}`);\n sections.push('');\n\n // Agenda\n sections.push(`## Agenda`);\n meeting.agenda.forEach((item, i) => {\n sections.push(`${i + 1}. ${item}`);\n });\n sections.push('');\n\n // Opening statements\n const openingEntries = transcript.filter((e) => e.agendaItemIndex === -1);\n if (openingEntries.length > 0) {\n sections.push(`## Opening Statements`);\n for (const entry of openingEntries) {\n sections.push(`### ${entry.speakerRole}`);\n sections.push(entry.content);\n sections.push('');\n }\n }\n\n // Discussion per agenda item\n for (let i = 0; i < meeting.agenda.length; i++) {\n const itemEntries = transcript.filter((e) => e.agendaItemIndex === i);\n if (itemEntries.length > 0) {\n sections.push(`## Discussion: ${meeting.agenda[i]}`);\n for (const entry of itemEntries) {\n sections.push(`**${entry.speakerRole}** (round ${entry.roundNumber}):`);\n sections.push(entry.content);\n sections.push('');\n }\n }\n }\n\n // Synthesis\n const synthesisEntries = transcript.filter((e) => e.agendaItemIndex === -2);\n if (synthesisEntries.length > 0) {\n sections.push(`## Final Positions`);\n for (const entry of synthesisEntries) {\n sections.push(`### ${entry.speakerRole}`);\n sections.push(entry.content);\n sections.push('');\n }\n }\n\n const content = sections.join('\\n');\n\n // --- Extract action items from synthesis entries ---\n\n const actionItems: ActionItem[] = speakerRoles.map((role, idx) => ({\n id: `action-${this.meetingId}-${idx}`,\n title: `${role} deliverables`,\n description: `Action items committed by ${role} during synthesis phase`,\n assignedDepartment: 'engineering', // default; will be refined by compactor\n assignedRole: role,\n priority: 'medium' as const,\n dependencies: [],\n acceptanceCriteria: ['Deliverables completed as stated in final position'],\n }));\n\n const minutesRecord = createMinutes({\n meetingId: this.meetingId,\n format: 'summary',\n content,\n actionItems,\n });\n\n // Mark meeting as completed\n updateMeeting(this.meetingId, {\n status: 'completed' as MeetingStatus,\n completedAt: Date.now(),\n });\n\n logger.info('Minutes generated', { meetingId: this.meetingId });\n\n return minutesRecord.id;\n }\n\n // ---- Completion status --------------------------------------------------\n\n /**\n * Check whether the meeting has been completed (minutes generated).\n */\n isComplete(): boolean {\n const meeting = getMeeting(this.meetingId);\n if (!meeting) return false;\n return ['completed', 'compacted', 'reported'].includes(meeting.status);\n }\n\n // ---- Transcript access --------------------------------------------------\n\n /**\n * Get all transcript entries for this meeting.\n */\n getTranscript(): TranscriptEntry[] {\n return getTranscript(this.meetingId);\n }\n}\n","import { z } from 'zod';\nimport { MeetingRunner } from '../orchestrator/meeting-runner.js';\nimport { getMinutesByMeeting } from '../storage/index.js';\n\nexport const generateMinutesSchema = {\n meetingId: z.string().describe('Meeting ID to generate minutes for'),\n};\n\nexport async function generateMinutesHandler({\n meetingId,\n}: {\n meetingId: string;\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const runner = new MeetingRunner(meetingId);\n const minutesId = await runner.generateMinutes();\n\n // Fetch the generated minutes to include the content\n const minutes = getMinutesByMeeting(meetingId);\n\n const result = {\n minutesId,\n meetingId,\n content: minutes?.content ?? '',\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import { createServer as createHttpServer } from 'node:http';\nimport { WebSocketServer, WebSocket } from 'ws';\nimport { getDashboardHTML } from './html.js';\nimport { StateBridge } from './state-bridge.js';\nimport { DashboardClient } from './client.js';\nimport { eventBus } from '../orchestrator/event-bus.js';\nimport { getConfig } from '../utils/config.js';\nimport { logger } from '../utils/logger.js';\nimport type { AgentEvent, ServerMessage } from '../types/dashboard-events.js';\n\nexport interface DashboardHandle {\n isOwner: boolean;\n close: () => void;\n}\n\nexport interface DashboardOptions {\n sessionId: string;\n projectPath: string;\n projectName: string;\n}\n\nexport function startDashboard(options: DashboardOptions): Promise<DashboardHandle> {\n const port = getConfig().DASHBOARD_PORT;\n\n return new Promise((resolve) => {\n const httpServer = createHttpServer((req, res) => {\n if (req.url === '/' || req.url === '/index.html') {\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(getDashboardHTML());\n } else {\n res.writeHead(404);\n res.end('Not Found');\n }\n });\n\n httpServer.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n // Port in use — become a client\n logger.info(`Dashboard port ${port} in use — connecting as client`);\n const client = new DashboardClient(options.sessionId, options.projectName, options.projectPath);\n client.connect(port);\n resolve({\n isOwner: false,\n close: () => client.disconnect(),\n });\n } else {\n logger.error(`Dashboard error: ${err.message}`);\n resolve({ isOwner: false, close: () => {} });\n }\n });\n\n httpServer.listen(port, '127.0.0.1', () => {\n logger.info(`Dashboard owner — running at http://localhost:${port}`);\n\n const wss = new WebSocketServer({ server: httpServer });\n const bridge = new StateBridge();\n\n // Register own session\n const displayName = bridge.registerSession({\n sessionId: options.sessionId,\n projectPath: options.projectPath,\n projectName: options.projectName,\n });\n logger.info(`Registered own session: ${displayName}`);\n\n // Forward local events to bridge\n eventBus.on('agent_event', (event: AgentEvent) => {\n bridge.handleSessionEvent(options.sessionId, event);\n });\n\n // Handle browser clients + MCP server clients\n wss.on('connection', (ws: WebSocket) => {\n // Send full snapshot\n ws.send(JSON.stringify(bridge.getSnapshot()));\n\n ws.on('message', (data: Buffer) => {\n try {\n const msg: ServerMessage = JSON.parse(data.toString());\n\n if (msg.type === 'register') {\n const name = bridge.registerSession({\n sessionId: msg.sessionId,\n projectPath: msg.projectPath,\n projectName: msg.projectName,\n });\n // Notify all browser clients\n const notification = JSON.stringify({\n type: 'session-registered',\n sessionId: msg.sessionId,\n displayName: name,\n projectPath: msg.projectPath,\n });\n wss.clients.forEach((c) => {\n if (c !== ws && c.readyState === WebSocket.OPEN) c.send(notification);\n });\n } else if (msg.type === 'session-event') {\n bridge.handleSessionEvent(msg.sessionId, msg.event);\n } else if (msg.type === 'unregister') {\n bridge.unregisterSession(msg.sessionId);\n const notification = JSON.stringify({\n type: 'session-unregistered',\n sessionId: msg.sessionId,\n });\n wss.clients.forEach((c) => {\n if (c.readyState === WebSocket.OPEN) c.send(notification);\n });\n } else if ((msg as any).type === 'ping') {\n ws.send(JSON.stringify({ type: 'pong' }));\n }\n } catch {\n // ignore malformed\n }\n });\n });\n\n // Broadcast deltas to all browser clients\n bridge.on('broadcast', (data: string) => {\n wss.clients.forEach((c) => {\n if (c.readyState === WebSocket.OPEN) c.send(data);\n });\n });\n\n resolve({\n isOwner: true,\n close: () => {\n bridge.unregisterSession(options.sessionId);\n wss.close();\n httpServer.close();\n },\n });\n });\n });\n}\n","/**\n * getDashboardHTML() — returns the full inline HTML/CSS/JS for the Open Coleslaw\n * real-time dashboard. Everything is self-contained; the only external deps are\n * Cytoscape.js + dagre loaded from CDN.\n *\n * Multi-session aware: one tab per project session in the tab bar.\n */\n\nexport function getDashboardHTML(): string {\n return /* html */ `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n<title>Open Coleslaw Dashboard</title>\n\n<!-- CDN deps -->\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.30.4/cytoscape.min.js\"></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/dagre/0.8.5/dagre.min.js\"></script>\n<script src=\"https://unpkg.com/cytoscape-dagre@2.5.0/cytoscape-dagre.js\"></script>\n\n<!-- Google Fonts: JetBrains Mono -->\n<link rel=\"preconnect\" href=\"https://fonts.googleapis.com\" />\n<link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin />\n<link href=\"https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500;600;700&display=swap\" rel=\"stylesheet\" />\n\n<style>\n/* ===================================================================\n RESET & VARIABLES\n =================================================================== */\n*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\n\n:root {\n --bg: #0a0e17;\n --surface: #111827;\n --border: #1e293b;\n --cyan: #00f0ff;\n --purple: #a855f7;\n --lightcyan: #22d3ee;\n --success: #10b981;\n --warning: #f59e0b;\n --error: #ef4444;\n --text: #e2e8f0;\n --text2: #94a3b8;\n --font: 'JetBrains Mono', 'Fira Code', monospace;\n}\n\nhtml, body {\n width: 100%; height: 100%;\n overflow: hidden;\n background: var(--bg);\n color: var(--text);\n font-family: var(--font);\n font-size: 13px;\n line-height: 1.5;\n}\n\n/* ===================================================================\n LAYOUT — five areas via CSS Grid\n =================================================================== */\n#app {\n display: grid;\n width: 100%; height: 100%;\n grid-template-rows: 48px 36px 1fr 200px;\n grid-template-columns: 1fr 320px;\n grid-template-areas:\n \"header header\"\n \"tabs tabs\"\n \"graph sidebar\"\n \"log log\";\n}\n\n/* ===================================================================\n HEADER\n =================================================================== */\n#header {\n grid-area: header;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0 20px;\n background: var(--surface);\n border-bottom: 1px solid var(--border);\n gap: 16px;\n z-index: 10;\n}\n\n#header .brand {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 16px;\n font-weight: 700;\n color: var(--cyan);\n text-shadow: 0 0 12px rgba(0,240,255,0.5);\n white-space: nowrap;\n}\n\n#header .center-status {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n}\n\n.conn-dot {\n width: 10px; height: 10px;\n border-radius: 50%;\n background: var(--error);\n transition: background 0.3s;\n box-shadow: 0 0 6px rgba(239,68,68,0.6);\n}\n.conn-dot.connected {\n background: var(--success);\n box-shadow: 0 0 6px rgba(16,185,129,0.6);\n}\n.conn-dot.reconnecting {\n background: var(--warning);\n box-shadow: 0 0 6px rgba(245,158,11,0.6);\n animation: breathe 1.5s ease-in-out infinite;\n}\n\n#header .right-stats {\n display: flex;\n align-items: center;\n gap: 14px;\n font-size: 12px;\n}\n\n.badge {\n background: rgba(0,240,255,0.1);\n border: 1px solid rgba(0,240,255,0.25);\n padding: 2px 10px;\n border-radius: 12px;\n font-size: 11px;\n white-space: nowrap;\n}\n.badge.purple { background: rgba(168,85,247,0.1); border-color: rgba(168,85,247,0.3); }\n.badge.amber { background: rgba(245,158,11,0.1); border-color: rgba(245,158,11,0.3); color: var(--warning); }\n.badge.green { background: rgba(16,185,129,0.1); border-color: rgba(16,185,129,0.3); color: var(--success); }\n\n/* ===================================================================\n TAB BAR\n =================================================================== */\n#tab-bar {\n grid-area: tabs;\n display: flex;\n align-items: stretch;\n background: var(--surface);\n border-bottom: 1px solid var(--border);\n padding: 0 12px;\n gap: 2px;\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none;\n}\n#tab-bar::-webkit-scrollbar { display: none; }\n\n.session-tab {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 0 14px;\n font-size: 11px;\n font-family: var(--font);\n font-weight: 500;\n color: var(--text2);\n background: transparent;\n border: none;\n border-bottom: 2px solid transparent;\n cursor: pointer;\n white-space: nowrap;\n transition: color 0.2s, border-color 0.2s, opacity 0.2s;\n position: relative;\n}\n.session-tab:hover {\n color: var(--text);\n background: rgba(255,255,255,0.02);\n}\n.session-tab.active {\n color: var(--cyan);\n border-bottom-color: var(--cyan);\n text-shadow: 0 0 8px rgba(0,240,255,0.4);\n}\n.session-tab.inactive {\n opacity: 0.45;\n text-decoration: line-through;\n color: var(--text2);\n}\n.session-tab.inactive:hover {\n opacity: 0.6;\n}\n\n.tab-badge {\n font-size: 9px;\n padding: 1px 5px;\n border-radius: 8px;\n background: rgba(0,240,255,0.15);\n color: var(--cyan);\n font-weight: 700;\n min-width: 16px;\n text-align: center;\n}\n.tab-badge.meeting {\n background: rgba(245,158,11,0.2);\n color: var(--warning);\n}\n\n.tab-empty-msg {\n display: flex;\n align-items: center;\n font-size: 11px;\n color: var(--text2);\n font-style: italic;\n padding: 0 8px;\n}\n\n/* ===================================================================\n GRAPH VIEWPORT\n =================================================================== */\n#graph-container {\n grid-area: graph;\n background: var(--bg);\n position: relative;\n overflow: hidden;\n}\n#cy {\n width: 100%; height: 100%;\n}\n/* watermark text */\n#graph-container::after {\n content: 'AGENT GRAPH';\n position: absolute;\n bottom: 12px; left: 16px;\n font-size: 10px;\n color: rgba(148,163,184,0.25);\n letter-spacing: 3px;\n pointer-events: none;\n}\n\n/* ===================================================================\n SIDEBAR\n =================================================================== */\n#sidebar {\n grid-area: sidebar;\n background: var(--surface);\n border-left: 1px solid var(--border);\n padding: 16px;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n#sidebar h2 {\n font-size: 12px;\n text-transform: uppercase;\n letter-spacing: 2px;\n color: var(--text2);\n margin-bottom: 4px;\n}\n\n.sidebar-empty {\n color: var(--text2);\n font-style: italic;\n font-size: 12px;\n margin-top: 40px;\n text-align: center;\n}\n\n.detail-row {\n display: flex;\n justify-content: space-between;\n padding: 4px 0;\n border-bottom: 1px solid var(--border);\n font-size: 12px;\n}\n.detail-row .label { color: var(--text2); }\n.detail-row .value { color: var(--text); font-weight: 500; }\n\n.status-chip {\n display: inline-block;\n padding: 1px 8px;\n border-radius: 6px;\n font-size: 11px;\n font-weight: 600;\n}\n.status-chip.idle { background: rgba(148,163,184,0.15); color: var(--text2); }\n.status-chip.working { background: rgba(0,240,255,0.15); color: var(--cyan); }\n.status-chip.in-meeting { background: rgba(245,158,11,0.15); color: var(--warning); }\n.status-chip.spawning-workers { background: rgba(168,85,247,0.15); color: var(--purple); }\n.status-chip.aggregating { background: rgba(34,211,238,0.15); color: var(--lightcyan); }\n.status-chip.waiting-for-user { background: rgba(245,158,11,0.15); color: var(--warning); }\n.status-chip.completed { background: rgba(16,185,129,0.15); color: var(--success); }\n.status-chip.failed { background: rgba(239,68,68,0.15); color: var(--error); }\n\n.task-block {\n background: rgba(0,0,0,0.3);\n border: 1px solid var(--border);\n border-radius: 6px;\n padding: 10px;\n font-size: 12px;\n color: var(--text2);\n line-height: 1.6;\n max-height: 160px;\n overflow-y: auto;\n}\n\n/* Children list */\n.children-list {\n list-style: none;\n padding: 0;\n font-size: 12px;\n}\n.children-list li {\n padding: 3px 0;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n.children-list li::before {\n content: '';\n display: inline-block;\n width: 6px; height: 6px;\n border-radius: 50%;\n background: var(--lightcyan);\n}\n\n/* Task history */\n#task-history {\n max-height: 250px;\n overflow-y: auto;\n}\n.history-item {\n font-size: 11px;\n padding: 4px 0;\n border-bottom: 1px solid rgba(30,41,59,0.5);\n color: var(--text2);\n}\n\n/* ===================================================================\n EVENT LOG\n =================================================================== */\n#event-log {\n grid-area: log;\n background: var(--surface);\n border-top: 1px solid var(--border);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n#event-log .log-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px 16px;\n font-size: 10px;\n text-transform: uppercase;\n letter-spacing: 2px;\n color: var(--text2);\n border-bottom: 1px solid var(--border);\n flex-shrink: 0;\n}\n#event-log .log-header .pause-indicator {\n color: var(--warning);\n font-weight: 600;\n display: none;\n}\n#event-log .log-header .pause-indicator.visible {\n display: inline;\n}\n\n#log-entries {\n flex: 1;\n overflow-y: auto;\n padding: 4px 0;\n font-size: 12px;\n scroll-behavior: smooth;\n}\n\n.log-entry {\n display: flex;\n gap: 12px;\n padding: 3px 16px;\n border-bottom: 1px solid rgba(30,41,59,0.3);\n align-items: baseline;\n}\n.log-entry:hover { background: rgba(255,255,255,0.02); }\n\n.log-time {\n color: var(--text2);\n font-size: 11px;\n flex-shrink: 0;\n min-width: 64px;\n}\n.log-session {\n color: var(--cyan);\n font-size: 10px;\n flex-shrink: 0;\n min-width: 80px;\n max-width: 120px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n opacity: 0.7;\n}\n.log-kind {\n font-weight: 600;\n flex-shrink: 0;\n min-width: 90px;\n font-size: 11px;\n}\n.log-msg {\n color: var(--text);\n flex: 1;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* Kind colours */\n.log-kind.spawn { color: var(--cyan); }\n.log-kind.destroy { color: var(--error); }\n.log-kind.state { color: var(--purple); }\n.log-kind.task { color: var(--lightcyan); }\n.log-kind.done { color: var(--success); }\n.log-kind.msg { color: var(--text); }\n.log-kind.mention { color: var(--error); }\n.log-kind.resolved { color: var(--success); }\n.log-kind.cost { color: var(--warning); }\n.log-kind.session { color: var(--purple); }\n\n/* ===================================================================\n ANIMATIONS\n =================================================================== */\n@keyframes breathe {\n 0%, 100% { opacity: 0.4; }\n 50% { opacity: 1; }\n}\n@keyframes pulse-glow {\n 0%, 100% { box-shadow: 0 0 4px rgba(0,240,255,0.3); }\n 50% { box-shadow: 0 0 18px rgba(0,240,255,0.7); }\n}\n\n/* Custom scrollbar */\n::-webkit-scrollbar { width: 6px; }\n::-webkit-scrollbar-track { background: var(--bg); }\n::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }\n::-webkit-scrollbar-thumb:hover { background: #334155; }\n</style>\n</head>\n<body>\n\n<div id=\"app\">\n <!-- HEADER ------------------------------------------------------------ -->\n <header id=\"header\">\n <div class=\"brand\">\n <span style=\"font-size:22px\">&#x1F96C;</span>\n <span>Open Coleslaw</span>\n </div>\n <div class=\"center-status\">\n <span class=\"conn-dot\" id=\"conn-dot\"></span>\n <span id=\"conn-label\">Connecting...</span>\n </div>\n <div class=\"right-stats\">\n <span class=\"badge\" id=\"badge-sessions\">0 sessions</span>\n <span class=\"badge\" id=\"badge-agents\">0 agents</span>\n <span class=\"badge purple\" id=\"badge-meeting\">No meeting</span>\n <span class=\"badge green\" id=\"badge-cost\">$0.0000</span>\n </div>\n </header>\n\n <!-- TAB BAR ----------------------------------------------------------- -->\n <div id=\"tab-bar\">\n <span class=\"tab-empty-msg\" id=\"tab-empty\">Waiting for sessions...</span>\n </div>\n\n <!-- GRAPH ------------------------------------------------------------- -->\n <div id=\"graph-container\">\n <div id=\"cy\"></div>\n </div>\n\n <!-- SIDEBAR ----------------------------------------------------------- -->\n <aside id=\"sidebar\">\n <h2>Agent Details</h2>\n <div class=\"sidebar-empty\" id=\"sidebar-empty\">Click a node to inspect</div>\n <div id=\"sidebar-content\" style=\"display:none;\"></div>\n </aside>\n\n <!-- EVENT LOG --------------------------------------------------------- -->\n <div id=\"event-log\">\n <div class=\"log-header\">\n <span>Event Log</span>\n <span class=\"pause-indicator\" id=\"log-pause\">PAUSED (scroll up)</span>\n </div>\n <div id=\"log-entries\"></div>\n </div>\n</div>\n\n<script>\n// ======================================================================\n// IIFE -- all dashboard JS\n// ======================================================================\n(function () {\n 'use strict';\n\n // ====================================================================\n // 1. STATE STORE (per-session)\n // ====================================================================\n // sessions: Map<sessionId, { displayName, projectPath, isActive, agents: Map, edges: [], meeting, totalCost, eventHistory[] }>\n const sessions = new Map();\n let activeTabId = null; // currently viewed session\n let selectedAgentId = null; // clicked node\n\n function getSession(id) { return sessions.get(id); }\n\n function activeSession() {\n if (!activeTabId) return null;\n return sessions.get(activeTabId) || null;\n }\n\n // ====================================================================\n // 2. CONNECTION MANAGER -- WebSocket with exponential backoff\n // ====================================================================\n const ConnectionManager = {\n ws: null,\n backoff: 1000,\n maxBackoff: 30000,\n timer: null,\n _heartbeat: null,\n\n connect() {\n const proto = location.protocol === 'https:' ? 'wss' : 'ws';\n const url = proto + '://' + location.host;\n this.ws = new WebSocket(url);\n this.setStatus('reconnecting');\n\n this.ws.onopen = () => {\n this.backoff = 1000;\n this.setStatus('connected');\n };\n\n this.ws.onmessage = (msg) => {\n try {\n const data = JSON.parse(msg.data);\n this.handleMessage(data);\n } catch (e) {\n console.error('[WS] Parse error:', e);\n }\n };\n\n this.ws.onclose = () => {\n this.setStatus('disconnected');\n this.scheduleReconnect();\n };\n\n this.ws.onerror = () => {};\n\n if (this._heartbeat) clearInterval(this._heartbeat);\n this._heartbeat = setInterval(() => {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify({ type: 'ping' }));\n }\n }, 25000);\n },\n\n handleMessage(data) {\n switch (data.type) {\n case 'multi-snapshot':\n this.handleMultiSnapshot(data);\n break;\n case 'session-delta':\n this.handleSessionDelta(data);\n break;\n case 'session-registered':\n this.handleSessionRegistered(data);\n break;\n case 'session-unregistered':\n this.handleSessionUnregistered(data);\n break;\n case 'pong':\n break;\n default:\n break;\n }\n },\n\n handleMultiSnapshot(data) {\n sessions.clear();\n (data.sessions || []).forEach(function (s) {\n var agentsMap = new Map();\n (s.snapshot.agents || []).forEach(function (a) { agentsMap.set(a.id, a); });\n sessions.set(s.sessionId, {\n displayName: s.displayName,\n projectPath: s.projectPath,\n isActive: s.isActive,\n agents: agentsMap,\n edges: s.snapshot.edges || [],\n meeting: s.snapshot.meeting || null,\n totalCost: s.snapshot.totalCost || 0,\n eventHistory: [],\n });\n });\n // Auto-select first active tab if none selected\n if (!activeTabId || !sessions.has(activeTabId)) {\n var first = null;\n sessions.forEach(function (s, id) { if (!first && s.isActive) first = id; });\n if (!first && sessions.size > 0) first = sessions.keys().next().value;\n activeTabId = first;\n }\n TabBar.render();\n StatusBar.update();\n GraphRenderer.rebuild();\n },\n\n handleSessionDelta(data) {\n var sess = sessions.get(data.sessionId);\n if (!sess) {\n // Session not yet known -- create a placeholder\n sess = {\n displayName: data.displayName,\n projectPath: '',\n isActive: true,\n agents: new Map(),\n edges: [],\n meeting: null,\n totalCost: 0,\n eventHistory: [],\n };\n sessions.set(data.sessionId, sess);\n TabBar.render();\n }\n\n (data.events || []).forEach(function (ev) {\n applyEventToSession(data.sessionId, sess, ev);\n });\n\n TabBar.updateBadge(data.sessionId);\n StatusBar.update();\n\n // Rebuild graph only if this is the active tab\n if (data.sessionId === activeTabId) {\n GraphRenderer.rebuild();\n if (selectedAgentId) SidebarPanel.show(selectedAgentId);\n }\n },\n\n handleSessionRegistered(data) {\n if (!sessions.has(data.sessionId)) {\n sessions.set(data.sessionId, {\n displayName: data.displayName,\n projectPath: data.projectPath,\n isActive: true,\n agents: new Map(),\n edges: [],\n meeting: null,\n totalCost: 0,\n eventHistory: [],\n });\n }\n // Auto-select if no tab is active\n if (!activeTabId) activeTabId = data.sessionId;\n TabBar.render();\n StatusBar.update();\n EventLog.appendSystem(data.displayName, 'Session connected');\n },\n\n handleSessionUnregistered(data) {\n var sess = sessions.get(data.sessionId);\n if (sess) {\n sess.isActive = false;\n TabBar.render();\n StatusBar.update();\n EventLog.appendSystem(sess.displayName, 'Session disconnected');\n }\n },\n\n scheduleReconnect() {\n if (this.timer) clearTimeout(this.timer);\n this.timer = setTimeout(() => {\n this.backoff = Math.min(this.backoff * 2, this.maxBackoff);\n this.connect();\n }, this.backoff);\n },\n\n setStatus(status) {\n var dot = document.getElementById('conn-dot');\n var label = document.getElementById('conn-label');\n dot.className = 'conn-dot';\n if (status === 'connected') {\n dot.classList.add('connected');\n label.textContent = 'Connected';\n } else if (status === 'reconnecting') {\n dot.classList.add('reconnecting');\n label.textContent = 'Connecting...';\n } else {\n label.textContent = 'Disconnected';\n }\n },\n };\n\n // ====================================================================\n // Event application (scoped to a session)\n // ====================================================================\n function applyEventToSession(sessionId, sess, ev) {\n sess.eventHistory.push(ev);\n if (sess.eventHistory.length > 500) sess.eventHistory.shift();\n\n EventLog.append(sessionId, sess.displayName, ev);\n\n switch (ev.kind) {\n case 'agent_spawned': {\n var agent = {\n id: ev.agentId,\n type: ev.agentType,\n label: ev.label,\n status: 'idle',\n parentId: ev.parentId,\n department: ev.department,\n currentTask: null,\n costUsd: 0,\n };\n sess.agents.set(ev.agentId, agent);\n if (ev.parentId) {\n sess.edges.push({\n id: 'edge-' + ev.parentId + '-' + ev.agentId,\n source: ev.parentId,\n target: ev.agentId,\n edgeType: 'hierarchy',\n active: true,\n label: '',\n });\n }\n break;\n }\n case 'agent_destroyed': {\n sess.agents.delete(ev.agentId);\n sess.edges = sess.edges.filter(function (e) {\n return e.source !== ev.agentId && e.target !== ev.agentId;\n });\n if (sessionId === activeTabId && selectedAgentId === ev.agentId) {\n selectedAgentId = null;\n SidebarPanel.clear();\n }\n break;\n }\n case 'state_changed': {\n var a = sess.agents.get(ev.agentId);\n if (a) a.status = ev.to;\n break;\n }\n case 'task_assigned': {\n var a = sess.agents.get(ev.agentId);\n if (a) { a.currentTask = ev.taskSummary; a.status = 'working'; }\n break;\n }\n case 'task_completed': {\n var a = sess.agents.get(ev.agentId);\n if (a) { a.currentTask = null; a.status = ev.result === 'success' ? 'completed' : 'failed'; }\n break;\n }\n case 'message_sent': {\n var edgeId = 'msg-' + ev.fromId + '-' + ev.toId + '-' + Date.now();\n var edge = { id: edgeId, source: ev.fromId, target: ev.toId, edgeType: 'message', active: true, label: ev.summary };\n sess.edges.push(edge);\n setTimeout(function () {\n sess.edges = sess.edges.filter(function (e) { return e.id !== edgeId; });\n if (sessionId === activeTabId) GraphRenderer.rebuild();\n }, 5000);\n break;\n }\n case 'cost_update': {\n sess.totalCost = ev.totalCost;\n break;\n }\n default:\n break;\n }\n }\n\n // ====================================================================\n // 3. TAB BAR\n // ====================================================================\n var TabBar = {\n render: function () {\n var bar = document.getElementById('tab-bar');\n var emptyMsg = document.getElementById('tab-empty');\n\n // Remove old tabs (keep the empty msg span)\n var old = bar.querySelectorAll('.session-tab');\n old.forEach(function (el) { el.remove(); });\n\n if (sessions.size === 0) {\n emptyMsg.style.display = '';\n return;\n }\n emptyMsg.style.display = 'none';\n\n sessions.forEach(function (sess, sessionId) {\n var tab = document.createElement('button');\n tab.className = 'session-tab';\n if (sessionId === activeTabId) tab.classList.add('active');\n if (!sess.isActive) tab.classList.add('inactive');\n tab.dataset.sessionId = sessionId;\n\n // Tab label\n var lbl = document.createElement('span');\n lbl.textContent = sess.displayName || sessionId.slice(0, 8);\n tab.appendChild(lbl);\n\n // Agent count badge\n var badge = document.createElement('span');\n badge.className = 'tab-badge';\n badge.textContent = String(sess.agents.size);\n tab.appendChild(badge);\n\n // Meeting indicator\n if (sess.meeting) {\n var mb = document.createElement('span');\n mb.className = 'tab-badge meeting';\n mb.textContent = 'MTG';\n tab.appendChild(mb);\n }\n\n tab.addEventListener('click', function () {\n TabBar.switchTo(sessionId);\n });\n\n bar.appendChild(tab);\n });\n },\n\n switchTo: function (sessionId) {\n activeTabId = sessionId;\n selectedAgentId = null;\n SidebarPanel.clear();\n this.render();\n StatusBar.update();\n GraphRenderer.rebuild();\n },\n\n updateBadge: function (sessionId) {\n var bar = document.getElementById('tab-bar');\n var tabs = bar.querySelectorAll('.session-tab');\n tabs.forEach(function (tab) {\n if (tab.dataset.sessionId === sessionId) {\n var sess = sessions.get(sessionId);\n if (!sess) return;\n var badge = tab.querySelector('.tab-badge:not(.meeting)');\n if (badge) badge.textContent = String(sess.agents.size);\n }\n });\n },\n };\n\n // ====================================================================\n // 4. GRAPH RENDERER -- Cytoscape.js\n // ====================================================================\n var GraphRenderer = {\n cy: null,\n _layoutTimer: null,\n _animFrame: null,\n _dashOffset: 0,\n\n init: function () {\n this.cy = cytoscape({\n container: document.getElementById('cy'),\n style: [\n // --- NODES ---\n {\n selector: 'node',\n style: {\n 'label': 'data(label)',\n 'text-valign': 'bottom',\n 'text-halign': 'center',\n 'text-margin-y': 8,\n 'font-family': \"'JetBrains Mono', monospace\",\n 'font-size': 10,\n 'color': '#94a3b8',\n 'text-outline-width': 0,\n 'background-color': '#1e293b',\n 'border-width': 2,\n 'border-color': '#334155',\n 'width': 40,\n 'height': 40,\n 'transition-property': 'background-color, border-color, border-width, opacity, width, height',\n 'transition-duration': '0.3s',\n },\n },\n // Orchestrator\n {\n selector: 'node[tier=\"orchestrator\"]',\n style: {\n 'width': 60, 'height': 60,\n 'border-width': 3,\n 'border-color': '#00f0ff',\n 'background-color': 'rgba(0,240,255,0.1)',\n 'color': '#00f0ff',\n 'font-size': 12, 'font-weight': '700',\n 'text-outline-color': '#0a0e17',\n 'text-outline-width': 2,\n },\n },\n // Leader\n {\n selector: 'node[tier=\"leader\"]',\n style: {\n 'width': 48, 'height': 48,\n 'border-width': 2,\n 'border-color': '#a855f7',\n 'background-color': 'rgba(168,85,247,0.1)',\n 'color': '#a855f7',\n 'font-size': 11, 'font-weight': '600',\n },\n },\n // Worker\n {\n selector: 'node[tier=\"worker\"]',\n style: {\n 'width': 36, 'height': 36,\n 'border-width': 2,\n 'border-color': '#22d3ee',\n 'background-color': 'rgba(34,211,238,0.08)',\n 'color': '#22d3ee',\n 'font-size': 10,\n },\n },\n // Status: idle\n { selector: 'node[status=\"idle\"]', style: { 'opacity': 0.5, 'border-color': '#475569' } },\n // Status: working\n { selector: 'node[status=\"working\"]', style: { 'border-width': 3, 'opacity': 1 } },\n // Status: in-meeting\n { selector: 'node[status=\"in-meeting\"]', style: { 'border-color': '#f59e0b', 'background-color': 'rgba(245,158,11,0.1)', 'opacity': 1 } },\n // Status: spawning-workers\n { selector: 'node[status=\"spawning-workers\"]', style: { 'border-color': '#a855f7', 'opacity': 1 } },\n // Status: waiting-for-user\n { selector: 'node[status=\"waiting-for-user\"]', style: { 'border-color': '#f59e0b', 'opacity': 0.8 } },\n // Status: aggregating\n { selector: 'node[status=\"aggregating\"]', style: { 'border-color': '#22d3ee', 'opacity': 1 } },\n // Status: completed\n { selector: 'node[status=\"completed\"]', style: { 'border-color': '#10b981', 'background-color': 'rgba(16,185,129,0.1)', 'opacity': 0.7 } },\n // Status: failed\n { selector: 'node[status=\"failed\"]', style: { 'border-color': '#ef4444', 'background-color': 'rgba(239,68,68,0.1)', 'opacity': 0.8 } },\n // Selected node\n { selector: 'node:selected', style: { 'border-width': 4, 'overlay-padding': 6, 'overlay-color': '#00f0ff', 'overlay-opacity': 0.08 } },\n // --- EDGES ---\n {\n selector: 'edge',\n style: {\n 'width': 1.5,\n 'line-color': '#334155',\n 'target-arrow-color': '#334155',\n 'target-arrow-shape': 'triangle',\n 'arrow-scale': 0.8,\n 'curve-style': 'bezier',\n 'opacity': 0.5,\n 'transition-property': 'line-color, opacity, width',\n 'transition-duration': '0.3s',\n },\n },\n { selector: 'edge[edgeType=\"hierarchy\"][?active]', style: { 'line-color': '#475569', 'target-arrow-color': '#475569', 'line-style': 'solid', 'opacity': 0.6, 'width': 1.5 } },\n { selector: 'edge[edgeType=\"delegation\"]', style: { 'line-color': '#a855f7', 'target-arrow-color': '#a855f7', 'line-style': 'dashed', 'line-dash-pattern': [8, 4], 'opacity': 0.8, 'width': 2 } },\n { selector: 'edge[edgeType=\"report\"]', style: { 'line-color': '#10b981', 'target-arrow-color': '#10b981', 'opacity': 0.8, 'width': 2 } },\n { selector: 'edge[edgeType=\"message\"]', style: { 'line-color': '#22d3ee', 'target-arrow-color': '#22d3ee', 'line-style': 'dashed', 'line-dash-pattern': [6, 3], 'opacity': 0.7, 'width': 1.5 } },\n { selector: 'edge[edgeType=\"mention\"]', style: { 'line-color': '#ef4444', 'target-arrow-color': '#ef4444', 'line-style': 'dashed', 'line-dash-pattern': [4, 4], 'opacity': 0.9, 'width': 2.5 } },\n ],\n layout: { name: 'preset' },\n minZoom: 0.3,\n maxZoom: 3,\n wheelSensitivity: 0.3,\n });\n\n // Click handling\n this.cy.on('tap', 'node', function (evt) {\n var id = evt.target.id();\n selectedAgentId = id;\n SidebarPanel.show(id);\n });\n\n this.cy.on('tap', function (evt) {\n if (evt.target === GraphRenderer.cy) {\n selectedAgentId = null;\n SidebarPanel.clear();\n }\n });\n\n this.startAnimations();\n },\n\n rebuild: function () {\n if (!this.cy) return;\n this.cy.elements().remove();\n\n var sess = activeSession();\n if (!sess) return;\n\n sess.agents.forEach(function (agent) {\n GraphRenderer.cy.add({\n group: 'nodes',\n data: {\n id: agent.id,\n label: agent.label,\n tier: agent.type,\n status: agent.status,\n department: agent.department,\n },\n });\n });\n\n sess.edges.forEach(function (edge) {\n if (GraphRenderer.cy.getElementById(edge.source).length && GraphRenderer.cy.getElementById(edge.target).length) {\n GraphRenderer.cy.add({\n group: 'edges',\n data: {\n id: edge.id,\n source: edge.source,\n target: edge.target,\n edgeType: edge.edgeType,\n active: edge.active,\n },\n });\n }\n });\n\n this.runLayout();\n },\n\n runLayout: function () {\n if (!this.cy || this.cy.nodes().length === 0) return;\n this.cy.layout({\n name: 'dagre',\n rankDir: 'TB',\n rankSep: 80,\n nodeSep: 40,\n edgeSep: 20,\n animate: true,\n animationDuration: 500,\n animationEasing: 'ease-out',\n padding: 40,\n }).run();\n },\n\n startAnimations: function () {\n var self = this;\n var animate = function () {\n self._dashOffset += 0.5;\n if (self.cy) {\n self.cy.edges('[edgeType=\"delegation\"], [edgeType=\"message\"], [edgeType=\"mention\"]').forEach(function (edge) {\n edge.style('line-dash-offset', -self._dashOffset);\n });\n\n var t = Date.now();\n self.cy.nodes('[status=\"working\"]').forEach(function (node) {\n var glow = 2 + Math.sin(t / 400) * 1;\n node.style('border-width', glow);\n });\n self.cy.nodes('[status=\"in-meeting\"]').forEach(function (node) {\n var op = 0.4 + (Math.sin(t / 1000) + 1) * 0.3;\n node.style('opacity', op);\n });\n self.cy.nodes('[status=\"waiting-for-user\"]').forEach(function (node) {\n var op = 0.5 + (Math.sin(t / 1500) + 1) * 0.25;\n node.style('opacity', op);\n });\n self.cy.nodes('[status=\"spawning-workers\"]').forEach(function (node) {\n var c = Math.sin(t / 600) > 0 ? '#a855f7' : '#22d3ee';\n node.style('border-color', c);\n });\n }\n self._animFrame = requestAnimationFrame(animate);\n };\n self._animFrame = requestAnimationFrame(animate);\n },\n };\n\n // ====================================================================\n // 5. SIDEBAR PANEL\n // ====================================================================\n var SidebarPanel = {\n show: function (agentId) {\n var sess = activeSession();\n if (!sess) { this.clear(); return; }\n var agent = sess.agents.get(agentId);\n if (!agent) { this.clear(); return; }\n\n document.getElementById('sidebar-empty').style.display = 'none';\n var el = document.getElementById('sidebar-content');\n el.style.display = 'block';\n\n // Children\n var children = [];\n sess.agents.forEach(function (a) {\n if (a.parentId === agentId) children.push(a);\n });\n\n // Recent events for this agent\n var recentEvents = sess.eventHistory\n .filter(function (ev) { return ev.agentId === agentId || ev.fromId === agentId || ev.toId === agentId; })\n .slice(-10)\n .reverse();\n\n var tierIcon = agent.type === 'orchestrator' ? '&#x1F3AF;' : agent.type === 'leader' ? '&#x1F451;' : '&#x2699;&#xFE0F;';\n\n el.innerHTML =\n '<div style=\"text-align:center;margin-bottom:8px;\">' +\n '<span style=\"font-size:28px;\">' + tierIcon + '</span>' +\n '<div style=\"font-size:14px;font-weight:700;color:var(--cyan);margin-top:4px;\">' + escHtml(agent.label) + '</div>' +\n '<div style=\"font-size:11px;color:var(--text2);\">' + escHtml(agent.id) + '</div>' +\n '</div>' +\n '<div class=\"detail-row\"><span class=\"label\">Type</span><span class=\"value\">' + agent.type + '</span></div>' +\n '<div class=\"detail-row\"><span class=\"label\">Department</span><span class=\"value\">' + escHtml(agent.department) + '</span></div>' +\n '<div class=\"detail-row\"><span class=\"label\">Status</span><span class=\"value\"><span class=\"status-chip ' + agent.status + '\">' + agent.status + '</span></span></div>' +\n '<div class=\"detail-row\"><span class=\"label\">Cost</span><span class=\"value\">$' + agent.costUsd.toFixed(4) + '</span></div>' +\n '<div class=\"detail-row\"><span class=\"label\">Workers</span><span class=\"value\">' + children.length + '</span></div>' +\n (agent.currentTask\n ? '<h2 style=\"margin-top:12px;\">Current Task</h2><div class=\"task-block\">' + escHtml(agent.currentTask) + '</div>'\n : '') +\n (children.length > 0\n ? '<h2 style=\"margin-top:12px;\">Children</h2><ul class=\"children-list\">' +\n children.map(function (c) { return '<li>' + escHtml(c.label) + ' <span class=\"status-chip ' + c.status + '\" style=\"font-size:10px;\">' + c.status + '</span></li>'; }).join('') +\n '</ul>'\n : '') +\n (recentEvents.length > 0\n ? '<h2 style=\"margin-top:12px;\">Recent Activity</h2><div id=\"task-history\">' +\n recentEvents.map(function (ev) { return '<div class=\"history-item\">' + summarizeEventShort(ev) + '</div>'; }).join('') +\n '</div>'\n : '');\n },\n\n clear: function () {\n document.getElementById('sidebar-empty').style.display = 'block';\n document.getElementById('sidebar-content').style.display = 'none';\n },\n };\n\n // ====================================================================\n // 6. EVENT LOG\n // ====================================================================\n var EventLog = {\n el: null,\n pauseEl: null,\n autoScroll: true,\n maxEntries: 500,\n\n init: function () {\n this.el = document.getElementById('log-entries');\n this.pauseEl = document.getElementById('log-pause');\n var self = this;\n this.el.addEventListener('scroll', function () {\n var atBottom = self.el.scrollHeight - self.el.scrollTop - self.el.clientHeight < 30;\n self.autoScroll = atBottom;\n self.pauseEl.classList.toggle('visible', !atBottom);\n });\n },\n\n append: function (sessionId, displayName, ev) {\n var row = document.createElement('div');\n row.className = 'log-entry';\n\n var now = new Date();\n var ts = pad2(now.getHours()) + ':' + pad2(now.getMinutes()) + ':' + pad2(now.getSeconds());\n\n var kindLabel = '';\n var kindClass = '';\n var message = '';\n\n switch (ev.kind) {\n case 'agent_spawned':\n kindLabel = 'SPAWN'; kindClass = 'spawn';\n message = '<b>' + escHtml(ev.label) + '</b> (' + ev.agentType + ') in ' + escHtml(ev.department);\n break;\n case 'agent_destroyed':\n kindLabel = 'DESTROY'; kindClass = 'destroy';\n message = escHtml(ev.agentId);\n break;\n case 'state_changed':\n kindLabel = 'STATE'; kindClass = 'state';\n message = escHtml(ev.agentId) + ': ' + ev.from + ' &#x2192; ' + ev.to;\n break;\n case 'task_assigned':\n kindLabel = 'TASK'; kindClass = 'task';\n message = escHtml(ev.agentId) + ': ' + escHtml(ev.taskSummary);\n break;\n case 'task_completed':\n kindLabel = ev.result === 'success' ? 'SUCCESS' : 'FAILED';\n kindClass = ev.result === 'success' ? 'done' : 'destroy';\n message = escHtml(ev.agentId);\n break;\n case 'message_sent':\n kindLabel = 'MSG'; kindClass = 'msg';\n message = escHtml(ev.fromId) + ' &#x2192; ' + escHtml(ev.toId) + ': ' + escHtml(ev.summary);\n break;\n case 'mention_created':\n kindLabel = '@MENTION'; kindClass = 'mention';\n message = escHtml(ev.summary) + ' [' + ev.urgency + ']';\n break;\n case 'mention_resolved':\n kindLabel = '@RESOLVED'; kindClass = 'resolved';\n message = escHtml(ev.mentionId) + ': ' + escHtml(ev.decision);\n break;\n case 'cost_update':\n kindLabel = 'COST'; kindClass = 'cost';\n message = 'Total: $' + ev.totalCost.toFixed(4);\n break;\n default:\n kindLabel = 'EVENT'; kindClass = '';\n message = JSON.stringify(ev);\n }\n\n row.innerHTML =\n '<span class=\"log-time\">' + ts + '</span>' +\n '<span class=\"log-session\">' + escHtml(displayName) + '</span>' +\n '<span class=\"log-kind ' + kindClass + '\">' + kindLabel + '</span>' +\n '<span class=\"log-msg\">' + message + '</span>';\n\n this.el.appendChild(row);\n\n while (this.el.children.length > this.maxEntries) {\n this.el.removeChild(this.el.firstChild);\n }\n\n if (this.autoScroll) {\n this.el.scrollTop = this.el.scrollHeight;\n }\n },\n\n appendSystem: function (displayName, message) {\n var row = document.createElement('div');\n row.className = 'log-entry';\n var now = new Date();\n var ts = pad2(now.getHours()) + ':' + pad2(now.getMinutes()) + ':' + pad2(now.getSeconds());\n row.innerHTML =\n '<span class=\"log-time\">' + ts + '</span>' +\n '<span class=\"log-session\">' + escHtml(displayName) + '</span>' +\n '<span class=\"log-kind session\">SESSION</span>' +\n '<span class=\"log-msg\">' + escHtml(message) + '</span>';\n this.el.appendChild(row);\n if (this.autoScroll) this.el.scrollTop = this.el.scrollHeight;\n },\n };\n\n // ====================================================================\n // 7. STATUS BAR\n // ====================================================================\n var StatusBar = {\n update: function () {\n // Session count\n var totalSessions = sessions.size;\n var activeSessions = 0;\n sessions.forEach(function (s) { if (s.isActive) activeSessions++; });\n document.getElementById('badge-sessions').textContent = activeSessions + '/' + totalSessions + ' sessions';\n\n // Agent count + meeting + cost for active tab\n var sess = activeSession();\n if (sess) {\n document.getElementById('badge-agents').textContent = sess.agents.size + ' agent' + (sess.agents.size !== 1 ? 's' : '');\n\n if (sess.meeting) {\n document.getElementById('badge-meeting').textContent = sess.meeting.phase;\n document.getElementById('badge-meeting').className = 'badge amber';\n } else {\n document.getElementById('badge-meeting').textContent = 'No meeting';\n document.getElementById('badge-meeting').className = 'badge purple';\n }\n\n document.getElementById('badge-cost').textContent = '$' + sess.totalCost.toFixed(4);\n } else {\n document.getElementById('badge-agents').textContent = '0 agents';\n document.getElementById('badge-meeting').textContent = 'No meeting';\n document.getElementById('badge-meeting').className = 'badge purple';\n document.getElementById('badge-cost').textContent = '$0.0000';\n }\n },\n };\n\n // ====================================================================\n // HELPERS\n // ====================================================================\n function escHtml(str) {\n if (typeof str !== 'string') return String(str || '');\n return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');\n }\n\n function pad2(n) {\n return n < 10 ? '0' + n : String(n);\n }\n\n function summarizeEventShort(ev) {\n switch (ev.kind) {\n case 'agent_spawned': return 'Spawned: ' + escHtml(ev.label);\n case 'agent_destroyed': return 'Destroyed';\n case 'state_changed': return ev.from + ' &#x2192; ' + ev.to;\n case 'task_assigned': return 'Task: ' + escHtml(ev.taskSummary);\n case 'task_completed': return 'Completed: ' + ev.result;\n case 'message_sent': return 'Msg to ' + escHtml(ev.toId);\n case 'mention_created': return '@mention: ' + escHtml(ev.summary);\n case 'mention_resolved': return '@resolved: ' + escHtml(ev.decision);\n case 'cost_update': return 'Cost: $' + ev.totalCost.toFixed(4);\n default: return ev.kind;\n }\n }\n\n // ====================================================================\n // BOOT\n // ====================================================================\n document.addEventListener('DOMContentLoaded', function () {\n GraphRenderer.init();\n EventLog.init();\n StatusBar.update();\n ConnectionManager.connect();\n });\n\n})();\n</script>\n</body>\n</html>`;\n}\n","/**\n * StateBridge — manages per-session state and emits 'broadcast' events\n * for the dashboard server to relay to browser WebSocket clients.\n *\n * Supports multiple sessions (one per MCP server instance). Each session\n * tracks its own agent graph independently. Disconnected sessions are kept\n * (grayed-out tab) rather than deleted.\n */\n\nimport { EventEmitter } from 'node:events';\nimport type {\n AgentState,\n EdgeState,\n MeetingState,\n AgentEvent,\n MultiSessionSnapshot,\n SessionDelta,\n} from '../types/dashboard-events.js';\nimport { logger } from '../utils/logger.js';\n\n// ---------------------------------------------------------------------------\n// Per-session state container\n// ---------------------------------------------------------------------------\n\ninterface SessionState {\n projectName: string;\n displayName: string;\n projectPath: string;\n isActive: boolean;\n agents: Map<string, AgentState>;\n edges: EdgeState[];\n meeting: MeetingState | null;\n totalCost: number;\n eventLog: Array<{ timestamp: number; event: AgentEvent }>;\n}\n\n// ---------------------------------------------------------------------------\n// StateBridge\n// ---------------------------------------------------------------------------\n\nexport class StateBridge extends EventEmitter {\n private sessions = new Map<string, SessionState>();\n private debounceTimers = new Map<string, NodeJS.Timeout>();\n private pendingEvents = new Map<string, AgentEvent[]>();\n\n // -----------------------------------------------------------------------\n // Session lifecycle\n // -----------------------------------------------------------------------\n\n registerSession(info: {\n sessionId: string;\n projectPath: string;\n projectName: string;\n }): string {\n const displayName = this.getUniqueDisplayName(info.projectName);\n\n this.sessions.set(info.sessionId, {\n projectName: info.projectName,\n displayName,\n projectPath: info.projectPath,\n isActive: true,\n agents: new Map(),\n edges: [],\n meeting: null,\n totalCost: 0,\n eventLog: [],\n });\n\n logger.info(`Session registered: ${displayName} (${info.sessionId})`);\n\n // Notify browser clients about the new session\n this.emit(\n 'broadcast',\n JSON.stringify({\n type: 'session-registered',\n sessionId: info.sessionId,\n displayName,\n projectPath: info.projectPath,\n }),\n );\n\n return displayName;\n }\n\n unregisterSession(sessionId: string): void {\n const session = this.sessions.get(sessionId);\n if (session) {\n session.isActive = false;\n logger.info(`Session deactivated: ${session.displayName}`);\n\n // Don't delete — keep for display (grayed-out tab)\n this.emit(\n 'broadcast',\n JSON.stringify({\n type: 'session-unregistered',\n sessionId,\n }),\n );\n }\n }\n\n // -----------------------------------------------------------------------\n // Event handling\n // -----------------------------------------------------------------------\n\n handleSessionEvent(sessionId: string, event: AgentEvent): void {\n const session = this.sessions.get(sessionId);\n if (!session) return;\n\n // Apply event to session state\n this.applyEvent(session, event);\n\n // Queue for debounced broadcast\n if (!this.pendingEvents.has(sessionId)) {\n this.pendingEvents.set(sessionId, []);\n }\n this.pendingEvents.get(sessionId)!.push(event);\n\n // Debounce broadcast per session (100ms)\n if (!this.debounceTimers.has(sessionId)) {\n this.debounceTimers.set(\n sessionId,\n setTimeout(() => {\n this.flushEvents(sessionId);\n this.debounceTimers.delete(sessionId);\n }, 100),\n );\n }\n }\n\n // -----------------------------------------------------------------------\n // Snapshot (sent to newly connected browser clients)\n // -----------------------------------------------------------------------\n\n getSnapshot(): MultiSessionSnapshot {\n return {\n type: 'multi-snapshot',\n sessions: Array.from(this.sessions.entries()).map(([sessionId, s]) => ({\n sessionId,\n displayName: s.displayName,\n projectPath: s.projectPath,\n isActive: s.isActive,\n snapshot: {\n agents: Array.from(s.agents.values()),\n edges: [...s.edges],\n meeting: s.meeting,\n totalCost: s.totalCost,\n },\n })),\n };\n }\n\n // -----------------------------------------------------------------------\n // Private — unique display name\n // -----------------------------------------------------------------------\n\n private getUniqueDisplayName(projectName: string): string {\n const existing = Array.from(this.sessions.values()).map(\n (s) => s.displayName,\n );\n if (!existing.includes(projectName)) return projectName;\n let i = 1;\n while (existing.includes(`${projectName} (${i})`)) i++;\n return `${projectName} (${i})`;\n }\n\n // -----------------------------------------------------------------------\n // Private — state mutations (scoped to a session)\n // -----------------------------------------------------------------------\n\n private applyEvent(session: SessionState, event: AgentEvent): void {\n session.eventLog.push({ timestamp: Date.now(), event });\n // Keep log bounded\n if (session.eventLog.length > 500) session.eventLog.shift();\n\n switch (event.kind) {\n case 'agent_spawned': {\n const agent: AgentState = {\n id: event.agentId,\n type: event.agentType,\n label: event.label,\n status: 'idle',\n parentId: event.parentId,\n department: event.department,\n currentTask: null,\n costUsd: 0,\n };\n session.agents.set(event.agentId, agent);\n\n if (event.parentId) {\n session.edges.push({\n id: `edge-${event.parentId}-${event.agentId}`,\n source: event.parentId,\n target: event.agentId,\n edgeType: 'hierarchy',\n active: true,\n label: '',\n });\n }\n break;\n }\n\n case 'agent_destroyed': {\n session.agents.delete(event.agentId);\n session.edges = session.edges.filter(\n (e) => e.source !== event.agentId && e.target !== event.agentId,\n );\n break;\n }\n\n case 'state_changed': {\n const a = session.agents.get(event.agentId);\n if (a) a.status = event.to;\n break;\n }\n\n case 'task_assigned': {\n const a = session.agents.get(event.agentId);\n if (a) {\n a.currentTask = event.taskSummary;\n a.status = 'working';\n }\n break;\n }\n\n case 'task_completed': {\n const a = session.agents.get(event.agentId);\n if (a) {\n a.currentTask = null;\n a.status = event.result === 'success' ? 'completed' : 'failed';\n }\n break;\n }\n\n case 'message_sent': {\n const edgeId = `msg-${event.fromId}-${event.toId}-${Date.now()}`;\n session.edges.push({\n id: edgeId,\n source: event.fromId,\n target: event.toId,\n edgeType: 'message',\n active: true,\n label: event.summary,\n });\n // Remove transient message edges after 5 seconds\n setTimeout(() => {\n session.edges = session.edges.filter((e) => e.id !== edgeId);\n }, 5_000);\n break;\n }\n\n case 'mention_created':\n case 'mention_resolved':\n // Logged but don't mutate the agent graph.\n break;\n\n case 'cost_update': {\n session.totalCost = event.totalCost;\n break;\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // Private — flush debounced events\n // -----------------------------------------------------------------------\n\n private flushEvents(sessionId: string): void {\n const events = this.pendingEvents.get(sessionId);\n const session = this.sessions.get(sessionId);\n if (!events || !session || events.length === 0) return;\n\n const delta: SessionDelta = {\n type: 'session-delta',\n sessionId,\n displayName: session.displayName,\n timestamp: Date.now(),\n events: [...events],\n };\n\n this.emit('broadcast', JSON.stringify(delta));\n this.pendingEvents.set(sessionId, []);\n }\n}\n","import WebSocket from 'ws';\nimport type { AgentEvent, RegisterMessage, SessionEventMessage, UnregisterMessage } from '../types/dashboard-events.js';\nimport { eventBus } from '../orchestrator/event-bus.js';\nimport { logger } from '../utils/logger.js';\n\nexport class DashboardClient {\n private ws: WebSocket | null = null;\n private sessionId: string;\n private projectName: string;\n private projectPath: string;\n\n constructor(sessionId: string, projectName: string, projectPath: string) {\n this.sessionId = sessionId;\n this.projectName = projectName;\n this.projectPath = projectPath;\n }\n\n connect(port: number): void {\n this.ws = new WebSocket(`ws://127.0.0.1:${port}`);\n\n this.ws.on('open', () => {\n logger.info(`Connected to dashboard as client (session: ${this.sessionId})`);\n // Register this session\n const msg: RegisterMessage = {\n type: 'register',\n sessionId: this.sessionId,\n projectPath: this.projectPath,\n projectName: this.projectName,\n };\n this.ws!.send(JSON.stringify(msg));\n\n // Forward local events to the dashboard server\n eventBus.on('agent_event', (event: AgentEvent) => {\n if (this.ws?.readyState === WebSocket.OPEN) {\n const sessionMsg: SessionEventMessage = {\n type: 'session-event',\n sessionId: this.sessionId,\n event,\n };\n this.ws.send(JSON.stringify(sessionMsg));\n }\n });\n });\n\n this.ws.on('error', (err) => {\n logger.warn(`Dashboard client error: ${err.message}`);\n });\n\n this.ws.on('close', () => {\n logger.info('Dashboard client disconnected');\n });\n }\n\n disconnect(): void {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n const msg: UnregisterMessage = {\n type: 'unregister',\n sessionId: this.sessionId,\n };\n this.ws.send(JSON.stringify(msg));\n this.ws.close();\n }\n this.ws = null;\n }\n}\n"],"mappings":";;;;;;AAAA,SAAS,kBAAkB;AAC3B,SAAS,4BAA4B;;;ACDrC,SAAS,iBAAiB;;;ACA1B,SAAS,SAAS;;;ACAlB,SAAS,MAAMA,eAAc;;;ACA7B,SAAS,MAAM,cAAc;AAmB7B,SAAS,WAAW,KAA0B;AAC5C,SAAO;AAAA,IACL,IAAI,IAAI;AAAA,IACR,MAAM,IAAI;AAAA,IACV,MAAM,IAAI;AAAA,IACV,YAAY,IAAI;AAAA,IAChB,UAAU,IAAI;AAAA,IACd,WAAW,IAAI;AAAA,IACf,QAAQ,IAAI;AAAA,IACZ,aAAa,IAAI;AAAA,IACjB,WAAW,IAAI;AAAA,IACf,WAAW,IAAI;AAAA,IACf,aAAa,IAAI;AAAA,IACjB,SAAS,IAAI;AAAA,EACf;AACF;AAEO,SAAS,YACd,OAMW;AACX,QAAM,KAAK,MAAM;AACjB,QAAM,KAAK,MAAM,MAAM,OAAO;AAC9B,QAAM,YAAY,MAAM,aAAa,KAAK,IAAI;AAC9C,QAAM,cAAc,MAAM,eAAe;AACzC,QAAM,UAAU,MAAM,WAAW;AAEjC,KAAG;AAAA,IACD;AAAA;AAAA,EAEF,EAAE;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,MAAM,MAAM;AAAA,IACZ,MAAM,MAAM;AAAA,IACZ,YAAY,MAAM;AAAA,IAClB,UAAU,MAAM;AAAA,IAChB,WAAW,MAAM;AAAA,IACjB,QAAQ,MAAM;AAAA,IACd,aAAa,MAAM;AAAA,IACnB,WAAW,MAAM;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,SAAS,IAA8B;AACrD,QAAM,KAAK,MAAM;AACjB,QAAM,MAAM,GAAG,QAAQ,mCAAmC,EAAE,IAAI,EAAE;AAClE,SAAO,MAAM,WAAW,GAAG,IAAI;AACjC;AAEO,SAAS,YACd,IACA,SACkB;AAClB,QAAM,KAAK,MAAM;AACjB,QAAM,WAAW,SAAS,EAAE;AAC5B,MAAI,CAAC,SAAU,QAAO;AAEtB,QAAM,SAAmB,CAAC;AAC1B,QAAM,SAAoB,CAAC;AAE3B,MAAI,QAAQ,SAAS,QAAW;AAAE,WAAO,KAAK,UAAU;AAAG,WAAO,KAAK,QAAQ,IAAI;AAAA,EAAG;AACtF,MAAI,QAAQ,SAAS,QAAW;AAAE,WAAO,KAAK,UAAU;AAAG,WAAO,KAAK,QAAQ,IAAI;AAAA,EAAG;AACtF,MAAI,QAAQ,eAAe,QAAW;AAAE,WAAO,KAAK,gBAAgB;AAAG,WAAO,KAAK,QAAQ,UAAU;AAAA,EAAG;AACxG,MAAI,QAAQ,aAAa,QAAW;AAAE,WAAO,KAAK,eAAe;AAAG,WAAO,KAAK,QAAQ,QAAQ;AAAA,EAAG;AACnG,MAAI,QAAQ,cAAc,QAAW;AAAE,WAAO,KAAK,gBAAgB;AAAG,WAAO,KAAK,QAAQ,SAAS;AAAA,EAAG;AACtG,MAAI,QAAQ,WAAW,QAAW;AAAE,WAAO,KAAK,YAAY;AAAG,WAAO,KAAK,QAAQ,MAAM;AAAA,EAAG;AAC5F,MAAI,QAAQ,gBAAgB,QAAW;AAAE,WAAO,KAAK,kBAAkB;AAAG,WAAO,KAAK,QAAQ,WAAW;AAAA,EAAG;AAC5G,MAAI,QAAQ,cAAc,QAAW;AAAE,WAAO,KAAK,gBAAgB;AAAG,WAAO,KAAK,QAAQ,SAAS;AAAA,EAAG;AACtG,MAAI,QAAQ,cAAc,QAAW;AAAE,WAAO,KAAK,gBAAgB;AAAG,WAAO,KAAK,QAAQ,SAAS;AAAA,EAAG;AACtG,MAAI,QAAQ,gBAAgB,QAAW;AAAE,WAAO,KAAK,kBAAkB;AAAG,WAAO,KAAK,QAAQ,WAAW;AAAA,EAAG;AAC5G,MAAI,QAAQ,YAAY,QAAW;AAAE,WAAO,KAAK,cAAc;AAAG,WAAO,KAAK,QAAQ,OAAO;AAAA,EAAG;AAEhG,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,SAAO,KAAK,EAAE;AACd,KAAG,QAAQ,qBAAqB,OAAO,KAAK,IAAI,CAAC,eAAe,EAAE,IAAI,GAAG,MAAM;AAE/E,SAAO,SAAS,EAAE;AACpB;AAEO,SAAS,oBAAoB,WAAgC;AAClE,QAAM,KAAK,MAAM;AACjB,QAAM,OAAO,GACV,QAAQ,2CAA2C,EACnD,IAAI,SAAS;AAChB,SAAO,KAAK,IAAI,UAAU;AAC5B;AAEO,SAAS,mBAAmB,UAA+B;AAChE,QAAM,KAAK,MAAM;AACjB,QAAM,OAAO,GACV,QAAQ,0CAA0C,EAClD,IAAI,QAAQ;AACf,SAAO,KAAK,IAAI,UAAU;AAC5B;AAMO,SAAS,aAAa,QAAsC;AACjE,QAAM,QAAQ,SAAS,MAAM;AAC7B,MAAI,CAAC,MAAO,QAAO;AAEnB,QAAM,WAAW,mBAAmB,MAAM;AAC1C,QAAM,WAA0B;AAAA,IAC9B,GAAG;AAAA,IACH,UAAU,SACP,IAAI,CAAC,UAAU,aAAa,MAAM,EAAE,CAAC,EACrC,OAAO,CAAC,SAAgC,SAAS,IAAI;AAAA,EAC1D;AAEA,SAAO;AACT;;;AC1JA,SAAS,MAAMC,eAAc;AAkB7B,SAAS,gCAAsC;AAC7C,QAAM,KAAK,MAAM;AAEjB,QAAM,OAAO,GAAG,QAAQ,+BAA+B,EAAE,IAAI;AAC7D,QAAM,YAAY,KAAK,KAAK,CAAC,MAAM,EAAE,SAAS,qBAAqB;AACnE,MAAI,CAAC,WAAW;AACd,OAAG,KAAK,uEAAuE;AAAA,EACjF;AACF;AAEA,IAAI,gBAAgB;AAEpB,SAAS,aAAa,KAA0B;AAC9C,SAAO;AAAA,IACL,IAAI,IAAI;AAAA,IACR,OAAO,IAAI;AAAA,IACX,QAAQ,KAAK,MAAM,IAAI,MAAM;AAAA,IAC7B,gBAAgB,KAAK,MAAM,IAAI,eAAe;AAAA,IAC9C,QAAQ,IAAI;AAAA,IACZ,OAAO,IAAI;AAAA,IACX,WAAW,IAAI;AAAA,IACf,aAAa,IAAI;AAAA,IACjB,aAAa,IAAI;AAAA,IACjB,mBAAmB,IAAI,uBAAuB;AAAA,EAChD;AACF;AAEO,SAAS,cACd,SAQS;AACT,MAAI,CAAC,eAAe;AAClB,kCAA8B;AAC9B,oBAAgB;AAAA,EAClB;AAEA,QAAM,KAAK,MAAM;AACjB,QAAM,KAAK,QAAQ,MAAMC,QAAO;AAChC,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,cAAc,QAAQ,eAAe;AAC3C,QAAM,oBAAoB,QAAQ,qBAAqB;AAEvD,KAAG;AAAA,IACD;AAAA;AAAA,EAEF,EAAE;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,KAAK,UAAU,QAAQ,MAAM;AAAA,IAC7B,KAAK,UAAU,QAAQ,cAAc;AAAA,IACrC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,OAAO,QAAQ;AAAA,IACf,QAAQ,QAAQ;AAAA,IAChB,gBAAgB,QAAQ;AAAA,IACxB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa,QAAQ;AAAA,IACrB;AAAA,EACF;AACF;AAEO,SAAS,WAAW,IAA4B;AACrD,MAAI,CAAC,eAAe;AAClB,kCAA8B;AAC9B,oBAAgB;AAAA,EAClB;AAEA,QAAM,KAAK,MAAM;AACjB,QAAM,MAAM,GAAG,QAAQ,qCAAqC,EAAE,IAAI,EAAE;AACpE,SAAO,MAAM,aAAa,GAAG,IAAI;AACnC;AAEO,SAAS,cACd,IACA,SACgB;AAChB,QAAM,KAAK,MAAM;AACjB,QAAM,WAAW,WAAW,EAAE;AAC9B,MAAI,CAAC,SAAU,QAAO;AAEtB,QAAM,SAAmB,CAAC;AAC1B,QAAM,SAAoB,CAAC;AAE3B,MAAI,QAAQ,UAAU,QAAW;AAAE,WAAO,KAAK,WAAW;AAAG,WAAO,KAAK,QAAQ,KAAK;AAAA,EAAG;AACzF,MAAI,QAAQ,WAAW,QAAW;AAAE,WAAO,KAAK,YAAY;AAAG,WAAO,KAAK,KAAK,UAAU,QAAQ,MAAM,CAAC;AAAA,EAAG;AAC5G,MAAI,QAAQ,mBAAmB,QAAW;AAAE,WAAO,KAAK,qBAAqB;AAAG,WAAO,KAAK,KAAK,UAAU,QAAQ,cAAc,CAAC;AAAA,EAAG;AACrI,MAAI,QAAQ,WAAW,QAAW;AAAE,WAAO,KAAK,YAAY;AAAG,WAAO,KAAK,QAAQ,MAAM;AAAA,EAAG;AAC5F,MAAI,QAAQ,UAAU,QAAW;AAAE,WAAO,KAAK,WAAW;AAAG,WAAO,KAAK,QAAQ,KAAK;AAAA,EAAG;AACzF,MAAI,QAAQ,cAAc,QAAW;AAAE,WAAO,KAAK,gBAAgB;AAAG,WAAO,KAAK,QAAQ,SAAS;AAAA,EAAG;AACtG,MAAI,QAAQ,gBAAgB,QAAW;AAAE,WAAO,KAAK,kBAAkB;AAAG,WAAO,KAAK,QAAQ,WAAW;AAAA,EAAG;AAC5G,MAAI,QAAQ,gBAAgB,QAAW;AAAE,WAAO,KAAK,kBAAkB;AAAG,WAAO,KAAK,QAAQ,WAAW;AAAA,EAAG;AAC5G,MAAI,QAAQ,sBAAsB,QAAW;AAAE,WAAO,KAAK,yBAAyB;AAAG,WAAO,KAAK,QAAQ,iBAAiB;AAAA,EAAG;AAE/H,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,SAAO,KAAK,EAAE;AACd,KAAG,QAAQ,uBAAuB,OAAO,KAAK,IAAI,CAAC,eAAe,EAAE,IAAI,GAAG,MAAM;AAEjF,SAAO,WAAW,EAAE;AACtB;AAEO,SAAS,aAAa,cAAyC;AACpE,MAAI,CAAC,eAAe;AAClB,kCAA8B;AAC9B,oBAAgB;AAAA,EAClB;AAEA,QAAM,KAAK,MAAM;AACjB,MAAI;AAEJ,MAAI,cAAc;AAChB,WAAO,GACJ,QAAQ,kEAAkE,EAC1E,IAAI,YAAY;AAAA,EACrB,OAAO;AACL,WAAO,GACJ,QAAQ,iDAAiD,EACzD,IAAI;AAAA,EACT;AAEA,SAAO,KAAK,IAAI,YAAY;AAC9B;;;AC9JA,SAAS,MAAMC,eAAc;AAoB7B,SAAS,YAAY,KAA8B;AACjD,SAAO;AAAA,IACL,IAAI,IAAI;AAAA,IACR,UAAU,IAAI;AAAA,IACd,WAAW,IAAI;AAAA,IACf,iBAAiB,IAAI;AAAA,IACrB,UAAU,IAAI;AAAA,IACd,QAAQ,IAAI;AAAA,IACZ,cAAc,IAAI;AAAA,IAClB,cAAc,IAAI;AAAA,IAClB,cAAc,IAAI;AAAA,IAClB,cAAc,KAAK,MAAM,IAAI,YAAY;AAAA,IACzC,WAAW,IAAI;AAAA,IACf,aAAa,IAAI;AAAA,IACjB,SAAS,IAAI;AAAA,EACf;AACF;AAsDO,SAAS,UAAU,IAAiC;AACzD,QAAM,KAAK,MAAM;AACjB,QAAM,MAAM,GAAG,QAAQ,oCAAoC,EAAE,IAAI,EAAE;AACnE,SAAO,MAAM,YAAY,GAAG,IAAI;AAClC;AAEO,SAAS,aACd,IACA,SACqB;AACrB,QAAM,KAAK,MAAM;AACjB,QAAM,WAAW,UAAU,EAAE;AAC7B,MAAI,CAAC,SAAU,QAAO;AAEtB,QAAM,SAAmB,CAAC;AAC1B,QAAM,SAAoB,CAAC;AAE3B,MAAI,QAAQ,aAAa,QAAW;AAAE,WAAO,KAAK,eAAe;AAAG,WAAO,KAAK,QAAQ,QAAQ;AAAA,EAAG;AACnG,MAAI,QAAQ,cAAc,QAAW;AAAE,WAAO,KAAK,gBAAgB;AAAG,WAAO,KAAK,QAAQ,SAAS;AAAA,EAAG;AACtG,MAAI,QAAQ,oBAAoB,QAAW;AAAE,WAAO,KAAK,sBAAsB;AAAG,WAAO,KAAK,QAAQ,eAAe;AAAA,EAAG;AACxH,MAAI,QAAQ,aAAa,QAAW;AAAE,WAAO,KAAK,eAAe;AAAG,WAAO,KAAK,QAAQ,QAAQ;AAAA,EAAG;AACnG,MAAI,QAAQ,WAAW,QAAW;AAAE,WAAO,KAAK,YAAY;AAAG,WAAO,KAAK,QAAQ,MAAM;AAAA,EAAG;AAC5F,MAAI,QAAQ,iBAAiB,QAAW;AAAE,WAAO,KAAK,mBAAmB;AAAG,WAAO,KAAK,QAAQ,YAAY;AAAA,EAAG;AAC/G,MAAI,QAAQ,iBAAiB,QAAW;AAAE,WAAO,KAAK,mBAAmB;AAAG,WAAO,KAAK,QAAQ,YAAY;AAAA,EAAG;AAC/G,MAAI,QAAQ,iBAAiB,QAAW;AAAE,WAAO,KAAK,mBAAmB;AAAG,WAAO,KAAK,QAAQ,YAAY;AAAA,EAAG;AAC/G,MAAI,QAAQ,iBAAiB,QAAW;AAAE,WAAO,KAAK,kBAAkB;AAAG,WAAO,KAAK,KAAK,UAAU,QAAQ,YAAY,CAAC;AAAA,EAAG;AAC9H,MAAI,QAAQ,cAAc,QAAW;AAAE,WAAO,KAAK,gBAAgB;AAAG,WAAO,KAAK,QAAQ,SAAS;AAAA,EAAG;AACtG,MAAI,QAAQ,gBAAgB,QAAW;AAAE,WAAO,KAAK,kBAAkB;AAAG,WAAO,KAAK,QAAQ,WAAW;AAAA,EAAG;AAC5G,MAAI,QAAQ,YAAY,QAAW;AAAE,WAAO,KAAK,cAAc;AAAG,WAAO,KAAK,QAAQ,OAAO;AAAA,EAAG;AAEhG,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,SAAO,KAAK,EAAE;AACd,KAAG,QAAQ,sBAAsB,OAAO,KAAK,IAAI,CAAC,eAAe,EAAE,IAAI,GAAG,MAAM;AAEhF,SAAO,UAAU,EAAE;AACrB;AAEO,SAAS,oBAAoB,UAAkC;AACpE,QAAM,KAAK,MAAM;AACjB,QAAM,OAAO,GACV,QAAQ,mEAAmE,EAC3E,IAAI,QAAQ;AACf,SAAO,KAAK,IAAI,WAAW;AAC7B;;;ACtIA,SAAS,MAAMC,eAAc;AAkB7B,SAAS,aAAa,KAAgC;AACpD,SAAO;AAAA,IACL,IAAI,IAAI;AAAA,IACR,WAAW,IAAI;AAAA,IACf,YAAY,IAAI;AAAA,IAChB,SAAS,IAAI;AAAA,IACb,SAAS,KAAK,MAAM,IAAI,OAAO;AAAA,IAC/B,SAAS,IAAI;AAAA,IACb,QAAQ,IAAI;AAAA,IACZ,cAAc,IAAI;AAAA,IAClB,eAAe,IAAI;AAAA,IACnB,WAAW,IAAI;AAAA,IACf,YAAY,IAAI;AAAA,EAClB;AACF;AAgDO,SAAS,WAAW,IAAkC;AAC3D,QAAM,KAAK,MAAM;AACjB,QAAM,MAAM,GAAG,QAAQ,qCAAqC,EAAE,IAAI,EAAE;AACpE,SAAO,MAAM,aAAa,GAAG,IAAI;AACnC;AAEO,SAAS,cACd,IACA,SACsB;AACtB,QAAM,KAAK,MAAM;AACjB,QAAM,WAAW,WAAW,EAAE;AAC9B,MAAI,CAAC,SAAU,QAAO;AAEtB,QAAM,SAAmB,CAAC;AAC1B,QAAM,SAAoB,CAAC;AAE3B,MAAI,QAAQ,cAAc,QAAW;AAAE,WAAO,KAAK,gBAAgB;AAAG,WAAO,KAAK,QAAQ,SAAS;AAAA,EAAG;AACtG,MAAI,QAAQ,eAAe,QAAW;AAAE,WAAO,KAAK,iBAAiB;AAAG,WAAO,KAAK,QAAQ,UAAU;AAAA,EAAG;AACzG,MAAI,QAAQ,YAAY,QAAW;AAAE,WAAO,KAAK,aAAa;AAAG,WAAO,KAAK,QAAQ,OAAO;AAAA,EAAG;AAC/F,MAAI,QAAQ,YAAY,QAAW;AAAE,WAAO,KAAK,aAAa;AAAG,WAAO,KAAK,KAAK,UAAU,QAAQ,OAAO,CAAC;AAAA,EAAG;AAC/G,MAAI,QAAQ,YAAY,QAAW;AAAE,WAAO,KAAK,aAAa;AAAG,WAAO,KAAK,QAAQ,OAAO;AAAA,EAAG;AAC/F,MAAI,QAAQ,WAAW,QAAW;AAAE,WAAO,KAAK,YAAY;AAAG,WAAO,KAAK,QAAQ,MAAM;AAAA,EAAG;AAC5F,MAAI,QAAQ,iBAAiB,QAAW;AAAE,WAAO,KAAK,mBAAmB;AAAG,WAAO,KAAK,QAAQ,YAAY;AAAA,EAAG;AAC/G,MAAI,QAAQ,kBAAkB,QAAW;AAAE,WAAO,KAAK,oBAAoB;AAAG,WAAO,KAAK,QAAQ,aAAa;AAAA,EAAG;AAClH,MAAI,QAAQ,cAAc,QAAW;AAAE,WAAO,KAAK,gBAAgB;AAAG,WAAO,KAAK,QAAQ,SAAS;AAAA,EAAG;AACtG,MAAI,QAAQ,eAAe,QAAW;AAAE,WAAO,KAAK,iBAAiB;AAAG,WAAO,KAAK,QAAQ,UAAU;AAAA,EAAG;AAEzG,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,SAAO,KAAK,EAAE;AACd,KAAG,QAAQ,uBAAuB,OAAO,KAAK,IAAI,CAAC,eAAe,EAAE,IAAI,GAAG,MAAM;AAEjF,SAAO,WAAW,EAAE;AACtB;AAEO,SAAS,sBAAuC;AACrD,QAAM,KAAK,MAAM;AACjB,QAAM,OAAO,GACV,QAAQ,yEAAyE,EACjF,IAAI;AACP,SAAO,KAAK,IAAI,YAAY;AAC9B;AAEO,SAAS,sBAAsB,WAAoC;AACxE,QAAM,KAAK,MAAM;AACjB,QAAM,OAAO,GACV,QAAQ,qEAAqE,EAC7E,IAAI,SAAS;AAChB,SAAO,KAAK,IAAI,YAAY;AAC9B;;;AClIA,SAAS,MAAMC,eAAc;AAa7B,SAAS,aAAa,KAAgC;AACpD,SAAO;AAAA,IACL,IAAI,IAAI;AAAA,IACR,WAAW,IAAI;AAAA,IACf,QAAQ,IAAI;AAAA,IACZ,SAAS,IAAI;AAAA,IACb,aAAa,KAAK,MAAM,IAAI,YAAY;AAAA,IACxC,WAAW,IAAI;AAAA,EACjB;AACF;AAEO,SAAS,cACd,SAIe;AACf,QAAM,KAAK,MAAM;AACjB,QAAM,KAAK,QAAQ,MAAMC,QAAO;AAChC,QAAM,YAAY,QAAQ,aAAa,KAAK,IAAI;AAEhD,KAAG;AAAA,IACD;AAAA;AAAA,EAEF,EAAE;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,KAAK,UAAU,QAAQ,WAAW;AAAA,IAClC;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,WAAW,QAAQ;AAAA,IACnB,QAAQ,QAAQ;AAAA,IAChB,SAAS,QAAQ;AAAA,IACjB,aAAa,QAAQ;AAAA,IACrB;AAAA,EACF;AACF;AAEO,SAAS,oBAAoB,WAAyC;AAC3E,QAAM,KAAK,MAAM;AACjB,QAAM,MAAM,GACT,QAAQ,4CAA4C,EACpD,IAAI,SAAS;AAChB,SAAO,MAAM,aAAa,GAAG,IAAI;AACnC;;;ACrDO,SAAS,oBAAoB,WAAiC;AACnE,QAAM,KAAK,MAAM;AACjB,QAAM,MAAM,GACT,QAAQ,uDAAuD,EAC/D,IAAI,SAAS;AAEhB,MAAI,CAAC,IAAK,QAAO,CAAC;AAElB,SAAO,KAAK,MAAM,IAAI,YAAY;AACpC;;;ACgEO,IAAM,mBAAiD;AAAA,EAC5D,cAAc,CAAC,QAAQ,QAAQ,MAAM;AAAA,EACrC,aAAa,CAAC,QAAQ,QAAQ,QAAQ,SAAS,QAAQ,MAAM;AAAA,EAC7D,IAAI,CAAC,QAAQ,QAAQ,QAAQ,MAAM;AAAA,EACnC,SAAS,CAAC,MAAM;AAAA,EAChB,UAAU,CAAC,QAAQ,QAAQ,QAAQ,WAAW;AAChD;;;AC5EA,IAAM,sBAA+D,oBAAI,IAAgC;AAAA,EACvG;AAAA,IACE;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MAEF,YAAY;AAAA,MACZ,aAAa,CAAC,mBAAmB,gBAAgB,qBAAqB;AAAA,MACtE,cAAc,iBAAiB;AAAA,IACjC;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MAEF,YAAY;AAAA,MACZ,aAAa,CAAC,eAAe,aAAa,YAAY;AAAA,MACtD,cAAc,iBAAiB;AAAA,IACjC;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MAEF,YAAY;AAAA,MACZ,aAAa,CAAC,eAAe,eAAe,oBAAoB,aAAa;AAAA,MAC7E,cAAc,iBAAiB;AAAA,IACjC;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MAEF,YAAY;AAAA,MACZ,aAAa,CAAC,yBAAyB,kBAAkB;AAAA,MACzD,cAAc,iBAAiB;AAAA,IACjC;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MAEF,YAAY;AAAA,MACZ,aAAa,CAAC,iBAAiB,gBAAgB,kBAAkB;AAAA,MACjE,cAAc,iBAAiB;AAAA,IACjC;AAAA,EACF;AACF,CAAC;AAGD,IAAM,qBAA0D,IAAI;AAAA,EAClE,CAAC,GAAG,oBAAoB,OAAO,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC;AACrE;AAMO,SAAS,cAAc,MAAkC;AAC9D,QAAM,OAAO,oBAAoB,IAAI,IAAI;AACzC,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,MAAM,uBAAuB,IAAI,EAAE;AAAA,EAC/C;AACA,SAAO;AACT;;;AC1FA,SAAS,oBAAoB;AAsB7B,IAAM,WAAN,MAAe;AAAA,EACI,UAAU,IAAI,aAAa;AAAA,EAE5C,cAAc;AAEZ,SAAK,QAAQ,gBAAgB,EAAE;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,eAAe,OAAyB;AACtC,SAAK,QAAQ,KAAK,eAAe,KAAK;AAGtC,UAAM,QAAwB;AAAA,MAC5B,MAAM;AAAA,MACN,WAAW,KAAK,IAAI;AAAA,MACpB,QAAQ,CAAC,KAAK;AAAA,IAChB;AACA,SAAK,QAAQ,KAAK,aAAa,KAAK;AAAA,EAKtC;AAAA;AAAA;AAAA;AAAA,EAKA,sBAAsB,UAAgC;AACpD,SAAK,QAAQ,KAAK,aAAa,QAAQ;AAAA,EACzC;AAAA;AAAA,EAIA,GAAmC,OAAU,UAAsD;AACjG,SAAK,QAAQ,GAAG,OAAO,QAAwC;AAAA,EACjE;AAAA,EAEA,IAAoC,OAAU,UAAsD;AAClG,SAAK,QAAQ,IAAI,OAAO,QAAwC;AAAA,EAClE;AAAA,EAEA,KAAqC,OAAU,UAAsD;AACnG,SAAK,QAAQ,KAAK,OAAO,QAAwC;AAAA,EACnE;AAAA;AAAA,EAIA,mBAAmB,OAAoC;AACrD,QAAI,OAAO;AACT,WAAK,QAAQ,mBAAmB,KAAK;AAAA,IACvC,OAAO;AACL,WAAK,QAAQ,mBAAmB;AAAA,IAClC;AAAA,EACF;AAAA,EAEA,cAAc,OAAqC;AACjD,WAAO,KAAK,QAAQ,cAAc,KAAK;AAAA,EACzC;AACF;AAOO,IAAM,WAAW,IAAI,SAAS;;;AClErC,IAAM,iBAA2C;AAAA,EAC/C,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AACT;AAMA,IAAM,SAAN,MAAa;AAAA,EACH,WAAqB;AAAA;AAAA;AAAA;AAAA;AAAA,EAM7B,SAAS,OAAuB;AAC9B,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,WAAqB;AACnB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,SAAiB,SAA4B;AACjD,SAAK,IAAI,SAAS,SAAS,OAAO;AAAA,EACpC;AAAA,EAEA,KAAK,SAAiB,SAA4B;AAChD,SAAK,IAAI,QAAQ,SAAS,OAAO;AAAA,EACnC;AAAA,EAEA,KAAK,SAAiB,SAA4B;AAChD,SAAK,IAAI,QAAQ,SAAS,OAAO;AAAA,EACnC;AAAA,EAEA,MAAM,SAAiB,SAA4B;AACjD,SAAK,IAAI,SAAS,SAAS,OAAO;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAMQ,IAAI,OAAiB,SAAiB,SAA4B;AACxE,QAAI,eAAe,KAAK,IAAI,eAAe,KAAK,QAAQ,GAAG;AACzD;AAAA,IACF;AAEA,UAAM,QAAkB;AAAA,MACtB,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MAClC;AAAA,MACA;AAAA,IACF;AAEA,QAAI,WAAW,OAAO,KAAK,OAAO,EAAE,SAAS,GAAG;AAC9C,YAAM,UAAU;AAAA,IAClB;AAGA,YAAQ,OAAO,MAAM,KAAK,UAAU,KAAK,IAAI,IAAI;AAAA,EACnD;AACF;AAOO,IAAM,SAAS,IAAI,OAAO;;;AC3F1B,IAAM,aAAN,MAAiB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKL,gBAAgB,oBAAI,IAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAU5D,YAAY,YAAwB,WAA8B;AAChE,UAAM,WAAW,cAAc,UAAU;AAEzC,UAAM,QAAQ,YAAY;AAAA,MACxB,MAAM;AAAA,MACN,MAAM,SAAS;AAAA,MACf;AAAA,MACA,UAAU;AAAA;AAAA,MACV;AAAA,MACA,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,WAAW;AAAA,IACb,CAAC;AAED,SAAK,cAAc,IAAI,MAAM,IAAI,KAAK;AAEtC,WAAO,KAAK,mBAAmB,SAAS,UAAU,IAAI;AAAA,MACpD,SAAS,MAAM;AAAA,MACf;AAAA,MACA;AAAA,IACF,CAAC;AAED,aAAS,eAAe;AAAA,MACtB,MAAM;AAAA,MACN,SAAS,MAAM;AAAA,MACf,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO,SAAS;AAAA,MAChB;AAAA,IACF,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,qBAAqB,WAAgC;AAEnD,UAAM,YAAY,CAAC,GAAG,KAAK,cAAc,OAAO,CAAC,EAAE;AAAA,MACjD,CAAC,MAAM,EAAE,cAAc;AAAA,IACzB;AAEA,QAAI,UAAU,SAAS,GAAG;AACxB,aAAO;AAAA,IACT;AAGA,WAAO,oBAAoB,SAAS,EAAE;AAAA,MACpC,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,WAAW,eAAe,EAAE,WAAW;AAAA,IACzE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAAiB,UAAwB;AACvC,UAAM,SAAS,KAAK,cAAc,IAAI,QAAQ;AAE9C,gBAAY,UAAU;AAAA,MACpB,QAAQ;AAAA,MACR,aAAa,KAAK,IAAI;AAAA,IACxB,CAAC;AAED,SAAK,cAAc,OAAO,QAAQ;AAElC,WAAO,KAAK,uBAAuB,QAAQ,IAAI;AAAA,MAC7C,SAAS;AAAA,MACT,YAAY,QAAQ;AAAA,IACtB,CAAC;AAED,aAAS,eAAe;AAAA,MACtB,MAAM;AAAA,MACN,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AACF;;;AXtFA,IAAM,sBAAoD;AAAA,EACxD,cAAc;AAAA,IACZ;AAAA,IAAgB;AAAA,IAAU;AAAA,IAAU;AAAA,IAAO;AAAA,IAAc;AAAA,IACzD;AAAA,IAAa;AAAA,IAAY;AAAA,IAAY;AAAA,IAAoB;AAAA,IACzD;AAAA,IAAiB;AAAA,IAAa;AAAA,EAChC;AAAA,EACA,aAAa;AAAA,IACX;AAAA,IAAQ;AAAA,IAAa;AAAA,IAAS;AAAA,IAAW;AAAA,IAAO;AAAA,IAAO;AAAA,IACvD;AAAA,IAAW;AAAA,IAAY;AAAA,IAAS;AAAA,IAAU;AAAA,IAAS;AAAA,IACnD;AAAA,IAAU;AAAA,IAAU;AAAA,IAAU;AAAA,IAAQ;AAAA,IAAY;AAAA,EACpD;AAAA,EACA,IAAI;AAAA,IACF;AAAA,IAAQ;AAAA,IAAW;AAAA,IAAY;AAAA,IAAe;AAAA,IAAS;AAAA,IACvD;AAAA,IAAc;AAAA,IAAa;AAAA,IAAiB;AAAA,IAAY;AAAA,IACxD;AAAA,IAAa;AAAA,IAAO;AAAA,IAAoB;AAAA,EAC1C;AAAA,EACA,SAAS;AAAA,IACP;AAAA,IAAgB;AAAA,IAAQ;AAAA,IAAS;AAAA,IAAY;AAAA,IAC7C;AAAA,IAAa;AAAA,IAAe;AAAA,IAAW;AAAA,IAAS;AAAA,IAChD;AAAA,IAAW;AAAA,IAAO;AAAA,EACpB;AAAA,EACA,UAAU;AAAA,IACR;AAAA,IAAY;AAAA,IAAW;AAAA,IAAe;AAAA,IAAU;AAAA,IAAW;AAAA,IAC3D;AAAA,IAAY;AAAA,IAAa;AAAA,IAAW;AAAA,IAAU;AAAA,IAC9C;AAAA,IAAa;AAAA,EACf;AACF;AAqCO,IAAM,eAAN,MAAmB;AAAA,EACP,aAAa,IAAI,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA,EAM5B;AAAA,EAEjB,YAAY,gBAAyB;AACnC,SAAK,iBAAiB,kBAAkB;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,cAAc,OAAe,QAAgC;AAC3D,UAAM,SAAS,CAAC,OAAO,GAAG,MAAM,EAAE,KAAK,GAAG,EAAE,YAAY;AAExD,UAAM,SAAS,oBAAI,IAAwB;AAE3C,eAAW,CAAC,MAAM,QAAQ,KAAK,OAAO,QAAQ,mBAAmB,GAA+B;AAC9F,UAAI,QAAQ;AACZ,iBAAW,MAAM,UAAU;AACzB,YAAI,OAAO,SAAS,EAAE,GAAG;AACvB;AAAA,QACF;AAAA,MACF;AACA,UAAI,QAAQ,GAAG;AACb,eAAO,IAAI,MAAM,KAAK;AAAA,MACxB;AAAA,IACF;AAEA,QAAI,OAAO,SAAS,GAAG;AAGrB,UAAI,OAAO,UAAU,GAAG;AACtB,eAAO,MAAM,gFAAgF;AAAA,UAC3F,WAAW;AAAA,QACb,CAAC;AACD,eAAO,CAAC,gBAAgB,aAAa;AAAA,MACvC;AACA,aAAO,MAAM,qEAAqE;AAAA,QAChF,WAAW;AAAA,MACb,CAAC;AACD,aAAO,CAAC,aAAa;AAAA,IACvB;AAGA,UAAM,WAAW,CAAC,GAAG,OAAO,QAAQ,CAAC,EAClC,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,EAC1B,IAAI,CAAC,CAAC,IAAI,MAAM,IAAI;AAEvB,WAAO,MAAM,yBAAyB,SAAS,KAAK,IAAI,CAAC,IAAI,EAAE,WAAW,MAAM,CAAC;AAEjF,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,aAAa,MAA+C;AAC1D,UAAM,EAAE,OAAO,OAAO,IAAI;AAC1B,UAAM,cAAc,KAAK,eAAe,KAAK,cAAc,OAAO,MAAM;AAExE,WAAO,KAAK,sBAAsB,KAAK,wBAAwB,YAAY,KAAK,IAAI,CAAC,GAAG;AAGxF,UAAM,YAAYC,QAAO;AACzB,kBAAc;AAAA,MACZ,IAAI;AAAA,MACJ;AAAA,MACA;AAAA,MACA,gBAAgB,YAAY,IAAI,CAAC,MAAM,GAAG,CAAC,SAAS;AAAA,MACpD,aAAa,KAAK;AAAA,MAClB,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,WAAW,KAAK,IAAI;AAAA,MACpB,mBAAmB,KAAK,qBAAqB;AAAA,IAC/C,CAAC;AAED,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,aAAa,MAKU;AACrB,UAAM,kBAAkB,WAAW,KAAK,iBAAiB;AACzD,QAAI,CAAC,iBAAiB;AACpB,YAAM,IAAI,MAAM,+BAA+B,KAAK,iBAAiB,EAAE;AAAA,IACzE;AAEA,UAAM,kBAAkB,oBAAoB,KAAK,iBAAiB;AAClE,QAAI,CAAC,iBAAiB;AACpB,YAAM,IAAI,MAAM,0CAA0C,KAAK,iBAAiB,EAAE;AAAA,IACpF;AAGA,UAAM,gBACJ,0BAA0B,gBAAgB,KAAK,MAAM,KAAK,iBAAiB;AAAA;AAAA;AAAA,EACtC,gBAAgB,OAAO;AAAA;AAAA;AAAA;AAE9D,UAAM,gBAAgB,gBAAgB,KAAK;AAE3C,WAAO;AAAA,MACL,0BAA0B,gBAAgB,KAAK,SAAS,KAAK,KAAK;AAAA,MAClE,EAAE,WAAW,KAAK,kBAAkB;AAAA,IACtC;AAEA,WAAO,KAAK,aAAa;AAAA,MACvB,OAAO;AAAA,MACP,QAAQ,KAAK;AAAA,MACb,aAAa,KAAK;AAAA,MAClB,mBAAmB,KAAK;AAAA,IAC1B,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,YAAgC;AAE9B,UAAM,cAAc,aAAa;AACjC,UAAM,iBAAiB,YAAY;AAAA,MACjC,CAAC,MAAM,CAAC,CAAC,aAAa,aAAa,UAAU,YAAY,WAAW,EAAE,SAAS,EAAE,MAAM;AAAA,IACzF;AAGA,UAAM,kBAAkB,oBAAoB;AAG5C,UAAM,YAAY,aAAa,KAAK,cAAc;AAElD,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA,EAKA,gBAA4B;AAC1B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,QAAgB;AACd,WAAO,KAAK;AAAA,EACd;AACF;;;AD/QO,IAAM,qBAAqB;AAAA,EAChC,OAAO,EAAE,OAAO,EAAE,SAAS,eAAe;AAAA,EAC1C,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,cAAc;AAAA,EACnD,aAAa,EACV,MAAM,EAAE,OAAO,CAAC,EAChB,SAAS,EACT,SAAS,gCAAgC;AAC9C;AAEA,eAAsB,oBAAoB;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AACF,GAI8E;AAC5E,MAAI;AACF,UAAM,eAAe,IAAI,aAAa;AACtC,UAAM,SAAS,aAAa,aAAa;AAAA,MACvC;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;Aa1CA,SAAS,KAAAC,UAAS;AAQX,IAAM,yBAAyB;AAAA,EACpC,WAAWC,GACR,OAAO,EACP,SAAS,EACT,SAAS,6CAA6C;AAC3D;AAEA,eAAsB,wBAAwB;AAAA,EAC5C;AACF,GAE8E;AAC5E,MAAI;AACF,QAAI,WAAW;AACb,YAAM,UAAU,WAAW,SAAS;AACpC,UAAI,CAAC,SAAS;AACZ,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,KAAK;AAAA,gBACT,EAAE,OAAO,sBAAsB,SAAS,GAAG;AAAA,gBAC3C;AAAA,gBACA;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF;AAEA,YAAM,SAAS,oBAAoB,SAAS;AAC5C,YAAM,UAAU,OAAO;AAAA,QAAQ,CAAC,UAC9B,oBAAoB,MAAM,EAAE;AAAA,MAC9B;AAEA,YAAMC,UAAS;AAAA,QACb;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAUA,SAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,MACnE;AAAA,IACF;AAGA,UAAM,cAAc,aAAa;AACjC,UAAM,iBAAiB,YAAY;AAAA,MACjC,CAAC,MACC,CAAC,CAAC,aAAa,aAAa,UAAU,YAAY,WAAW,EAAE;AAAA,QAC7D,EAAE;AAAA,MACJ;AAAA,IACJ;AAEA,UAAM,SAAS;AAAA,MACb,eAAe,YAAY;AAAA,MAC3B,gBAAgB,eAAe,IAAI,CAAC,OAAO;AAAA,QACzC,IAAI,EAAE;AAAA,QACN,OAAO,EAAE;AAAA,QACT,QAAQ,EAAE;AAAA,QACV,OAAO,EAAE;AAAA,QACT,WAAW,EAAE;AAAA,MACf,EAAE;AAAA,IACJ;AAEA,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;ACvFA,SAAS,KAAAC,UAAS;AAGX,IAAM,mBAAmB;AAAA,EAC9B,WAAWC,GAAE,OAAO,EAAE,SAAS,YAAY;AAAA,EAC3C,QAAQA,GACL,KAAK,CAAC,QAAQ,WAAW,YAAY,CAAC,EACtC,QAAQ,MAAM,EACd,SAAS,EACT,SAAS,eAAe;AAC7B;AAEA,eAAsB,kBAAkB;AAAA,EACtC;AAAA,EACA;AACF,GAG8E;AAC5E,MAAI;AACF,UAAM,UAAU,oBAAoB,SAAS;AAC7C,QAAI,CAAC,SAAS;AACZ,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK;AAAA,cACT,EAAE,OAAO,iCAAiC,SAAS,GAAG;AAAA,cACtD;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,QACA,SAAS;AAAA,MACX;AAAA,IACF;AAEA,UAAM,kBAAkB,UAAU;AAElC,QAAI;AAEJ,YAAQ,iBAAiB;AAAA,MACvB,KAAK;AACH,iBAAS;AAAA,UACP,IAAI,QAAQ;AAAA,UACZ,WAAW,QAAQ;AAAA,UACnB,QAAQ,QAAQ;AAAA,UAChB,SAAS,QAAQ;AAAA,UACjB,aAAa,QAAQ;AAAA,UACrB,WAAW,QAAQ;AAAA,QACrB;AACA;AAAA,MAEF,KAAK,WAAW;AAEd,cAAM,iBACJ,QAAQ,QAAQ,SAAS,MACrB,QAAQ,QAAQ,MAAM,GAAG,GAAG,IAAI,QAChC,QAAQ;AACd,iBAAS;AAAA,UACP,IAAI,QAAQ;AAAA,UACZ,WAAW,QAAQ;AAAA,UACnB,SAAS;AAAA,UACT,iBAAiB,QAAQ,YAAY;AAAA,UACrC,WAAW,QAAQ;AAAA,QACrB;AACA;AAAA,MACF;AAAA,MAEA,KAAK;AACH,iBAAS;AAAA,UACP,WAAW,QAAQ;AAAA,UACnB,aAAa,QAAQ;AAAA,UACrB,YAAY,QAAQ,YAAY;AAAA,QAClC;AACA;AAAA,IACJ;AAEA,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;AC1FA,SAAS,KAAAC,UAAS;;;ACMlB,SAAS,MAAMC,eAAc;AAU7B,IAAMC,uBAAoD;AAAA,EACxD,cAAc;AAAA,IACZ;AAAA,IAAU;AAAA,IAAU;AAAA,IAAgB;AAAA,IAAa;AAAA,IACjD;AAAA,IAAc;AAAA,IAAiB;AAAA,IAAQ;AAAA,EACzC;AAAA,EACA,aAAa;AAAA,IACX;AAAA,IAAa;AAAA,IAAQ;AAAA,IAAW;AAAA,IAAS;AAAA,IAAY;AAAA,IACrD;AAAA,IAAW;AAAA,IAAU;AAAA,IAAM;AAAA,IAAM;AAAA,EACnC;AAAA,EACA,IAAI;AAAA,IACF;AAAA,IAAQ;AAAA,IAAW;AAAA,IAAY;AAAA,IAAY;AAAA,IAAS;AAAA,IACpD;AAAA,IAAc;AAAA,IAAc;AAAA,IAAO;AAAA,IAAM;AAAA,EAC3C;AAAA,EACA,SAAS;AAAA,IACP;AAAA,IAAe;AAAA,IAAc;AAAA,IAAuB;AAAA,IACpD;AAAA,IAAY;AAAA,IAAW;AAAA,IAAS;AAAA,IAAQ;AAAA,EAC1C;AAAA,EACA,UAAU;AAAA,IACR;AAAA,IAAY;AAAA,IAAW;AAAA,IAAe;AAAA,IAAa;AAAA,IACnD;AAAA,IAAY;AAAA,IAAO;AAAA,IAAa;AAAA,IAAM;AAAA,EACxC;AACF;AAMA,IAAM,oBAA8D;AAAA,EAClE,UAAU;AAAA,IACR;AAAA,IAAY;AAAA,IAAU;AAAA,IAAW;AAAA,IAAY;AAAA,IAAQ;AAAA,IACrD;AAAA,IAAM;AAAA,IAAM;AAAA,EACd;AAAA,EACA,MAAM;AAAA,IACJ;AAAA,IAAiB;AAAA,IAAa;AAAA,IAAQ;AAAA,IAAY;AAAA,IAClD;AAAA,IAAM;AAAA,IAAM;AAAA,EACd;AAAA,EACA,QAAQ;AAAA,IACN;AAAA,IAAU;AAAA,IAAU;AAAA,IAAY;AAAA,IAAM;AAAA,EACxC;AAAA,EACA,KAAK;AAAA,IACH;AAAA,IAAgB;AAAA,IAAgB;AAAA,IAAY;AAAA,IAC5C;AAAA,IAAM;AAAA,IAAM;AAAA,EACd;AACF;AAMA,SAAS,iBAAiB,MAA0B;AAClD,QAAM,QAAQ,KAAK,YAAY;AAC/B,MAAI,WAAuB;AAC3B,MAAI,YAAY;AAEhB,aAAW,CAAC,MAAM,QAAQ,KAAK,OAAO,QAAQA,oBAAmB,GAA+B;AAC9F,UAAM,QAAQ,SAAS;AAAA,MACrB,CAAC,KAAK,OAAO,OAAO,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,IAAI;AAAA,MAC3D;AAAA,IACF;AACA,QAAI,QAAQ,WAAW;AACrB,kBAAY;AACZ,iBAAW;AAAA,IACb;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,eAAe,MAAsC;AAC5D,QAAM,QAAQ,KAAK,YAAY;AAG/B,aAAW,YAAY,CAAC,YAAY,QAAQ,UAAU,KAAK,GAAY;AACrE,UAAM,WAAW,kBAAkB,QAAQ;AAC3C,QAAI,SAAS,KAAK,CAAC,OAAO,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,GAAG;AAC3D,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAEA,IAAM,uBAAmD;AAAA,EACvD,cAAc;AAAA,EACd,aAAa;AAAA,EACb,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,UAAU;AACZ;AAMO,IAAM,YAAN,MAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWrB,MAAM,eACJ,WACA,wBACuB;AACvB,WAAO,KAAK,sBAAsB,EAAE,UAAU,CAAC;AAG/C,UAAM,UAAU,oBAAoB,SAAS;AAC7C,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,iCAAiC,SAAS,EAAE;AAAA,IAC9D;AAGA,UAAM,eAA6B,QAAQ,YAAY,IAAI,CAAC,SAAS;AACnE,YAAM,WAAW,GAAG,KAAK,KAAK,IAAI,KAAK,WAAW,IAAI,0BAA0B,EAAE;AAClF,YAAM,aAAa,iBAAiB,QAAQ;AAC5C,YAAM,WAAW,eAAe,QAAQ;AAExC,aAAO;AAAA,QACL,GAAG;AAAA,QACH,oBAAoB;AAAA,QACpB,cAAc,qBAAqB,UAAU;AAAA,QAC7C;AAAA,MACF;AAAA,IACF,CAAC;AAGD,QAAI,aAAa,WAAW,GAAG;AAC7B,YAAM,YAAY,KAAK,mBAAmB,QAAQ,OAAO;AACzD,mBAAa,KAAK,GAAG,SAAS;AAAA,IAChC;AAGA,UAAM,KAAK,MAAM;AACjB,OAAG,QAAQ,kDAAkD,EAAE;AAAA,MAC7D,KAAK,UAAU,YAAY;AAAA,MAC3B,QAAQ;AAAA,IACV;AAEA,WAAO,KAAK,qBAAqB;AAAA,MAC/B;AAAA,MACA,iBAAiB,aAAa;AAAA,IAChC,CAA4B;AAG5B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAMQ,mBAAmB,SAA+B;AACxD,UAAM,QAAsB,CAAC;AAC7B,UAAM,QAAQ,QAAQ,MAAM,IAAI;AAEhC,eAAW,QAAQ,OAAO;AACxB,YAAM,UAAU,KAAK,KAAK;AAE1B,UACE,QAAQ,WAAW,IAAI,KACvB,QAAQ,SAAS,KACjB,YAAY,YACZ,YAAY,qBACZ,YAAY,kCACZ,YAAY,8BACZ;AACA,cAAM,OAAO,QAAQ,MAAM,CAAC;AAC5B,cAAM,aAAa,iBAAiB,IAAI;AACxC,cAAM,WAAW,eAAe,IAAI;AAEpC,cAAM,KAAK;AAAA,UACT,IAAIC,QAAO;AAAA,UACX,OAAO,KAAK,MAAM,GAAG,EAAE;AAAA,UACvB,aAAa;AAAA,UACb,oBAAoB;AAAA,UACpB,cAAc,qBAAqB,UAAU;AAAA,UAC7C;AAAA,UACA,cAAc,CAAC;AAAA,UACf,oBAAoB,CAAC;AAAA,QACvB,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACF;;;AD5MO,IAAM,uBAAuB;AAAA,EAClC,WAAWC,GAAE,OAAO,EAAE,SAAS,YAAY;AAAA,EAC3C,wBAAwBA,GACrB,OAAO,EACP,SAAS,EACT,SAAS,wCAAwC;AACtD;AAEA,eAAsB,sBAAsB;AAAA,EAC1C;AAAA,EACA;AACF,GAG8E;AAC5E,MAAI;AACF,UAAM,YAAY,IAAI,UAAU;AAChC,UAAM,QAAQ,MAAM,UAAU;AAAA,MAC5B;AAAA,MACA;AAAA,IACF;AAEA,UAAM,SAAS;AAAA,MACb;AAAA,MACA,gBAAgB,MAAM;AAAA,MACtB;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;AE3CA,SAAS,KAAAC,UAAS;AAGX,IAAM,qBAAqB;AAAA,EAChC,WAAWC,GAAE,OAAO,EAAE,SAAS,YAAY;AAAA,EAC3C,SAASA,GACN,MAAMA,GAAE,OAAO,CAAC,EAChB,SAAS,EACT,SAAS,mCAAmC;AACjD;AAEA,eAAsB,oBAAoB;AAAA,EACxC;AAAA,EACA;AACF,GAG8E;AAC5E,MAAI;AACF,UAAM,WAAW,oBAAoB,SAAS;AAE9C,QAAI,SAAS,WAAW,GAAG;AACzB,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK;AAAA,cACT;AAAA,gBACE,OAAO,+BAA+B,SAAS;AAAA,cACjD;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,QACA,SAAS;AAAA,MACX;AAAA,IACF;AAGA,UAAM,iBAAiB,UACnB,SAAS,OAAO,CAAC,MAAM,QAAQ,SAAS,EAAE,EAAE,CAAC,IAC7C;AAEJ,QAAI,eAAe,WAAW,GAAG;AAC/B,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK;AAAA,cACT,EAAE,OAAO,qDAAqD;AAAA,cAC9D;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,QACA,SAAS;AAAA,MACX;AAAA,IACF;AAGA,UAAM,oBAAoB,oBAAI,IAAmC;AACjE,eAAW,QAAQ,gBAAgB;AACjC,YAAM,OAAO,KAAK;AAClB,UAAI,CAAC,kBAAkB,IAAI,IAAI,GAAG;AAChC,0BAAkB,IAAI,MAAM,CAAC,CAAC;AAAA,MAChC;AACA,wBAAkB,IAAI,IAAI,EAAG,KAAK,IAAI;AAAA,IACxC;AAEA,UAAM,cAGD,CAAC;AAEN,eAAW,CAAC,YAAY,KAAK,KAAK,mBAAmB;AACnD,kBAAY,KAAK,EAAE,YAAY,MAAM,CAAC;AAAA,IACxC;AAEA,UAAM,SAAS;AAAA,MACb;AAAA,MACA,YAAY,eAAe;AAAA,MAC3B;AAAA,MACA,cACE;AAAA,IAEJ;AAEA,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;AClGA,eAAsB,sBAGnB;AACD,MAAI;AACF,UAAM,OAAO,aAAa,mBAAmB;AAE7C,UAAM,SAAS;AAAA,MACb,MAAM;AAAA,MACN,WAAW,SAAS;AAAA,IACtB;AAEA,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;AC1BA,SAAS,KAAAC,UAAS;AAIX,IAAM,yBAAyB;AAAA,EACpC,WAAWC,GAAE,OAAO,EAAE,SAAS,iCAAiC;AAAA,EAChE,UAAUA,GAAE,OAAO,EAAE,SAAS,+BAA+B;AAAA,EAC7D,WAAWA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,qCAAqC;AACjF;AAEA,eAAsB,wBAAwB;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AACF,GAI8E;AAC5E,MAAI;AACF,UAAM,UAAU,WAAW,SAAS;AAEpC,QAAI,CAAC,SAAS;AACZ,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK;AAAA,cACT,EAAE,OAAO,sBAAsB,SAAS,GAAG;AAAA,cAC3C;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,QACA,SAAS;AAAA,MACX;AAAA,IACF;AAEA,QAAI,QAAQ,WAAW,YAAY;AACjC,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK;AAAA,cACT,EAAE,OAAO,6BAA6B,SAAS,GAAG;AAAA,cAClD;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,QACA,SAAS;AAAA,MACX;AAAA,IACF;AAEA,UAAM,WAAW,cAAc,WAAW;AAAA,MACxC,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,eAAe,aAAa;AAAA,MAC5B,YAAY,KAAK,IAAI;AAAA,IACvB,CAAC;AAED,aAAS,eAAe;AAAA,MACtB,MAAM;AAAA,MACN;AAAA,MACA;AAAA,IACF,CAAC;AAED,WAAO;AAAA,MACL,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,MAAM,KAAK;AAAA,YACT,EAAE,SAAS,MAAM,SAAS,SAAS;AAAA,YACnC;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;ACxFA,SAAS,KAAAC,UAAS;AAOX,IAAM,oBAAoB;AAAA,EAC/B,QAAQC,GACL,KAAK,CAAC,WAAW,YAAY,KAAK,CAAC,EACnC,QAAQ,SAAS,EACjB,SAAS,EACT,SAAS,2BAA2B;AAAA,EACvC,WAAWA,GACR,OAAO,EACP,SAAS,EACT,SAAS,+BAA+B;AAC7C;AAEA,eAAsB,mBAAmB;AAAA,EACvC;AAAA,EACA;AACF,GAG8E;AAC5E,MAAI;AACF,UAAM,kBAAkB,UAAU;AAClC,QAAI;AAEJ,QAAI,WAAW;AAEb,YAAM,gBAAgB,sBAAsB,SAAS;AACrD,UAAI,oBAAoB,OAAO;AAC7B,mBAAW;AAAA,MACb,OAAO;AACL,mBAAW,cAAc,OAAO,CAAC,MAAM,EAAE,WAAW,eAAe;AAAA,MACrE;AAAA,IACF,WAAW,oBAAoB,WAAW;AACxC,iBAAW,oBAAoB;AAAA,IACjC,WAAW,oBAAoB,YAAY;AAYzC,YAAM,EAAE,OAAAC,OAAM,IAAI,MAAM,OAAO,kBAAkB;AACjD,YAAM,KAAKA,OAAM;AAcjB,YAAM,OAAO,GACV,QAAQ,0EAA0E,EAClF,IAAI;AACP,iBAAW,KAAK,IAAI,CAAC,SAAS;AAAA,QAC5B,IAAI,IAAI;AAAA,QACR,WAAW,IAAI;AAAA,QACf,YAAY,IAAI;AAAA,QAChB,SAAS,IAAI;AAAA,QACb,SAAS,KAAK,MAAM,IAAI,OAAO;AAAA,QAC/B,SAAS,IAAI;AAAA,QACb,QAAQ,IAAI;AAAA,QACZ,cAAc,IAAI;AAAA,QAClB,eAAe,IAAI;AAAA,QACnB,WAAW,IAAI;AAAA,QACf,YAAY,IAAI;AAAA,MAClB,EAAE;AAAA,IACJ,OAAO;AAEL,YAAM,EAAE,OAAAA,OAAM,IAAI,MAAM,OAAO,kBAAkB;AACjD,YAAM,KAAKA,OAAM;AAcjB,YAAM,OAAO,GACV,QAAQ,gDAAgD,EACxD,IAAI;AACP,iBAAW,KAAK,IAAI,CAAC,SAAS;AAAA,QAC5B,IAAI,IAAI;AAAA,QACR,WAAW,IAAI;AAAA,QACf,YAAY,IAAI;AAAA,QAChB,SAAS,IAAI;AAAA,QACb,SAAS,KAAK,MAAM,IAAI,OAAO;AAAA,QAC/B,SAAS,IAAI;AAAA,QACb,QAAQ,IAAI;AAAA,QACZ,cAAc,IAAI;AAAA,QAClB,eAAe,IAAI;AAAA,QACnB,WAAW,IAAI;AAAA,QACf,YAAY,IAAI;AAAA,MAClB,EAAE;AAAA,IACJ;AAEA,UAAM,SAAS;AAAA,MACb,OAAO,SAAS;AAAA,MAChB,QAAQ;AAAA,MACR,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;AAAA,MACjC;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;ACzIA,SAAS,KAAAC,UAAS;AAWX,IAAM,sBAAsB;AAAA,EACjC,WAAWC,GAAE,OAAO,EAAE,SAAS,6BAA6B;AAAA,EAC5D,QAAQA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yBAAyB;AAClE;AAEA,eAAsB,qBAAqB;AAAA,EACzC;AAAA,EACA;AACF,GAG8E;AAC5E,MAAI;AACF,UAAM,UAAU,WAAW,SAAS;AAEpC,QAAI,CAAC,SAAS;AACZ,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK;AAAA,cACT,EAAE,OAAO,sBAAsB,SAAS,GAAG;AAAA,cAC3C;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,QACA,SAAS;AAAA,MACX;AAAA,IACF;AAEA,QAAI,QAAQ,WAAW,eAAe,QAAQ,WAAW,aAAa;AACpE,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK;AAAA,cACT;AAAA,gBACE,OAAO,mDAAmD,QAAQ,MAAM;AAAA,cAC1E;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,QACA,SAAS;AAAA,MACX;AAAA,IACF;AAGA,kBAAc,WAAW,EAAE,QAAQ,aAAa,aAAa,KAAK,IAAI,EAAE,CAAC;AAGzE,UAAM,SAAS,oBAAoB,SAAS;AAC5C,QAAI,kBAAkB;AACtB,QAAI,gBAAgB;AAEpB,eAAW,SAAS,QAAQ;AAC1B,UAAI,MAAM,WAAW,eAAe,MAAM,WAAW,UAAU;AAC7D,oBAAY,MAAM,IAAI,EAAE,QAAQ,aAAa,aAAa,KAAK,IAAI,EAAE,CAAC;AACtE;AAEA,iBAAS,eAAe;AAAA,UACtB,MAAM;AAAA,UACN,SAAS,MAAM;AAAA,UACf,MAAM,MAAM;AAAA,UACZ,IAAI;AAAA,QACN,CAAC;AAAA,MACH;AAGA,YAAM,UAAU,oBAAoB,MAAM,EAAE;AAC5C,iBAAW,UAAU,SAAS;AAC5B,YAAI,OAAO,WAAW,eAAe,OAAO,WAAW,UAAU;AAC/D,uBAAa,OAAO,IAAI;AAAA,YACtB,QAAQ;AAAA,YACR,cAAc,UAAU;AAAA,YACxB,aAAa,KAAK,IAAI;AAAA,UACxB,CAAC;AACD;AAEA,mBAAS,eAAe;AAAA,YACtB,MAAM;AAAA,YACN,SAAS,OAAO;AAAA,YAChB,QAAQ;AAAA,UACV,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAEA,UAAM,SAAS;AAAA,MACb,SAAS;AAAA,MACT;AAAA,MACA,gBAAgB,QAAQ;AAAA,MACxB,QAAQ,UAAU;AAAA,MAClB;AAAA,MACA;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;AC1HA,SAAS,KAAAC,UAAS;AAIX,IAAM,qBAAqB;AAAA,EAChC,QAAQC,GACL,KAAK,CAAC,WAAW,WAAW,aAAa,aAAa,UAAU,KAAK,CAAC,EACtE,QAAQ,KAAK,EACb,SAAS,EACT,SAAS,2BAA2B;AAAA,EACvC,OAAOA,GACJ,OAAO,EACP,QAAQ,EAAE,EACV,SAAS,EACT,SAAS,sCAAsC;AACpD;AAIA,IAAM,mBAAoC;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,eAAsB,oBAAoB;AAAA,EACxC;AAAA,EACA;AACF,GAG8E;AAC5E,MAAI;AACF,UAAM,kBAAkB,UAAU;AAClC,UAAM,iBAAiB,SAAS;AAEhC,QAAI;AAEJ,QAAI,oBAAoB,OAAO;AAC7B,iBAAW,aAAa;AAAA,IAC1B,WAAW,oBAAoB,WAAW;AAExC,YAAM,MAAM,aAAa;AACzB,iBAAW,IAAI,OAAO,CAAC,MAAM,iBAAiB,SAAS,EAAE,MAAM,CAAC;AAAA,IAClE,OAAO;AACL,iBAAW,aAAa,eAAgC;AAAA,IAC1D;AAGA,UAAM,UAAU,SAAS,MAAM,GAAG,cAAc;AAEhD,UAAM,SAAS;AAAA,MACb,OAAO,SAAS;AAAA,MAChB,UAAU,QAAQ;AAAA,MAClB,QAAQ;AAAA,MACR,UAAU,QAAQ,IAAI,CAAC,OAAO;AAAA,QAC5B,IAAI,EAAE;AAAA,QACN,OAAO,EAAE;AAAA,QACT,QAAQ,EAAE;AAAA,QACV,OAAO,EAAE;AAAA,QACT,kBAAkB,EAAE,eAAe;AAAA,QACnC,WAAW,EAAE;AAAA,MACf,EAAE;AAAA,IACJ;AAEA,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;AClFA,SAAS,KAAAC,WAAS;AAQX,IAAM,sBAAsB;AAAA,EACjC,WAAWC,IAAE,OAAO,EAAE,SAAS,4CAA4C;AAC7E;AAEA,eAAsB,qBAAqB;AAAA,EACzC;AACF,GAE8E;AAC5E,MAAI;AACF,UAAM,UAAU,WAAW,SAAS;AACpC,QAAI,CAAC,SAAS;AACZ,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK;AAAA,cACT,EAAE,OAAO,sBAAsB,SAAS,GAAG;AAAA,cAC3C;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,QACA,SAAS;AAAA,MACX;AAAA,IACF;AAEA,UAAM,UAAU,oBAAoB,SAAS;AAC7C,UAAM,SAAS,oBAAoB,SAAS;AAG5C,UAAM,uBAeD,CAAC;AAEN,QAAI,iBAAiB;AACrB,QAAI,cAAc;AAClB,QAAI,eAAe;AACnB,QAAI,YAAY;AAEhB,eAAW,SAAS,QAAQ;AAC1B,YAAM,UAAU,oBAAoB,MAAM,EAAE;AAE5C,YAAM,YAAY,QAAQ,OAAO,CAAC,MAAM,EAAE,WAAW,WAAW,EAAE;AAClE,YAAM,SAAS,QAAQ,OAAO,CAAC,MAAM,EAAE,WAAW,QAAQ,EAAE;AAC5D,YAAM,UAAU,QAAQ;AAAA,QACtB,CAAC,MAAM,EAAE,WAAW,aAAa,EAAE,WAAW;AAAA,MAChD,EAAE;AACF,YAAM,WAAW,QAAQ,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,SAAS,CAAC;AAE9D,wBAAkB;AAClB,qBAAe;AACf,sBAAgB;AAChB,mBAAa;AAEb,UAAI,QAAQ,SAAS,GAAG;AACtB,6BAAqB,KAAK;AAAA,UACxB,YAAY,MAAM;AAAA,UAClB,UAAU,MAAM;AAAA,UAChB,YAAY,MAAM;AAAA,UAClB,SAAS,QAAQ,IAAI,CAAC,OAAO;AAAA,YAC3B,IAAI,EAAE;AAAA,YACN,iBAAiB,EAAE;AAAA,YACnB,QAAQ,EAAE;AAAA,YACV,SAAS,EAAE;AAAA,YACX,cAAc,EAAE;AAAA,UAClB,EAAE;AAAA,UACF;AAAA,UACA;AAAA,UACA;AAAA,UACA,WAAW;AAAA,QACb,CAAC;AAAA,MACH;AAAA,IACF;AAEA,UAAM,SAAS;AAAA,MACb;AAAA,MACA,OAAO,QAAQ;AAAA,MACf,QAAQ,QAAQ;AAAA,MAChB,iBAAiB,SAAS,YAAY,UAAU;AAAA,MAChD,SAAS;AAAA,QACP,cAAc,iBAAiB,cAAc;AAAA,QAC7C,WAAW;AAAA,QACX,QAAQ;AAAA,QACR,SAAS;AAAA,QACT;AAAA,MACF;AAAA,MACA,aAAa;AAAA,IACf;AAEA,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;AC3HA,SAAS,KAAAC,WAAS;;;ACQlB,SAAS,cAAc,eAAe,kBAAkB;AACxD,SAAS,QAAAC,aAAY;;;ACTrB,SAAS,iBAAiB;AAC1B,SAAS,eAAe;AACxB,SAAS,YAAY;AAqBrB,SAAS,cAAyB;AAChC,QAAM,WAAW,KAAK,QAAQ,GAAG,gBAAgB;AACjD,SAAO;AAAA,IACL;AAAA,IACA,SAAS,KAAK,UAAU,SAAS;AAAA,IACjC,aAAa,KAAK,UAAU,SAAS;AAAA,IACrC,gBAAgB;AAAA,EAClB;AACF;AAGA,IAAI,UAA4B;AAYzB,SAAS,YAAuB;AACrC,MAAI,CAAC,SAAS;AACZ,cAAU,YAAY;AAAA,EACxB;AACA,SAAO;AACT;AAOO,SAAS,iBAAuB;AACrC,QAAM,SAAS,UAAU;AACzB,YAAU,OAAO,UAAU,EAAE,WAAW,KAAK,CAAC;AAC9C,YAAU,OAAO,aAAa,EAAE,WAAW,KAAK,CAAC;AACnD;;;AD9BA,IAAM,iBAAkD;AAAA,EACtD;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AACF;AAEA,IAAM,kBAAmD;AAAA,EACvD;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AACF;AAMO,IAAM,qBAAN,MAAyB;AAAA,EACtB,eAA6B,CAAC;AAAA,EAC9B;AAAA,EAER,cAAc;AACZ,UAAM,EAAE,SAAS,IAAI,UAAU;AAC/B,SAAK,eAAeC,MAAK,UAAU,eAAe;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAAiC;AAErC,UAAM,WAAyB;AAAA,MAC7B,GAAG;AAAA,MACH,GAAG;AAAA,IACL,EAAE,IAAI,CAAC,SAAS,EAAE,GAAG,KAAK,WAAW,EAAE,EAAE;AAGzC,UAAM,SAAS,KAAK,kBAAkB;AACtC,SAAK,eAAe,CAAC,GAAG,UAAU,GAAG,MAAM;AAC3C,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAS,KAAmD;AAChE,UAAM,QAAoB,EAAE,GAAG,KAAK,WAAW,KAAK,IAAI,EAAE;AAG1D,UAAM,SAAS,KAAK,kBAAkB,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,IAAI,IAAI;AACzE,WAAO,KAAK,KAAK;AACjB,SAAK,mBAAmB,MAAM;AAG9B,UAAM,KAAK,QAAQ;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAW,MAAsB,MAA6B;AAClE,UAAM,SAAS,KAAK,kBAAkB,EAAE;AAAA,MACtC,CAAC,MAAM,EAAE,EAAE,SAAS,QAAQ,EAAE,SAAS;AAAA,IACzC;AACA,SAAK,mBAAmB,MAAM;AAG9B,UAAM,KAAK,QAAQ;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,MAAoC;AAC7C,WAAO,KAAK,aAAa,OAAO,CAAC,MAAM,EAAE,SAAS,IAAI;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,MAAsC;AAC/C,WAAO,KAAK,aAAa,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,MAAuB;AACzB,WAAO,KAAK,aAAa,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAyB;AACvB,UAAM,WAAqB,CAAC;AAE5B,UAAM,QAA0B,CAAC,QAAQ,SAAS,WAAW,SAAS,MAAM;AAC5E,eAAW,QAAQ,OAAO;AACxB,YAAM,OAAO,KAAK,WAAW,IAAI;AACjC,UAAI,KAAK,WAAW,EAAG;AAEvB,YAAM,QAAQ,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC,IAAI;AAC7D,YAAM,QAAQ,KAAK,IAAI,CAAC,MAAM;AAC5B,cAAM,MAAM,EAAE,YAAY,KAAK;AAC/B,eAAO,OAAO,EAAE,IAAI,KAAK,GAAG,WAAM,EAAE,WAAW,cAAc,EAAE,OAAO;AAAA,MACxE,CAAC;AACD,eAAS,KAAK,OAAO,KAAK;AAAA,EAAK,MAAM,KAAK,IAAI,CAAC,EAAE;AAAA,IACnD;AAEA,WAAO,SAAS,KAAK,MAAM;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAMQ,oBAAkC;AACxC,QAAI,CAAC,WAAW,KAAK,YAAY,GAAG;AAClC,aAAO,CAAC;AAAA,IACV;AACA,QAAI;AACF,YAAM,MAAM,aAAa,KAAK,cAAc,OAAO;AACnD,YAAM,SAAkB,KAAK,MAAM,GAAG;AACtC,UAAI,CAAC,MAAM,QAAQ,MAAM,EAAG,QAAO,CAAC;AACpC,aAAO;AAAA,IACT,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA,EAEQ,mBAAmB,SAA6B;AACtD,kBAAc,KAAK,cAAc,KAAK,UAAU,SAAS,MAAM,CAAC,GAAG,OAAO;AAAA,EAC5E;AACF;;;AExPA,SAAS,aAAAC,YAAW,iBAAAC,sBAAqB;AACzC,SAAS,QAAAC,aAAY;AA0BrB,SAAS,aAAa,MAAsB;AAC1C,SAAO,KACJ,YAAY,EACZ,QAAQ,eAAe,GAAG,EAC1B,QAAQ,YAAY,EAAE;AAC3B;AAEA,SAAS,OAAO,SAAkC;AAChD,QAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,SAAO;AAAA,IACL;AAAA,IACA,YAAY,QAAQ,IAAI;AAAA,IACxB,mBAAmB,QAAQ,WAAW;AAAA,IACtC,eAAe,QAAQ,OAAO;AAAA,IAC9B,eAAe,GAAG;AAAA,IAClB;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAEA,SAAS,UAAU,MAA8B;AAC/C,QAAM,EAAE,SAAS,IAAI,UAAU;AAC/B,QAAM,MAAMC,MAAK,UAAU,UAAU,IAAI,GAAG;AAC5C,EAAAC,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAClC,SAAO;AACT;AAMA,SAAS,aAAa,SAAkC;AACtD,SAAO;AAAA,IACL,OAAO,OAAO;AAAA,IACd;AAAA,IACA,mBAAmB,QAAQ,IAAI;AAAA,IAC/B,MAAM,QAAQ,WAAW;AAAA,IACzB;AAAA,IACA,eAAe,QAAQ,OAAO;AAAA,IAC9B,wBAAwB,QAAQ,WAAW;AAAA,IAC3C;AAAA,IACA;AAAA,IACA,0BAA0B,aAAa,QAAQ,IAAI,CAAC;AAAA,IACpD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,wCAAwC,QAAQ,WAAW;AAAA,IAC3D;AAAA,IACA,cAAc,QAAQ,IAAI;AAAA,IAC1B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAEA,SAAS,cAAc,SAAkC;AACvD,SAAO;AAAA,IACL,OAAO,OAAO;AAAA,IACd;AAAA,IACA,oBAAoB,QAAQ,IAAI;AAAA,IAChC,MAAM,QAAQ,WAAW;AAAA,IACzB;AAAA,IACA,eAAe,QAAQ,OAAO;AAAA,IAC9B,wBAAwB,QAAQ,WAAW;AAAA,IAC3C;AAAA,IACA;AAAA,IACA,sBAAsB,aAAa,QAAQ,IAAI,CAAC;AAAA,IAChD;AAAA,IACA;AAAA,IACA;AAAA,IACA,sBAAsB,QAAQ,IAAI;AAAA,IAClC;AAAA,IACA,WAAW,QAAQ,IAAI;AAAA,IACvB;AAAA,IACA,QAAQ,QAAQ,WAAW;AAAA,IAC3B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAEA,SAAS,gBAAgB,SAAkC;AACzD,SAAO;AAAA,IACL,OAAO,OAAO;AAAA,IACd;AAAA,IACA,sBAAsB,QAAQ,IAAI;AAAA,IAClC,MAAM,QAAQ,WAAW;AAAA,IACzB;AAAA,IACA,eAAe,QAAQ,OAAO;AAAA,IAC9B,wBAAwB,QAAQ,WAAW;AAAA,IAC3C;AAAA,IACA;AAAA,IACA,6BAA6B,aAAa,QAAQ,IAAI,CAAC;AAAA,IACvD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,mBAAmB,QAAQ,IAAI;AAAA,IAC/B,uBAAuB,QAAQ,WAAW;AAAA,IAC1C,iBAAiB,QAAQ,IAAI;AAAA,IAC7B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,qBAAqB,QAAQ,IAAI;AAAA,IACjC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAEA,SAAS,cAAc,SAAkC;AAEvD,QAAM,aACJ,kCAAkC,KAAK,QAAQ,IAAI,KACnD,kCAAkC,KAAK,QAAQ,WAAW;AAE5D,MAAI,YAAY;AACd,WAAO;AAAA,MACL;AAAA,MACA,cAAc,QAAQ,IAAI;AAAA,MAC1B,qBAAqB,QAAQ,WAAW;AAAA,MACxC,iBAAiB,QAAQ,OAAO;AAAA,MAChC,kBAAiB,oBAAI,KAAK,GAAE,YAAY,CAAC;AAAA,MACzC;AAAA,MACA,KAAK,QAAQ,IAAI;AAAA,MACjB;AAAA,MACA,GAAG,QAAQ,WAAW;AAAA,MACtB;AAAA,MACA;AAAA,MACA;AAAA,MACA,uBAAuB,QAAQ,WAAW;AAAA,MAC1C;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACb;AAEA,QAAM,OAAO;AAAA,IACX,OAAO;AAAA,MACL,aAAa;AAAA,MACb,MAAM,QAAQ;AAAA,MACd,aAAa,QAAQ;AAAA,MACrB,SAAS,QAAQ;AAAA,MACjB,UAAS,oBAAI,KAAK,GAAE,YAAY;AAAA,MAChC,aAAa,QAAQ;AAAA,IACvB;AAAA,IACA,QAAQ,CAAC;AAAA,EACX;AAEA,SAAO,KAAK,UAAU,MAAM,MAAM,CAAC,IAAI;AACzC;AAEA,SAAS,aAAa,SAAkC;AACtD,SAAO;AAAA,IACL,OAAO,OAAO;AAAA,IACd;AAAA,IACA,mBAAmB,QAAQ,IAAI;AAAA,IAC/B,MAAM,QAAQ,WAAW;AAAA,IACzB;AAAA,IACA,eAAe,QAAQ,OAAO;AAAA,IAC9B,wBAAwB,QAAQ,WAAW;AAAA,IAC3C;AAAA,IACA;AAAA,IACA,0BAA0B,aAAa,QAAQ,IAAI,CAAC;AAAA,IACpD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,iDAAiD,QAAQ,WAAW;AAAA,IACpE;AAAA,IACA,cAAc,QAAQ,IAAI;AAAA,IAC1B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,kBAAkB,QAAQ,IAAI;AAAA,IAC9B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAMA,SAAS,aAAa,KAAqB;AACzC,SAAO,IACJ,MAAM,SAAS,EACf,IAAI,CAAC,SAAS,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC,EAAE,YAAY,CAAC,EACxE,KAAK,EAAE;AACZ;AAYO,SAAS,mBAAmB,SAA0C;AAC3E,QAAM,WAAW,aAAa,QAAQ,IAAI;AAG1C,QAAM,kBACJ,QAAQ,SAAS,YAChB,kCAAkC,KAAK,QAAQ,IAAI,KAClD,kCAAkC,KAAK,QAAQ,WAAW;AAE9D,MAAI;AACJ,MAAI,QAAQ,SAAS,SAAS;AAC5B,UAAM,kBAAkB,QAAQ;AAAA,EAClC,OAAO;AACL,UAAM;AAAA,EACR;AAEA,QAAM,MAAM,UAAU,QAAQ,IAAI;AAClC,QAAM,WAAWD,MAAK,KAAK,GAAG,QAAQ,GAAG,GAAG,EAAE;AAG9C,MAAI;AACJ,UAAQ,QAAQ,MAAM;AAAA,IACpB,KAAK;AACH,aAAO,aAAa,OAAO;AAC3B;AAAA,IACF,KAAK;AACH,aAAO,cAAc,OAAO;AAC5B;AAAA,IACF,KAAK;AACH,aAAO,gBAAgB,OAAO;AAC9B;AAAA,IACF,KAAK;AACH,aAAO,cAAc,OAAO;AAC5B;AAAA,IACF,KAAK;AACH,aAAO,aAAa,OAAO;AAC3B;AAAA,EACJ;AAGA,EAAAE,eAAc,UAAU,MAAM,OAAO;AAErC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,eAAe;AAAA,MACb,MAAM,QAAQ;AAAA,MACd,MAAM,QAAQ;AAAA,MACd,aAAa,QAAQ;AAAA,MACrB,SAAS,QAAQ;AAAA,MACjB,WAAW;AAAA,MACX;AAAA,IACF;AAAA,EACF;AACF;;;AC3VA,SAAS,gBAAAC,eAAc,iBAAAC,sBAAqB;AAC5C,SAAS,QAAAC,aAAY;AAcrB,eAAsB,kBACpB,UACe;AACf,QAAM,EAAE,SAAS,IAAI,UAAU;AAC/B,QAAM,YAAYC,MAAK,UAAU,iBAAiB;AAElD,QAAM,aAAa,SAAS,eAAe;AAE3C,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AAEX,EAAAC,eAAc,WAAW,OAAO,OAAO;AACzC;;;ACrBA,IAAM,gBAA+B;AAAA,EACnC;AAAA,IACE,MAAM;AAAA,IACN,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAMO,IAAM,mBAAN,MAAuB;AAAA,EACpB;AAAA,EAER,cAAc;AACZ,SAAK,WAAW,IAAI,mBAAmB;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAsB;AAC1B,UAAM,KAAK,SAAS,QAAQ;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,eAAe,SAA0C;AAE7D,UAAM,aAAa,QAAQ,YAAY,EAAE,KAAK;AAE9C,eAAW,OAAO,MAAM,KAAK,SAAS,QAAQ,GAAG;AAC/C,UAAI,WAAW,SAAS,IAAI,KAAK,YAAY,CAAC,GAAG;AAC/C,eAAO,EAAE,oBAAoB,MAAM;AAAA,MACrC;AAAA,IACF;AAGA,eAAW,QAAQ,eAAe;AAChC,iBAAW,WAAW,KAAK,UAAU;AACnC,YAAI,QAAQ,KAAK,OAAO,GAAG;AACzB,gBAAM,gBAAgB,YAAY,OAAO;AACzC,iBAAO;AAAA,YACL,oBAAoB;AAAA,YACpB,eAAe,KAAK;AAAA,YACpB,eAAe;AAAA,YACf,sBAAsB,QAAQ,MAAM,GAAG,GAAG;AAAA,YAC1C,kBAAkB,eAAe,SAAS,KAAK,IAAI;AAAA,UACrD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,WAAO;AAAA,MACL,oBAAoB;AAAA,MACpB,eAAe;AAAA,MACf,eAAe,YAAY,OAAO;AAAA,MAClC,sBAAsB,QAAQ,MAAM,GAAG,GAAG;AAAA,MAC1C,kBAAkB;AAAA,IACpB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAiB,SAAiD;AAEtE,UAAM,SAAS,mBAAmB,OAAO;AAGzC,UAAM,KAAK,SAAS,SAAS,OAAO,aAAa;AAGjD,UAAM,kBAAkB,KAAK,QAAQ;AAGrC,UAAM,aAAyB;AAAA,MAC7B,GAAG,OAAO;AAAA,MACV,WAAW,KAAK,IAAI;AAAA,IACtB;AAEA,UAAM,UACJ,WAAW,QAAQ,IAAI,KAAK,QAAQ,IAAI,MAAM,QAAQ,WAAW,WACxD,OAAO,QAAQ;AAE1B,WAAO,EAAE,YAAY,UAAU,OAAO,UAAU,QAAQ;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBAA0C;AAC9C,WAAO,KAAK,SAAS,QAAQ;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,iBAAiB,MAA6B;AAClD,UAAM,MAAM,KAAK,SAAS,WAAW,IAAI;AACzC,QAAI,CAAC,KAAK;AACR,YAAM,IAAI,MAAM,yBAAyB,IAAI,EAAE;AAAA,IACjD;AACA,QAAI,IAAI,WAAW;AACjB,YAAM,IAAI,MAAM,sCAAsC,IAAI,EAAE;AAAA,IAC9D;AAEA,UAAM,KAAK,SAAS,WAAW,IAAI,MAAM,IAAI;AAG7C,UAAM,kBAAkB,KAAK,QAAQ;AAAA,EACvC;AACF;AASA,SAAS,YAAY,SAAyB;AAE5C,QAAM,aAAa,QAAQ,MAAM,cAAc;AAC/C,MAAI,WAAY,QAAO,WAAW,CAAC;AAGnC,QAAM,QAAQ,QACX,QAAQ,oBAAoB,EAAE,EAC9B,MAAM,KAAK,EACX,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,EAC1B,MAAM,GAAG,CAAC;AAEb,SAAO,MAAM,KAAK,GAAG,EAAE,YAAY,KAAK;AAC1C;AAKA,SAAS,eAAe,SAAiB,MAA8B;AACrE,UAAQ,MAAM;AAAA,IACZ,KAAK,QAAQ;AACX,YAAM,cAAc,QAAQ,MAAM,4BAA4B;AAC9D,UAAI,YAAa,QAAO,UAAU,YAAY,CAAC,EAAE,KAAK,CAAC;AACvD,YAAM,aAAa,QAAQ,MAAM,2BAA2B;AAC5D,UAAI,WAAY,QAAO,SAAS,WAAW,CAAC,EAAE,KAAK,CAAC;AACpD,YAAM,YAAY,QAAQ,MAAM,0BAA0B;AAC1D,UAAI,UAAW,QAAO,QAAQ,UAAU,CAAC,EAAE,KAAK,CAAC;AACjD,aAAO;AAAA,IACT;AAAA,IACA,KAAK;AACH,aAAO,IAAI,YAAY,OAAO,CAAC;AAAA,IACjC,KAAK,QAAQ;AACX,YAAM,aAAa,QAAQ,MAAM,oBAAoB;AACrD,UAAI,WAAY,QAAO,SAAS,WAAW,CAAC,EAAE,KAAK,CAAC;AACpD,aAAO;AAAA,IACT;AAAA,IACA,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,EACX;AACF;;;ALzPO,IAAM,yBAAyB;AAAA,EACpC,MAAMC,IACH,KAAK,CAAC,QAAQ,SAAS,WAAW,SAAS,MAAM,CAAC,EAClD,SAAS,8BAA8B;AAAA,EAC1C,MAAMA,IAAE,OAAO,EAAE,SAAS,6BAA6B;AAAA,EACvD,aAAaA,IAAE,OAAO,EAAE,SAAS,0BAA0B;AAAA,EAC3D,SAASA,IAAE,OAAO,EAAE,SAAS,yCAAyC;AAAA,EACtE,aAAaA,IACV,OAAO,EACP,SAAS,EACT,SAAS,+CAA+C;AAC7D;AAEA,eAAsB,wBAAwB;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAM8E;AAC5E,MAAI;AACF,UAAM,UAAU,IAAI,iBAAiB;AACrC,UAAM,QAAQ,KAAK;AAEnB,UAAM,UAA2B;AAAA,MAC/B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa,eAAe;AAAA,IAC9B;AAEA,UAAM,SAAS,MAAM,QAAQ,iBAAiB,OAAO;AAErD,UAAM,SAAS;AAAA,MACb,QAAQ;AAAA,MACR,YAAY;AAAA,QACV,MAAM,OAAO,WAAW;AAAA,QACxB,MAAM,OAAO,WAAW;AAAA,QACxB,aAAa,OAAO,WAAW;AAAA,QAC/B,SAAS,OAAO,WAAW;AAAA,QAC3B,WAAW,OAAO,WAAW;AAAA,MAC/B;AAAA,MACA,UAAU,OAAO;AAAA,MACjB,SAAS,OAAO;AAAA,IAClB;AAEA,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;AMtEA,SAAS,KAAAC,WAAS;;;AC8BX,IAAM,cAAN,MAAkB;AAAA,EACf,iBAAgC;AAAA,EAChC,UAAuB,CAAC;AAAA;AAAA,EAGhC,UAAU,UAAwB;AAChC,SAAK,iBAAiB;AAAA,EACxB;AAAA;AAAA,EAGA,WAAW,SAAiB,WAAmB,SAAuB;AACpE,SAAK,QAAQ,KAAK;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,MACA,YAAY,KAAK,IAAI;AAAA,IACvB,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,WAAW,WAAiC;AAC1C,UAAM,YAAoC,CAAC;AAC3C,UAAM,eAAuC,CAAC;AAC9C,UAAM,SAAiC,CAAC;AACxC,QAAI,WAAW;AAGf,QAAI;AACF,YAAM,KAAK,MAAM;AASjB,UAAI;AACJ,UAAI,WAAW;AACb,oBAAY,GACT,QAAQ,gFAAgF,EACxF,IAAI,SAAS;AAAA,MAClB,OAAO;AACL,oBAAY,GACT,QAAQ,2DAA2D,EACnE,IAAI;AAAA,MACT;AAEA,iBAAW,OAAO,WAAW;AAC3B,cAAM,OAAO,IAAI,YAAY;AAC7B,YAAI,SAAS,EAAG;AAEhB,oBAAY;AACZ,cAAM,MAAM,IAAI,cAAc;AAC9B,kBAAU,GAAG,KAAK,UAAU,GAAG,KAAK,KAAK;AACzC,qBAAa,IAAI,UAAU,KAAK,aAAa,IAAI,UAAU,KAAK,KAAK;AACrE,eAAO,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,KAAK;AAAA,MAC/C;AASA,UAAI;AACJ,UAAI,WAAW;AACb,qBAAa,GACV,QAAQ,0EAA0E,EAClF,IAAI,SAAS;AAAA,MAClB,OAAO;AACL,qBAAa,GACV,QAAQ,qDAAqD,EAC7D,IAAI;AAAA,MACT;AAEA,iBAAW,OAAO,YAAY;AAC5B,cAAM,OAAO,IAAI,YAAY;AAC7B,YAAI,SAAS,EAAG;AAEhB,oBAAY;AACZ,kBAAU,IAAI,UAAU,KAAK,UAAU,IAAI,UAAU,KAAK,KAAK;AAC/D,eAAO,QAAQ,KAAK,OAAO,QAAQ,KAAK,KAAK;AAI7C,cAAM,SAAS,GACZ,QAAQ,4CAA4C,EACpD,IAAI,IAAI,SAAS;AACpB,YAAI,QAAQ;AACV,uBAAa,OAAO,UAAU,KAAK,aAAa,OAAO,UAAU,KAAK,KAAK;AAAA,QAC7E;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAGA,UAAM,kBAAkB,YACpB,KAAK,QAAQ,OAAO,CAAC,MAAM,EAAE,cAAc,SAAS,IACpD,KAAK;AAET,eAAW,SAAS,iBAAiB;AACnC,kBAAY,MAAM;AAClB,gBAAU,MAAM,SAAS,KAAK,UAAU,MAAM,SAAS,KAAK,KAAK,MAAM;AAAA,IACzE;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa,KAAK;AAAA,MAClB,iBAAiB,KAAK,mBAAmB,OAAO,KAAK,iBAAiB,WAAW;AAAA,IACnF;AAAA,EACF;AAAA;AAAA,EAGA,cAA6B;AAC3B,QAAI,KAAK,mBAAmB,KAAM,QAAO;AAEzC,UAAM,UAAU,KAAK,WAAW;AAChC,QAAI,QAAQ,YAAY,KAAK,gBAAgB;AAC3C,aAAO,qBAAqB,QAAQ,SAAS,QAAQ,CAAC,CAAC,cAAc,KAAK,eAAe,QAAQ,CAAC,CAAC;AAAA,IACrG;AAEA,UAAM,YAAY,KAAK,iBAAiB,QAAQ;AAChD,QAAI,YAAY,KAAK,iBAAiB,KAAK;AACzC,aAAO,oBAAoB,QAAQ,SAAS,QAAQ,CAAC,CAAC,iBAAiB,UAAU,QAAQ,CAAC,CAAC,kBAAkB,KAAK,eAAe,QAAQ,CAAC,CAAC;AAAA,IAC7I;AAEA,WAAO;AAAA,EACT;AACF;AAGO,IAAM,cAAc,IAAI,YAAY;;;ADpKpC,IAAM,uBAAuB;AAAA,EAClC,WAAWC,IAAE,OAAO,EAAE,SAAS,EAAE,SAAS,qCAAqC;AACjF;AAEA,eAAsB,sBAAsB;AAAA,EAC1C;AACF,GAE8E;AAC5E,MAAI;AACF,UAAM,UAAU,YAAY,WAAW,SAAS;AAChD,UAAM,gBAAgB,YAAY,YAAY;AAE9C,UAAM,SAAkC;AAAA,MACtC,GAAG;AAAA,IACL;AAEA,QAAI,eAAe;AACjB,aAAO,gBAAgB;AAAA,IACzB;AAEA,QAAI,WAAW;AACb,aAAO,oBAAoB;AAAA,IAC7B;AAEA,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;AExCA,SAAS,KAAAC,WAAS;AAIX,IAAM,qBAAqB;AAAA,EAChC,mBAAmBC,IAAE,OAAO,EAAE,SAAS,0CAA0C;AAAA,EACjF,OAAOA,IAAE,OAAO,EAAE,SAAS,mCAAmC;AAAA,EAC9D,QAAQA,IAAE,MAAMA,IAAE,OAAO,CAAC,EAAE,SAAS,kCAAkC;AAAA,EACvE,aAAaA,IACV,MAAMA,IAAE,OAAO,CAAC,EAChB,SAAS,EACT,SAAS,gCAAgC;AAC9C;AAEA,eAAsB,oBAAoB;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAK8E;AAC5E,MAAI;AACF,UAAM,eAAe,IAAI,aAAa;AACtC,UAAM,SAAS,aAAa,aAAa;AAAA,MACvC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;AC9CA,SAAS,KAAAC,WAAS;;;ACmBlB,SAAS,sBACP,WACA,WACA,aACA,iBACA,aACA,SACiB;AACjB,QAAM,KAAK,MAAM;AACjB,QAAM,MAAM,KAAK,IAAI;AACrB,QAAM,aAAa,KAAK,KAAK,QAAQ,SAAS,CAAC;AAE/C,QAAM,SAAS,GACZ;AAAA,IACC;AAAA;AAAA;AAAA,EAGF,EACC,IAAI,WAAW,WAAW,aAAa,iBAAiB,aAAa,SAAS,YAAY,GAAG;AAEhG,SAAO;AAAA,IACL,IAAI,OAAO,OAAO,eAAe;AAAA,IACjC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,EACb;AACF;AAEA,SAAS,cAAc,WAAsC;AAC3D,QAAM,KAAK,MAAM;AAYjB,QAAM,OAAO,GACV,QAAQ,+EAA+E,EACvF,IAAI,SAAS;AAEhB,SAAO,KAAK,IAAI,CAAC,OAAO;AAAA,IACtB,IAAI,EAAE;AAAA,IACN,WAAW,EAAE;AAAA,IACb,WAAW,EAAE;AAAA,IACb,aAAa,EAAE;AAAA,IACf,iBAAiB,EAAE;AAAA,IACnB,aAAa,EAAE;AAAA,IACf,SAAS,EAAE;AAAA,IACX,YAAY,EAAE;AAAA,IACd,WAAW,EAAE;AAAA,EACf,EAAE;AACJ;AAUO,IAAM,gBAAN,MAAoB;AAAA,EACR;AAAA,EAEjB,YAAY,WAAmB;AAC7B,SAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,cACE,aACA,iBACA,aACA,SACiB;AACjB,UAAM,UAAU,WAAW,KAAK,SAAS;AACzC,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,sBAAsB,KAAK,SAAS,EAAE;AAAA,IACxD;AAGA,UAAM,QAAQ;AAAA,MACZ,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,WAAO,MAAM,qBAAqB,WAAW,UAAU,eAAe,WAAW,WAAW,KAAK;AAAA,MAC/F,WAAW,KAAK;AAAA,IAClB,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,kBAAmC;AACvC,UAAM,UAAU,WAAW,KAAK,SAAS;AACzC,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,sBAAsB,KAAK,SAAS,EAAE;AAAA,IACxD;AAGA,kBAAc,KAAK,WAAW;AAAA,MAC5B,OAAO;AAAA,MACP,QAAQ;AAAA,IACV,CAAC;AAED,UAAM,aAAa,cAAc,KAAK,SAAS;AAI/C,UAAM,WAAqB,CAAC;AAG5B,UAAM,eAAe,CAAC,GAAG,IAAI,IAAI,WAAW,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAEtE,aAAS,KAAK,mBAAmB;AACjC,aAAS,KAAK,aAAa,QAAQ,KAAK,EAAE;AAC1C,aAAS,KAAK,aAAY,oBAAI,KAAK,GAAE,YAAY,CAAC,EAAE;AACpD,aAAS,KAAK,oBAAoB,aAAa,KAAK,IAAI,CAAC,EAAE;AAC3D,aAAS,KAAK,EAAE;AAGhB,aAAS,KAAK,WAAW;AACzB,YAAQ,OAAO,QAAQ,CAAC,MAAM,MAAM;AAClC,eAAS,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE;AAAA,IACnC,CAAC;AACD,aAAS,KAAK,EAAE;AAGhB,UAAM,iBAAiB,WAAW,OAAO,CAAC,MAAM,EAAE,oBAAoB,EAAE;AACxE,QAAI,eAAe,SAAS,GAAG;AAC7B,eAAS,KAAK,uBAAuB;AACrC,iBAAW,SAAS,gBAAgB;AAClC,iBAAS,KAAK,OAAO,MAAM,WAAW,EAAE;AACxC,iBAAS,KAAK,MAAM,OAAO;AAC3B,iBAAS,KAAK,EAAE;AAAA,MAClB;AAAA,IACF;AAGA,aAAS,IAAI,GAAG,IAAI,QAAQ,OAAO,QAAQ,KAAK;AAC9C,YAAM,cAAc,WAAW,OAAO,CAAC,MAAM,EAAE,oBAAoB,CAAC;AACpE,UAAI,YAAY,SAAS,GAAG;AAC1B,iBAAS,KAAK,kBAAkB,QAAQ,OAAO,CAAC,CAAC,EAAE;AACnD,mBAAW,SAAS,aAAa;AAC/B,mBAAS,KAAK,KAAK,MAAM,WAAW,aAAa,MAAM,WAAW,IAAI;AACtE,mBAAS,KAAK,MAAM,OAAO;AAC3B,mBAAS,KAAK,EAAE;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AAGA,UAAM,mBAAmB,WAAW,OAAO,CAAC,MAAM,EAAE,oBAAoB,EAAE;AAC1E,QAAI,iBAAiB,SAAS,GAAG;AAC/B,eAAS,KAAK,oBAAoB;AAClC,iBAAW,SAAS,kBAAkB;AACpC,iBAAS,KAAK,OAAO,MAAM,WAAW,EAAE;AACxC,iBAAS,KAAK,MAAM,OAAO;AAC3B,iBAAS,KAAK,EAAE;AAAA,MAClB;AAAA,IACF;AAEA,UAAM,UAAU,SAAS,KAAK,IAAI;AAIlC,UAAM,cAA4B,aAAa,IAAI,CAAC,MAAM,SAAS;AAAA,MACjE,IAAI,UAAU,KAAK,SAAS,IAAI,GAAG;AAAA,MACnC,OAAO,GAAG,IAAI;AAAA,MACd,aAAa,6BAA6B,IAAI;AAAA,MAC9C,oBAAoB;AAAA;AAAA,MACpB,cAAc;AAAA,MACd,UAAU;AAAA,MACV,cAAc,CAAC;AAAA,MACf,oBAAoB,CAAC,oDAAoD;AAAA,IAC3E,EAAE;AAEF,UAAM,gBAAgB,cAAc;AAAA,MAClC,WAAW,KAAK;AAAA,MAChB,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,IACF,CAAC;AAGD,kBAAc,KAAK,WAAW;AAAA,MAC5B,QAAQ;AAAA,MACR,aAAa,KAAK,IAAI;AAAA,IACxB,CAAC;AAED,WAAO,KAAK,qBAAqB,EAAE,WAAW,KAAK,UAAU,CAAC;AAE9D,WAAO,cAAc;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAsB;AACpB,UAAM,UAAU,WAAW,KAAK,SAAS;AACzC,QAAI,CAAC,QAAS,QAAO;AACrB,WAAO,CAAC,aAAa,aAAa,UAAU,EAAE,SAAS,QAAQ,MAAM;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBAAmC;AACjC,WAAO,cAAc,KAAK,SAAS;AAAA,EACrC;AACF;;;AD/PO,IAAM,sBAAsB;AAAA,EACjC,WAAWC,IAAE,OAAO,EAAE,SAAS,YAAY;AAAA,EAC3C,aAAaA,IAAE,OAAO,EAAE,SAAS,oEAAoE;AAAA,EACrG,iBAAiBA,IACd,OAAO,EACP,SAAS,8EAA8E;AAAA,EAC1F,aAAaA,IAAE,OAAO,EAAE,SAAS,mDAAmD;AAAA,EACpF,SAASA,IAAE,OAAO,EAAE,SAAS,yCAAyC;AACxE;AAEA,eAAsB,qBAAqB;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAM8E;AAC5E,MAAI;AACF,UAAM,SAAS,IAAI,cAAc,SAAS;AAC1C,UAAM,QAAQ,OAAO,cAAc,aAAa,iBAAiB,aAAa,OAAO;AAErF,UAAM,SAAS;AAAA,MACb,SAAS;AAAA,MACT,SAAS,MAAM;AAAA,MACf;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;AEnDA,SAAS,KAAAC,WAAS;AAIX,IAAM,wBAAwB;AAAA,EACnC,WAAWC,IAAE,OAAO,EAAE,SAAS,oCAAoC;AACrE;AAEA,eAAsB,uBAAuB;AAAA,EAC3C;AACF,GAE8E;AAC5E,MAAI;AACF,UAAM,SAAS,IAAI,cAAc,SAAS;AAC1C,UAAM,YAAY,MAAM,OAAO,gBAAgB;AAG/C,UAAM,UAAU,oBAAoB,SAAS;AAE7C,UAAM,SAAS;AAAA,MACb;AAAA,MACA;AAAA,MACA,SAAS,SAAS,WAAW;AAAA,IAC/B;AAEA,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;ApCHO,SAAS,eAA0B;AACxC,QAAM,SAAS,IAAI,UAAU;AAAA,IAC3B,MAAM;AAAA,IACN,SAAS;AAAA,EACX,CAAC;AAGD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AACT;;;AqCzKA,SAAS,gBAAgB,wBAAwB;AACjD,SAAS,iBAAiB,aAAAC,kBAAiB;;;ACOpC,SAAS,mBAA2B;AACzC;AAAA;AAAA,IAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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","names":["uuidv4","uuidv4","uuidv4","uuidv4","uuidv4","uuidv4","uuidv4","uuidv4","z","z","result","z","z","z","uuidv4","DEPARTMENT_KEYWORDS","uuidv4","z","z","z","z","z","z","z","getDb","z","z","z","z","z","z","z","join","join","mkdirSync","writeFileSync","join","join","mkdirSync","writeFileSync","readFileSync","writeFileSync","join","join","writeFileSync","z","z","z","z","z","z","z","z","z","WebSocket","EventEmitter","EventEmitter","WebSocket"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/server.ts","../src/tools/start-meeting.ts","../src/orchestrator/orchestrator.ts","../src/storage/agent-store.ts","../src/storage/meeting-store.ts","../src/storage/worker-store.ts","../src/storage/mention-store.ts","../src/storage/minutes-store.ts","../src/storage/task-store.ts","../src/types/agent.ts","../src/agents/departments.ts","../src/orchestrator/event-bus.ts","../src/utils/logger.ts","../src/orchestrator/leader-pool.ts","../src/tools/get-meeting-status.ts","../src/tools/get-minutes.ts","../src/tools/compact-minutes.ts","../src/meeting/compactor.ts","../src/tools/execute-tasks.ts","../src/tools/get-agent-tree.ts","../src/tools/respond-to-mention.ts","../src/tools/get-mentions.ts","../src/tools/cancel-meeting.ts","../src/tools/list-meetings.ts","../src/tools/get-task-report.ts","../src/tools/create-capability.ts","../src/extension/capability-registry.ts","../src/utils/config.ts","../src/extension/generator.ts","../src/extension/guide-updater.ts","../src/extension/extension-manager.ts","../src/tools/get-cost-summary.ts","../src/utils/cost-tracker.ts","../src/tools/chain-meeting.ts","../src/tools/add-transcript.ts","../src/orchestrator/meeting-runner.ts","../src/tools/generate-minutes.ts","../src/dashboard/server.ts","../src/dashboard/html.ts","../src/dashboard/state-bridge.ts","../src/dashboard/client.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { createServer } from './server.js';\nimport { ensureDataDirs } from './utils/config.js';\nimport { startDashboard } from './dashboard/server.js';\n\nasync function main() {\n ensureDataDirs();\n\n // Only start dashboard if not explicitly disabled\n const isBareSubprocess = process.env['CLAUDE_CODE_SIMPLE'] === '1';\n\n if (!isBareSubprocess) {\n const sessionId = randomUUID();\n const projectPath = process.cwd();\n const projectName = projectPath.split('/').pop() ?? 'unknown';\n startDashboard({ sessionId, projectPath, projectName }).catch(() => {});\n }\n\n const server = createServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\nmain().catch((error) => {\n console.error('Fatal error:', error);\n process.exit(1);\n});\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport {\n startMeetingSchema,\n startMeetingHandler,\n getMeetingStatusSchema,\n getMeetingStatusHandler,\n getMinutesSchema,\n getMinutesHandler,\n compactMinutesSchema,\n compactMinutesHandler,\n executeTasksSchema,\n executeTasksHandler,\n getAgentTreeHandler,\n respondToMentionSchema,\n respondToMentionHandler,\n getMentionsSchema,\n getMentionsHandler,\n cancelMeetingSchema,\n cancelMeetingHandler,\n listMeetingsSchema,\n listMeetingsHandler,\n getTaskReportSchema,\n getTaskReportHandler,\n createCapabilitySchema,\n createCapabilityHandler,\n getCostSummarySchema,\n getCostSummaryHandler,\n chainMeetingSchema,\n chainMeetingHandler,\n addTranscriptSchema,\n addTranscriptHandler,\n generateMinutesSchema,\n generateMinutesHandler,\n} from './tools/index.js';\n\nexport function createServer(): McpServer {\n const server = new McpServer({\n name: 'open-coleslaw',\n version: '0.1.0',\n });\n\n // 1. start-meeting\n server.tool(\n 'start-meeting',\n 'Create a new meeting record with topic and agenda. Returns meetingId and recommended departments. Does NOT run the meeting.',\n startMeetingSchema,\n startMeetingHandler,\n );\n\n // 2. get-meeting-status\n server.tool(\n 'get-meeting-status',\n 'Get the status of a specific meeting or all active meetings',\n getMeetingStatusSchema,\n getMeetingStatusHandler,\n );\n\n // 3. get-minutes\n server.tool(\n 'get-minutes',\n 'Retrieve meeting minutes in full, summary, or tasks-only format',\n getMinutesSchema,\n getMinutesHandler,\n );\n\n // 4. compact-minutes\n server.tool(\n 'compact-minutes',\n 'Compact meeting minutes into a structured, department-assigned task list',\n compactMinutesSchema,\n compactMinutesHandler,\n );\n\n // 5. execute-tasks\n server.tool(\n 'execute-tasks',\n 'Get the task list from compacted minutes for agent dispatch. Does NOT spawn workers.',\n executeTasksSchema,\n executeTasksHandler,\n );\n\n // 6. get-agent-tree\n server.tool(\n 'get-agent-tree',\n 'Return the full agent hierarchy tree',\n getAgentTreeHandler,\n );\n\n // 7. respond-to-mention\n server.tool(\n 'respond-to-mention',\n 'Respond to a pending @mention with a decision',\n respondToMentionSchema,\n respondToMentionHandler,\n );\n\n // 8. get-mentions\n server.tool(\n 'get-mentions',\n 'List @mentions filtered by status and/or meeting',\n getMentionsSchema,\n getMentionsHandler,\n );\n\n // 9. cancel-meeting\n server.tool(\n 'cancel-meeting',\n 'Cancel an active meeting and clean up its agents and workers',\n cancelMeetingSchema,\n cancelMeetingHandler,\n );\n\n // 10. list-meetings\n server.tool(\n 'list-meetings',\n 'List meetings with optional status filter and pagination',\n listMeetingsSchema,\n listMeetingsHandler,\n );\n\n // 11. get-task-report\n server.tool(\n 'get-task-report',\n 'Generate a task execution report for a meeting with per-department breakdown',\n getTaskReportSchema,\n getTaskReportHandler,\n );\n\n // 12. create-capability\n server.tool(\n 'create-capability',\n 'Create a new extension capability (hook, skill, command, asset, or loop)',\n createCapabilitySchema,\n createCapabilityHandler,\n );\n\n // 13. get-cost-summary\n server.tool(\n 'get-cost-summary',\n 'Get cost summary for a specific meeting or overall across all meetings',\n getCostSummarySchema,\n getCostSummaryHandler,\n );\n\n // 14. chain-meeting\n server.tool(\n 'chain-meeting',\n 'Create a new meeting chained from a previous meeting, using its minutes as context. Does NOT run the meeting.',\n chainMeetingSchema,\n chainMeetingHandler,\n );\n\n // 15. add-transcript\n server.tool(\n 'add-transcript',\n 'Add a transcript entry to a meeting. Used to record speaker contributions during meeting phases.',\n addTranscriptSchema,\n addTranscriptHandler,\n );\n\n // 16. generate-minutes\n server.tool(\n 'generate-minutes',\n 'Generate PRD minutes from all stored transcripts for a meeting. Marks the meeting as completed.',\n generateMinutesSchema,\n generateMinutesHandler,\n );\n\n return server;\n}\n","import { z } from 'zod';\nimport { Orchestrator } from '../orchestrator/orchestrator.js';\nimport type { Department } from '../types/index.js';\n\nexport const startMeetingSchema = {\n topic: z.string().describe('Meeting topic'),\n agenda: z.array(z.string()).describe('Agenda items'),\n departments: z\n .array(z.string())\n .optional()\n .describe('Specific departments to invite'),\n};\n\nexport async function startMeetingHandler({\n topic,\n agenda,\n departments,\n}: {\n topic: string;\n agenda: string[];\n departments?: string[];\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const orchestrator = new Orchestrator();\n const result = orchestrator.startMeeting({\n topic,\n agenda,\n departments: departments as Department[] | undefined,\n });\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import { v4 as uuidv4 } from 'uuid';\nimport type {\n Department,\n Meeting,\n MentionRecord,\n} from '../types/index.js';\nimport {\n createMeeting,\n updateMeeting,\n getMeeting,\n listMeetings,\n listPendingMentions,\n getAgentTree,\n getMinutesByMeeting,\n} from '../storage/index.js';\nimport type { AgentTreeNode } from '../storage/index.js';\nimport { LeaderPool } from './leader-pool.js';\nimport { logger } from '../utils/logger.js';\n\n// ---------------------------------------------------------------------------\n// Keyword maps for leader selection heuristics\n// ---------------------------------------------------------------------------\n\nconst DEPARTMENT_KEYWORDS: Record<Department, string[]> = {\n architecture: [\n 'architecture', 'design', 'schema', 'api', 'data model', 'module',\n 'interface', 'contract', 'coupling', 'dependency graph', 'adr',\n 'system design', 'blueprint', 'data flow',\n ],\n engineering: [\n 'code', 'implement', 'build', 'feature', 'bug', 'fix', 'refactor',\n 'develop', 'function', 'class', 'module', 'write', 'create',\n 'modify', 'update', 'delete', 'crud', 'endpoint', 'migration',\n ],\n qa: [\n 'test', 'quality', 'security', 'performance', 'audit', 'coverage',\n 'regression', 'benchmark', 'vulnerability', 'pen test', 'lint',\n 'assertion', 'e2e', 'integration test', 'unit test',\n ],\n product: [\n 'requirements', 'user', 'story', 'priority', 'acceptance criteria',\n 'user flow', 'stakeholder', 'roadmap', 'scope', 'use case',\n 'persona', 'mvp', 'specification',\n ],\n research: [\n 'research', 'explore', 'investigate', 'search', 'analyze', 'find',\n 'discover', 'benchmark', 'compare', 'survey', 'documentation',\n 'reference', 'existing code',\n ],\n};\n\n// ---------------------------------------------------------------------------\n// StartMeeting options & result\n// ---------------------------------------------------------------------------\n\nexport interface StartMeetingOptions {\n topic: string;\n agenda: string[];\n departments?: Department[];\n previousMeetingId?: string | null;\n}\n\nexport interface StartMeetingResult {\n meetingId: string;\n departments: Department[];\n agenda: string[];\n topic: string;\n}\n\n// ---------------------------------------------------------------------------\n// Orchestrator status\n// ---------------------------------------------------------------------------\n\nexport interface OrchestratorStatus {\n activeMeetings: Meeting[];\n pendingMentions: MentionRecord[];\n agentTree: AgentTreeNode | null;\n}\n\n// ---------------------------------------------------------------------------\n// Orchestrator — creates meeting records and selects leaders\n//\n// No longer runs meetings itself. Meetings are orchestrated by Claude Code's\n// Agent tool via skill/agent markdown files.\n// ---------------------------------------------------------------------------\n\nexport class Orchestrator {\n private readonly leaderPool = new LeaderPool();\n\n /**\n * Internal ID for the orchestrator \"agent\". Used as the meeting initiator\n * and as the root of the agent tree.\n */\n private readonly orchestratorId: string;\n\n constructor(orchestratorId?: string) {\n this.orchestratorId = orchestratorId ?? 'orchestrator-root';\n }\n\n // ---- leader selection ---------------------------------------------------\n\n /**\n * Analyse a topic and agenda to determine which department leaders should\n * be convened for a meeting.\n *\n * Uses keyword-based heuristics:\n * - Matches topic + agenda text against per-department keyword lists.\n * - Scores each department by the number of keyword hits.\n * - Selects departments with at least one hit.\n * - Falls back to engineering + architecture for complex topics (multiple\n * agenda items) or engineering alone for simple ones.\n */\n selectLeaders(topic: string, agenda: string[]): Department[] {\n const corpus = [topic, ...agenda].join(' ').toLowerCase();\n\n const scores = new Map<Department, number>();\n\n for (const [dept, keywords] of Object.entries(DEPARTMENT_KEYWORDS) as [Department, string[]][]) {\n let score = 0;\n for (const kw of keywords) {\n if (corpus.includes(kw)) {\n score++;\n }\n }\n if (score > 0) {\n scores.set(dept, score);\n }\n }\n\n if (scores.size === 0) {\n // Fallback: complex topics (3+ agenda items) get architecture + engineering;\n // simple ones get engineering only.\n if (agenda.length >= 3) {\n logger.debug('No keyword matches; defaulting to architecture + engineering (complex topic)', {\n meetingId: topic,\n });\n return ['architecture', 'engineering'];\n }\n logger.debug('No keyword matches; defaulting to engineering only (simple topic)', {\n meetingId: topic,\n });\n return ['engineering'];\n }\n\n // Sort by score descending and take all with hits\n const selected = [...scores.entries()]\n .sort((a, b) => b[1] - a[1])\n .map(([dept]) => dept);\n\n logger.debug(`Selected departments: ${selected.join(', ')}`, { meetingId: topic });\n\n return selected;\n }\n\n // ---- start meeting ------------------------------------------------------\n\n /**\n * Create a new meeting record and return meeting info + recommended leaders.\n *\n * Does NOT run the meeting. The calling agent (via skill markdown) is\n * responsible for orchestrating the meeting phases using add-transcript\n * and generate-minutes MCP tools.\n */\n startMeeting(opts: StartMeetingOptions): StartMeetingResult {\n const { topic, agenda } = opts;\n const departments = opts.departments ?? this.selectLeaders(topic, agenda);\n\n logger.info(`Creating meeting: \"${topic}\" with departments: [${departments.join(', ')}]`);\n\n // Create the meeting record\n const meetingId = uuidv4();\n createMeeting({\n id: meetingId,\n topic,\n agenda,\n participantIds: departments.map((d) => `${d}-leader`),\n initiatedBy: this.orchestratorId,\n status: 'pending',\n phase: 'orchestrator-phase',\n startedAt: Date.now(),\n previousMeetingId: opts.previousMeetingId ?? null,\n });\n\n return {\n meetingId,\n departments,\n agenda,\n topic,\n };\n }\n\n // ---- chain meeting -------------------------------------------------------\n\n /**\n * Create a new meeting chained from a previous meeting.\n *\n * Loads minutes from the previous meeting and includes them as context for\n * the new meeting topic. The new meeting's `previousMeetingId` is set for\n * traceability.\n *\n * Does NOT run the meeting (same as startMeeting).\n */\n chainMeeting(opts: {\n previousMeetingId: string;\n topic: string;\n agenda: string[];\n departments?: Department[];\n }): StartMeetingResult {\n const previousMeeting = getMeeting(opts.previousMeetingId);\n if (!previousMeeting) {\n throw new Error(`Previous meeting not found: ${opts.previousMeetingId}`);\n }\n\n const previousMinutes = getMinutesByMeeting(opts.previousMeetingId);\n if (!previousMinutes) {\n throw new Error(`No minutes found for previous meeting: ${opts.previousMeetingId}`);\n }\n\n // Prepend the previous meeting context to the topic\n const contextPrefix =\n `[Chained from meeting \"${previousMeeting.topic}\" (${opts.previousMeetingId})]\\n\\n` +\n `--- Previous Meeting Minutes ---\\n${previousMinutes.content}\\n--- End Previous Minutes ---\\n\\n`;\n\n const enrichedTopic = contextPrefix + opts.topic;\n\n logger.info(\n `Chaining meeting from \"${previousMeeting.topic}\" -> \"${opts.topic}\"`,\n { meetingId: opts.previousMeetingId },\n );\n\n return this.startMeeting({\n topic: enrichedTopic,\n agenda: opts.agenda,\n departments: opts.departments,\n previousMeetingId: opts.previousMeetingId,\n });\n }\n\n // ---- status -------------------------------------------------------------\n\n /**\n * Return a summary of all active meetings, pending @mentions, and the\n * current agent tree.\n */\n getStatus(): OrchestratorStatus {\n // Active meetings: anything not completed/cancelled/failed\n const allMeetings = listMeetings();\n const activeMeetings = allMeetings.filter(\n (m) => !['completed', 'cancelled', 'failed', 'reported', 'compacted'].includes(m.status),\n );\n\n // Pending @mentions across all meetings\n const pendingMentions = listPendingMentions();\n\n // Agent tree rooted at the orchestrator (may be null if no agents yet)\n const agentTree = getAgentTree(this.orchestratorId);\n\n return {\n activeMeetings,\n pendingMentions,\n agentTree,\n };\n }\n\n // ---- accessors ----------------------------------------------------------\n\n /** The leader pool used by this orchestrator instance. */\n getLeaderPool(): LeaderPool {\n return this.leaderPool;\n }\n\n /** The orchestrator's agent ID. */\n getId(): string {\n return this.orchestratorId;\n }\n}\n","import { v4 as uuidv4 } from 'uuid';\nimport { getDb } from './db.js';\nimport type { AgentNode, AgentTier, AgentStatus, Department } from '../types/index.js';\n\ninterface AgentRow {\n id: string;\n tier: string;\n role: string;\n department: string;\n parent_id: string | null;\n meeting_id: string | null;\n status: string;\n current_task: string | null;\n session_id: string | null;\n spawned_at: number;\n completed_at: number | null;\n cost_usd: number;\n}\n\nfunction rowToAgent(row: AgentRow): AgentNode {\n return {\n id: row.id,\n tier: row.tier as AgentTier,\n role: row.role,\n department: row.department as Department,\n parentId: row.parent_id,\n meetingId: row.meeting_id,\n status: row.status as AgentStatus,\n currentTask: row.current_task,\n sessionId: row.session_id,\n spawnedAt: row.spawned_at,\n completedAt: row.completed_at,\n costUsd: row.cost_usd,\n };\n}\n\nexport function createAgent(\n agent: Omit<AgentNode, 'id' | 'spawnedAt' | 'completedAt' | 'costUsd'> & {\n id?: string;\n spawnedAt?: number;\n completedAt?: number | null;\n costUsd?: number;\n }\n): AgentNode {\n const db = getDb();\n const id = agent.id ?? uuidv4();\n const spawnedAt = agent.spawnedAt ?? Date.now();\n const completedAt = agent.completedAt ?? null;\n const costUsd = agent.costUsd ?? 0;\n\n db.prepare(\n `INSERT INTO agents (id, tier, role, department, parent_id, meeting_id, status, current_task, session_id, spawned_at, completed_at, cost_usd)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`\n ).run(\n id,\n agent.tier,\n agent.role,\n agent.department,\n agent.parentId,\n agent.meetingId,\n agent.status,\n agent.currentTask,\n agent.sessionId,\n spawnedAt,\n completedAt,\n costUsd\n );\n\n return {\n id,\n tier: agent.tier,\n role: agent.role,\n department: agent.department,\n parentId: agent.parentId,\n meetingId: agent.meetingId,\n status: agent.status,\n currentTask: agent.currentTask,\n sessionId: agent.sessionId,\n spawnedAt,\n completedAt,\n costUsd,\n };\n}\n\nexport function getAgent(id: string): AgentNode | null {\n const db = getDb();\n const row = db.prepare('SELECT * FROM agents WHERE id = ?').get(id) as AgentRow | undefined;\n return row ? rowToAgent(row) : null;\n}\n\nexport function updateAgent(\n id: string,\n updates: Partial<Omit<AgentNode, 'id'>>\n): AgentNode | null {\n const db = getDb();\n const existing = getAgent(id);\n if (!existing) return null;\n\n const fields: string[] = [];\n const values: unknown[] = [];\n\n if (updates.tier !== undefined) { fields.push('tier = ?'); values.push(updates.tier); }\n if (updates.role !== undefined) { fields.push('role = ?'); values.push(updates.role); }\n if (updates.department !== undefined) { fields.push('department = ?'); values.push(updates.department); }\n if (updates.parentId !== undefined) { fields.push('parent_id = ?'); values.push(updates.parentId); }\n if (updates.meetingId !== undefined) { fields.push('meeting_id = ?'); values.push(updates.meetingId); }\n if (updates.status !== undefined) { fields.push('status = ?'); values.push(updates.status); }\n if (updates.currentTask !== undefined) { fields.push('current_task = ?'); values.push(updates.currentTask); }\n if (updates.sessionId !== undefined) { fields.push('session_id = ?'); values.push(updates.sessionId); }\n if (updates.spawnedAt !== undefined) { fields.push('spawned_at = ?'); values.push(updates.spawnedAt); }\n if (updates.completedAt !== undefined) { fields.push('completed_at = ?'); values.push(updates.completedAt); }\n if (updates.costUsd !== undefined) { fields.push('cost_usd = ?'); values.push(updates.costUsd); }\n\n if (fields.length === 0) return existing;\n\n values.push(id);\n db.prepare(`UPDATE agents SET ${fields.join(', ')} WHERE id = ?`).run(...values);\n\n return getAgent(id);\n}\n\nexport function listAgentsByMeeting(meetingId: string): AgentNode[] {\n const db = getDb();\n const rows = db\n .prepare('SELECT * FROM agents WHERE meeting_id = ?')\n .all(meetingId) as AgentRow[];\n return rows.map(rowToAgent);\n}\n\nexport function listAgentsByParent(parentId: string): AgentNode[] {\n const db = getDb();\n const rows = db\n .prepare('SELECT * FROM agents WHERE parent_id = ?')\n .all(parentId) as AgentRow[];\n return rows.map(rowToAgent);\n}\n\nexport interface AgentTreeNode extends AgentNode {\n children: AgentTreeNode[];\n}\n\nexport function getAgentTree(rootId: string): AgentTreeNode | null {\n const agent = getAgent(rootId);\n if (!agent) return null;\n\n const children = listAgentsByParent(rootId);\n const treeNode: AgentTreeNode = {\n ...agent,\n children: children\n .map((child) => getAgentTree(child.id))\n .filter((node): node is AgentTreeNode => node !== null),\n };\n\n return treeNode;\n}\n","import { v4 as uuidv4 } from 'uuid';\nimport { getDb } from './db.js';\nimport type { Meeting, MeetingStatus, MeetingPhase } from '../types/index.js';\n\ninterface MeetingRow {\n id: string;\n topic: string;\n agenda: string;\n participant_ids: string;\n status: string;\n phase: string;\n started_at: number | null;\n completed_at: number | null;\n initiated_by: string;\n previous_meeting_id?: string | null;\n}\n\n/** Ensure the previous_meeting_id column exists (backward-compat migration). */\nfunction ensurePreviousMeetingIdColumn(): void {\n const db = getDb();\n // PRAGMA table_info returns rows for each column; check if the column exists.\n const cols = db.prepare(\"PRAGMA table_info('meetings')\").all() as Array<{ name: string }>;\n const hasColumn = cols.some((c) => c.name === 'previous_meeting_id');\n if (!hasColumn) {\n db.exec('ALTER TABLE meetings ADD COLUMN previous_meeting_id TEXT DEFAULT NULL');\n }\n}\n\nlet columnChecked = false;\n\nfunction rowToMeeting(row: MeetingRow): Meeting {\n return {\n id: row.id,\n topic: row.topic,\n agenda: JSON.parse(row.agenda) as string[],\n participantIds: JSON.parse(row.participant_ids) as string[],\n status: row.status as MeetingStatus,\n phase: row.phase as MeetingPhase,\n startedAt: row.started_at,\n completedAt: row.completed_at,\n initiatedBy: row.initiated_by,\n previousMeetingId: row.previous_meeting_id ?? null,\n };\n}\n\nexport function createMeeting(\n meeting: Omit<Meeting, 'id' | 'status' | 'phase' | 'startedAt' | 'completedAt' | 'previousMeetingId'> & {\n id?: string;\n status?: MeetingStatus;\n phase?: MeetingPhase;\n startedAt?: number | null;\n completedAt?: number | null;\n previousMeetingId?: string | null;\n }\n): Meeting {\n if (!columnChecked) {\n ensurePreviousMeetingIdColumn();\n columnChecked = true;\n }\n\n const db = getDb();\n const id = meeting.id ?? uuidv4();\n const status = meeting.status ?? 'pending';\n const phase = meeting.phase ?? 'orchestrator-phase';\n const startedAt = meeting.startedAt ?? null;\n const completedAt = meeting.completedAt ?? null;\n const previousMeetingId = meeting.previousMeetingId ?? null;\n\n db.prepare(\n `INSERT INTO meetings (id, topic, agenda, participant_ids, status, phase, started_at, completed_at, initiated_by, previous_meeting_id)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`\n ).run(\n id,\n meeting.topic,\n JSON.stringify(meeting.agenda),\n JSON.stringify(meeting.participantIds),\n status,\n phase,\n startedAt,\n completedAt,\n meeting.initiatedBy,\n previousMeetingId\n );\n\n return {\n id,\n topic: meeting.topic,\n agenda: meeting.agenda,\n participantIds: meeting.participantIds,\n status,\n phase,\n startedAt,\n completedAt,\n initiatedBy: meeting.initiatedBy,\n previousMeetingId,\n };\n}\n\nexport function getMeeting(id: string): Meeting | null {\n if (!columnChecked) {\n ensurePreviousMeetingIdColumn();\n columnChecked = true;\n }\n\n const db = getDb();\n const row = db.prepare('SELECT * FROM meetings WHERE id = ?').get(id) as MeetingRow | undefined;\n return row ? rowToMeeting(row) : null;\n}\n\nexport function updateMeeting(\n id: string,\n updates: Partial<Omit<Meeting, 'id'>>\n): Meeting | null {\n const db = getDb();\n const existing = getMeeting(id);\n if (!existing) return null;\n\n const fields: string[] = [];\n const values: unknown[] = [];\n\n if (updates.topic !== undefined) { fields.push('topic = ?'); values.push(updates.topic); }\n if (updates.agenda !== undefined) { fields.push('agenda = ?'); values.push(JSON.stringify(updates.agenda)); }\n if (updates.participantIds !== undefined) { fields.push('participant_ids = ?'); values.push(JSON.stringify(updates.participantIds)); }\n if (updates.status !== undefined) { fields.push('status = ?'); values.push(updates.status); }\n if (updates.phase !== undefined) { fields.push('phase = ?'); values.push(updates.phase); }\n if (updates.startedAt !== undefined) { fields.push('started_at = ?'); values.push(updates.startedAt); }\n if (updates.completedAt !== undefined) { fields.push('completed_at = ?'); values.push(updates.completedAt); }\n if (updates.initiatedBy !== undefined) { fields.push('initiated_by = ?'); values.push(updates.initiatedBy); }\n if (updates.previousMeetingId !== undefined) { fields.push('previous_meeting_id = ?'); values.push(updates.previousMeetingId); }\n\n if (fields.length === 0) return existing;\n\n values.push(id);\n db.prepare(`UPDATE meetings SET ${fields.join(', ')} WHERE id = ?`).run(...values);\n\n return getMeeting(id);\n}\n\nexport function listMeetings(statusFilter?: MeetingStatus): Meeting[] {\n if (!columnChecked) {\n ensurePreviousMeetingIdColumn();\n columnChecked = true;\n }\n\n const db = getDb();\n let rows: MeetingRow[];\n\n if (statusFilter) {\n rows = db\n .prepare('SELECT * FROM meetings WHERE status = ? ORDER BY started_at DESC')\n .all(statusFilter) as MeetingRow[];\n } else {\n rows = db\n .prepare('SELECT * FROM meetings ORDER BY started_at DESC')\n .all() as MeetingRow[];\n }\n\n return rows.map(rowToMeeting);\n}\n","import { v4 as uuidv4 } from 'uuid';\nimport { getDb } from './db.js';\nimport type { WorkerRecord, WorkerStatus, TaskType } from '../types/index.js';\n\ninterface WorkerRow {\n id: string;\n leader_id: string;\n meeting_id: string;\n task_description: string;\n task_type: string | null;\n status: string;\n input_context: string | null;\n output_result: string | null;\n error_message: string | null;\n dependencies: string;\n spawned_at: number;\n completed_at: number | null;\n cost_usd: number;\n}\n\nfunction rowToWorker(row: WorkerRow): WorkerRecord {\n return {\n id: row.id,\n leaderId: row.leader_id,\n meetingId: row.meeting_id,\n taskDescription: row.task_description,\n taskType: row.task_type as TaskType | null,\n status: row.status as WorkerStatus,\n inputContext: row.input_context,\n outputResult: row.output_result,\n errorMessage: row.error_message,\n dependencies: JSON.parse(row.dependencies) as string[],\n spawnedAt: row.spawned_at,\n completedAt: row.completed_at,\n costUsd: row.cost_usd,\n };\n}\n\nexport function createWorker(\n worker: Omit<WorkerRecord, 'id' | 'status' | 'spawnedAt' | 'completedAt' | 'costUsd'> & {\n id?: string;\n status?: WorkerStatus;\n spawnedAt?: number;\n completedAt?: number | null;\n costUsd?: number;\n }\n): WorkerRecord {\n const db = getDb();\n const id = worker.id ?? uuidv4();\n const status = worker.status ?? 'pending';\n const spawnedAt = worker.spawnedAt ?? Date.now();\n const completedAt = worker.completedAt ?? null;\n const costUsd = worker.costUsd ?? 0;\n\n db.prepare(\n `INSERT INTO workers (id, leader_id, meeting_id, task_description, task_type, status, input_context, output_result, error_message, dependencies, spawned_at, completed_at, cost_usd)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`\n ).run(\n id,\n worker.leaderId,\n worker.meetingId,\n worker.taskDescription,\n worker.taskType,\n status,\n worker.inputContext,\n worker.outputResult,\n worker.errorMessage,\n JSON.stringify(worker.dependencies),\n spawnedAt,\n completedAt,\n costUsd\n );\n\n return {\n id,\n leaderId: worker.leaderId,\n meetingId: worker.meetingId,\n taskDescription: worker.taskDescription,\n taskType: worker.taskType,\n status,\n inputContext: worker.inputContext,\n outputResult: worker.outputResult,\n errorMessage: worker.errorMessage,\n dependencies: worker.dependencies,\n spawnedAt,\n completedAt,\n costUsd,\n };\n}\n\nexport function getWorker(id: string): WorkerRecord | null {\n const db = getDb();\n const row = db.prepare('SELECT * FROM workers WHERE id = ?').get(id) as WorkerRow | undefined;\n return row ? rowToWorker(row) : null;\n}\n\nexport function updateWorker(\n id: string,\n updates: Partial<Omit<WorkerRecord, 'id'>>\n): WorkerRecord | null {\n const db = getDb();\n const existing = getWorker(id);\n if (!existing) return null;\n\n const fields: string[] = [];\n const values: unknown[] = [];\n\n if (updates.leaderId !== undefined) { fields.push('leader_id = ?'); values.push(updates.leaderId); }\n if (updates.meetingId !== undefined) { fields.push('meeting_id = ?'); values.push(updates.meetingId); }\n if (updates.taskDescription !== undefined) { fields.push('task_description = ?'); values.push(updates.taskDescription); }\n if (updates.taskType !== undefined) { fields.push('task_type = ?'); values.push(updates.taskType); }\n if (updates.status !== undefined) { fields.push('status = ?'); values.push(updates.status); }\n if (updates.inputContext !== undefined) { fields.push('input_context = ?'); values.push(updates.inputContext); }\n if (updates.outputResult !== undefined) { fields.push('output_result = ?'); values.push(updates.outputResult); }\n if (updates.errorMessage !== undefined) { fields.push('error_message = ?'); values.push(updates.errorMessage); }\n if (updates.dependencies !== undefined) { fields.push('dependencies = ?'); values.push(JSON.stringify(updates.dependencies)); }\n if (updates.spawnedAt !== undefined) { fields.push('spawned_at = ?'); values.push(updates.spawnedAt); }\n if (updates.completedAt !== undefined) { fields.push('completed_at = ?'); values.push(updates.completedAt); }\n if (updates.costUsd !== undefined) { fields.push('cost_usd = ?'); values.push(updates.costUsd); }\n\n if (fields.length === 0) return existing;\n\n values.push(id);\n db.prepare(`UPDATE workers SET ${fields.join(', ')} WHERE id = ?`).run(...values);\n\n return getWorker(id);\n}\n\nexport function listWorkersByLeader(leaderId: string): WorkerRecord[] {\n const db = getDb();\n const rows = db\n .prepare('SELECT * FROM workers WHERE leader_id = ? ORDER BY spawned_at ASC')\n .all(leaderId) as WorkerRow[];\n return rows.map(rowToWorker);\n}\n","import { v4 as uuidv4 } from 'uuid';\nimport { getDb } from './db.js';\nimport type { MentionRecord, MentionUrgency, MentionStatus, MentionOption } from '../types/index.js';\n\ninterface MentionRow {\n id: string;\n meeting_id: string;\n agenda_item: string | null;\n summary: string;\n options: string;\n urgency: string;\n status: string;\n user_decision: string | null;\n user_reasoning: string | null;\n created_at: number;\n resolved_at: number | null;\n}\n\nfunction rowToMention(row: MentionRow): MentionRecord {\n return {\n id: row.id,\n meetingId: row.meeting_id,\n agendaItem: row.agenda_item,\n summary: row.summary,\n options: JSON.parse(row.options) as MentionOption[],\n urgency: row.urgency as MentionUrgency,\n status: row.status as MentionStatus,\n userDecision: row.user_decision,\n userReasoning: row.user_reasoning,\n createdAt: row.created_at,\n resolvedAt: row.resolved_at,\n };\n}\n\nexport function createMention(\n mention: Omit<MentionRecord, 'id' | 'status' | 'createdAt' | 'resolvedAt'> & {\n id?: string;\n status?: MentionStatus;\n createdAt?: number;\n resolvedAt?: number | null;\n }\n): MentionRecord {\n const db = getDb();\n const id = mention.id ?? uuidv4();\n const status = mention.status ?? 'pending';\n const createdAt = mention.createdAt ?? Date.now();\n const resolvedAt = mention.resolvedAt ?? null;\n\n db.prepare(\n `INSERT INTO mentions (id, meeting_id, agenda_item, summary, options, urgency, status, user_decision, user_reasoning, created_at, resolved_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`\n ).run(\n id,\n mention.meetingId,\n mention.agendaItem,\n mention.summary,\n JSON.stringify(mention.options),\n mention.urgency,\n status,\n mention.userDecision,\n mention.userReasoning,\n createdAt,\n resolvedAt\n );\n\n return {\n id,\n meetingId: mention.meetingId,\n agendaItem: mention.agendaItem,\n summary: mention.summary,\n options: mention.options,\n urgency: mention.urgency,\n status,\n userDecision: mention.userDecision,\n userReasoning: mention.userReasoning,\n createdAt,\n resolvedAt,\n };\n}\n\nexport function getMention(id: string): MentionRecord | null {\n const db = getDb();\n const row = db.prepare('SELECT * FROM mentions WHERE id = ?').get(id) as MentionRow | undefined;\n return row ? rowToMention(row) : null;\n}\n\nexport function updateMention(\n id: string,\n updates: Partial<Omit<MentionRecord, 'id'>>\n): MentionRecord | null {\n const db = getDb();\n const existing = getMention(id);\n if (!existing) return null;\n\n const fields: string[] = [];\n const values: unknown[] = [];\n\n if (updates.meetingId !== undefined) { fields.push('meeting_id = ?'); values.push(updates.meetingId); }\n if (updates.agendaItem !== undefined) { fields.push('agenda_item = ?'); values.push(updates.agendaItem); }\n if (updates.summary !== undefined) { fields.push('summary = ?'); values.push(updates.summary); }\n if (updates.options !== undefined) { fields.push('options = ?'); values.push(JSON.stringify(updates.options)); }\n if (updates.urgency !== undefined) { fields.push('urgency = ?'); values.push(updates.urgency); }\n if (updates.status !== undefined) { fields.push('status = ?'); values.push(updates.status); }\n if (updates.userDecision !== undefined) { fields.push('user_decision = ?'); values.push(updates.userDecision); }\n if (updates.userReasoning !== undefined) { fields.push('user_reasoning = ?'); values.push(updates.userReasoning); }\n if (updates.createdAt !== undefined) { fields.push('created_at = ?'); values.push(updates.createdAt); }\n if (updates.resolvedAt !== undefined) { fields.push('resolved_at = ?'); values.push(updates.resolvedAt); }\n\n if (fields.length === 0) return existing;\n\n values.push(id);\n db.prepare(`UPDATE mentions SET ${fields.join(', ')} WHERE id = ?`).run(...values);\n\n return getMention(id);\n}\n\nexport function listPendingMentions(): MentionRecord[] {\n const db = getDb();\n const rows = db\n .prepare(\"SELECT * FROM mentions WHERE status = 'pending' ORDER BY created_at ASC\")\n .all() as MentionRow[];\n return rows.map(rowToMention);\n}\n\nexport function listMentionsByMeeting(meetingId: string): MentionRecord[] {\n const db = getDb();\n const rows = db\n .prepare('SELECT * FROM mentions WHERE meeting_id = ? ORDER BY created_at ASC')\n .all(meetingId) as MentionRow[];\n return rows.map(rowToMention);\n}\n","import { v4 as uuidv4 } from 'uuid';\nimport { getDb } from './db.js';\nimport type { MinutesRecord, MinutesFormat, ActionItem } from '../types/index.js';\n\ninterface MinutesRow {\n id: string;\n meeting_id: string;\n format: string;\n content: string;\n action_items: string;\n created_at: number;\n}\n\nfunction rowToMinutes(row: MinutesRow): MinutesRecord {\n return {\n id: row.id,\n meetingId: row.meeting_id,\n format: row.format as MinutesFormat,\n content: row.content,\n actionItems: JSON.parse(row.action_items) as ActionItem[],\n createdAt: row.created_at,\n };\n}\n\nexport function createMinutes(\n minutes: Omit<MinutesRecord, 'id' | 'createdAt'> & {\n id?: string;\n createdAt?: number;\n }\n): MinutesRecord {\n const db = getDb();\n const id = minutes.id ?? uuidv4();\n const createdAt = minutes.createdAt ?? Date.now();\n\n db.prepare(\n `INSERT INTO minutes (id, meeting_id, format, content, action_items, created_at)\n VALUES (?, ?, ?, ?, ?, ?)`\n ).run(\n id,\n minutes.meetingId,\n minutes.format,\n minutes.content,\n JSON.stringify(minutes.actionItems),\n createdAt\n );\n\n return {\n id,\n meetingId: minutes.meetingId,\n format: minutes.format,\n content: minutes.content,\n actionItems: minutes.actionItems,\n createdAt,\n };\n}\n\nexport function getMinutesByMeeting(meetingId: string): MinutesRecord | null {\n const db = getDb();\n const row = db\n .prepare('SELECT * FROM minutes WHERE meeting_id = ?')\n .get(meetingId) as MinutesRow | undefined;\n return row ? rowToMinutes(row) : null;\n}\n","import { getDb } from './db.js';\nimport type { ActionItem } from '../types/index.js';\n\ninterface MinutesRow {\n id: string;\n meeting_id: string;\n action_items: string;\n}\n\nexport function getTasksFromMinutes(meetingId: string): ActionItem[] {\n const db = getDb();\n const row = db\n .prepare('SELECT action_items FROM minutes WHERE meeting_id = ?')\n .get(meetingId) as Pick<MinutesRow, 'action_items'> | undefined;\n\n if (!row) return [];\n\n return JSON.parse(row.action_items) as ActionItem[];\n}\n\nexport function updateTaskInMinutes(\n meetingId: string,\n taskId: string,\n updates: Partial<Omit<ActionItem, 'id'>>\n): ActionItem | null {\n const db = getDb();\n const row = db\n .prepare('SELECT id, action_items FROM minutes WHERE meeting_id = ?')\n .get(meetingId) as Pick<MinutesRow, 'id' | 'action_items'> | undefined;\n\n if (!row) return null;\n\n const actionItems = JSON.parse(row.action_items) as ActionItem[];\n const index = actionItems.findIndex((item) => item.id === taskId);\n\n if (index === -1) return null;\n\n const updated: ActionItem = { ...actionItems[index], ...updates, id: taskId };\n actionItems[index] = updated;\n\n db.prepare('UPDATE minutes SET action_items = ? WHERE id = ?').run(\n JSON.stringify(actionItems),\n row.id\n );\n\n return updated;\n}\n","export type AgentTier = 'orchestrator' | 'leader' | 'worker';\n\nexport type AgentStatus =\n | 'idle'\n | 'in-meeting'\n | 'working'\n | 'spawning-workers'\n | 'aggregating'\n | 'waiting-for-user'\n | 'completed'\n | 'failed';\n\nexport type Department =\n | 'architecture'\n | 'engineering'\n | 'qa'\n | 'product'\n | 'research';\n\nexport type LeaderRole =\n | 'architect'\n | 'engineer'\n | 'qa'\n | 'product-manager'\n | 'researcher';\n\nexport type WorkerType =\n | 'schema-designer'\n | 'api-designer'\n | 'dependency-analyzer'\n | 'feature-dev'\n | 'bug-fixer'\n | 'refactorer'\n | 'test-writer'\n | 'test-runner'\n | 'security-auditor'\n | 'perf-tester'\n | 'requirements-analyzer'\n | 'user-flow-mapper'\n | 'code-explorer'\n | 'doc-searcher'\n | 'benchmark-runner'\n | 'minutes-writer'\n | 'compactor';\n\nexport interface AgentNode {\n id: string;\n tier: AgentTier;\n role: string;\n department: Department;\n parentId: string | null;\n meetingId: string | null;\n status: AgentStatus;\n currentTask: string | null;\n sessionId: string | null;\n spawnedAt: number;\n completedAt: number | null;\n costUsd: number;\n}\n\nexport interface AgentConfig {\n model: string;\n maxTurns: number;\n\n allowedTools: string[];\n}\n\nexport const TIER_CONFIGS: Record<AgentTier, Omit<AgentConfig, 'allowedTools'>> = {\n orchestrator: {\n model: 'claude-opus-4-6',\n maxTurns: 10,\n },\n leader: {\n model: 'claude-sonnet-4-6',\n maxTurns: 20,\n },\n worker: {\n model: 'claude-sonnet-4-6',\n maxTurns: 30,\n },\n};\n\nexport const DEPARTMENT_TOOLS: Record<Department, string[]> = {\n architecture: ['Read', 'Grep', 'Glob'],\n engineering: ['Read', 'Grep', 'Glob', 'Write', 'Edit', 'Bash'],\n qa: ['Read', 'Grep', 'Glob', 'Bash'],\n product: ['Read'],\n research: ['Read', 'Grep', 'Glob', 'WebSearch'],\n};\n","import type { Department, LeaderRole, WorkerType } from '../types/index.js';\nimport { DEPARTMENT_TOOLS } from '../types/index.js';\n\n/** Full metadata for a department. */\nexport interface DepartmentInfo {\n name: Department;\n description: string;\n leaderRole: LeaderRole;\n workerTypes: WorkerType[];\n allowedTools: string[];\n}\n\nconst DEPARTMENT_REGISTRY: ReadonlyMap<Department, DepartmentInfo> = new Map<Department, DepartmentInfo>([\n [\n 'architecture',\n {\n name: 'architecture',\n description:\n 'Responsible for system design, schema definitions, API surface design, and dependency analysis. ' +\n 'The architecture department plans before code is written — it produces blueprints, not implementations.',\n leaderRole: 'architect',\n workerTypes: ['schema-designer', 'api-designer', 'dependency-analyzer'],\n allowedTools: DEPARTMENT_TOOLS.architecture,\n },\n ],\n [\n 'engineering',\n {\n name: 'engineering',\n description:\n 'Responsible for writing, modifying, and refactoring production code. ' +\n 'Engineering owns feature development, bug fixes, and code quality improvements.',\n leaderRole: 'engineer',\n workerTypes: ['feature-dev', 'bug-fixer', 'refactorer'],\n allowedTools: DEPARTMENT_TOOLS.engineering,\n },\n ],\n [\n 'qa',\n {\n name: 'qa',\n description:\n 'Responsible for test creation, test execution, security auditing, and performance testing. ' +\n 'QA ensures deliverables meet acceptance criteria and do not introduce regressions.',\n leaderRole: 'qa',\n workerTypes: ['test-writer', 'test-runner', 'security-auditor', 'perf-tester'],\n allowedTools: DEPARTMENT_TOOLS.qa,\n },\n ],\n [\n 'product',\n {\n name: 'product',\n description:\n 'Responsible for requirements analysis, user-flow mapping, and stakeholder alignment. ' +\n 'Product translates user intent into well-scoped, actionable requirements for other departments.',\n leaderRole: 'product-manager',\n workerTypes: ['requirements-analyzer', 'user-flow-mapper'],\n allowedTools: DEPARTMENT_TOOLS.product,\n },\n ],\n [\n 'research',\n {\n name: 'research',\n description:\n 'Responsible for codebase exploration, documentation search, benchmarking, and knowledge gathering. ' +\n 'Research produces facts and context that inform decisions made by other departments.',\n leaderRole: 'researcher',\n workerTypes: ['code-explorer', 'doc-searcher', 'benchmark-runner'],\n allowedTools: DEPARTMENT_TOOLS.research,\n },\n ],\n]);\n\n/** Reverse lookup: leader role → department. */\nconst ROLE_TO_DEPARTMENT: ReadonlyMap<LeaderRole, Department> = new Map<LeaderRole, Department>(\n [...DEPARTMENT_REGISTRY.values()].map((d) => [d.leaderRole, d.name]),\n);\n\n/**\n * Get the full metadata for a single department.\n * Throws if the department key is unknown.\n */\nexport function getDepartment(dept: Department): DepartmentInfo {\n const info = DEPARTMENT_REGISTRY.get(dept);\n if (!info) {\n throw new Error(`Unknown department: ${dept}`);\n }\n return info;\n}\n\n/**\n * Return metadata for every registered department.\n */\nexport function getAllDepartments(): DepartmentInfo[] {\n return [...DEPARTMENT_REGISTRY.values()];\n}\n\n/**\n * Resolve a leader role back to its owning department.\n * Throws if the role is unknown.\n */\nexport function getDepartmentForRole(role: LeaderRole): Department {\n const dept = ROLE_TO_DEPARTMENT.get(role);\n if (dept === undefined) {\n throw new Error(`Unknown leader role: ${role}`);\n }\n return dept;\n}\n","import { EventEmitter } from 'node:events';\nimport type { AgentEvent, DashboardEvent } from '../types/index.js';\n\n// ---------------------------------------------------------------------------\n// Typed event map\n// ---------------------------------------------------------------------------\n\n/**\n * Events emitted by the internal event bus.\n *\n * - `agent_event` — individual agent lifecycle events (spawned, destroyed, state change, etc.)\n * - `dashboard` — full dashboard payloads (snapshot or delta) intended for the WebSocket dashboard.\n */\nexport interface EventBusEvents {\n agent_event: [event: AgentEvent];\n dashboard: [event: DashboardEvent];\n}\n\n// ---------------------------------------------------------------------------\n// EventBus class\n// ---------------------------------------------------------------------------\n\nclass EventBus {\n private readonly emitter = new EventEmitter();\n\n constructor() {\n // Allow a reasonable number of listeners (leaders + dashboard + internal consumers)\n this.emitter.setMaxListeners(50);\n }\n\n // ---- emit ---------------------------------------------------------------\n\n /**\n * Emit a single agent lifecycle event.\n *\n * The event is:\n * 1. Broadcast to all `agent_event` listeners.\n * 2. Wrapped in a `delta` dashboard event and broadcast to `dashboard` listeners.\n * 3. (Planned) Persisted to SQLite via the storage layer.\n */\n emitAgentEvent(event: AgentEvent): void {\n this.emitter.emit('agent_event', event);\n\n // Wrap in a delta for the dashboard\n const delta: DashboardEvent = {\n type: 'delta',\n timestamp: Date.now(),\n events: [event],\n };\n this.emitter.emit('dashboard', delta);\n\n // TODO: persist to SQLite once the storage layer is implemented\n // import { eventStore } from '../storage/event-store.js';\n // eventStore.persist(event);\n }\n\n /**\n * Emit a full dashboard snapshot (used on initial WebSocket connection).\n */\n emitDashboardSnapshot(snapshot: DashboardEvent): void {\n this.emitter.emit('dashboard', snapshot);\n }\n\n // ---- subscribe ----------------------------------------------------------\n\n on<K extends keyof EventBusEvents>(event: K, listener: (...args: EventBusEvents[K]) => void): void {\n this.emitter.on(event, listener as (...args: unknown[]) => void);\n }\n\n off<K extends keyof EventBusEvents>(event: K, listener: (...args: EventBusEvents[K]) => void): void {\n this.emitter.off(event, listener as (...args: unknown[]) => void);\n }\n\n once<K extends keyof EventBusEvents>(event: K, listener: (...args: EventBusEvents[K]) => void): void {\n this.emitter.once(event, listener as (...args: unknown[]) => void);\n }\n\n // ---- utility ------------------------------------------------------------\n\n removeAllListeners(event?: keyof EventBusEvents): void {\n if (event) {\n this.emitter.removeAllListeners(event);\n } else {\n this.emitter.removeAllListeners();\n }\n }\n\n listenerCount(event: keyof EventBusEvents): number {\n return this.emitter.listenerCount(event);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Singleton export\n// ---------------------------------------------------------------------------\n\n/** Global event bus singleton for internal inter-agent communication. */\nexport const eventBus = new EventBus();\n","/**\n * Structured logger that writes to stderr.\n *\n * stdout is reserved for the MCP stdio transport, so all diagnostic output\n * goes to stderr to avoid corrupting the JSON-RPC stream.\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error';\n\nexport interface LogContext {\n meetingId?: string;\n agentId?: string;\n department?: string;\n [key: string]: unknown;\n}\n\ninterface LogEntry {\n timestamp: string;\n level: LogLevel;\n message: string;\n context?: LogContext;\n}\n\n// ---------------------------------------------------------------------------\n// Level ordering\n// ---------------------------------------------------------------------------\n\nconst LEVEL_PRIORITY: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\n// ---------------------------------------------------------------------------\n// Logger class\n// ---------------------------------------------------------------------------\n\nclass Logger {\n private minLevel: LogLevel = 'info';\n\n /**\n * Set the minimum log level. Messages below this level are silently dropped.\n * Defaults to 'info'. Set to 'debug' for verbose output.\n */\n setLevel(level: LogLevel): void {\n this.minLevel = level;\n }\n\n getLevel(): LogLevel {\n return this.minLevel;\n }\n\n debug(message: string, context?: LogContext): void {\n this.log('debug', message, context);\n }\n\n info(message: string, context?: LogContext): void {\n this.log('info', message, context);\n }\n\n warn(message: string, context?: LogContext): void {\n this.log('warn', message, context);\n }\n\n error(message: string, context?: LogContext): void {\n this.log('error', message, context);\n }\n\n // -----------------------------------------------------------------------\n // Internal\n // -----------------------------------------------------------------------\n\n private log(level: LogLevel, message: string, context?: LogContext): void {\n if (LEVEL_PRIORITY[level] < LEVEL_PRIORITY[this.minLevel]) {\n return;\n }\n\n const entry: LogEntry = {\n timestamp: new Date().toISOString(),\n level,\n message,\n };\n\n if (context && Object.keys(context).length > 0) {\n entry.context = context;\n }\n\n // Write to stderr as a single JSON line for easy parsing\n process.stderr.write(JSON.stringify(entry) + '\\n');\n }\n}\n\n// ---------------------------------------------------------------------------\n// Singleton export\n// ---------------------------------------------------------------------------\n\n/** Global structured logger — writes to stderr to keep stdout clean for MCP. */\nexport const logger = new Logger();\n","import { v4 as uuidv4 } from 'uuid';\nimport type { AgentNode, Department } from '../types/index.js';\nimport { createAgent, updateAgent, listAgentsByMeeting } from '../storage/index.js';\nimport { getDepartment } from '../agents/departments.js';\nimport { eventBus } from './event-bus.js';\nimport { logger } from '../utils/logger.js';\n\n// ---------------------------------------------------------------------------\n// LeaderPool — manages leader agent lifecycles\n// ---------------------------------------------------------------------------\n\nexport class LeaderPool {\n /**\n * Active leaders keyed by their agent ID.\n * This is a fast in-memory index; the source of truth is SQLite.\n */\n private readonly activeLeaders = new Map<string, AgentNode>();\n\n // ---- spawn --------------------------------------------------------------\n\n /**\n * Spawn a new leader agent for the given department and meeting.\n *\n * Persists the agent to SQLite and emits an `agent_spawned` event on the\n * event bus.\n */\n spawnLeader(department: Department, meetingId: string): AgentNode {\n const deptInfo = getDepartment(department);\n\n const agent = createAgent({\n tier: 'leader',\n role: deptInfo.leaderRole,\n department,\n parentId: null, // The orchestrator is implicit; no stored orchestrator agent row yet.\n meetingId,\n status: 'in-meeting',\n currentTask: null,\n sessionId: null,\n });\n\n this.activeLeaders.set(agent.id, agent);\n\n logger.info(`Spawned leader: ${deptInfo.leaderRole}`, {\n agentId: agent.id,\n department,\n meetingId,\n });\n\n eventBus.emitAgentEvent({\n kind: 'agent_spawned',\n agentId: agent.id,\n agentType: 'leader',\n parentId: null,\n label: deptInfo.leaderRole,\n department,\n });\n\n return agent;\n }\n\n // ---- query --------------------------------------------------------------\n\n /**\n * Return all currently-active leaders assigned to a given meeting.\n *\n * Falls back to a SQLite query filtered by status so that leaders which were\n * deactivated out-of-band are excluded.\n */\n getLeadersForMeeting(meetingId: string): AgentNode[] {\n // Fast path: filter in-memory cache\n const fromCache = [...this.activeLeaders.values()].filter(\n (a) => a.meetingId === meetingId,\n );\n\n if (fromCache.length > 0) {\n return fromCache;\n }\n\n // Slow path: query storage (e.g. after a server restart)\n return listAgentsByMeeting(meetingId).filter(\n (a) => a.tier === 'leader' && a.status !== 'completed' && a.status !== 'failed',\n );\n }\n\n // ---- deactivate ---------------------------------------------------------\n\n /**\n * Mark a leader as completed and remove it from the in-memory cache.\n */\n deactivateLeader(leaderId: string): void {\n const leader = this.activeLeaders.get(leaderId);\n\n updateAgent(leaderId, {\n status: 'completed',\n completedAt: Date.now(),\n });\n\n this.activeLeaders.delete(leaderId);\n\n logger.info(`Deactivated leader: ${leaderId}`, {\n agentId: leaderId,\n department: leader?.department,\n });\n\n eventBus.emitAgentEvent({\n kind: 'agent_destroyed',\n agentId: leaderId,\n });\n }\n}\n","import { z } from 'zod';\nimport {\n getMeeting,\n listMeetings,\n listAgentsByMeeting,\n listWorkersByLeader,\n} from '../storage/index.js';\n\nexport const getMeetingStatusSchema = {\n meetingId: z\n .string()\n .optional()\n .describe('Specific meeting ID, or omit for all active'),\n};\n\nexport async function getMeetingStatusHandler({\n meetingId,\n}: {\n meetingId?: string;\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n if (meetingId) {\n const meeting = getMeeting(meetingId);\n if (!meeting) {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n { error: `Meeting not found: ${meetingId}` },\n null,\n 2,\n ),\n },\n ],\n isError: true,\n };\n }\n\n const agents = listAgentsByMeeting(meetingId);\n const workers = agents.flatMap((agent) =>\n listWorkersByLeader(agent.id),\n );\n\n const result = {\n meeting,\n agents,\n workers,\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n }\n\n // Return all active meetings summary\n const allMeetings = listMeetings();\n const activeMeetings = allMeetings.filter(\n (m) =>\n !['completed', 'cancelled', 'failed', 'reported', 'compacted'].includes(\n m.status,\n ),\n );\n\n const result = {\n totalMeetings: allMeetings.length,\n activeMeetings: activeMeetings.map((m) => ({\n id: m.id,\n topic: m.topic,\n status: m.status,\n phase: m.phase,\n startedAt: m.startedAt,\n })),\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import { z } from 'zod';\nimport { getMinutesByMeeting } from '../storage/index.js';\n\nexport const getMinutesSchema = {\n meetingId: z.string().describe('Meeting ID'),\n format: z\n .enum(['full', 'summary', 'tasks_only'])\n .default('full')\n .optional()\n .describe('Output format'),\n};\n\nexport async function getMinutesHandler({\n meetingId,\n format,\n}: {\n meetingId: string;\n format?: 'full' | 'summary' | 'tasks_only';\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const minutes = getMinutesByMeeting(meetingId);\n if (!minutes) {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n { error: `No minutes found for meeting: ${meetingId}` },\n null,\n 2,\n ),\n },\n ],\n isError: true,\n };\n }\n\n const effectiveFormat = format ?? 'full';\n\n let result: unknown;\n\n switch (effectiveFormat) {\n case 'full':\n result = {\n id: minutes.id,\n meetingId: minutes.meetingId,\n format: minutes.format,\n content: minutes.content,\n actionItems: minutes.actionItems,\n createdAt: minutes.createdAt,\n };\n break;\n\n case 'summary': {\n // Extract a summary: first 500 chars of content + action item count\n const summaryContent =\n minutes.content.length > 500\n ? minutes.content.slice(0, 500) + '...'\n : minutes.content;\n result = {\n id: minutes.id,\n meetingId: minutes.meetingId,\n summary: summaryContent,\n actionItemCount: minutes.actionItems.length,\n createdAt: minutes.createdAt,\n };\n break;\n }\n\n case 'tasks_only':\n result = {\n meetingId: minutes.meetingId,\n actionItems: minutes.actionItems,\n totalTasks: minutes.actionItems.length,\n };\n break;\n }\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import { z } from 'zod';\nimport { Compactor } from '../meeting/compactor.js';\n\nexport const compactMinutesSchema = {\n meetingId: z.string().describe('Meeting ID'),\n additionalInstructions: z\n .string()\n .optional()\n .describe('Additional instructions for compaction'),\n};\n\nexport async function compactMinutesHandler({\n meetingId,\n additionalInstructions,\n}: {\n meetingId: string;\n additionalInstructions?: string;\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const compactor = new Compactor();\n const tasks = await compactor.compactMinutes(\n meetingId,\n additionalInstructions,\n );\n\n const result = {\n meetingId,\n tasksGenerated: tasks.length,\n tasks,\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","/**\n * Compacts meeting minutes into a structured task list per department.\n *\n * Assigns departments and priorities based on keyword analysis.\n */\n\nimport { v4 as uuidv4 } from 'uuid';\nimport { getMinutesByMeeting, createMinutes } from '../storage/index.js';\nimport { getDb } from '../storage/db.js';\nimport type { ActionItem, Department, MinutesRecord } from '../types/index.js';\nimport { logger } from '../utils/logger.js';\n\n// ---------------------------------------------------------------------------\n// Keyword → department mapping\n// ---------------------------------------------------------------------------\n\nconst DEPARTMENT_KEYWORDS: Record<Department, string[]> = {\n architecture: [\n 'schema', 'design', 'architecture', 'blueprint', 'dependency',\n 'api design', 'system design', '아키텍처', '설계',\n ],\n engineering: [\n 'implement', 'code', 'develop', 'build', 'refactor', 'fix',\n 'feature', 'module', '구현', '개발', '코드',\n ],\n qa: [\n 'test', 'quality', 'coverage', 'security', 'audit', 'performance',\n 'regression', 'validation', '테스트', '검증', '품질',\n ],\n product: [\n 'requirement', 'user story', 'acceptance criteria', 'stakeholder',\n 'priority', 'roadmap', 'scope', '요구사항', '사용자',\n ],\n research: [\n 'research', 'explore', 'investigate', 'benchmark', 'compare',\n 'evaluate', 'poc', 'prototype', '조사', '탐색',\n ],\n};\n\n// ---------------------------------------------------------------------------\n// Keyword → priority mapping\n// ---------------------------------------------------------------------------\n\nconst PRIORITY_KEYWORDS: Record<ActionItem['priority'], string[]> = {\n critical: [\n 'critical', 'urgent', 'blocker', 'blocking', 'asap', 'immediately',\n '긴급', '즉시', 'p0',\n ],\n high: [\n 'high priority', 'important', 'must', 'required', 'essential',\n '중요', '필수', 'p1',\n ],\n medium: [\n 'medium', 'should', 'moderate', '보통', 'p2',\n ],\n low: [\n 'low priority', 'nice to have', 'optional', 'consider',\n '낮음', '선택', 'p3',\n ],\n};\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction detectDepartment(text: string): Department {\n const lower = text.toLowerCase();\n let bestDept: Department = 'engineering';\n let bestScore = 0;\n\n for (const [dept, keywords] of Object.entries(DEPARTMENT_KEYWORDS) as [Department, string[]][]) {\n const score = keywords.reduce(\n (acc, kw) => acc + (lower.includes(kw.toLowerCase()) ? 1 : 0),\n 0,\n );\n if (score > bestScore) {\n bestScore = score;\n bestDept = dept;\n }\n }\n\n return bestDept;\n}\n\nfunction detectPriority(text: string): ActionItem['priority'] {\n const lower = text.toLowerCase();\n\n // Check from highest to lowest — first match wins\n for (const priority of ['critical', 'high', 'medium', 'low'] as const) {\n const keywords = PRIORITY_KEYWORDS[priority];\n if (keywords.some((kw) => lower.includes(kw.toLowerCase()))) {\n return priority;\n }\n }\n\n return 'medium';\n}\n\nconst LEADER_ROLE_FOR_DEPT: Record<Department, string> = {\n architecture: 'architect',\n engineering: 'engineer',\n qa: 'qa',\n product: 'product-manager',\n research: 'researcher',\n};\n\n// ---------------------------------------------------------------------------\n// Compactor\n// ---------------------------------------------------------------------------\n\nexport class Compactor {\n /**\n * Compact minutes into actionable, department-assigned tasks.\n *\n * 1. Load minutes for the meeting\n * 2. Parse action items from the minutes content\n * 3. Assign each to a department based on keywords\n * 4. Set priorities based on keywords\n * 5. Save updated action items to minutes record\n * 6. Return the structured task list\n */\n async compactMinutes(\n meetingId: string,\n additionalInstructions?: string,\n ): Promise<ActionItem[]> {\n logger.info('Compacting minutes', { meetingId });\n\n // 1. Load existing minutes\n const minutes = getMinutesByMeeting(meetingId);\n if (!minutes) {\n throw new Error(`No minutes found for meeting: ${meetingId}`);\n }\n\n // 2–4. Refine existing action items with department + priority detection\n const refinedItems: ActionItem[] = minutes.actionItems.map((item) => {\n const fullText = `${item.title} ${item.description} ${additionalInstructions ?? ''}`;\n const department = detectDepartment(fullText);\n const priority = detectPriority(fullText);\n\n return {\n ...item,\n assignedDepartment: department,\n assignedRole: LEADER_ROLE_FOR_DEPT[department],\n priority,\n };\n });\n\n // If there are no existing action items, try to extract from minutes content\n if (refinedItems.length === 0) {\n const extracted = this.extractFromContent(minutes.content);\n refinedItems.push(...extracted);\n }\n\n // 5. Update the minutes record in the DB\n const db = getDb();\n db.prepare('UPDATE minutes SET action_items = ? WHERE id = ?').run(\n JSON.stringify(refinedItems),\n minutes.id,\n );\n\n logger.info('Minutes compacted', {\n meetingId,\n actionItemCount: refinedItems.length,\n } as Record<string, unknown>);\n\n // 6. Return the structured task list\n return refinedItems;\n }\n\n // -------------------------------------------------------------------------\n // Fallback extraction from raw minutes content\n // -------------------------------------------------------------------------\n\n private extractFromContent(content: string): ActionItem[] {\n const items: ActionItem[] = [];\n const lines = content.split('\\n');\n\n for (const line of lines) {\n const trimmed = line.trim();\n // Look for lines that start with \"- \" or numbered items under action sections\n if (\n trimmed.startsWith('- ') &&\n trimmed.length > 5 &&\n trimmed !== '- None' &&\n trimmed !== '- None recorded' &&\n trimmed !== '- No action items identified' &&\n trimmed !== '- No action items recorded'\n ) {\n const text = trimmed.slice(2);\n const department = detectDepartment(text);\n const priority = detectPriority(text);\n\n items.push({\n id: uuidv4(),\n title: text.slice(0, 80),\n description: text,\n assignedDepartment: department,\n assignedRole: LEADER_ROLE_FOR_DEPT[department],\n priority,\n dependencies: [],\n acceptanceCriteria: [],\n });\n }\n }\n\n return items;\n }\n}\n","import { z } from 'zod';\nimport { getTasksFromMinutes } from '../storage/index.js';\n\nexport const executeTasksSchema = {\n meetingId: z.string().describe('Meeting ID'),\n taskIds: z\n .array(z.string())\n .optional()\n .describe('Specific tasks to execute, or all'),\n};\n\nexport async function executeTasksHandler({\n meetingId,\n taskIds,\n}: {\n meetingId: string;\n taskIds?: string[];\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const allTasks = getTasksFromMinutes(meetingId);\n\n if (allTasks.length === 0) {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n error: `No tasks found for meeting: ${meetingId}. Run compact-minutes first.`,\n },\n null,\n 2,\n ),\n },\n ],\n isError: true,\n };\n }\n\n // Filter tasks if specific IDs provided\n const tasksToExecute = taskIds\n ? allTasks.filter((t) => taskIds.includes(t.id))\n : allTasks;\n\n if (tasksToExecute.length === 0) {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n { error: 'No matching tasks found for the provided task IDs.' },\n null,\n 2,\n ),\n },\n ],\n isError: true,\n };\n }\n\n // Group tasks by department for the caller\n const tasksByDepartment = new Map<string, typeof tasksToExecute>();\n for (const task of tasksToExecute) {\n const dept = task.assignedDepartment;\n if (!tasksByDepartment.has(dept)) {\n tasksByDepartment.set(dept, []);\n }\n tasksByDepartment.get(dept)!.push(task);\n }\n\n const departments: Array<{\n department: string;\n tasks: typeof tasksToExecute;\n }> = [];\n\n for (const [department, tasks] of tasksByDepartment) {\n departments.push({ department, tasks });\n }\n\n const result = {\n meetingId,\n totalTasks: tasksToExecute.length,\n departments,\n instructions:\n 'These tasks should be dispatched to implementer agents. ' +\n 'The orchestrator agent will use Claude Code Agent tool to run each task.',\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import { getAgentTree } from '../storage/index.js';\n\nexport async function getAgentTreeHandler(): Promise<{\n content: { type: 'text'; text: string }[];\n isError?: boolean;\n}> {\n try {\n const tree = getAgentTree('orchestrator-root');\n\n const result = {\n root: tree,\n hasAgents: tree !== null,\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import { z } from 'zod';\nimport { getMention, updateMention } from '../storage/index.js';\nimport { eventBus } from '../orchestrator/event-bus.js';\n\nexport const respondToMentionSchema = {\n mentionId: z.string().describe('ID of the mention to respond to'),\n decision: z.string().describe('The decision made by the user'),\n reasoning: z.string().optional().describe('Optional reasoning for the decision'),\n};\n\nexport async function respondToMentionHandler({\n mentionId,\n decision,\n reasoning,\n}: {\n mentionId: string;\n decision: string;\n reasoning?: string;\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const mention = getMention(mentionId);\n\n if (!mention) {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n { error: `Mention not found: ${mentionId}` },\n null,\n 2,\n ),\n },\n ],\n isError: true,\n };\n }\n\n if (mention.status === 'resolved') {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n { error: `Mention already resolved: ${mentionId}` },\n null,\n 2,\n ),\n },\n ],\n isError: true,\n };\n }\n\n const resolved = updateMention(mentionId, {\n status: 'resolved',\n userDecision: decision,\n userReasoning: reasoning ?? null,\n resolvedAt: Date.now(),\n });\n\n eventBus.emitAgentEvent({\n kind: 'mention_resolved',\n mentionId,\n decision,\n });\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n { success: true, mention: resolved },\n null,\n 2,\n ),\n },\n ],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import { z } from 'zod';\nimport {\n listPendingMentions,\n listMentionsByMeeting,\n} from '../storage/index.js';\nimport type { MentionRecord } from '../types/index.js';\n\nexport const getMentionsSchema = {\n status: z\n .enum(['pending', 'resolved', 'all'])\n .default('pending')\n .optional()\n .describe('Filter mentions by status'),\n meetingId: z\n .string()\n .optional()\n .describe('Filter mentions by meeting ID'),\n};\n\nexport async function getMentionsHandler({\n status,\n meetingId,\n}: {\n status?: 'pending' | 'resolved' | 'all';\n meetingId?: string;\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const effectiveStatus = status ?? 'pending';\n let mentions: MentionRecord[];\n\n if (meetingId) {\n // Get all mentions for this meeting, then filter by status\n const allForMeeting = listMentionsByMeeting(meetingId);\n if (effectiveStatus === 'all') {\n mentions = allForMeeting;\n } else {\n mentions = allForMeeting.filter((m) => m.status === effectiveStatus);\n }\n } else if (effectiveStatus === 'pending') {\n mentions = listPendingMentions();\n } else if (effectiveStatus === 'resolved') {\n // listPendingMentions only returns pending; for resolved we need to\n // get all and filter. Since there is no dedicated storage function for\n // resolved mentions, we use listMentionsByMeeting with no meetingId —\n // but that requires a meetingId. Instead we get pending and note the\n // limitation, or we query directly.\n // For a clean approach, list all meetings' mentions by getting pending\n // and noting this is a filtered view.\n // Actually, we can use the DB directly through the existing functions.\n // The simplest correct approach: get all pending and return empty since\n // we want resolved. But that's wrong. Let's just get all mentions.\n // Since there's no listAllMentions, we'll import getDb and query directly.\n const { getDb } = await import('../storage/db.js');\n const db = getDb();\n interface MentionRow {\n id: string;\n meeting_id: string;\n agenda_item: string | null;\n summary: string;\n options: string;\n urgency: string;\n status: string;\n user_decision: string | null;\n user_reasoning: string | null;\n created_at: number;\n resolved_at: number | null;\n }\n const rows = db\n .prepare(\"SELECT * FROM mentions WHERE status = 'resolved' ORDER BY created_at ASC\")\n .all() as MentionRow[];\n mentions = rows.map((row) => ({\n id: row.id,\n meetingId: row.meeting_id,\n agendaItem: row.agenda_item,\n summary: row.summary,\n options: JSON.parse(row.options),\n urgency: row.urgency as MentionRecord['urgency'],\n status: row.status as MentionRecord['status'],\n userDecision: row.user_decision,\n userReasoning: row.user_reasoning,\n createdAt: row.created_at,\n resolvedAt: row.resolved_at,\n }));\n } else {\n // 'all'\n const { getDb } = await import('../storage/db.js');\n const db = getDb();\n interface MentionRow {\n id: string;\n meeting_id: string;\n agenda_item: string | null;\n summary: string;\n options: string;\n urgency: string;\n status: string;\n user_decision: string | null;\n user_reasoning: string | null;\n created_at: number;\n resolved_at: number | null;\n }\n const rows = db\n .prepare('SELECT * FROM mentions ORDER BY created_at ASC')\n .all() as MentionRow[];\n mentions = rows.map((row) => ({\n id: row.id,\n meetingId: row.meeting_id,\n agendaItem: row.agenda_item,\n summary: row.summary,\n options: JSON.parse(row.options),\n urgency: row.urgency as MentionRecord['urgency'],\n status: row.status as MentionRecord['status'],\n userDecision: row.user_decision,\n userReasoning: row.user_reasoning,\n createdAt: row.created_at,\n resolvedAt: row.resolved_at,\n }));\n }\n\n const result = {\n count: mentions.length,\n status: effectiveStatus,\n ...(meetingId ? { meetingId } : {}),\n mentions,\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import { z } from 'zod';\nimport {\n getMeeting,\n updateMeeting,\n listAgentsByMeeting,\n updateAgent,\n listWorkersByLeader,\n updateWorker,\n} from '../storage/index.js';\nimport { eventBus } from '../orchestrator/event-bus.js';\n\nexport const cancelMeetingSchema = {\n meetingId: z.string().describe('ID of the meeting to cancel'),\n reason: z.string().optional().describe('Reason for cancellation'),\n};\n\nexport async function cancelMeetingHandler({\n meetingId,\n reason,\n}: {\n meetingId: string;\n reason?: string;\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const meeting = getMeeting(meetingId);\n\n if (!meeting) {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n { error: `Meeting not found: ${meetingId}` },\n null,\n 2,\n ),\n },\n ],\n isError: true,\n };\n }\n\n if (meeting.status === 'completed' || meeting.status === 'cancelled') {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n {\n error: `Meeting cannot be cancelled: current status is '${meeting.status}'`,\n },\n null,\n 2,\n ),\n },\n ],\n isError: true,\n };\n }\n\n // Update meeting status to cancelled\n updateMeeting(meetingId, { status: 'cancelled', completedAt: Date.now() });\n\n // Find all agents for this meeting and mark them as completed\n const agents = listAgentsByMeeting(meetingId);\n let agentsCancelled = 0;\n let workersFailed = 0;\n\n for (const agent of agents) {\n if (agent.status !== 'completed' && agent.status !== 'failed') {\n updateAgent(agent.id, { status: 'completed', completedAt: Date.now() });\n agentsCancelled++;\n\n eventBus.emitAgentEvent({\n kind: 'state_changed',\n agentId: agent.id,\n from: agent.status,\n to: 'completed',\n });\n }\n\n // Find all workers for this agent (leader) and mark them as failed\n const workers = listWorkersByLeader(agent.id);\n for (const worker of workers) {\n if (worker.status !== 'completed' && worker.status !== 'failed') {\n updateWorker(worker.id, {\n status: 'failed',\n errorMessage: reason ?? 'Meeting cancelled',\n completedAt: Date.now(),\n });\n workersFailed++;\n\n eventBus.emitAgentEvent({\n kind: 'task_completed',\n agentId: worker.id,\n result: 'failure',\n });\n }\n }\n }\n\n const result = {\n success: true,\n meetingId,\n previousStatus: meeting.status,\n reason: reason ?? 'No reason provided',\n agentsCancelled,\n workersFailed,\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import { z } from 'zod';\nimport { listMeetings } from '../storage/index.js';\nimport type { MeetingStatus } from '../types/index.js';\n\nexport const listMeetingsSchema = {\n status: z\n .enum(['pending', 'running', 'completed', 'cancelled', 'failed', 'all'])\n .default('all')\n .optional()\n .describe('Filter meetings by status'),\n limit: z\n .number()\n .default(20)\n .optional()\n .describe('Maximum number of meetings to return'),\n};\n\n// Map the user-facing \"running\" status to the internal statuses that represent\n// an active/running meeting.\nconst RUNNING_STATUSES: MeetingStatus[] = [\n 'convening',\n 'opening',\n 'discussion',\n 'synthesis',\n 'minutes-generation',\n 'executing',\n 'aggregation',\n 'waiting-for-user',\n];\n\nexport async function listMeetingsHandler({\n status,\n limit,\n}: {\n status?: 'pending' | 'running' | 'completed' | 'cancelled' | 'failed' | 'all';\n limit?: number;\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const effectiveStatus = status ?? 'all';\n const effectiveLimit = limit ?? 20;\n\n let meetings;\n\n if (effectiveStatus === 'all') {\n meetings = listMeetings();\n } else if (effectiveStatus === 'running') {\n // \"running\" maps to multiple internal statuses\n const all = listMeetings();\n meetings = all.filter((m) => RUNNING_STATUSES.includes(m.status));\n } else {\n meetings = listMeetings(effectiveStatus as MeetingStatus);\n }\n\n // Apply limit\n const limited = meetings.slice(0, effectiveLimit);\n\n const result = {\n total: meetings.length,\n returned: limited.length,\n status: effectiveStatus,\n meetings: limited.map((m) => ({\n id: m.id,\n topic: m.topic,\n status: m.status,\n phase: m.phase,\n participantCount: m.participantIds.length,\n startedAt: m.startedAt,\n })),\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import { z } from 'zod';\nimport {\n getMeeting,\n getMinutesByMeeting,\n listAgentsByMeeting,\n listWorkersByLeader,\n} from '../storage/index.js';\n\nexport const getTaskReportSchema = {\n meetingId: z.string().describe('ID of the meeting to generate a report for'),\n};\n\nexport async function getTaskReportHandler({\n meetingId,\n}: {\n meetingId: string;\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const meeting = getMeeting(meetingId);\n if (!meeting) {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(\n { error: `Meeting not found: ${meetingId}` },\n null,\n 2,\n ),\n },\n ],\n isError: true,\n };\n }\n\n const minutes = getMinutesByMeeting(meetingId);\n const agents = listAgentsByMeeting(meetingId);\n\n // Collect all workers grouped by leader/department\n const departmentBreakdowns: Array<{\n department: string;\n leaderId: string;\n leaderRole: string;\n workers: Array<{\n id: string;\n taskDescription: string;\n status: string;\n costUsd: number;\n errorMessage: string | null;\n }>;\n completed: number;\n failed: number;\n pending: number;\n totalCost: number;\n }> = [];\n\n let totalCompleted = 0;\n let totalFailed = 0;\n let totalPending = 0;\n let totalCost = 0;\n\n for (const agent of agents) {\n const workers = listWorkersByLeader(agent.id);\n\n const completed = workers.filter((w) => w.status === 'completed').length;\n const failed = workers.filter((w) => w.status === 'failed').length;\n const pending = workers.filter(\n (w) => w.status === 'pending' || w.status === 'running',\n ).length;\n const deptCost = workers.reduce((acc, w) => acc + w.costUsd, 0);\n\n totalCompleted += completed;\n totalFailed += failed;\n totalPending += pending;\n totalCost += deptCost;\n\n if (workers.length > 0) {\n departmentBreakdowns.push({\n department: agent.department,\n leaderId: agent.id,\n leaderRole: agent.role,\n workers: workers.map((w) => ({\n id: w.id,\n taskDescription: w.taskDescription,\n status: w.status,\n costUsd: w.costUsd,\n errorMessage: w.errorMessage,\n })),\n completed,\n failed,\n pending,\n totalCost: deptCost,\n });\n }\n }\n\n const result = {\n meetingId,\n topic: meeting.topic,\n status: meeting.status,\n actionItemCount: minutes?.actionItems.length ?? 0,\n summary: {\n totalWorkers: totalCompleted + totalFailed + totalPending,\n completed: totalCompleted,\n failed: totalFailed,\n pending: totalPending,\n totalCost,\n },\n departments: departmentBreakdowns,\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import { z } from 'zod';\nimport { ExtensionManager } from '../extension/extension-manager.js';\nimport type { CapabilityType } from '../extension/capability-registry.js';\nimport type { GenerateRequest } from '../extension/generator.js';\n\nexport const createCapabilitySchema = {\n type: z\n .enum(['hook', 'skill', 'command', 'asset', 'loop'])\n .describe('Type of capability to create'),\n name: z.string().describe('Name for the new capability'),\n description: z.string().describe('What the capability does'),\n trigger: z.string().describe('When the capability should be triggered'),\n userRequest: z\n .string()\n .optional()\n .describe('Original user request that triggered creation'),\n};\n\nexport async function createCapabilityHandler({\n type,\n name,\n description,\n trigger,\n userRequest,\n}: {\n type: 'hook' | 'skill' | 'command' | 'asset' | 'loop';\n name: string;\n description: string;\n trigger: string;\n userRequest?: string;\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const manager = new ExtensionManager();\n await manager.init();\n\n const request: GenerateRequest = {\n type: type as CapabilityType,\n name,\n description,\n trigger,\n userRequest: userRequest ?? description,\n };\n\n const result = await manager.createCapability(request);\n\n const output = {\n status: 'created',\n capability: {\n type: result.capability.type,\n name: result.capability.name,\n description: result.capability.description,\n trigger: result.capability.trigger,\n isBuiltIn: result.capability.isBuiltIn,\n },\n filePath: result.filePath,\n summary: result.summary,\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","/**\n * capability-registry.ts — Tracks all registered capabilities (built-in + custom).\n *\n * The registry is persisted to ~/.open-coleslaw/registry.json.\n * Built-in capabilities (the 6 hooks + 6 skills that ship with the project) are\n * hardcoded; custom capabilities are added/removed dynamically at runtime.\n */\n\nimport { readFileSync, writeFileSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { getConfig } from '../utils/config.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type CapabilityType = 'hook' | 'skill' | 'command' | 'asset' | 'loop';\n\nexport interface Capability {\n type: CapabilityType;\n name: string;\n description: string;\n trigger: string;\n createdAt: number;\n isBuiltIn: boolean;\n filePath: string;\n}\n\n// ---------------------------------------------------------------------------\n// Built-in capability definitions\n// ---------------------------------------------------------------------------\n\nconst BUILT_IN_HOOKS: Omit<Capability, 'createdAt'>[] = [\n {\n type: 'hook',\n name: 'pre-read',\n description: 'Loads rules + plugin guide + CLAUDE.md/README before execution',\n trigger: 'Before every execution',\n isBuiltIn: true,\n filePath: 'src/hooks/pre-read.ts',\n },\n {\n type: 'hook',\n name: 'auto-route',\n description: 'Analyzes user prompts and auto-routes to appropriate skill/agent',\n trigger: 'On every user prompt',\n isBuiltIn: true,\n filePath: 'src/hooks/auto-route.ts',\n },\n {\n type: 'hook',\n name: 'auto-commit',\n description: 'Creates conventional commits after task completion',\n trigger: 'After task completion when git is connected',\n isBuiltIn: true,\n filePath: 'src/hooks/auto-commit.ts',\n },\n {\n type: 'hook',\n name: 'doc-update',\n description: 'Updates CLAUDE.md/README.md after process completion',\n trigger: 'After process completion',\n isBuiltIn: true,\n filePath: 'src/hooks/doc-update.ts',\n },\n {\n type: 'hook',\n name: 'flow-verify',\n description: 'Verifies PRD user flows after development',\n trigger: 'After development phase completes',\n isBuiltIn: true,\n filePath: 'src/hooks/flow-verify.ts',\n },\n {\n type: 'hook',\n name: 'mvp-cycle',\n description: 'Triggers re-meeting on verification failure',\n trigger: 'When flow-verify reports failure',\n isBuiltIn: true,\n filePath: 'src/hooks/mvp-cycle.ts',\n },\n];\n\nconst BUILT_IN_SKILLS: Omit<Capability, 'createdAt'>[] = [\n {\n type: 'skill',\n name: 'meeting',\n description: 'Start a meeting (auto-selects leaders if topic given)',\n trigger: '/meeting [topic]',\n isBuiltIn: true,\n filePath: 'src/skills/meeting.ts',\n },\n {\n type: 'skill',\n name: 'status',\n description: 'Show current meetings, agents, and pending mentions',\n trigger: '/status',\n isBuiltIn: true,\n filePath: 'src/skills/status.ts',\n },\n {\n type: 'skill',\n name: 'dashboard',\n description: 'Open web dashboard at http://localhost:35143',\n trigger: '/dashboard',\n isBuiltIn: true,\n filePath: 'src/skills/dashboard.ts',\n },\n {\n type: 'skill',\n name: 'mention',\n description: 'View and respond to pending @mentions',\n trigger: '/mention',\n isBuiltIn: true,\n filePath: 'src/skills/mention.ts',\n },\n {\n type: 'skill',\n name: 'agents',\n description: 'Show full agent hierarchy tree',\n trigger: '/agents',\n isBuiltIn: true,\n filePath: 'src/skills/agents.ts',\n },\n {\n type: 'skill',\n name: 'minutes',\n description: 'View meeting minutes',\n trigger: '/minutes [meetingId]',\n isBuiltIn: true,\n filePath: 'src/skills/minutes.ts',\n },\n];\n\n// ---------------------------------------------------------------------------\n// Registry class\n// ---------------------------------------------------------------------------\n\nexport class CapabilityRegistry {\n private capabilities: Capability[] = [];\n private registryPath: string;\n\n constructor() {\n const { DATA_DIR } = getConfig();\n this.registryPath = join(DATA_DIR, 'registry.json');\n }\n\n /**\n * Load all capabilities: built-in (hardcoded) + custom (from registry.json).\n */\n async loadAll(): Promise<Capability[]> {\n // Start with built-in capabilities (timestamp 0 — they always existed)\n const builtIns: Capability[] = [\n ...BUILT_IN_HOOKS,\n ...BUILT_IN_SKILLS,\n ].map((cap) => ({ ...cap, createdAt: 0 }));\n\n // Merge in custom capabilities from persistent storage\n const custom = this.readCustomEntries();\n this.capabilities = [...builtIns, ...custom];\n return this.capabilities;\n }\n\n /**\n * Register a new custom capability and persist.\n */\n async register(cap: Omit<Capability, 'createdAt'>): Promise<void> {\n const entry: Capability = { ...cap, createdAt: Date.now() };\n\n // Remove any existing entry with the same name to avoid duplicates\n const custom = this.readCustomEntries().filter((c) => c.name !== cap.name);\n custom.push(entry);\n this.writeCustomEntries(custom);\n\n // Refresh in-memory list\n await this.loadAll();\n }\n\n /**\n * Unregister a custom capability and persist.\n */\n async unregister(type: CapabilityType, name: string): Promise<void> {\n const custom = this.readCustomEntries().filter(\n (c) => !(c.type === type && c.name === name),\n );\n this.writeCustomEntries(custom);\n\n // Refresh in-memory list\n await this.loadAll();\n }\n\n /**\n * Find capabilities by type.\n */\n findByType(type: CapabilityType): Capability[] {\n return this.capabilities.filter((c) => c.type === type);\n }\n\n /**\n * Find a capability by name.\n */\n findByName(name: string): Capability | undefined {\n return this.capabilities.find((c) => c.name === name);\n }\n\n /**\n * Check whether a capability with the given name exists.\n */\n has(name: string): boolean {\n return this.capabilities.some((c) => c.name === name);\n }\n\n /**\n * Format all capabilities as a human-readable list suitable for plugin-guide.md.\n */\n formatForGuide(): string {\n const sections: string[] = [];\n\n const types: CapabilityType[] = ['hook', 'skill', 'command', 'asset', 'loop'];\n for (const type of types) {\n const caps = this.findByType(type);\n if (caps.length === 0) continue;\n\n const label = type.charAt(0).toUpperCase() + type.slice(1) + 's';\n const lines = caps.map((c) => {\n const tag = c.isBuiltIn ? '' : ' [custom]';\n return `- **${c.name}**${tag} — ${c.description} (trigger: ${c.trigger})`;\n });\n sections.push(`### ${label}\\n${lines.join('\\n')}`);\n }\n\n return sections.join('\\n\\n');\n }\n\n // -------------------------------------------------------------------------\n // Private helpers\n // -------------------------------------------------------------------------\n\n private readCustomEntries(): Capability[] {\n if (!existsSync(this.registryPath)) {\n return [];\n }\n try {\n const raw = readFileSync(this.registryPath, 'utf-8');\n const parsed: unknown = JSON.parse(raw);\n if (!Array.isArray(parsed)) return [];\n return parsed as Capability[];\n } catch {\n return [];\n }\n }\n\n private writeCustomEntries(entries: Capability[]): void {\n writeFileSync(this.registryPath, JSON.stringify(entries, null, 2), 'utf-8');\n }\n}\n","import { mkdirSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface AppConfig {\n /** Root data directory: ~/.open-coleslaw/ */\n DATA_DIR: string;\n /** SQLite database path: ~/.open-coleslaw/data.db */\n DB_PATH: string;\n /** Directory for meeting minutes files: ~/.open-coleslaw/minutes/ */\n MINUTES_DIR: string;\n /** WebSocket dashboard port */\n DASHBOARD_PORT: number;\n}\n\n// ---------------------------------------------------------------------------\n// Defaults\n// ---------------------------------------------------------------------------\n\nfunction buildConfig(): AppConfig {\n const DATA_DIR = join(homedir(), '.open-coleslaw');\n return {\n DATA_DIR,\n DB_PATH: join(DATA_DIR, 'data.db'),\n MINUTES_DIR: join(DATA_DIR, 'minutes'),\n DASHBOARD_PORT: 35143,\n };\n}\n\n// Singleton — computed once, reused thereafter.\nlet _config: AppConfig | null = null;\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Return the runtime configuration.\n *\n * Values are derived from well-known paths under `~/.open-coleslaw/`.\n * The config object is created once and cached for the lifetime of the process.\n */\nexport function getConfig(): AppConfig {\n if (!_config) {\n _config = buildConfig();\n }\n return _config;\n}\n\n/**\n * Ensure all required data directories exist (creates them recursively if missing).\n *\n * Call this once during server startup before any storage or file I/O.\n */\nexport function ensureDataDirs(): void {\n const config = getConfig();\n mkdirSync(config.DATA_DIR, { recursive: true });\n mkdirSync(config.MINUTES_DIR, { recursive: true });\n}\n","/**\n * generator.ts — Generates code for new capabilities.\n *\n * Each capability type has a template that produces a standalone file.\n * Generated files are placed in ~/.open-coleslaw/custom-{type}s/.\n */\n\nimport { mkdirSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { getConfig } from '../utils/config.js';\nimport type { CapabilityType, Capability } from './capability-registry.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface GenerateRequest {\n type: CapabilityType;\n name: string;\n description: string;\n trigger: string;\n userRequest: string;\n}\n\nexport interface GenerateResult {\n filePath: string;\n code: string;\n registryEntry: Omit<Capability, 'createdAt'>;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction sanitizeName(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n}\n\nfunction header(request: GenerateRequest): string {\n const now = new Date().toISOString();\n return [\n `// Auto-generated by open-coleslaw extension system`,\n `// Name: ${request.name}`,\n `// Description: ${request.description}`,\n `// Trigger: ${request.trigger}`,\n `// Created: ${now}`,\n '',\n ].join('\\n');\n}\n\nfunction customDir(type: CapabilityType): string {\n const { DATA_DIR } = getConfig();\n const dir = join(DATA_DIR, `custom-${type}s`);\n mkdirSync(dir, { recursive: true });\n return dir;\n}\n\n// ---------------------------------------------------------------------------\n// Templates per capability type\n// ---------------------------------------------------------------------------\n\nfunction generateHook(request: GenerateRequest): string {\n return [\n header(request),\n `/**`,\n ` * Custom hook: ${request.name}`,\n ` * ${request.description}`,\n ` *`,\n ` * Trigger: ${request.trigger}`,\n ` * Original request: ${request.userRequest}`,\n ` *`,\n ` * Usage:`,\n ` * node custom-hooks/${sanitizeName(request.name)}.js`,\n ` */`,\n ``,\n `function main() {`,\n ` // Read input from stdin or environment if needed`,\n ` const input = process.env.HOOK_INPUT ?? '';`,\n ``,\n ` // TODO: Implement hook logic for \"${request.description}\"`,\n ` const result = {`,\n ` hook: '${request.name}',`,\n ` status: 'executed',`,\n ` input,`,\n ` timestamp: new Date().toISOString(),`,\n ` };`,\n ``,\n ` process.stdout.write(JSON.stringify(result));`,\n `}`,\n ``,\n `main();`,\n ``,\n ].join('\\n');\n}\n\nfunction generateSkill(request: GenerateRequest): string {\n return [\n header(request),\n `/**`,\n ` * Custom skill: ${request.name}`,\n ` * ${request.description}`,\n ` *`,\n ` * Trigger: ${request.trigger}`,\n ` * Original request: ${request.userRequest}`,\n ` */`,\n ``,\n `export function get${toPascalCase(request.name)}SkillPrompt(args) {`,\n ` const input = args?.trim() ?? '';`,\n ``,\n ` return [`,\n ` '<command-name>${request.name}</command-name>',`,\n ` '',`,\n ` '## ${request.name} Skill',`,\n ` '',`,\n ` '${request.description}',`,\n ` '',`,\n ` input ? \\`User input: \\${input}\\` : 'No input provided.',`,\n ` '',`,\n ` 'Instructions:',`,\n ` '1. Analyze the user request',`,\n ` '2. Perform the action described above',`,\n ` '3. Report the result to the user',`,\n ` ].join('\\\\n');`,\n `}`,\n ``,\n ].join('\\n');\n}\n\nfunction generateCommand(request: GenerateRequest): string {\n return [\n header(request),\n `/**`,\n ` * Custom command: ${request.name}`,\n ` * ${request.description}`,\n ` *`,\n ` * Trigger: ${request.trigger}`,\n ` * Original request: ${request.userRequest}`,\n ` *`,\n ` * Usage:`,\n ` * node custom-commands/${sanitizeName(request.name)}.js [action] [args...]`,\n ` */`,\n ``,\n `function main() {`,\n ` const args = process.argv.slice(2);`,\n ` const action = args[0] ?? 'default';`,\n ` const rest = args.slice(1);`,\n ``,\n ` const handlers = {`,\n ` default: () => ({`,\n ` command: '${request.name}',`,\n ` description: '${request.description}',`,\n ` usage: '${request.name}:action [args]',`,\n ` }),`,\n ` run: () => {`,\n ` // TODO: Implement the primary command action`,\n ` return {`,\n ` command: '${request.name}',`,\n ` action: 'run',`,\n ` args: rest,`,\n ` status: 'executed',`,\n ` timestamp: new Date().toISOString(),`,\n ` };`,\n ` },`,\n ` };`,\n ``,\n ` const handler = handlers[action] ?? handlers.default;`,\n ` const result = handler();`,\n ` process.stdout.write(JSON.stringify(result, null, 2));`,\n `}`,\n ``,\n `main();`,\n ``,\n ].join('\\n');\n}\n\nfunction generateAsset(request: GenerateRequest): string {\n // Assets can be JSON or Markdown. Default to JSON for configs, Markdown for docs.\n const isMarkdown =\n /template|guide|doc|readme|note/i.test(request.name) ||\n /template|guide|doc|readme|note/i.test(request.description);\n\n if (isMarkdown) {\n return [\n `<!-- Auto-generated by open-coleslaw extension system -->`,\n `<!-- Name: ${request.name} -->`,\n `<!-- Description: ${request.description} -->`,\n `<!-- Trigger: ${request.trigger} -->`,\n `<!-- Created: ${new Date().toISOString()} -->`,\n ``,\n `# ${request.name}`,\n ``,\n `${request.description}`,\n ``,\n `## Details`,\n ``,\n `> Original request: ${request.userRequest}`,\n ``,\n `<!-- TODO: Fill in content -->`,\n ``,\n ].join('\\n');\n }\n\n const data = {\n _meta: {\n generatedBy: 'open-coleslaw extension system',\n name: request.name,\n description: request.description,\n trigger: request.trigger,\n created: new Date().toISOString(),\n userRequest: request.userRequest,\n },\n config: {},\n };\n\n return JSON.stringify(data, null, 2) + '\\n';\n}\n\nfunction generateLoop(request: GenerateRequest): string {\n return [\n header(request),\n `/**`,\n ` * Custom loop: ${request.name}`,\n ` * ${request.description}`,\n ` *`,\n ` * Trigger: ${request.trigger}`,\n ` * Original request: ${request.userRequest}`,\n ` *`,\n ` * Usage:`,\n ` * node custom-loops/${sanitizeName(request.name)}.js`,\n ` */`,\n ``,\n `const INTERVAL_MS = 30000; // 30 seconds`,\n `const MAX_ITERATIONS = 100;`,\n ``,\n `async function check() {`,\n ` // TODO: Implement the condition check for \"${request.description}\"`,\n ` const result = {`,\n ` loop: '${request.name}',`,\n ` iteration: 0,`,\n ` timestamp: new Date().toISOString(),`,\n ` conditionMet: false,`,\n ` };`,\n ` return result;`,\n `}`,\n ``,\n `async function main() {`,\n ` let iteration = 0;`,\n ``,\n ` while (iteration < MAX_ITERATIONS) {`,\n ` iteration++;`,\n ` const result = await check();`,\n ` result.iteration = iteration;`,\n ``,\n ` process.stdout.write(JSON.stringify(result) + '\\\\n');`,\n ``,\n ` if (result.conditionMet) {`,\n ` process.stdout.write(JSON.stringify({`,\n ` loop: '${request.name}',`,\n ` status: 'completed',`,\n ` totalIterations: iteration,`,\n ` }) + '\\\\n');`,\n ` break;`,\n ` }`,\n ``,\n ` await new Promise((resolve) => setTimeout(resolve, INTERVAL_MS));`,\n ` }`,\n `}`,\n ``,\n `main().catch((err) => {`,\n ` process.stderr.write(String(err));`,\n ` process.exit(1);`,\n `});`,\n ``,\n ].join('\\n');\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction toPascalCase(str: string): string {\n return str\n .split(/[-_\\s]+/)\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join('');\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Generate code for a new capability.\n *\n * Returns the file path where the code was written, the code itself,\n * and the registry entry to persist.\n */\nexport function generateCapability(request: GenerateRequest): GenerateResult {\n const safeName = sanitizeName(request.name);\n\n // Determine file extension based on type\n const isAssetMarkdown =\n request.type === 'asset' &&\n (/template|guide|doc|readme|note/i.test(request.name) ||\n /template|guide|doc|readme|note/i.test(request.description));\n\n let ext: string;\n if (request.type === 'asset') {\n ext = isAssetMarkdown ? '.md' : '.json';\n } else {\n ext = '.js';\n }\n\n const dir = customDir(request.type);\n const filePath = join(dir, `${safeName}${ext}`);\n\n // Generate the code\n let code: string;\n switch (request.type) {\n case 'hook':\n code = generateHook(request);\n break;\n case 'skill':\n code = generateSkill(request);\n break;\n case 'command':\n code = generateCommand(request);\n break;\n case 'asset':\n code = generateAsset(request);\n break;\n case 'loop':\n code = generateLoop(request);\n break;\n }\n\n // Write the file\n writeFileSync(filePath, code, 'utf-8');\n\n return {\n filePath,\n code,\n registryEntry: {\n type: request.type,\n name: request.name,\n description: request.description,\n trigger: request.trigger,\n isBuiltIn: false,\n filePath,\n },\n };\n}\n","/**\n * guide-updater.ts — Updates plugin-guide.md and rules.md when capabilities change.\n *\n * Regenerates plugin-guide.md with the current set of capabilities.\n * For rules.md, only appends custom rules — never removes base rules.\n */\n\nimport { readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { getConfig } from '../utils/config.js';\nimport type { CapabilityRegistry } from './capability-registry.js';\n\n// ---------------------------------------------------------------------------\n// Plugin guide\n// ---------------------------------------------------------------------------\n\n/**\n * Regenerate plugin-guide.md with the current set of registered capabilities.\n *\n * The guide is written to ~/.open-coleslaw/plugin-guide.md where the pre-read\n * hook picks it up.\n */\nexport async function updatePluginGuide(\n registry: CapabilityRegistry,\n): Promise<void> {\n const { DATA_DIR } = getConfig();\n const guidePath = join(DATA_DIR, 'plugin-guide.md');\n\n const capSection = registry.formatForGuide();\n\n const guide = [\n '# Open-Coleslaw Plugin Guide',\n '',\n '## Overview',\n 'Multi-agent orchestrator for Claude Code. Hierarchical agent system:',\n 'Orchestrator (proxy) -> Part Leaders (team leads) -> Workers (executors)',\n '',\n '## Registered Capabilities',\n '',\n capSection,\n '',\n '## Agent Tiers',\n '| Tier | Model | Role |',\n '|------|-------|------|',\n '| Orchestrator | claude-opus-4-6 (1M) | Full-picture routing, delegation |',\n '| Leader | claude-sonnet-4-6 | Meetings, technical decisions |',\n '| Worker (impl) | claude-sonnet-4-6 | Code, implementation |',\n '| Worker (research) | claude-haiku-4-5 | Quick lookups |',\n '',\n '## Departments',\n '- Architecture: system design, API, schema',\n '- Engineering: implementation, code quality',\n '- QA: testing, security, performance',\n '- Product: requirements, user stories',\n '- Research: codebase exploration, docs',\n '',\n '## Meeting Minutes',\n 'Saved to: ~/.open-coleslaw/minutes/',\n 'Index: ~/.open-coleslaw/minutes/INDEX.md',\n 'Format: PRD with frontmatter metadata + tags',\n '',\n '## Extension System',\n 'Custom capabilities are stored in ~/.open-coleslaw/custom-{type}s/.',\n 'Use the `create-capability` MCP tool to add new hooks, skills, commands, assets, or loops.',\n 'Registry: ~/.open-coleslaw/registry.json',\n '',\n ].join('\\n');\n\n writeFileSync(guidePath, guide, 'utf-8');\n}\n\n// ---------------------------------------------------------------------------\n// Rules\n// ---------------------------------------------------------------------------\n\n/** Sentinel that marks the beginning of the custom-rules block. */\nconst CUSTOM_RULES_START = '## Custom Rules';\nconst CUSTOM_RULES_END = '<!-- /custom-rules -->';\n\n/**\n * Append custom rules to rules.md without removing any base rules.\n *\n * Custom rules are bracketed between a `## Custom Rules` heading and\n * a closing HTML comment so they can be cleanly replaced on subsequent calls.\n */\nexport async function updateRulesIfNeeded(\n customRules: string[],\n): Promise<void> {\n if (customRules.length === 0) return;\n\n const { DATA_DIR } = getConfig();\n const rulesPath = join(DATA_DIR, 'rules.md');\n\n let existing: string;\n try {\n existing = readFileSync(rulesPath, 'utf-8');\n } catch {\n // If no rules.md yet, start from an empty document\n existing = '';\n }\n\n // Strip any previous custom-rules block\n const startIdx = existing.indexOf(CUSTOM_RULES_START);\n const endIdx = existing.indexOf(CUSTOM_RULES_END);\n let base: string;\n if (startIdx !== -1 && endIdx !== -1) {\n base =\n existing.slice(0, startIdx).trimEnd() +\n '\\n' +\n existing.slice(endIdx + CUSTOM_RULES_END.length).trimStart();\n } else if (startIdx !== -1) {\n base = existing.slice(0, startIdx).trimEnd();\n } else {\n base = existing;\n }\n\n // Build the new custom-rules section\n const rulesBlock = [\n '',\n CUSTOM_RULES_START,\n ...customRules.map((r) => `- ${r}`),\n CUSTOM_RULES_END,\n ].join('\\n');\n\n const updated = base.trimEnd() + '\\n' + rulesBlock + '\\n';\n writeFileSync(rulesPath, updated, 'utf-8');\n}\n","/**\n * extension-manager.ts — Top-level orchestrator for the extension system.\n *\n * Coordinates the CapabilityRegistry, code generator, and guide updater\n * so that the rest of the system has a single entry-point for extension\n * operations.\n */\n\nimport { CapabilityRegistry } from './capability-registry.js';\nimport type {\n CapabilityType,\n Capability,\n} from './capability-registry.js';\nimport { generateCapability } from './generator.js';\nimport type { GenerateRequest } from './generator.js';\nimport { updatePluginGuide } from './guide-updater.js';\n\n// ---------------------------------------------------------------------------\n// Analysis result\n// ---------------------------------------------------------------------------\n\nexport interface AnalysisResult {\n needsNewCapability: boolean;\n suggestedType?: CapabilityType;\n suggestedName?: string;\n suggestedDescription?: string;\n suggestedTrigger?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Creation result\n// ---------------------------------------------------------------------------\n\nexport interface CreateResult {\n capability: Capability;\n filePath: string;\n summary: string;\n}\n\n// ---------------------------------------------------------------------------\n// Keyword patterns for request analysis\n// ---------------------------------------------------------------------------\n\ninterface KeywordRule {\n type: CapabilityType;\n patterns: RegExp[];\n}\n\nconst KEYWORD_RULES: KeywordRule[] = [\n {\n type: 'hook',\n patterns: [\n /\\bevery\\s+time\\b/i,\n /\\balways\\b/i,\n /\\bbefore\\s+\\w+/i,\n /\\bafter\\s+\\w+/i,\n /\\bwhen\\s+\\w+/i,\n /\\bon\\s+(every|each)\\b/i,\n ],\n },\n {\n type: 'skill',\n patterns: [\n /\\/\\w+/,\n /\\bslash\\s+command\\b/i,\n /\\bshortcut\\b/i,\n /\\bskill\\b/i,\n ],\n },\n {\n type: 'asset',\n patterns: [\n /\\btemplate\\b/i,\n /\\bconfig\\b/i,\n /\\bsettings\\b/i,\n /\\bconfiguration\\b/i,\n ],\n },\n {\n type: 'loop',\n patterns: [\n /\\bcheck\\s+every\\b/i,\n /\\bpoll\\b/i,\n /\\bwatch\\b/i,\n /\\bmonitor\\b/i,\n /\\brepeatedly\\b/i,\n /\\bperiodically\\b/i,\n ],\n },\n];\n\n// ---------------------------------------------------------------------------\n// ExtensionManager\n// ---------------------------------------------------------------------------\n\nexport class ExtensionManager {\n private registry: CapabilityRegistry;\n\n constructor() {\n this.registry = new CapabilityRegistry();\n }\n\n /**\n * Initialize: load the registry from disk.\n */\n async init(): Promise<void> {\n await this.registry.loadAll();\n }\n\n /**\n * Analyze a user request to decide whether a new capability is needed.\n *\n * Uses keyword matching to suggest the capability type. Returns\n * `needsNewCapability: false` when the request matches an existing\n * capability name.\n */\n async analyzeRequest(request: string): Promise<AnalysisResult> {\n // If a capability with a matching name already exists, no creation needed\n const normalized = request.toLowerCase().trim();\n\n for (const cap of await this.registry.loadAll()) {\n if (normalized.includes(cap.name.toLowerCase())) {\n return { needsNewCapability: false };\n }\n }\n\n // Try to match keyword rules\n for (const rule of KEYWORD_RULES) {\n for (const pattern of rule.patterns) {\n if (pattern.test(request)) {\n const nameCandidate = extractName(request);\n return {\n needsNewCapability: true,\n suggestedType: rule.type,\n suggestedName: nameCandidate,\n suggestedDescription: request.slice(0, 120),\n suggestedTrigger: extractTrigger(request, rule.type),\n };\n }\n }\n }\n\n // Default: treat as a generic command\n return {\n needsNewCapability: true,\n suggestedType: 'command',\n suggestedName: extractName(request),\n suggestedDescription: request.slice(0, 120),\n suggestedTrigger: 'On user invocation',\n };\n }\n\n /**\n * Create a new capability, persist it, and update the plugin guide.\n */\n async createCapability(request: GenerateRequest): Promise<CreateResult> {\n // Generate the code file\n const result = generateCapability(request);\n\n // Register in the capability registry\n await this.registry.register(result.registryEntry);\n\n // Refresh the plugin guide so pre-read picks it up\n await updatePluginGuide(this.registry);\n\n // Build the full Capability object to return\n const capability: Capability = {\n ...result.registryEntry,\n createdAt: Date.now(),\n };\n\n const summary =\n `Created ${request.type} \"${request.name}\": ${request.description}. ` +\n `File: ${result.filePath}`;\n\n return { capability, filePath: result.filePath, summary };\n }\n\n /**\n * List all capabilities (built-in + custom).\n */\n async listCapabilities(): Promise<Capability[]> {\n return this.registry.loadAll();\n }\n\n /**\n * Remove a custom capability by name.\n *\n * Built-in capabilities cannot be removed.\n */\n async removeCapability(name: string): Promise<void> {\n const cap = this.registry.findByName(name);\n if (!cap) {\n throw new Error(`Capability not found: ${name}`);\n }\n if (cap.isBuiltIn) {\n throw new Error(`Cannot remove built-in capability: ${name}`);\n }\n\n await this.registry.unregister(cap.type, name);\n\n // Refresh the plugin guide\n await updatePluginGuide(this.registry);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Extract a reasonable short name from a user request string.\n */\nfunction extractName(request: string): string {\n // Try to pull out a slash-command name like /foo\n const slashMatch = request.match(/\\/(\\w[\\w-]*)/);\n if (slashMatch) return slashMatch[1];\n\n // Otherwise, take the first few meaningful words\n const words = request\n .replace(/[^a-zA-Z0-9\\s-]/g, '')\n .split(/\\s+/)\n .filter((w) => w.length > 2)\n .slice(0, 3);\n\n return words.join('-').toLowerCase() || 'unnamed';\n}\n\n/**\n * Generate a trigger description from the request and inferred type.\n */\nfunction extractTrigger(request: string, type: CapabilityType): string {\n switch (type) {\n case 'hook': {\n const beforeMatch = request.match(/before\\s+(\\w[\\w\\s]{0,30})/i);\n if (beforeMatch) return `Before ${beforeMatch[1].trim()}`;\n const afterMatch = request.match(/after\\s+(\\w[\\w\\s]{0,30})/i);\n if (afterMatch) return `After ${afterMatch[1].trim()}`;\n const whenMatch = request.match(/when\\s+(\\w[\\w\\s]{0,30})/i);\n if (whenMatch) return `When ${whenMatch[1].trim()}`;\n return 'On configured trigger';\n }\n case 'skill':\n return `/${extractName(request)}`;\n case 'loop': {\n const everyMatch = request.match(/every\\s+([\\w\\s]+)/i);\n if (everyMatch) return `Every ${everyMatch[1].trim()}`;\n return 'On interval';\n }\n case 'asset':\n return 'When referenced';\n case 'command':\n return 'On user invocation';\n }\n}\n","import { z } from 'zod';\nimport { costTracker } from '../utils/cost-tracker.js';\n\nexport const getCostSummarySchema = {\n meetingId: z.string().optional().describe('Optional meeting ID to filter costs'),\n};\n\nexport async function getCostSummaryHandler({\n meetingId,\n}: {\n meetingId?: string;\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const summary = costTracker.getSummary(meetingId);\n const budgetWarning = costTracker.checkBudget();\n\n const result: Record<string, unknown> = {\n ...summary,\n };\n\n if (budgetWarning) {\n result.budgetWarning = budgetWarning;\n }\n\n if (meetingId) {\n result.filteredByMeeting = meetingId;\n }\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import { getDb } from '../storage/db.js';\n\n// ---------------------------------------------------------------------------\n// Cost summary\n// ---------------------------------------------------------------------------\n\nexport interface CostSummary {\n totalUsd: number;\n byMeeting: Record<string, number>;\n byDepartment: Record<string, number>;\n byTier: Record<string, number>;\n budgetLimit: number | null;\n budgetRemaining: number | null;\n}\n\n// ---------------------------------------------------------------------------\n// In-memory cost entry\n// ---------------------------------------------------------------------------\n\ninterface CostEntry {\n agentId: string;\n meetingId: string;\n costUsd: number;\n recordedAt: number;\n}\n\n// ---------------------------------------------------------------------------\n// CostTracker\n// ---------------------------------------------------------------------------\n\nexport class CostTracker {\n private budgetLimitUsd: number | null = null;\n private entries: CostEntry[] = [];\n\n /** Set a budget limit in USD. */\n setBudget(limitUsd: number): void {\n this.budgetLimitUsd = limitUsd;\n }\n\n /** Record a cost for an agent action. */\n recordCost(agentId: string, meetingId: string, costUsd: number): void {\n this.entries.push({\n agentId,\n meetingId,\n costUsd,\n recordedAt: Date.now(),\n });\n }\n\n /** Get the current cost summary, combining in-memory entries with DB data. */\n getSummary(meetingId?: string): CostSummary {\n const byMeeting: Record<string, number> = {};\n const byDepartment: Record<string, number> = {};\n const byTier: Record<string, number> = {};\n let totalUsd = 0;\n\n // 1. Aggregate from the agents table in the DB\n try {\n const db = getDb();\n\n interface AgentCostRow {\n meeting_id: string | null;\n department: string;\n tier: string;\n cost_usd: number;\n }\n\n let agentRows: AgentCostRow[];\n if (meetingId) {\n agentRows = db\n .prepare('SELECT meeting_id, department, tier, cost_usd FROM agents WHERE meeting_id = ?')\n .all(meetingId) as AgentCostRow[];\n } else {\n agentRows = db\n .prepare('SELECT meeting_id, department, tier, cost_usd FROM agents')\n .all() as AgentCostRow[];\n }\n\n for (const row of agentRows) {\n const cost = row.cost_usd ?? 0;\n if (cost === 0) continue;\n\n totalUsd += cost;\n const mid = row.meeting_id ?? 'unknown';\n byMeeting[mid] = (byMeeting[mid] ?? 0) + cost;\n byDepartment[row.department] = (byDepartment[row.department] ?? 0) + cost;\n byTier[row.tier] = (byTier[row.tier] ?? 0) + cost;\n }\n\n // 2. Aggregate from the workers table\n interface WorkerCostRow {\n meeting_id: string;\n cost_usd: number;\n leader_id: string;\n }\n\n let workerRows: WorkerCostRow[];\n if (meetingId) {\n workerRows = db\n .prepare('SELECT meeting_id, cost_usd, leader_id FROM workers WHERE meeting_id = ?')\n .all(meetingId) as WorkerCostRow[];\n } else {\n workerRows = db\n .prepare('SELECT meeting_id, cost_usd, leader_id FROM workers')\n .all() as WorkerCostRow[];\n }\n\n for (const row of workerRows) {\n const cost = row.cost_usd ?? 0;\n if (cost === 0) continue;\n\n totalUsd += cost;\n byMeeting[row.meeting_id] = (byMeeting[row.meeting_id] ?? 0) + cost;\n byTier['worker'] = (byTier['worker'] ?? 0) + cost;\n\n // Look up the leader's department for the worker\n interface LeaderDeptRow { department: string }\n const leader = db\n .prepare('SELECT department FROM agents WHERE id = ?')\n .get(row.leader_id) as LeaderDeptRow | undefined;\n if (leader) {\n byDepartment[leader.department] = (byDepartment[leader.department] ?? 0) + cost;\n }\n }\n } catch {\n // DB might not be initialised yet; fall through to in-memory only\n }\n\n // 3. Aggregate in-memory entries\n const filteredEntries = meetingId\n ? this.entries.filter((e) => e.meetingId === meetingId)\n : this.entries;\n\n for (const entry of filteredEntries) {\n totalUsd += entry.costUsd;\n byMeeting[entry.meetingId] = (byMeeting[entry.meetingId] ?? 0) + entry.costUsd;\n }\n\n return {\n totalUsd,\n byMeeting,\n byDepartment,\n byTier,\n budgetLimit: this.budgetLimitUsd,\n budgetRemaining: this.budgetLimitUsd !== null ? this.budgetLimitUsd - totalUsd : null,\n };\n }\n\n /** Check if over budget. Returns a warning message or null. */\n checkBudget(): string | null {\n if (this.budgetLimitUsd === null) return null;\n\n const summary = this.getSummary();\n if (summary.totalUsd >= this.budgetLimitUsd) {\n return `Budget exceeded: $${summary.totalUsd.toFixed(4)} spent of $${this.budgetLimitUsd.toFixed(4)} limit`;\n }\n\n const remaining = this.budgetLimitUsd - summary.totalUsd;\n if (remaining < this.budgetLimitUsd * 0.1) {\n return `Budget warning: $${summary.totalUsd.toFixed(4)} spent, only $${remaining.toFixed(4)} remaining of $${this.budgetLimitUsd.toFixed(4)} limit`;\n }\n\n return null;\n }\n}\n\n/** Shared singleton instance. */\nexport const costTracker = new CostTracker();\n","import { z } from 'zod';\nimport { Orchestrator } from '../orchestrator/orchestrator.js';\nimport type { Department } from '../types/index.js';\n\nexport const chainMeetingSchema = {\n previousMeetingId: z.string().describe('ID of the previous meeting to chain from'),\n topic: z.string().describe('Topic for the new chained meeting'),\n agenda: z.array(z.string()).describe('Agenda items for the new meeting'),\n departments: z\n .array(z.string())\n .optional()\n .describe('Specific departments to invite'),\n};\n\nexport async function chainMeetingHandler({\n previousMeetingId,\n topic,\n agenda,\n departments,\n}: {\n previousMeetingId: string;\n topic: string;\n agenda: string[];\n departments?: string[];\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const orchestrator = new Orchestrator();\n const result = orchestrator.chainMeeting({\n previousMeetingId,\n topic,\n agenda,\n departments: departments as Department[] | undefined,\n });\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import { z } from 'zod';\nimport { MeetingRunner } from '../orchestrator/meeting-runner.js';\n\nexport const addTranscriptSchema = {\n meetingId: z.string().describe('Meeting ID'),\n speakerRole: z.string().describe('Role of the speaker (e.g. \"Architecture Lead\", \"Engineering Lead\")'),\n agendaItemIndex: z\n .number()\n .describe('Agenda item index (0-based). Use -1 for opening statements, -2 for synthesis'),\n roundNumber: z.number().describe('Discussion round number (0 for opening/synthesis)'),\n content: z.string().describe('The transcript content from the speaker'),\n};\n\nexport async function addTranscriptHandler({\n meetingId,\n speakerRole,\n agendaItemIndex,\n roundNumber,\n content,\n}: {\n meetingId: string;\n speakerRole: string;\n agendaItemIndex: number;\n roundNumber: number;\n content: string;\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const runner = new MeetingRunner(meetingId);\n const entry = runner.addTranscript(speakerRole, agendaItemIndex, roundNumber, content);\n\n const result = {\n success: true,\n entryId: entry.id,\n meetingId,\n speakerRole,\n agendaItemIndex,\n roundNumber,\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import type {\n TranscriptEntry,\n MeetingStatus,\n MeetingPhase,\n ActionItem,\n} from '../types/index.js';\nimport {\n getMeeting,\n updateMeeting,\n createMinutes,\n getMinutesByMeeting,\n} from '../storage/index.js';\nimport { getDb } from '../storage/db.js';\nimport { logger } from '../utils/logger.js';\n\n// ---------------------------------------------------------------------------\n// Transcript helpers (direct DB access since there is no transcript store)\n// ---------------------------------------------------------------------------\n\nfunction insertTranscriptEntry(\n meetingId: string,\n speakerId: string,\n speakerRole: string,\n agendaItemIndex: number,\n roundNumber: number,\n content: string,\n): TranscriptEntry {\n const db = getDb();\n const now = Date.now();\n const tokenCount = Math.ceil(content.length / 4); // rough approximation\n\n const result = db\n .prepare(\n `INSERT INTO transcript_entries\n (meeting_id, speaker_id, speaker_role, agenda_item_index, round_number, content, token_count, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(meetingId, speakerId, speakerRole, agendaItemIndex, roundNumber, content, tokenCount, now);\n\n return {\n id: Number(result.lastInsertRowid),\n meetingId,\n speakerId,\n speakerRole,\n agendaItemIndex,\n roundNumber,\n content,\n tokenCount,\n createdAt: now,\n };\n}\n\nfunction getTranscript(meetingId: string): TranscriptEntry[] {\n const db = getDb();\n interface TranscriptRow {\n id: number;\n meeting_id: string;\n speaker_id: string;\n speaker_role: string;\n agenda_item_index: number;\n round_number: number;\n content: string;\n token_count: number;\n created_at: number;\n }\n const rows = db\n .prepare('SELECT * FROM transcript_entries WHERE meeting_id = ? ORDER BY created_at ASC')\n .all(meetingId) as TranscriptRow[];\n\n return rows.map((r) => ({\n id: r.id,\n meetingId: r.meeting_id,\n speakerId: r.speaker_id,\n speakerRole: r.speaker_role,\n agendaItemIndex: r.agenda_item_index,\n roundNumber: r.round_number,\n content: r.content,\n tokenCount: r.token_count,\n createdAt: r.created_at,\n }));\n}\n\n// ---------------------------------------------------------------------------\n// MeetingRunner — data-only utility (no agent invocation)\n//\n// Stores transcript entries and generates minutes from stored transcripts.\n// Actual agent dispatch is handled by Claude Code's Agent tool, orchestrated\n// by skill/agent markdown files.\n// ---------------------------------------------------------------------------\n\nexport class MeetingRunner {\n private readonly meetingId: string;\n\n constructor(meetingId: string) {\n this.meetingId = meetingId;\n }\n\n // ---- Add transcript entry (called by MCP tool add-transcript) -----------\n\n /**\n * Add a transcript entry for this meeting.\n * Returns the created TranscriptEntry.\n */\n addTranscript(\n speakerRole: string,\n agendaItemIndex: number,\n roundNumber: number,\n content: string,\n ): TranscriptEntry {\n const meeting = getMeeting(this.meetingId);\n if (!meeting) {\n throw new Error(`Meeting not found: ${this.meetingId}`);\n }\n\n // Use speakerRole as speakerId since we no longer manage agent nodes here\n const entry = insertTranscriptEntry(\n this.meetingId,\n speakerRole,\n speakerRole,\n agendaItemIndex,\n roundNumber,\n content,\n );\n\n logger.debug(`Transcript added: ${speakerRole} (item ${agendaItemIndex}, round ${roundNumber})`, {\n meetingId: this.meetingId,\n });\n\n return entry;\n }\n\n // ---- Generate minutes from all transcripts ------------------------------\n\n /**\n * Generate meeting minutes by formatting all stored transcript entries.\n * Returns the minutesId of the created minutes record.\n */\n async generateMinutes(): Promise<string> {\n const meeting = getMeeting(this.meetingId);\n if (!meeting) {\n throw new Error(`Meeting not found: ${this.meetingId}`);\n }\n\n // Update phase\n updateMeeting(this.meetingId, {\n phase: 'minutes-generation' as MeetingPhase,\n status: 'minutes-generation' as MeetingStatus,\n });\n\n const transcript = getTranscript(this.meetingId);\n\n // --- Build the minutes content ---\n\n const sections: string[] = [];\n\n // Collect unique speaker roles from transcript\n const speakerRoles = [...new Set(transcript.map((e) => e.speakerRole))];\n\n sections.push(`# Meeting Minutes`);\n sections.push(`## Topic: ${meeting.topic}`);\n sections.push(`## Date: ${new Date().toISOString()}`);\n sections.push(`## Participants: ${speakerRoles.join(', ')}`);\n sections.push('');\n\n // Agenda\n sections.push(`## Agenda`);\n meeting.agenda.forEach((item, i) => {\n sections.push(`${i + 1}. ${item}`);\n });\n sections.push('');\n\n // Opening statements\n const openingEntries = transcript.filter((e) => e.agendaItemIndex === -1);\n if (openingEntries.length > 0) {\n sections.push(`## Opening Statements`);\n for (const entry of openingEntries) {\n sections.push(`### ${entry.speakerRole}`);\n sections.push(entry.content);\n sections.push('');\n }\n }\n\n // Discussion per agenda item\n for (let i = 0; i < meeting.agenda.length; i++) {\n const itemEntries = transcript.filter((e) => e.agendaItemIndex === i);\n if (itemEntries.length > 0) {\n sections.push(`## Discussion: ${meeting.agenda[i]}`);\n for (const entry of itemEntries) {\n sections.push(`**${entry.speakerRole}** (round ${entry.roundNumber}):`);\n sections.push(entry.content);\n sections.push('');\n }\n }\n }\n\n // Synthesis\n const synthesisEntries = transcript.filter((e) => e.agendaItemIndex === -2);\n if (synthesisEntries.length > 0) {\n sections.push(`## Final Positions`);\n for (const entry of synthesisEntries) {\n sections.push(`### ${entry.speakerRole}`);\n sections.push(entry.content);\n sections.push('');\n }\n }\n\n const content = sections.join('\\n');\n\n // --- Extract action items from synthesis entries ---\n\n const actionItems: ActionItem[] = speakerRoles.map((role, idx) => ({\n id: `action-${this.meetingId}-${idx}`,\n title: `${role} deliverables`,\n description: `Action items committed by ${role} during synthesis phase`,\n assignedDepartment: 'engineering', // default; will be refined by compactor\n assignedRole: role,\n priority: 'medium' as const,\n dependencies: [],\n acceptanceCriteria: ['Deliverables completed as stated in final position'],\n }));\n\n const minutesRecord = createMinutes({\n meetingId: this.meetingId,\n format: 'summary',\n content,\n actionItems,\n });\n\n // Mark meeting as completed\n updateMeeting(this.meetingId, {\n status: 'completed' as MeetingStatus,\n completedAt: Date.now(),\n });\n\n logger.info('Minutes generated', { meetingId: this.meetingId });\n\n return minutesRecord.id;\n }\n\n // ---- Completion status --------------------------------------------------\n\n /**\n * Check whether the meeting has been completed (minutes generated).\n */\n isComplete(): boolean {\n const meeting = getMeeting(this.meetingId);\n if (!meeting) return false;\n return ['completed', 'compacted', 'reported'].includes(meeting.status);\n }\n\n // ---- Transcript access --------------------------------------------------\n\n /**\n * Get all transcript entries for this meeting.\n */\n getTranscript(): TranscriptEntry[] {\n return getTranscript(this.meetingId);\n }\n}\n","import { z } from 'zod';\nimport { MeetingRunner } from '../orchestrator/meeting-runner.js';\nimport { getMinutesByMeeting } from '../storage/index.js';\n\nexport const generateMinutesSchema = {\n meetingId: z.string().describe('Meeting ID to generate minutes for'),\n};\n\nexport async function generateMinutesHandler({\n meetingId,\n}: {\n meetingId: string;\n}): Promise<{ content: { type: 'text'; text: string }[]; isError?: boolean }> {\n try {\n const runner = new MeetingRunner(meetingId);\n const minutesId = await runner.generateMinutes();\n\n // Fetch the generated minutes to include the content\n const minutes = getMinutesByMeeting(meetingId);\n\n const result = {\n minutesId,\n meetingId,\n content: minutes?.content ?? '',\n };\n\n return {\n content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return {\n content: [\n { type: 'text', text: JSON.stringify({ error: message }, null, 2) },\n ],\n isError: true,\n };\n }\n}\n","import { createServer as createHttpServer } from 'node:http';\nimport { WebSocketServer, WebSocket } from 'ws';\nimport { getDashboardHTML } from './html.js';\nimport { StateBridge } from './state-bridge.js';\nimport { DashboardClient } from './client.js';\nimport { eventBus } from '../orchestrator/event-bus.js';\nimport { getConfig } from '../utils/config.js';\nimport { logger } from '../utils/logger.js';\nimport type { AgentEvent, ServerMessage } from '../types/dashboard-events.js';\n\nexport interface DashboardHandle {\n isOwner: boolean;\n close: () => void;\n}\n\nexport interface DashboardOptions {\n sessionId: string;\n projectPath: string;\n projectName: string;\n}\n\nexport function startDashboard(options: DashboardOptions): Promise<DashboardHandle> {\n const port = getConfig().DASHBOARD_PORT;\n\n return new Promise((resolve) => {\n const httpServer = createHttpServer((req, res) => {\n if (req.url === '/' || req.url === '/index.html') {\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });\n res.end(getDashboardHTML());\n } else {\n res.writeHead(404);\n res.end('Not Found');\n }\n });\n\n httpServer.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n // Port in use — become a client\n logger.info(`Dashboard port ${port} in use — connecting as client`);\n const client = new DashboardClient(options.sessionId, options.projectName, options.projectPath);\n client.connect(port);\n resolve({\n isOwner: false,\n close: () => client.disconnect(),\n });\n } else {\n logger.error(`Dashboard error: ${err.message}`);\n resolve({ isOwner: false, close: () => {} });\n }\n });\n\n httpServer.listen(port, '127.0.0.1', () => {\n logger.info(`Dashboard owner — running at http://localhost:${port}`);\n\n const wss = new WebSocketServer({ server: httpServer });\n const bridge = new StateBridge();\n\n // Register own session\n const displayName = bridge.registerSession({\n sessionId: options.sessionId,\n projectPath: options.projectPath,\n projectName: options.projectName,\n });\n logger.info(`Registered own session: ${displayName}`);\n\n // Forward local events to bridge\n eventBus.on('agent_event', (event: AgentEvent) => {\n bridge.handleSessionEvent(options.sessionId, event);\n });\n\n // Handle browser clients + MCP server clients\n wss.on('connection', (ws: WebSocket) => {\n // Send full snapshot\n ws.send(JSON.stringify(bridge.getSnapshot()));\n\n ws.on('message', (data: Buffer) => {\n try {\n const msg: ServerMessage = JSON.parse(data.toString());\n\n if (msg.type === 'register') {\n const name = bridge.registerSession({\n sessionId: msg.sessionId,\n projectPath: msg.projectPath,\n projectName: msg.projectName,\n });\n // Notify all browser clients\n const notification = JSON.stringify({\n type: 'session-registered',\n sessionId: msg.sessionId,\n displayName: name,\n projectPath: msg.projectPath,\n });\n wss.clients.forEach((c) => {\n if (c !== ws && c.readyState === WebSocket.OPEN) c.send(notification);\n });\n } else if (msg.type === 'session-event') {\n bridge.handleSessionEvent(msg.sessionId, msg.event);\n } else if (msg.type === 'unregister') {\n bridge.unregisterSession(msg.sessionId);\n const notification = JSON.stringify({\n type: 'session-unregistered',\n sessionId: msg.sessionId,\n });\n wss.clients.forEach((c) => {\n if (c.readyState === WebSocket.OPEN) c.send(notification);\n });\n } else if ((msg as any).type === 'ping') {\n ws.send(JSON.stringify({ type: 'pong' }));\n }\n } catch {\n // ignore malformed\n }\n });\n });\n\n // Broadcast deltas to all browser clients\n bridge.on('broadcast', (data: string) => {\n wss.clients.forEach((c) => {\n if (c.readyState === WebSocket.OPEN) c.send(data);\n });\n });\n\n resolve({\n isOwner: true,\n close: () => {\n bridge.unregisterSession(options.sessionId);\n wss.close();\n httpServer.close();\n },\n });\n });\n });\n}\n","/**\n * getDashboardHTML() — returns the full inline HTML/CSS/JS for the Open Coleslaw\n * real-time dashboard. Everything is self-contained; the only external deps are\n * Cytoscape.js + dagre loaded from CDN.\n *\n * Multi-session aware: one tab per project session in the tab bar.\n */\n\nexport function getDashboardHTML(): string {\n return /* html */ `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n<title>Open Coleslaw Dashboard</title>\n\n<!-- CDN deps -->\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.30.4/cytoscape.min.js\"></script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/dagre/0.8.5/dagre.min.js\"></script>\n<script src=\"https://unpkg.com/cytoscape-dagre@2.5.0/cytoscape-dagre.js\"></script>\n\n<!-- Google Fonts: JetBrains Mono -->\n<link rel=\"preconnect\" href=\"https://fonts.googleapis.com\" />\n<link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin />\n<link href=\"https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500;600;700&display=swap\" rel=\"stylesheet\" />\n\n<style>\n/* ===================================================================\n RESET & VARIABLES\n =================================================================== */\n*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\n\n:root {\n --bg: #0a0e17;\n --surface: #111827;\n --border: #1e293b;\n --cyan: #00f0ff;\n --purple: #a855f7;\n --lightcyan: #22d3ee;\n --success: #10b981;\n --warning: #f59e0b;\n --error: #ef4444;\n --text: #e2e8f0;\n --text2: #94a3b8;\n --font: 'JetBrains Mono', 'Fira Code', monospace;\n}\n\nhtml, body {\n width: 100%; height: 100%;\n overflow: hidden;\n background: var(--bg);\n color: var(--text);\n font-family: var(--font);\n font-size: 13px;\n line-height: 1.5;\n}\n\n/* ===================================================================\n LAYOUT — five areas via CSS Grid\n =================================================================== */\n#app {\n display: grid;\n width: 100%; height: 100%;\n grid-template-rows: 48px 36px 1fr 200px;\n grid-template-columns: 1fr 320px;\n grid-template-areas:\n \"header header\"\n \"tabs tabs\"\n \"graph sidebar\"\n \"log log\";\n}\n\n/* ===================================================================\n HEADER\n =================================================================== */\n#header {\n grid-area: header;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0 20px;\n background: var(--surface);\n border-bottom: 1px solid var(--border);\n gap: 16px;\n z-index: 10;\n}\n\n#header .brand {\n display: flex;\n align-items: center;\n gap: 10px;\n font-size: 16px;\n font-weight: 700;\n color: var(--cyan);\n text-shadow: 0 0 12px rgba(0,240,255,0.5);\n white-space: nowrap;\n}\n\n#header .center-status {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n}\n\n.conn-dot {\n width: 10px; height: 10px;\n border-radius: 50%;\n background: var(--error);\n transition: background 0.3s;\n box-shadow: 0 0 6px rgba(239,68,68,0.6);\n}\n.conn-dot.connected {\n background: var(--success);\n box-shadow: 0 0 6px rgba(16,185,129,0.6);\n}\n.conn-dot.reconnecting {\n background: var(--warning);\n box-shadow: 0 0 6px rgba(245,158,11,0.6);\n animation: breathe 1.5s ease-in-out infinite;\n}\n\n#header .right-stats {\n display: flex;\n align-items: center;\n gap: 14px;\n font-size: 12px;\n}\n\n.badge {\n background: rgba(0,240,255,0.1);\n border: 1px solid rgba(0,240,255,0.25);\n padding: 2px 10px;\n border-radius: 12px;\n font-size: 11px;\n white-space: nowrap;\n}\n.badge.purple { background: rgba(168,85,247,0.1); border-color: rgba(168,85,247,0.3); }\n.badge.amber { background: rgba(245,158,11,0.1); border-color: rgba(245,158,11,0.3); color: var(--warning); }\n.badge.green { background: rgba(16,185,129,0.1); border-color: rgba(16,185,129,0.3); color: var(--success); }\n\n/* ===================================================================\n TAB BAR\n =================================================================== */\n#tab-bar {\n grid-area: tabs;\n display: flex;\n align-items: stretch;\n background: var(--surface);\n border-bottom: 1px solid var(--border);\n padding: 0 12px;\n gap: 2px;\n overflow-x: auto;\n overflow-y: hidden;\n scrollbar-width: none;\n}\n#tab-bar::-webkit-scrollbar { display: none; }\n\n.session-tab {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 0 14px;\n font-size: 11px;\n font-family: var(--font);\n font-weight: 500;\n color: var(--text2);\n background: transparent;\n border: none;\n border-bottom: 2px solid transparent;\n cursor: pointer;\n white-space: nowrap;\n transition: color 0.2s, border-color 0.2s, opacity 0.2s;\n position: relative;\n}\n.session-tab:hover {\n color: var(--text);\n background: rgba(255,255,255,0.02);\n}\n.session-tab.active {\n color: var(--cyan);\n border-bottom-color: var(--cyan);\n text-shadow: 0 0 8px rgba(0,240,255,0.4);\n}\n.session-tab.inactive {\n opacity: 0.45;\n text-decoration: line-through;\n color: var(--text2);\n}\n.session-tab.inactive:hover {\n opacity: 0.6;\n}\n\n.tab-badge {\n font-size: 9px;\n padding: 1px 5px;\n border-radius: 8px;\n background: rgba(0,240,255,0.15);\n color: var(--cyan);\n font-weight: 700;\n min-width: 16px;\n text-align: center;\n}\n.tab-badge.meeting {\n background: rgba(245,158,11,0.2);\n color: var(--warning);\n}\n\n.tab-empty-msg {\n display: flex;\n align-items: center;\n font-size: 11px;\n color: var(--text2);\n font-style: italic;\n padding: 0 8px;\n}\n\n/* ===================================================================\n GRAPH VIEWPORT\n =================================================================== */\n#graph-container {\n grid-area: graph;\n background: var(--bg);\n position: relative;\n overflow: hidden;\n}\n#cy {\n width: 100%; height: 100%;\n}\n/* watermark text */\n#graph-container::after {\n content: 'AGENT GRAPH';\n position: absolute;\n bottom: 12px; left: 16px;\n font-size: 10px;\n color: rgba(148,163,184,0.25);\n letter-spacing: 3px;\n pointer-events: none;\n}\n\n/* ===================================================================\n SIDEBAR\n =================================================================== */\n#sidebar {\n grid-area: sidebar;\n background: var(--surface);\n border-left: 1px solid var(--border);\n padding: 16px;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n#sidebar h2 {\n font-size: 12px;\n text-transform: uppercase;\n letter-spacing: 2px;\n color: var(--text2);\n margin-bottom: 4px;\n}\n\n.sidebar-empty {\n color: var(--text2);\n font-style: italic;\n font-size: 12px;\n margin-top: 40px;\n text-align: center;\n}\n\n.detail-row {\n display: flex;\n justify-content: space-between;\n padding: 4px 0;\n border-bottom: 1px solid var(--border);\n font-size: 12px;\n}\n.detail-row .label { color: var(--text2); }\n.detail-row .value { color: var(--text); font-weight: 500; }\n\n.status-chip {\n display: inline-block;\n padding: 1px 8px;\n border-radius: 6px;\n font-size: 11px;\n font-weight: 600;\n}\n.status-chip.idle { background: rgba(148,163,184,0.15); color: var(--text2); }\n.status-chip.working { background: rgba(0,240,255,0.15); color: var(--cyan); }\n.status-chip.in-meeting { background: rgba(245,158,11,0.15); color: var(--warning); }\n.status-chip.spawning-workers { background: rgba(168,85,247,0.15); color: var(--purple); }\n.status-chip.aggregating { background: rgba(34,211,238,0.15); color: var(--lightcyan); }\n.status-chip.waiting-for-user { background: rgba(245,158,11,0.15); color: var(--warning); }\n.status-chip.completed { background: rgba(16,185,129,0.15); color: var(--success); }\n.status-chip.failed { background: rgba(239,68,68,0.15); color: var(--error); }\n\n.task-block {\n background: rgba(0,0,0,0.3);\n border: 1px solid var(--border);\n border-radius: 6px;\n padding: 10px;\n font-size: 12px;\n color: var(--text2);\n line-height: 1.6;\n max-height: 160px;\n overflow-y: auto;\n}\n\n/* Children list */\n.children-list {\n list-style: none;\n padding: 0;\n font-size: 12px;\n}\n.children-list li {\n padding: 3px 0;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n.children-list li::before {\n content: '';\n display: inline-block;\n width: 6px; height: 6px;\n border-radius: 50%;\n background: var(--lightcyan);\n}\n\n/* Task history */\n#task-history {\n max-height: 250px;\n overflow-y: auto;\n}\n.history-item {\n font-size: 11px;\n padding: 4px 0;\n border-bottom: 1px solid rgba(30,41,59,0.5);\n color: var(--text2);\n}\n\n/* ===================================================================\n EVENT LOG\n =================================================================== */\n#event-log {\n grid-area: log;\n background: var(--surface);\n border-top: 1px solid var(--border);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n#event-log .log-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px 16px;\n font-size: 10px;\n text-transform: uppercase;\n letter-spacing: 2px;\n color: var(--text2);\n border-bottom: 1px solid var(--border);\n flex-shrink: 0;\n}\n#event-log .log-header .pause-indicator {\n color: var(--warning);\n font-weight: 600;\n display: none;\n}\n#event-log .log-header .pause-indicator.visible {\n display: inline;\n}\n\n#log-entries {\n flex: 1;\n overflow-y: auto;\n padding: 4px 0;\n font-size: 12px;\n scroll-behavior: smooth;\n}\n\n.log-entry {\n display: flex;\n gap: 12px;\n padding: 3px 16px;\n border-bottom: 1px solid rgba(30,41,59,0.3);\n align-items: baseline;\n}\n.log-entry:hover { background: rgba(255,255,255,0.02); }\n\n.log-time {\n color: var(--text2);\n font-size: 11px;\n flex-shrink: 0;\n min-width: 64px;\n}\n.log-session {\n color: var(--cyan);\n font-size: 10px;\n flex-shrink: 0;\n min-width: 80px;\n max-width: 120px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n opacity: 0.7;\n}\n.log-kind {\n font-weight: 600;\n flex-shrink: 0;\n min-width: 90px;\n font-size: 11px;\n}\n.log-msg {\n color: var(--text);\n flex: 1;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n/* Kind colours */\n.log-kind.spawn { color: var(--cyan); }\n.log-kind.destroy { color: var(--error); }\n.log-kind.state { color: var(--purple); }\n.log-kind.task { color: var(--lightcyan); }\n.log-kind.done { color: var(--success); }\n.log-kind.msg { color: var(--text); }\n.log-kind.mention { color: var(--error); }\n.log-kind.resolved { color: var(--success); }\n.log-kind.cost { color: var(--warning); }\n.log-kind.session { color: var(--purple); }\n\n/* ===================================================================\n ANIMATIONS\n =================================================================== */\n@keyframes breathe {\n 0%, 100% { opacity: 0.4; }\n 50% { opacity: 1; }\n}\n@keyframes pulse-glow {\n 0%, 100% { box-shadow: 0 0 4px rgba(0,240,255,0.3); }\n 50% { box-shadow: 0 0 18px rgba(0,240,255,0.7); }\n}\n\n/* Custom scrollbar */\n::-webkit-scrollbar { width: 6px; }\n::-webkit-scrollbar-track { background: var(--bg); }\n::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }\n::-webkit-scrollbar-thumb:hover { background: #334155; }\n</style>\n</head>\n<body>\n\n<div id=\"app\">\n <!-- HEADER ------------------------------------------------------------ -->\n <header id=\"header\">\n <div class=\"brand\">\n <span style=\"font-size:22px\">&#x1F96C;</span>\n <span>Open Coleslaw</span>\n </div>\n <div class=\"center-status\">\n <span class=\"conn-dot\" id=\"conn-dot\"></span>\n <span id=\"conn-label\">Connecting...</span>\n </div>\n <div class=\"right-stats\">\n <span class=\"badge\" id=\"badge-sessions\">0 sessions</span>\n <span class=\"badge\" id=\"badge-agents\">0 agents</span>\n <span class=\"badge purple\" id=\"badge-meeting\">No meeting</span>\n <span class=\"badge green\" id=\"badge-cost\">$0.0000</span>\n </div>\n </header>\n\n <!-- TAB BAR ----------------------------------------------------------- -->\n <div id=\"tab-bar\">\n <span class=\"tab-empty-msg\" id=\"tab-empty\">Waiting for sessions...</span>\n </div>\n\n <!-- GRAPH ------------------------------------------------------------- -->\n <div id=\"graph-container\">\n <div id=\"cy\"></div>\n </div>\n\n <!-- SIDEBAR ----------------------------------------------------------- -->\n <aside id=\"sidebar\">\n <h2>Agent Details</h2>\n <div class=\"sidebar-empty\" id=\"sidebar-empty\">Click a node to inspect</div>\n <div id=\"sidebar-content\" style=\"display:none;\"></div>\n </aside>\n\n <!-- EVENT LOG --------------------------------------------------------- -->\n <div id=\"event-log\">\n <div class=\"log-header\">\n <span>Event Log</span>\n <span class=\"pause-indicator\" id=\"log-pause\">PAUSED (scroll up)</span>\n </div>\n <div id=\"log-entries\"></div>\n </div>\n</div>\n\n<script>\n// ======================================================================\n// IIFE -- all dashboard JS\n// ======================================================================\n(function () {\n 'use strict';\n\n // ====================================================================\n // 1. STATE STORE (per-session)\n // ====================================================================\n // sessions: Map<sessionId, { displayName, projectPath, isActive, agents: Map, edges: [], meeting, totalCost, eventHistory[] }>\n const sessions = new Map();\n let activeTabId = null; // currently viewed session\n let selectedAgentId = null; // clicked node\n\n function getSession(id) { return sessions.get(id); }\n\n function activeSession() {\n if (!activeTabId) return null;\n return sessions.get(activeTabId) || null;\n }\n\n // ====================================================================\n // 2. CONNECTION MANAGER -- WebSocket with exponential backoff\n // ====================================================================\n const ConnectionManager = {\n ws: null,\n backoff: 1000,\n maxBackoff: 30000,\n timer: null,\n _heartbeat: null,\n\n connect() {\n const proto = location.protocol === 'https:' ? 'wss' : 'ws';\n const url = proto + '://' + location.host;\n this.ws = new WebSocket(url);\n this.setStatus('reconnecting');\n\n this.ws.onopen = () => {\n this.backoff = 1000;\n this.setStatus('connected');\n };\n\n this.ws.onmessage = (msg) => {\n try {\n const data = JSON.parse(msg.data);\n this.handleMessage(data);\n } catch (e) {\n console.error('[WS] Parse error:', e);\n }\n };\n\n this.ws.onclose = () => {\n this.setStatus('disconnected');\n this.scheduleReconnect();\n };\n\n this.ws.onerror = () => {};\n\n if (this._heartbeat) clearInterval(this._heartbeat);\n this._heartbeat = setInterval(() => {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify({ type: 'ping' }));\n }\n }, 25000);\n },\n\n handleMessage(data) {\n switch (data.type) {\n case 'multi-snapshot':\n this.handleMultiSnapshot(data);\n break;\n case 'session-delta':\n this.handleSessionDelta(data);\n break;\n case 'session-registered':\n this.handleSessionRegistered(data);\n break;\n case 'session-unregistered':\n this.handleSessionUnregistered(data);\n break;\n case 'pong':\n break;\n default:\n break;\n }\n },\n\n handleMultiSnapshot(data) {\n sessions.clear();\n (data.sessions || []).forEach(function (s) {\n var agentsMap = new Map();\n (s.snapshot.agents || []).forEach(function (a) { agentsMap.set(a.id, a); });\n sessions.set(s.sessionId, {\n displayName: s.displayName,\n projectPath: s.projectPath,\n isActive: s.isActive,\n agents: agentsMap,\n edges: s.snapshot.edges || [],\n meeting: s.snapshot.meeting || null,\n totalCost: s.snapshot.totalCost || 0,\n eventHistory: [],\n });\n });\n // Auto-select first active tab if none selected\n if (!activeTabId || !sessions.has(activeTabId)) {\n var first = null;\n sessions.forEach(function (s, id) { if (!first && s.isActive) first = id; });\n if (!first && sessions.size > 0) first = sessions.keys().next().value;\n activeTabId = first;\n }\n TabBar.render();\n StatusBar.update();\n GraphRenderer.rebuild();\n },\n\n handleSessionDelta(data) {\n var sess = sessions.get(data.sessionId);\n if (!sess) {\n // Session not yet known -- create a placeholder\n sess = {\n displayName: data.displayName,\n projectPath: '',\n isActive: true,\n agents: new Map(),\n edges: [],\n meeting: null,\n totalCost: 0,\n eventHistory: [],\n };\n sessions.set(data.sessionId, sess);\n TabBar.render();\n }\n\n (data.events || []).forEach(function (ev) {\n applyEventToSession(data.sessionId, sess, ev);\n });\n\n TabBar.updateBadge(data.sessionId);\n StatusBar.update();\n\n // Rebuild graph only if this is the active tab\n if (data.sessionId === activeTabId) {\n GraphRenderer.rebuild();\n if (selectedAgentId) SidebarPanel.show(selectedAgentId);\n }\n },\n\n handleSessionRegistered(data) {\n if (!sessions.has(data.sessionId)) {\n sessions.set(data.sessionId, {\n displayName: data.displayName,\n projectPath: data.projectPath,\n isActive: true,\n agents: new Map(),\n edges: [],\n meeting: null,\n totalCost: 0,\n eventHistory: [],\n });\n }\n // Auto-select if no tab is active\n if (!activeTabId) activeTabId = data.sessionId;\n TabBar.render();\n StatusBar.update();\n EventLog.appendSystem(data.displayName, 'Session connected');\n },\n\n handleSessionUnregistered(data) {\n var sess = sessions.get(data.sessionId);\n if (sess) {\n sess.isActive = false;\n TabBar.render();\n StatusBar.update();\n EventLog.appendSystem(sess.displayName, 'Session disconnected');\n }\n },\n\n scheduleReconnect() {\n if (this.timer) clearTimeout(this.timer);\n this.timer = setTimeout(() => {\n this.backoff = Math.min(this.backoff * 2, this.maxBackoff);\n this.connect();\n }, this.backoff);\n },\n\n setStatus(status) {\n var dot = document.getElementById('conn-dot');\n var label = document.getElementById('conn-label');\n dot.className = 'conn-dot';\n if (status === 'connected') {\n dot.classList.add('connected');\n label.textContent = 'Connected';\n } else if (status === 'reconnecting') {\n dot.classList.add('reconnecting');\n label.textContent = 'Connecting...';\n } else {\n label.textContent = 'Disconnected';\n }\n },\n };\n\n // ====================================================================\n // Event application (scoped to a session)\n // ====================================================================\n function applyEventToSession(sessionId, sess, ev) {\n sess.eventHistory.push(ev);\n if (sess.eventHistory.length > 500) sess.eventHistory.shift();\n\n EventLog.append(sessionId, sess.displayName, ev);\n\n switch (ev.kind) {\n case 'agent_spawned': {\n var agent = {\n id: ev.agentId,\n type: ev.agentType,\n label: ev.label,\n status: 'idle',\n parentId: ev.parentId,\n department: ev.department,\n currentTask: null,\n costUsd: 0,\n };\n sess.agents.set(ev.agentId, agent);\n if (ev.parentId) {\n sess.edges.push({\n id: 'edge-' + ev.parentId + '-' + ev.agentId,\n source: ev.parentId,\n target: ev.agentId,\n edgeType: 'hierarchy',\n active: true,\n label: '',\n });\n }\n break;\n }\n case 'agent_destroyed': {\n sess.agents.delete(ev.agentId);\n sess.edges = sess.edges.filter(function (e) {\n return e.source !== ev.agentId && e.target !== ev.agentId;\n });\n if (sessionId === activeTabId && selectedAgentId === ev.agentId) {\n selectedAgentId = null;\n SidebarPanel.clear();\n }\n break;\n }\n case 'state_changed': {\n var a = sess.agents.get(ev.agentId);\n if (a) a.status = ev.to;\n break;\n }\n case 'task_assigned': {\n var a = sess.agents.get(ev.agentId);\n if (a) { a.currentTask = ev.taskSummary; a.status = 'working'; }\n break;\n }\n case 'task_completed': {\n var a = sess.agents.get(ev.agentId);\n if (a) { a.currentTask = null; a.status = ev.result === 'success' ? 'completed' : 'failed'; }\n break;\n }\n case 'message_sent': {\n var edgeId = 'msg-' + ev.fromId + '-' + ev.toId + '-' + Date.now();\n var edge = { id: edgeId, source: ev.fromId, target: ev.toId, edgeType: 'message', active: true, label: ev.summary };\n sess.edges.push(edge);\n setTimeout(function () {\n sess.edges = sess.edges.filter(function (e) { return e.id !== edgeId; });\n if (sessionId === activeTabId) GraphRenderer.rebuild();\n }, 5000);\n break;\n }\n case 'cost_update': {\n sess.totalCost = ev.totalCost;\n break;\n }\n default:\n break;\n }\n }\n\n // ====================================================================\n // 3. TAB BAR\n // ====================================================================\n var TabBar = {\n render: function () {\n var bar = document.getElementById('tab-bar');\n var emptyMsg = document.getElementById('tab-empty');\n\n // Remove old tabs (keep the empty msg span)\n var old = bar.querySelectorAll('.session-tab');\n old.forEach(function (el) { el.remove(); });\n\n if (sessions.size === 0) {\n emptyMsg.style.display = '';\n return;\n }\n emptyMsg.style.display = 'none';\n\n sessions.forEach(function (sess, sessionId) {\n var tab = document.createElement('button');\n tab.className = 'session-tab';\n if (sessionId === activeTabId) tab.classList.add('active');\n if (!sess.isActive) tab.classList.add('inactive');\n tab.dataset.sessionId = sessionId;\n\n // Tab label\n var lbl = document.createElement('span');\n lbl.textContent = sess.displayName || sessionId.slice(0, 8);\n tab.appendChild(lbl);\n\n // Agent count badge\n var badge = document.createElement('span');\n badge.className = 'tab-badge';\n badge.textContent = String(sess.agents.size);\n tab.appendChild(badge);\n\n // Meeting indicator\n if (sess.meeting) {\n var mb = document.createElement('span');\n mb.className = 'tab-badge meeting';\n mb.textContent = 'MTG';\n tab.appendChild(mb);\n }\n\n tab.addEventListener('click', function () {\n TabBar.switchTo(sessionId);\n });\n\n bar.appendChild(tab);\n });\n },\n\n switchTo: function (sessionId) {\n activeTabId = sessionId;\n selectedAgentId = null;\n SidebarPanel.clear();\n this.render();\n StatusBar.update();\n GraphRenderer.rebuild();\n },\n\n updateBadge: function (sessionId) {\n var bar = document.getElementById('tab-bar');\n var tabs = bar.querySelectorAll('.session-tab');\n tabs.forEach(function (tab) {\n if (tab.dataset.sessionId === sessionId) {\n var sess = sessions.get(sessionId);\n if (!sess) return;\n var badge = tab.querySelector('.tab-badge:not(.meeting)');\n if (badge) badge.textContent = String(sess.agents.size);\n }\n });\n },\n };\n\n // ====================================================================\n // 4. GRAPH RENDERER -- Cytoscape.js\n // ====================================================================\n var GraphRenderer = {\n cy: null,\n _layoutTimer: null,\n _animFrame: null,\n _dashOffset: 0,\n\n init: function () {\n this.cy = cytoscape({\n container: document.getElementById('cy'),\n style: [\n // --- NODES ---\n {\n selector: 'node',\n style: {\n 'label': 'data(label)',\n 'text-valign': 'bottom',\n 'text-halign': 'center',\n 'text-margin-y': 8,\n 'font-family': \"'JetBrains Mono', monospace\",\n 'font-size': 10,\n 'color': '#94a3b8',\n 'text-outline-width': 0,\n 'background-color': '#1e293b',\n 'border-width': 2,\n 'border-color': '#334155',\n 'width': 40,\n 'height': 40,\n 'transition-property': 'background-color, border-color, border-width, opacity, width, height',\n 'transition-duration': '0.3s',\n },\n },\n // Orchestrator\n {\n selector: 'node[tier=\"orchestrator\"]',\n style: {\n 'width': 60, 'height': 60,\n 'border-width': 3,\n 'border-color': '#00f0ff',\n 'background-color': 'rgba(0,240,255,0.1)',\n 'color': '#00f0ff',\n 'font-size': 12, 'font-weight': '700',\n 'text-outline-color': '#0a0e17',\n 'text-outline-width': 2,\n },\n },\n // Leader\n {\n selector: 'node[tier=\"leader\"]',\n style: {\n 'width': 48, 'height': 48,\n 'border-width': 2,\n 'border-color': '#a855f7',\n 'background-color': 'rgba(168,85,247,0.1)',\n 'color': '#a855f7',\n 'font-size': 11, 'font-weight': '600',\n },\n },\n // Worker\n {\n selector: 'node[tier=\"worker\"]',\n style: {\n 'width': 36, 'height': 36,\n 'border-width': 2,\n 'border-color': '#22d3ee',\n 'background-color': 'rgba(34,211,238,0.08)',\n 'color': '#22d3ee',\n 'font-size': 10,\n },\n },\n // Status: idle\n { selector: 'node[status=\"idle\"]', style: { 'opacity': 0.5, 'border-color': '#475569' } },\n // Status: working\n { selector: 'node[status=\"working\"]', style: { 'border-width': 3, 'opacity': 1 } },\n // Status: in-meeting\n { selector: 'node[status=\"in-meeting\"]', style: { 'border-color': '#f59e0b', 'background-color': 'rgba(245,158,11,0.1)', 'opacity': 1 } },\n // Status: spawning-workers\n { selector: 'node[status=\"spawning-workers\"]', style: { 'border-color': '#a855f7', 'opacity': 1 } },\n // Status: waiting-for-user\n { selector: 'node[status=\"waiting-for-user\"]', style: { 'border-color': '#f59e0b', 'opacity': 0.8 } },\n // Status: aggregating\n { selector: 'node[status=\"aggregating\"]', style: { 'border-color': '#22d3ee', 'opacity': 1 } },\n // Status: completed\n { selector: 'node[status=\"completed\"]', style: { 'border-color': '#10b981', 'background-color': 'rgba(16,185,129,0.1)', 'opacity': 0.7 } },\n // Status: failed\n { selector: 'node[status=\"failed\"]', style: { 'border-color': '#ef4444', 'background-color': 'rgba(239,68,68,0.1)', 'opacity': 0.8 } },\n // Selected node\n { selector: 'node:selected', style: { 'border-width': 4, 'overlay-padding': 6, 'overlay-color': '#00f0ff', 'overlay-opacity': 0.08 } },\n // --- EDGES ---\n {\n selector: 'edge',\n style: {\n 'width': 1.5,\n 'line-color': '#334155',\n 'target-arrow-color': '#334155',\n 'target-arrow-shape': 'triangle',\n 'arrow-scale': 0.8,\n 'curve-style': 'bezier',\n 'opacity': 0.5,\n 'transition-property': 'line-color, opacity, width',\n 'transition-duration': '0.3s',\n },\n },\n { selector: 'edge[edgeType=\"hierarchy\"][?active]', style: { 'line-color': '#475569', 'target-arrow-color': '#475569', 'line-style': 'solid', 'opacity': 0.6, 'width': 1.5 } },\n { selector: 'edge[edgeType=\"delegation\"]', style: { 'line-color': '#a855f7', 'target-arrow-color': '#a855f7', 'line-style': 'dashed', 'line-dash-pattern': [8, 4], 'opacity': 0.8, 'width': 2 } },\n { selector: 'edge[edgeType=\"report\"]', style: { 'line-color': '#10b981', 'target-arrow-color': '#10b981', 'opacity': 0.8, 'width': 2 } },\n { selector: 'edge[edgeType=\"message\"]', style: { 'line-color': '#22d3ee', 'target-arrow-color': '#22d3ee', 'line-style': 'dashed', 'line-dash-pattern': [6, 3], 'opacity': 0.7, 'width': 1.5 } },\n { selector: 'edge[edgeType=\"mention\"]', style: { 'line-color': '#ef4444', 'target-arrow-color': '#ef4444', 'line-style': 'dashed', 'line-dash-pattern': [4, 4], 'opacity': 0.9, 'width': 2.5 } },\n ],\n layout: { name: 'preset' },\n minZoom: 0.3,\n maxZoom: 3,\n wheelSensitivity: 0.3,\n });\n\n // Click handling\n this.cy.on('tap', 'node', function (evt) {\n var id = evt.target.id();\n selectedAgentId = id;\n SidebarPanel.show(id);\n });\n\n this.cy.on('tap', function (evt) {\n if (evt.target === GraphRenderer.cy) {\n selectedAgentId = null;\n SidebarPanel.clear();\n }\n });\n\n this.startAnimations();\n },\n\n rebuild: function () {\n if (!this.cy) return;\n this.cy.elements().remove();\n\n var sess = activeSession();\n if (!sess) return;\n\n sess.agents.forEach(function (agent) {\n GraphRenderer.cy.add({\n group: 'nodes',\n data: {\n id: agent.id,\n label: agent.label,\n tier: agent.type,\n status: agent.status,\n department: agent.department,\n },\n });\n });\n\n sess.edges.forEach(function (edge) {\n if (GraphRenderer.cy.getElementById(edge.source).length && GraphRenderer.cy.getElementById(edge.target).length) {\n GraphRenderer.cy.add({\n group: 'edges',\n data: {\n id: edge.id,\n source: edge.source,\n target: edge.target,\n edgeType: edge.edgeType,\n active: edge.active,\n },\n });\n }\n });\n\n this.runLayout();\n },\n\n runLayout: function () {\n if (!this.cy || this.cy.nodes().length === 0) return;\n this.cy.layout({\n name: 'dagre',\n rankDir: 'TB',\n rankSep: 80,\n nodeSep: 40,\n edgeSep: 20,\n animate: true,\n animationDuration: 500,\n animationEasing: 'ease-out',\n padding: 40,\n }).run();\n },\n\n startAnimations: function () {\n var self = this;\n var animate = function () {\n self._dashOffset += 0.5;\n if (self.cy) {\n self.cy.edges('[edgeType=\"delegation\"], [edgeType=\"message\"], [edgeType=\"mention\"]').forEach(function (edge) {\n edge.style('line-dash-offset', -self._dashOffset);\n });\n\n var t = Date.now();\n self.cy.nodes('[status=\"working\"]').forEach(function (node) {\n var glow = 2 + Math.sin(t / 400) * 1;\n node.style('border-width', glow);\n });\n self.cy.nodes('[status=\"in-meeting\"]').forEach(function (node) {\n var op = 0.4 + (Math.sin(t / 1000) + 1) * 0.3;\n node.style('opacity', op);\n });\n self.cy.nodes('[status=\"waiting-for-user\"]').forEach(function (node) {\n var op = 0.5 + (Math.sin(t / 1500) + 1) * 0.25;\n node.style('opacity', op);\n });\n self.cy.nodes('[status=\"spawning-workers\"]').forEach(function (node) {\n var c = Math.sin(t / 600) > 0 ? '#a855f7' : '#22d3ee';\n node.style('border-color', c);\n });\n }\n self._animFrame = requestAnimationFrame(animate);\n };\n self._animFrame = requestAnimationFrame(animate);\n },\n };\n\n // ====================================================================\n // 5. SIDEBAR PANEL\n // ====================================================================\n var SidebarPanel = {\n show: function (agentId) {\n var sess = activeSession();\n if (!sess) { this.clear(); return; }\n var agent = sess.agents.get(agentId);\n if (!agent) { this.clear(); return; }\n\n document.getElementById('sidebar-empty').style.display = 'none';\n var el = document.getElementById('sidebar-content');\n el.style.display = 'block';\n\n // Children\n var children = [];\n sess.agents.forEach(function (a) {\n if (a.parentId === agentId) children.push(a);\n });\n\n // Recent events for this agent\n var recentEvents = sess.eventHistory\n .filter(function (ev) { return ev.agentId === agentId || ev.fromId === agentId || ev.toId === agentId; })\n .slice(-10)\n .reverse();\n\n var tierIcon = agent.type === 'orchestrator' ? '&#x1F3AF;' : agent.type === 'leader' ? '&#x1F451;' : '&#x2699;&#xFE0F;';\n\n el.innerHTML =\n '<div style=\"text-align:center;margin-bottom:8px;\">' +\n '<span style=\"font-size:28px;\">' + tierIcon + '</span>' +\n '<div style=\"font-size:14px;font-weight:700;color:var(--cyan);margin-top:4px;\">' + escHtml(agent.label) + '</div>' +\n '<div style=\"font-size:11px;color:var(--text2);\">' + escHtml(agent.id) + '</div>' +\n '</div>' +\n '<div class=\"detail-row\"><span class=\"label\">Type</span><span class=\"value\">' + agent.type + '</span></div>' +\n '<div class=\"detail-row\"><span class=\"label\">Department</span><span class=\"value\">' + escHtml(agent.department) + '</span></div>' +\n '<div class=\"detail-row\"><span class=\"label\">Status</span><span class=\"value\"><span class=\"status-chip ' + agent.status + '\">' + agent.status + '</span></span></div>' +\n '<div class=\"detail-row\"><span class=\"label\">Cost</span><span class=\"value\">$' + agent.costUsd.toFixed(4) + '</span></div>' +\n '<div class=\"detail-row\"><span class=\"label\">Workers</span><span class=\"value\">' + children.length + '</span></div>' +\n (agent.currentTask\n ? '<h2 style=\"margin-top:12px;\">Current Task</h2><div class=\"task-block\">' + escHtml(agent.currentTask) + '</div>'\n : '') +\n (children.length > 0\n ? '<h2 style=\"margin-top:12px;\">Children</h2><ul class=\"children-list\">' +\n children.map(function (c) { return '<li>' + escHtml(c.label) + ' <span class=\"status-chip ' + c.status + '\" style=\"font-size:10px;\">' + c.status + '</span></li>'; }).join('') +\n '</ul>'\n : '') +\n (recentEvents.length > 0\n ? '<h2 style=\"margin-top:12px;\">Recent Activity</h2><div id=\"task-history\">' +\n recentEvents.map(function (ev) { return '<div class=\"history-item\">' + summarizeEventShort(ev) + '</div>'; }).join('') +\n '</div>'\n : '');\n },\n\n clear: function () {\n document.getElementById('sidebar-empty').style.display = 'block';\n document.getElementById('sidebar-content').style.display = 'none';\n },\n };\n\n // ====================================================================\n // 6. EVENT LOG\n // ====================================================================\n var EventLog = {\n el: null,\n pauseEl: null,\n autoScroll: true,\n maxEntries: 500,\n\n init: function () {\n this.el = document.getElementById('log-entries');\n this.pauseEl = document.getElementById('log-pause');\n var self = this;\n this.el.addEventListener('scroll', function () {\n var atBottom = self.el.scrollHeight - self.el.scrollTop - self.el.clientHeight < 30;\n self.autoScroll = atBottom;\n self.pauseEl.classList.toggle('visible', !atBottom);\n });\n },\n\n append: function (sessionId, displayName, ev) {\n var row = document.createElement('div');\n row.className = 'log-entry';\n\n var now = new Date();\n var ts = pad2(now.getHours()) + ':' + pad2(now.getMinutes()) + ':' + pad2(now.getSeconds());\n\n var kindLabel = '';\n var kindClass = '';\n var message = '';\n\n switch (ev.kind) {\n case 'agent_spawned':\n kindLabel = 'SPAWN'; kindClass = 'spawn';\n message = '<b>' + escHtml(ev.label) + '</b> (' + ev.agentType + ') in ' + escHtml(ev.department);\n break;\n case 'agent_destroyed':\n kindLabel = 'DESTROY'; kindClass = 'destroy';\n message = escHtml(ev.agentId);\n break;\n case 'state_changed':\n kindLabel = 'STATE'; kindClass = 'state';\n message = escHtml(ev.agentId) + ': ' + ev.from + ' &#x2192; ' + ev.to;\n break;\n case 'task_assigned':\n kindLabel = 'TASK'; kindClass = 'task';\n message = escHtml(ev.agentId) + ': ' + escHtml(ev.taskSummary);\n break;\n case 'task_completed':\n kindLabel = ev.result === 'success' ? 'SUCCESS' : 'FAILED';\n kindClass = ev.result === 'success' ? 'done' : 'destroy';\n message = escHtml(ev.agentId);\n break;\n case 'message_sent':\n kindLabel = 'MSG'; kindClass = 'msg';\n message = escHtml(ev.fromId) + ' &#x2192; ' + escHtml(ev.toId) + ': ' + escHtml(ev.summary);\n break;\n case 'mention_created':\n kindLabel = '@MENTION'; kindClass = 'mention';\n message = escHtml(ev.summary) + ' [' + ev.urgency + ']';\n break;\n case 'mention_resolved':\n kindLabel = '@RESOLVED'; kindClass = 'resolved';\n message = escHtml(ev.mentionId) + ': ' + escHtml(ev.decision);\n break;\n case 'cost_update':\n kindLabel = 'COST'; kindClass = 'cost';\n message = 'Total: $' + ev.totalCost.toFixed(4);\n break;\n default:\n kindLabel = 'EVENT'; kindClass = '';\n message = JSON.stringify(ev);\n }\n\n row.innerHTML =\n '<span class=\"log-time\">' + ts + '</span>' +\n '<span class=\"log-session\">' + escHtml(displayName) + '</span>' +\n '<span class=\"log-kind ' + kindClass + '\">' + kindLabel + '</span>' +\n '<span class=\"log-msg\">' + message + '</span>';\n\n this.el.appendChild(row);\n\n while (this.el.children.length > this.maxEntries) {\n this.el.removeChild(this.el.firstChild);\n }\n\n if (this.autoScroll) {\n this.el.scrollTop = this.el.scrollHeight;\n }\n },\n\n appendSystem: function (displayName, message) {\n var row = document.createElement('div');\n row.className = 'log-entry';\n var now = new Date();\n var ts = pad2(now.getHours()) + ':' + pad2(now.getMinutes()) + ':' + pad2(now.getSeconds());\n row.innerHTML =\n '<span class=\"log-time\">' + ts + '</span>' +\n '<span class=\"log-session\">' + escHtml(displayName) + '</span>' +\n '<span class=\"log-kind session\">SESSION</span>' +\n '<span class=\"log-msg\">' + escHtml(message) + '</span>';\n this.el.appendChild(row);\n if (this.autoScroll) this.el.scrollTop = this.el.scrollHeight;\n },\n };\n\n // ====================================================================\n // 7. STATUS BAR\n // ====================================================================\n var StatusBar = {\n update: function () {\n // Session count\n var totalSessions = sessions.size;\n var activeSessions = 0;\n sessions.forEach(function (s) { if (s.isActive) activeSessions++; });\n document.getElementById('badge-sessions').textContent = activeSessions + '/' + totalSessions + ' sessions';\n\n // Agent count + meeting + cost for active tab\n var sess = activeSession();\n if (sess) {\n document.getElementById('badge-agents').textContent = sess.agents.size + ' agent' + (sess.agents.size !== 1 ? 's' : '');\n\n if (sess.meeting) {\n document.getElementById('badge-meeting').textContent = sess.meeting.phase;\n document.getElementById('badge-meeting').className = 'badge amber';\n } else {\n document.getElementById('badge-meeting').textContent = 'No meeting';\n document.getElementById('badge-meeting').className = 'badge purple';\n }\n\n document.getElementById('badge-cost').textContent = '$' + sess.totalCost.toFixed(4);\n } else {\n document.getElementById('badge-agents').textContent = '0 agents';\n document.getElementById('badge-meeting').textContent = 'No meeting';\n document.getElementById('badge-meeting').className = 'badge purple';\n document.getElementById('badge-cost').textContent = '$0.0000';\n }\n },\n };\n\n // ====================================================================\n // HELPERS\n // ====================================================================\n function escHtml(str) {\n if (typeof str !== 'string') return String(str || '');\n return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');\n }\n\n function pad2(n) {\n return n < 10 ? '0' + n : String(n);\n }\n\n function summarizeEventShort(ev) {\n switch (ev.kind) {\n case 'agent_spawned': return 'Spawned: ' + escHtml(ev.label);\n case 'agent_destroyed': return 'Destroyed';\n case 'state_changed': return ev.from + ' &#x2192; ' + ev.to;\n case 'task_assigned': return 'Task: ' + escHtml(ev.taskSummary);\n case 'task_completed': return 'Completed: ' + ev.result;\n case 'message_sent': return 'Msg to ' + escHtml(ev.toId);\n case 'mention_created': return '@mention: ' + escHtml(ev.summary);\n case 'mention_resolved': return '@resolved: ' + escHtml(ev.decision);\n case 'cost_update': return 'Cost: $' + ev.totalCost.toFixed(4);\n default: return ev.kind;\n }\n }\n\n // ====================================================================\n // BOOT\n // ====================================================================\n document.addEventListener('DOMContentLoaded', function () {\n GraphRenderer.init();\n EventLog.init();\n StatusBar.update();\n ConnectionManager.connect();\n });\n\n})();\n</script>\n</body>\n</html>`;\n}\n","/**\n * StateBridge — manages per-session state and emits 'broadcast' events\n * for the dashboard server to relay to browser WebSocket clients.\n *\n * Supports multiple sessions (one per MCP server instance). Each session\n * tracks its own agent graph independently. Disconnected sessions are kept\n * (grayed-out tab) rather than deleted.\n */\n\nimport { EventEmitter } from 'node:events';\nimport type {\n AgentState,\n EdgeState,\n MeetingState,\n AgentEvent,\n MultiSessionSnapshot,\n SessionDelta,\n} from '../types/dashboard-events.js';\nimport { logger } from '../utils/logger.js';\n\n// ---------------------------------------------------------------------------\n// Per-session state container\n// ---------------------------------------------------------------------------\n\ninterface SessionState {\n projectName: string;\n displayName: string;\n projectPath: string;\n isActive: boolean;\n agents: Map<string, AgentState>;\n edges: EdgeState[];\n meeting: MeetingState | null;\n totalCost: number;\n eventLog: Array<{ timestamp: number; event: AgentEvent }>;\n}\n\n// ---------------------------------------------------------------------------\n// StateBridge\n// ---------------------------------------------------------------------------\n\nexport class StateBridge extends EventEmitter {\n private sessions = new Map<string, SessionState>();\n private debounceTimers = new Map<string, NodeJS.Timeout>();\n private pendingEvents = new Map<string, AgentEvent[]>();\n\n // -----------------------------------------------------------------------\n // Session lifecycle\n // -----------------------------------------------------------------------\n\n registerSession(info: {\n sessionId: string;\n projectPath: string;\n projectName: string;\n }): string {\n const displayName = this.getUniqueDisplayName(info.projectName);\n\n this.sessions.set(info.sessionId, {\n projectName: info.projectName,\n displayName,\n projectPath: info.projectPath,\n isActive: true,\n agents: new Map(),\n edges: [],\n meeting: null,\n totalCost: 0,\n eventLog: [],\n });\n\n logger.info(`Session registered: ${displayName} (${info.sessionId})`);\n\n // Notify browser clients about the new session\n this.emit(\n 'broadcast',\n JSON.stringify({\n type: 'session-registered',\n sessionId: info.sessionId,\n displayName,\n projectPath: info.projectPath,\n }),\n );\n\n return displayName;\n }\n\n unregisterSession(sessionId: string): void {\n const session = this.sessions.get(sessionId);\n if (session) {\n session.isActive = false;\n logger.info(`Session deactivated: ${session.displayName}`);\n\n // Don't delete — keep for display (grayed-out tab)\n this.emit(\n 'broadcast',\n JSON.stringify({\n type: 'session-unregistered',\n sessionId,\n }),\n );\n }\n }\n\n // -----------------------------------------------------------------------\n // Event handling\n // -----------------------------------------------------------------------\n\n handleSessionEvent(sessionId: string, event: AgentEvent): void {\n const session = this.sessions.get(sessionId);\n if (!session) return;\n\n // Apply event to session state\n this.applyEvent(session, event);\n\n // Queue for debounced broadcast\n if (!this.pendingEvents.has(sessionId)) {\n this.pendingEvents.set(sessionId, []);\n }\n this.pendingEvents.get(sessionId)!.push(event);\n\n // Debounce broadcast per session (100ms)\n if (!this.debounceTimers.has(sessionId)) {\n this.debounceTimers.set(\n sessionId,\n setTimeout(() => {\n this.flushEvents(sessionId);\n this.debounceTimers.delete(sessionId);\n }, 100),\n );\n }\n }\n\n // -----------------------------------------------------------------------\n // Snapshot (sent to newly connected browser clients)\n // -----------------------------------------------------------------------\n\n getSnapshot(): MultiSessionSnapshot {\n return {\n type: 'multi-snapshot',\n sessions: Array.from(this.sessions.entries()).map(([sessionId, s]) => ({\n sessionId,\n displayName: s.displayName,\n projectPath: s.projectPath,\n isActive: s.isActive,\n snapshot: {\n agents: Array.from(s.agents.values()),\n edges: [...s.edges],\n meeting: s.meeting,\n totalCost: s.totalCost,\n },\n })),\n };\n }\n\n // -----------------------------------------------------------------------\n // Private — unique display name\n // -----------------------------------------------------------------------\n\n private getUniqueDisplayName(projectName: string): string {\n const existing = Array.from(this.sessions.values()).map(\n (s) => s.displayName,\n );\n if (!existing.includes(projectName)) return projectName;\n let i = 1;\n while (existing.includes(`${projectName} (${i})`)) i++;\n return `${projectName} (${i})`;\n }\n\n // -----------------------------------------------------------------------\n // Private — state mutations (scoped to a session)\n // -----------------------------------------------------------------------\n\n private applyEvent(session: SessionState, event: AgentEvent): void {\n session.eventLog.push({ timestamp: Date.now(), event });\n // Keep log bounded\n if (session.eventLog.length > 500) session.eventLog.shift();\n\n switch (event.kind) {\n case 'agent_spawned': {\n const agent: AgentState = {\n id: event.agentId,\n type: event.agentType,\n label: event.label,\n status: 'idle',\n parentId: event.parentId,\n department: event.department,\n currentTask: null,\n costUsd: 0,\n };\n session.agents.set(event.agentId, agent);\n\n if (event.parentId) {\n session.edges.push({\n id: `edge-${event.parentId}-${event.agentId}`,\n source: event.parentId,\n target: event.agentId,\n edgeType: 'hierarchy',\n active: true,\n label: '',\n });\n }\n break;\n }\n\n case 'agent_destroyed': {\n session.agents.delete(event.agentId);\n session.edges = session.edges.filter(\n (e) => e.source !== event.agentId && e.target !== event.agentId,\n );\n break;\n }\n\n case 'state_changed': {\n const a = session.agents.get(event.agentId);\n if (a) a.status = event.to;\n break;\n }\n\n case 'task_assigned': {\n const a = session.agents.get(event.agentId);\n if (a) {\n a.currentTask = event.taskSummary;\n a.status = 'working';\n }\n break;\n }\n\n case 'task_completed': {\n const a = session.agents.get(event.agentId);\n if (a) {\n a.currentTask = null;\n a.status = event.result === 'success' ? 'completed' : 'failed';\n }\n break;\n }\n\n case 'message_sent': {\n const edgeId = `msg-${event.fromId}-${event.toId}-${Date.now()}`;\n session.edges.push({\n id: edgeId,\n source: event.fromId,\n target: event.toId,\n edgeType: 'message',\n active: true,\n label: event.summary,\n });\n // Remove transient message edges after 5 seconds\n setTimeout(() => {\n session.edges = session.edges.filter((e) => e.id !== edgeId);\n }, 5_000);\n break;\n }\n\n case 'mention_created':\n case 'mention_resolved':\n // Logged but don't mutate the agent graph.\n break;\n\n case 'cost_update': {\n session.totalCost = event.totalCost;\n break;\n }\n }\n }\n\n // -----------------------------------------------------------------------\n // Private — flush debounced events\n // -----------------------------------------------------------------------\n\n private flushEvents(sessionId: string): void {\n const events = this.pendingEvents.get(sessionId);\n const session = this.sessions.get(sessionId);\n if (!events || !session || events.length === 0) return;\n\n const delta: SessionDelta = {\n type: 'session-delta',\n sessionId,\n displayName: session.displayName,\n timestamp: Date.now(),\n events: [...events],\n };\n\n this.emit('broadcast', JSON.stringify(delta));\n this.pendingEvents.set(sessionId, []);\n }\n}\n","import WebSocket from 'ws';\nimport type { AgentEvent, RegisterMessage, SessionEventMessage, UnregisterMessage } from '../types/dashboard-events.js';\nimport { eventBus } from '../orchestrator/event-bus.js';\nimport { logger } from '../utils/logger.js';\n\nexport class DashboardClient {\n private ws: WebSocket | null = null;\n private sessionId: string;\n private projectName: string;\n private projectPath: string;\n\n constructor(sessionId: string, projectName: string, projectPath: string) {\n this.sessionId = sessionId;\n this.projectName = projectName;\n this.projectPath = projectPath;\n }\n\n connect(port: number): void {\n this.ws = new WebSocket(`ws://127.0.0.1:${port}`);\n\n this.ws.on('open', () => {\n logger.info(`Connected to dashboard as client (session: ${this.sessionId})`);\n // Register this session\n const msg: RegisterMessage = {\n type: 'register',\n sessionId: this.sessionId,\n projectPath: this.projectPath,\n projectName: this.projectName,\n };\n this.ws!.send(JSON.stringify(msg));\n\n // Forward local events to the dashboard server\n eventBus.on('agent_event', (event: AgentEvent) => {\n if (this.ws?.readyState === WebSocket.OPEN) {\n const sessionMsg: SessionEventMessage = {\n type: 'session-event',\n sessionId: this.sessionId,\n event,\n };\n this.ws.send(JSON.stringify(sessionMsg));\n }\n });\n });\n\n this.ws.on('error', (err) => {\n logger.warn(`Dashboard client error: ${err.message}`);\n });\n\n this.ws.on('close', () => {\n logger.info('Dashboard client disconnected');\n });\n }\n\n disconnect(): void {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n const msg: UnregisterMessage = {\n type: 'unregister',\n sessionId: this.sessionId,\n };\n this.ws.send(JSON.stringify(msg));\n this.ws.close();\n }\n this.ws = null;\n }\n}\n"],"mappings":";;;;;;AAAA,SAAS,kBAAkB;AAC3B,SAAS,4BAA4B;;;ACDrC,SAAS,iBAAiB;;;ACA1B,SAAS,SAAS;;;ACAlB,SAAS,MAAMA,eAAc;;;ACA7B,SAAS,MAAM,cAAc;AAmB7B,SAAS,WAAW,KAA0B;AAC5C,SAAO;AAAA,IACL,IAAI,IAAI;AAAA,IACR,MAAM,IAAI;AAAA,IACV,MAAM,IAAI;AAAA,IACV,YAAY,IAAI;AAAA,IAChB,UAAU,IAAI;AAAA,IACd,WAAW,IAAI;AAAA,IACf,QAAQ,IAAI;AAAA,IACZ,aAAa,IAAI;AAAA,IACjB,WAAW,IAAI;AAAA,IACf,WAAW,IAAI;AAAA,IACf,aAAa,IAAI;AAAA,IACjB,SAAS,IAAI;AAAA,EACf;AACF;AAEO,SAAS,YACd,OAMW;AACX,QAAM,KAAK,MAAM;AACjB,QAAM,KAAK,MAAM,MAAM,OAAO;AAC9B,QAAM,YAAY,MAAM,aAAa,KAAK,IAAI;AAC9C,QAAM,cAAc,MAAM,eAAe;AACzC,QAAM,UAAU,MAAM,WAAW;AAEjC,KAAG;AAAA,IACD;AAAA;AAAA,EAEF,EAAE;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,MAAM,MAAM;AAAA,IACZ,MAAM,MAAM;AAAA,IACZ,YAAY,MAAM;AAAA,IAClB,UAAU,MAAM;AAAA,IAChB,WAAW,MAAM;AAAA,IACjB,QAAQ,MAAM;AAAA,IACd,aAAa,MAAM;AAAA,IACnB,WAAW,MAAM;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,SAAS,IAA8B;AACrD,QAAM,KAAK,MAAM;AACjB,QAAM,MAAM,GAAG,QAAQ,mCAAmC,EAAE,IAAI,EAAE;AAClE,SAAO,MAAM,WAAW,GAAG,IAAI;AACjC;AAEO,SAAS,YACd,IACA,SACkB;AAClB,QAAM,KAAK,MAAM;AACjB,QAAM,WAAW,SAAS,EAAE;AAC5B,MAAI,CAAC,SAAU,QAAO;AAEtB,QAAM,SAAmB,CAAC;AAC1B,QAAM,SAAoB,CAAC;AAE3B,MAAI,QAAQ,SAAS,QAAW;AAAE,WAAO,KAAK,UAAU;AAAG,WAAO,KAAK,QAAQ,IAAI;AAAA,EAAG;AACtF,MAAI,QAAQ,SAAS,QAAW;AAAE,WAAO,KAAK,UAAU;AAAG,WAAO,KAAK,QAAQ,IAAI;AAAA,EAAG;AACtF,MAAI,QAAQ,eAAe,QAAW;AAAE,WAAO,KAAK,gBAAgB;AAAG,WAAO,KAAK,QAAQ,UAAU;AAAA,EAAG;AACxG,MAAI,QAAQ,aAAa,QAAW;AAAE,WAAO,KAAK,eAAe;AAAG,WAAO,KAAK,QAAQ,QAAQ;AAAA,EAAG;AACnG,MAAI,QAAQ,cAAc,QAAW;AAAE,WAAO,KAAK,gBAAgB;AAAG,WAAO,KAAK,QAAQ,SAAS;AAAA,EAAG;AACtG,MAAI,QAAQ,WAAW,QAAW;AAAE,WAAO,KAAK,YAAY;AAAG,WAAO,KAAK,QAAQ,MAAM;AAAA,EAAG;AAC5F,MAAI,QAAQ,gBAAgB,QAAW;AAAE,WAAO,KAAK,kBAAkB;AAAG,WAAO,KAAK,QAAQ,WAAW;AAAA,EAAG;AAC5G,MAAI,QAAQ,cAAc,QAAW;AAAE,WAAO,KAAK,gBAAgB;AAAG,WAAO,KAAK,QAAQ,SAAS;AAAA,EAAG;AACtG,MAAI,QAAQ,cAAc,QAAW;AAAE,WAAO,KAAK,gBAAgB;AAAG,WAAO,KAAK,QAAQ,SAAS;AAAA,EAAG;AACtG,MAAI,QAAQ,gBAAgB,QAAW;AAAE,WAAO,KAAK,kBAAkB;AAAG,WAAO,KAAK,QAAQ,WAAW;AAAA,EAAG;AAC5G,MAAI,QAAQ,YAAY,QAAW;AAAE,WAAO,KAAK,cAAc;AAAG,WAAO,KAAK,QAAQ,OAAO;AAAA,EAAG;AAEhG,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,SAAO,KAAK,EAAE;AACd,KAAG,QAAQ,qBAAqB,OAAO,KAAK,IAAI,CAAC,eAAe,EAAE,IAAI,GAAG,MAAM;AAE/E,SAAO,SAAS,EAAE;AACpB;AAEO,SAAS,oBAAoB,WAAgC;AAClE,QAAM,KAAK,MAAM;AACjB,QAAM,OAAO,GACV,QAAQ,2CAA2C,EACnD,IAAI,SAAS;AAChB,SAAO,KAAK,IAAI,UAAU;AAC5B;AAEO,SAAS,mBAAmB,UAA+B;AAChE,QAAM,KAAK,MAAM;AACjB,QAAM,OAAO,GACV,QAAQ,0CAA0C,EAClD,IAAI,QAAQ;AACf,SAAO,KAAK,IAAI,UAAU;AAC5B;AAMO,SAAS,aAAa,QAAsC;AACjE,QAAM,QAAQ,SAAS,MAAM;AAC7B,MAAI,CAAC,MAAO,QAAO;AAEnB,QAAM,WAAW,mBAAmB,MAAM;AAC1C,QAAM,WAA0B;AAAA,IAC9B,GAAG;AAAA,IACH,UAAU,SACP,IAAI,CAAC,UAAU,aAAa,MAAM,EAAE,CAAC,EACrC,OAAO,CAAC,SAAgC,SAAS,IAAI;AAAA,EAC1D;AAEA,SAAO;AACT;;;AC1JA,SAAS,MAAMC,eAAc;AAkB7B,SAAS,gCAAsC;AAC7C,QAAM,KAAK,MAAM;AAEjB,QAAM,OAAO,GAAG,QAAQ,+BAA+B,EAAE,IAAI;AAC7D,QAAM,YAAY,KAAK,KAAK,CAAC,MAAM,EAAE,SAAS,qBAAqB;AACnE,MAAI,CAAC,WAAW;AACd,OAAG,KAAK,uEAAuE;AAAA,EACjF;AACF;AAEA,IAAI,gBAAgB;AAEpB,SAAS,aAAa,KAA0B;AAC9C,SAAO;AAAA,IACL,IAAI,IAAI;AAAA,IACR,OAAO,IAAI;AAAA,IACX,QAAQ,KAAK,MAAM,IAAI,MAAM;AAAA,IAC7B,gBAAgB,KAAK,MAAM,IAAI,eAAe;AAAA,IAC9C,QAAQ,IAAI;AAAA,IACZ,OAAO,IAAI;AAAA,IACX,WAAW,IAAI;AAAA,IACf,aAAa,IAAI;AAAA,IACjB,aAAa,IAAI;AAAA,IACjB,mBAAmB,IAAI,uBAAuB;AAAA,EAChD;AACF;AAEO,SAAS,cACd,SAQS;AACT,MAAI,CAAC,eAAe;AAClB,kCAA8B;AAC9B,oBAAgB;AAAA,EAClB;AAEA,QAAM,KAAK,MAAM;AACjB,QAAM,KAAK,QAAQ,MAAMC,QAAO;AAChC,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,cAAc,QAAQ,eAAe;AAC3C,QAAM,oBAAoB,QAAQ,qBAAqB;AAEvD,KAAG;AAAA,IACD;AAAA;AAAA,EAEF,EAAE;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,KAAK,UAAU,QAAQ,MAAM;AAAA,IAC7B,KAAK,UAAU,QAAQ,cAAc;AAAA,IACrC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,OAAO,QAAQ;AAAA,IACf,QAAQ,QAAQ;AAAA,IAChB,gBAAgB,QAAQ;AAAA,IACxB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa,QAAQ;AAAA,IACrB;AAAA,EACF;AACF;AAEO,SAAS,WAAW,IAA4B;AACrD,MAAI,CAAC,eAAe;AAClB,kCAA8B;AAC9B,oBAAgB;AAAA,EAClB;AAEA,QAAM,KAAK,MAAM;AACjB,QAAM,MAAM,GAAG,QAAQ,qCAAqC,EAAE,IAAI,EAAE;AACpE,SAAO,MAAM,aAAa,GAAG,IAAI;AACnC;AAEO,SAAS,cACd,IACA,SACgB;AAChB,QAAM,KAAK,MAAM;AACjB,QAAM,WAAW,WAAW,EAAE;AAC9B,MAAI,CAAC,SAAU,QAAO;AAEtB,QAAM,SAAmB,CAAC;AAC1B,QAAM,SAAoB,CAAC;AAE3B,MAAI,QAAQ,UAAU,QAAW;AAAE,WAAO,KAAK,WAAW;AAAG,WAAO,KAAK,QAAQ,KAAK;AAAA,EAAG;AACzF,MAAI,QAAQ,WAAW,QAAW;AAAE,WAAO,KAAK,YAAY;AAAG,WAAO,KAAK,KAAK,UAAU,QAAQ,MAAM,CAAC;AAAA,EAAG;AAC5G,MAAI,QAAQ,mBAAmB,QAAW;AAAE,WAAO,KAAK,qBAAqB;AAAG,WAAO,KAAK,KAAK,UAAU,QAAQ,cAAc,CAAC;AAAA,EAAG;AACrI,MAAI,QAAQ,WAAW,QAAW;AAAE,WAAO,KAAK,YAAY;AAAG,WAAO,KAAK,QAAQ,MAAM;AAAA,EAAG;AAC5F,MAAI,QAAQ,UAAU,QAAW;AAAE,WAAO,KAAK,WAAW;AAAG,WAAO,KAAK,QAAQ,KAAK;AAAA,EAAG;AACzF,MAAI,QAAQ,cAAc,QAAW;AAAE,WAAO,KAAK,gBAAgB;AAAG,WAAO,KAAK,QAAQ,SAAS;AAAA,EAAG;AACtG,MAAI,QAAQ,gBAAgB,QAAW;AAAE,WAAO,KAAK,kBAAkB;AAAG,WAAO,KAAK,QAAQ,WAAW;AAAA,EAAG;AAC5G,MAAI,QAAQ,gBAAgB,QAAW;AAAE,WAAO,KAAK,kBAAkB;AAAG,WAAO,KAAK,QAAQ,WAAW;AAAA,EAAG;AAC5G,MAAI,QAAQ,sBAAsB,QAAW;AAAE,WAAO,KAAK,yBAAyB;AAAG,WAAO,KAAK,QAAQ,iBAAiB;AAAA,EAAG;AAE/H,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,SAAO,KAAK,EAAE;AACd,KAAG,QAAQ,uBAAuB,OAAO,KAAK,IAAI,CAAC,eAAe,EAAE,IAAI,GAAG,MAAM;AAEjF,SAAO,WAAW,EAAE;AACtB;AAEO,SAAS,aAAa,cAAyC;AACpE,MAAI,CAAC,eAAe;AAClB,kCAA8B;AAC9B,oBAAgB;AAAA,EAClB;AAEA,QAAM,KAAK,MAAM;AACjB,MAAI;AAEJ,MAAI,cAAc;AAChB,WAAO,GACJ,QAAQ,kEAAkE,EAC1E,IAAI,YAAY;AAAA,EACrB,OAAO;AACL,WAAO,GACJ,QAAQ,iDAAiD,EACzD,IAAI;AAAA,EACT;AAEA,SAAO,KAAK,IAAI,YAAY;AAC9B;;;AC9JA,SAAS,MAAMC,eAAc;AAoB7B,SAAS,YAAY,KAA8B;AACjD,SAAO;AAAA,IACL,IAAI,IAAI;AAAA,IACR,UAAU,IAAI;AAAA,IACd,WAAW,IAAI;AAAA,IACf,iBAAiB,IAAI;AAAA,IACrB,UAAU,IAAI;AAAA,IACd,QAAQ,IAAI;AAAA,IACZ,cAAc,IAAI;AAAA,IAClB,cAAc,IAAI;AAAA,IAClB,cAAc,IAAI;AAAA,IAClB,cAAc,KAAK,MAAM,IAAI,YAAY;AAAA,IACzC,WAAW,IAAI;AAAA,IACf,aAAa,IAAI;AAAA,IACjB,SAAS,IAAI;AAAA,EACf;AACF;AAsDO,SAAS,UAAU,IAAiC;AACzD,QAAM,KAAK,MAAM;AACjB,QAAM,MAAM,GAAG,QAAQ,oCAAoC,EAAE,IAAI,EAAE;AACnE,SAAO,MAAM,YAAY,GAAG,IAAI;AAClC;AAEO,SAAS,aACd,IACA,SACqB;AACrB,QAAM,KAAK,MAAM;AACjB,QAAM,WAAW,UAAU,EAAE;AAC7B,MAAI,CAAC,SAAU,QAAO;AAEtB,QAAM,SAAmB,CAAC;AAC1B,QAAM,SAAoB,CAAC;AAE3B,MAAI,QAAQ,aAAa,QAAW;AAAE,WAAO,KAAK,eAAe;AAAG,WAAO,KAAK,QAAQ,QAAQ;AAAA,EAAG;AACnG,MAAI,QAAQ,cAAc,QAAW;AAAE,WAAO,KAAK,gBAAgB;AAAG,WAAO,KAAK,QAAQ,SAAS;AAAA,EAAG;AACtG,MAAI,QAAQ,oBAAoB,QAAW;AAAE,WAAO,KAAK,sBAAsB;AAAG,WAAO,KAAK,QAAQ,eAAe;AAAA,EAAG;AACxH,MAAI,QAAQ,aAAa,QAAW;AAAE,WAAO,KAAK,eAAe;AAAG,WAAO,KAAK,QAAQ,QAAQ;AAAA,EAAG;AACnG,MAAI,QAAQ,WAAW,QAAW;AAAE,WAAO,KAAK,YAAY;AAAG,WAAO,KAAK,QAAQ,MAAM;AAAA,EAAG;AAC5F,MAAI,QAAQ,iBAAiB,QAAW;AAAE,WAAO,KAAK,mBAAmB;AAAG,WAAO,KAAK,QAAQ,YAAY;AAAA,EAAG;AAC/G,MAAI,QAAQ,iBAAiB,QAAW;AAAE,WAAO,KAAK,mBAAmB;AAAG,WAAO,KAAK,QAAQ,YAAY;AAAA,EAAG;AAC/G,MAAI,QAAQ,iBAAiB,QAAW;AAAE,WAAO,KAAK,mBAAmB;AAAG,WAAO,KAAK,QAAQ,YAAY;AAAA,EAAG;AAC/G,MAAI,QAAQ,iBAAiB,QAAW;AAAE,WAAO,KAAK,kBAAkB;AAAG,WAAO,KAAK,KAAK,UAAU,QAAQ,YAAY,CAAC;AAAA,EAAG;AAC9H,MAAI,QAAQ,cAAc,QAAW;AAAE,WAAO,KAAK,gBAAgB;AAAG,WAAO,KAAK,QAAQ,SAAS;AAAA,EAAG;AACtG,MAAI,QAAQ,gBAAgB,QAAW;AAAE,WAAO,KAAK,kBAAkB;AAAG,WAAO,KAAK,QAAQ,WAAW;AAAA,EAAG;AAC5G,MAAI,QAAQ,YAAY,QAAW;AAAE,WAAO,KAAK,cAAc;AAAG,WAAO,KAAK,QAAQ,OAAO;AAAA,EAAG;AAEhG,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,SAAO,KAAK,EAAE;AACd,KAAG,QAAQ,sBAAsB,OAAO,KAAK,IAAI,CAAC,eAAe,EAAE,IAAI,GAAG,MAAM;AAEhF,SAAO,UAAU,EAAE;AACrB;AAEO,SAAS,oBAAoB,UAAkC;AACpE,QAAM,KAAK,MAAM;AACjB,QAAM,OAAO,GACV,QAAQ,mEAAmE,EAC3E,IAAI,QAAQ;AACf,SAAO,KAAK,IAAI,WAAW;AAC7B;;;ACtIA,SAAS,MAAMC,eAAc;AAkB7B,SAAS,aAAa,KAAgC;AACpD,SAAO;AAAA,IACL,IAAI,IAAI;AAAA,IACR,WAAW,IAAI;AAAA,IACf,YAAY,IAAI;AAAA,IAChB,SAAS,IAAI;AAAA,IACb,SAAS,KAAK,MAAM,IAAI,OAAO;AAAA,IAC/B,SAAS,IAAI;AAAA,IACb,QAAQ,IAAI;AAAA,IACZ,cAAc,IAAI;AAAA,IAClB,eAAe,IAAI;AAAA,IACnB,WAAW,IAAI;AAAA,IACf,YAAY,IAAI;AAAA,EAClB;AACF;AAgDO,SAAS,WAAW,IAAkC;AAC3D,QAAM,KAAK,MAAM;AACjB,QAAM,MAAM,GAAG,QAAQ,qCAAqC,EAAE,IAAI,EAAE;AACpE,SAAO,MAAM,aAAa,GAAG,IAAI;AACnC;AAEO,SAAS,cACd,IACA,SACsB;AACtB,QAAM,KAAK,MAAM;AACjB,QAAM,WAAW,WAAW,EAAE;AAC9B,MAAI,CAAC,SAAU,QAAO;AAEtB,QAAM,SAAmB,CAAC;AAC1B,QAAM,SAAoB,CAAC;AAE3B,MAAI,QAAQ,cAAc,QAAW;AAAE,WAAO,KAAK,gBAAgB;AAAG,WAAO,KAAK,QAAQ,SAAS;AAAA,EAAG;AACtG,MAAI,QAAQ,eAAe,QAAW;AAAE,WAAO,KAAK,iBAAiB;AAAG,WAAO,KAAK,QAAQ,UAAU;AAAA,EAAG;AACzG,MAAI,QAAQ,YAAY,QAAW;AAAE,WAAO,KAAK,aAAa;AAAG,WAAO,KAAK,QAAQ,OAAO;AAAA,EAAG;AAC/F,MAAI,QAAQ,YAAY,QAAW;AAAE,WAAO,KAAK,aAAa;AAAG,WAAO,KAAK,KAAK,UAAU,QAAQ,OAAO,CAAC;AAAA,EAAG;AAC/G,MAAI,QAAQ,YAAY,QAAW;AAAE,WAAO,KAAK,aAAa;AAAG,WAAO,KAAK,QAAQ,OAAO;AAAA,EAAG;AAC/F,MAAI,QAAQ,WAAW,QAAW;AAAE,WAAO,KAAK,YAAY;AAAG,WAAO,KAAK,QAAQ,MAAM;AAAA,EAAG;AAC5F,MAAI,QAAQ,iBAAiB,QAAW;AAAE,WAAO,KAAK,mBAAmB;AAAG,WAAO,KAAK,QAAQ,YAAY;AAAA,EAAG;AAC/G,MAAI,QAAQ,kBAAkB,QAAW;AAAE,WAAO,KAAK,oBAAoB;AAAG,WAAO,KAAK,QAAQ,aAAa;AAAA,EAAG;AAClH,MAAI,QAAQ,cAAc,QAAW;AAAE,WAAO,KAAK,gBAAgB;AAAG,WAAO,KAAK,QAAQ,SAAS;AAAA,EAAG;AACtG,MAAI,QAAQ,eAAe,QAAW;AAAE,WAAO,KAAK,iBAAiB;AAAG,WAAO,KAAK,QAAQ,UAAU;AAAA,EAAG;AAEzG,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,SAAO,KAAK,EAAE;AACd,KAAG,QAAQ,uBAAuB,OAAO,KAAK,IAAI,CAAC,eAAe,EAAE,IAAI,GAAG,MAAM;AAEjF,SAAO,WAAW,EAAE;AACtB;AAEO,SAAS,sBAAuC;AACrD,QAAM,KAAK,MAAM;AACjB,QAAM,OAAO,GACV,QAAQ,yEAAyE,EACjF,IAAI;AACP,SAAO,KAAK,IAAI,YAAY;AAC9B;AAEO,SAAS,sBAAsB,WAAoC;AACxE,QAAM,KAAK,MAAM;AACjB,QAAM,OAAO,GACV,QAAQ,qEAAqE,EAC7E,IAAI,SAAS;AAChB,SAAO,KAAK,IAAI,YAAY;AAC9B;;;AClIA,SAAS,MAAMC,eAAc;AAa7B,SAAS,aAAa,KAAgC;AACpD,SAAO;AAAA,IACL,IAAI,IAAI;AAAA,IACR,WAAW,IAAI;AAAA,IACf,QAAQ,IAAI;AAAA,IACZ,SAAS,IAAI;AAAA,IACb,aAAa,KAAK,MAAM,IAAI,YAAY;AAAA,IACxC,WAAW,IAAI;AAAA,EACjB;AACF;AAEO,SAAS,cACd,SAIe;AACf,QAAM,KAAK,MAAM;AACjB,QAAM,KAAK,QAAQ,MAAMC,QAAO;AAChC,QAAM,YAAY,QAAQ,aAAa,KAAK,IAAI;AAEhD,KAAG;AAAA,IACD;AAAA;AAAA,EAEF,EAAE;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,KAAK,UAAU,QAAQ,WAAW;AAAA,IAClC;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,WAAW,QAAQ;AAAA,IACnB,QAAQ,QAAQ;AAAA,IAChB,SAAS,QAAQ;AAAA,IACjB,aAAa,QAAQ;AAAA,IACrB;AAAA,EACF;AACF;AAEO,SAAS,oBAAoB,WAAyC;AAC3E,QAAM,KAAK,MAAM;AACjB,QAAM,MAAM,GACT,QAAQ,4CAA4C,EACpD,IAAI,SAAS;AAChB,SAAO,MAAM,aAAa,GAAG,IAAI;AACnC;;;ACrDO,SAAS,oBAAoB,WAAiC;AACnE,QAAM,KAAK,MAAM;AACjB,QAAM,MAAM,GACT,QAAQ,uDAAuD,EAC/D,IAAI,SAAS;AAEhB,MAAI,CAAC,IAAK,QAAO,CAAC;AAElB,SAAO,KAAK,MAAM,IAAI,YAAY;AACpC;;;ACgEO,IAAM,mBAAiD;AAAA,EAC5D,cAAc,CAAC,QAAQ,QAAQ,MAAM;AAAA,EACrC,aAAa,CAAC,QAAQ,QAAQ,QAAQ,SAAS,QAAQ,MAAM;AAAA,EAC7D,IAAI,CAAC,QAAQ,QAAQ,QAAQ,MAAM;AAAA,EACnC,SAAS,CAAC,MAAM;AAAA,EAChB,UAAU,CAAC,QAAQ,QAAQ,QAAQ,WAAW;AAChD;;;AC5EA,IAAM,sBAA+D,oBAAI,IAAgC;AAAA,EACvG;AAAA,IACE;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MAEF,YAAY;AAAA,MACZ,aAAa,CAAC,mBAAmB,gBAAgB,qBAAqB;AAAA,MACtE,cAAc,iBAAiB;AAAA,IACjC;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MAEF,YAAY;AAAA,MACZ,aAAa,CAAC,eAAe,aAAa,YAAY;AAAA,MACtD,cAAc,iBAAiB;AAAA,IACjC;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MAEF,YAAY;AAAA,MACZ,aAAa,CAAC,eAAe,eAAe,oBAAoB,aAAa;AAAA,MAC7E,cAAc,iBAAiB;AAAA,IACjC;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MAEF,YAAY;AAAA,MACZ,aAAa,CAAC,yBAAyB,kBAAkB;AAAA,MACzD,cAAc,iBAAiB;AAAA,IACjC;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MAEF,YAAY;AAAA,MACZ,aAAa,CAAC,iBAAiB,gBAAgB,kBAAkB;AAAA,MACjE,cAAc,iBAAiB;AAAA,IACjC;AAAA,EACF;AACF,CAAC;AAGD,IAAM,qBAA0D,IAAI;AAAA,EAClE,CAAC,GAAG,oBAAoB,OAAO,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC;AACrE;AAMO,SAAS,cAAc,MAAkC;AAC9D,QAAM,OAAO,oBAAoB,IAAI,IAAI;AACzC,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,MAAM,uBAAuB,IAAI,EAAE;AAAA,EAC/C;AACA,SAAO;AACT;;;AC1FA,SAAS,oBAAoB;AAsB7B,IAAM,WAAN,MAAe;AAAA,EACI,UAAU,IAAI,aAAa;AAAA,EAE5C,cAAc;AAEZ,SAAK,QAAQ,gBAAgB,EAAE;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,eAAe,OAAyB;AACtC,SAAK,QAAQ,KAAK,eAAe,KAAK;AAGtC,UAAM,QAAwB;AAAA,MAC5B,MAAM;AAAA,MACN,WAAW,KAAK,IAAI;AAAA,MACpB,QAAQ,CAAC,KAAK;AAAA,IAChB;AACA,SAAK,QAAQ,KAAK,aAAa,KAAK;AAAA,EAKtC;AAAA;AAAA;AAAA;AAAA,EAKA,sBAAsB,UAAgC;AACpD,SAAK,QAAQ,KAAK,aAAa,QAAQ;AAAA,EACzC;AAAA;AAAA,EAIA,GAAmC,OAAU,UAAsD;AACjG,SAAK,QAAQ,GAAG,OAAO,QAAwC;AAAA,EACjE;AAAA,EAEA,IAAoC,OAAU,UAAsD;AAClG,SAAK,QAAQ,IAAI,OAAO,QAAwC;AAAA,EAClE;AAAA,EAEA,KAAqC,OAAU,UAAsD;AACnG,SAAK,QAAQ,KAAK,OAAO,QAAwC;AAAA,EACnE;AAAA;AAAA,EAIA,mBAAmB,OAAoC;AACrD,QAAI,OAAO;AACT,WAAK,QAAQ,mBAAmB,KAAK;AAAA,IACvC,OAAO;AACL,WAAK,QAAQ,mBAAmB;AAAA,IAClC;AAAA,EACF;AAAA,EAEA,cAAc,OAAqC;AACjD,WAAO,KAAK,QAAQ,cAAc,KAAK;AAAA,EACzC;AACF;AAOO,IAAM,WAAW,IAAI,SAAS;;;AClErC,IAAM,iBAA2C;AAAA,EAC/C,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AACT;AAMA,IAAM,SAAN,MAAa;AAAA,EACH,WAAqB;AAAA;AAAA;AAAA;AAAA;AAAA,EAM7B,SAAS,OAAuB;AAC9B,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,WAAqB;AACnB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,SAAiB,SAA4B;AACjD,SAAK,IAAI,SAAS,SAAS,OAAO;AAAA,EACpC;AAAA,EAEA,KAAK,SAAiB,SAA4B;AAChD,SAAK,IAAI,QAAQ,SAAS,OAAO;AAAA,EACnC;AAAA,EAEA,KAAK,SAAiB,SAA4B;AAChD,SAAK,IAAI,QAAQ,SAAS,OAAO;AAAA,EACnC;AAAA,EAEA,MAAM,SAAiB,SAA4B;AACjD,SAAK,IAAI,SAAS,SAAS,OAAO;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAMQ,IAAI,OAAiB,SAAiB,SAA4B;AACxE,QAAI,eAAe,KAAK,IAAI,eAAe,KAAK,QAAQ,GAAG;AACzD;AAAA,IACF;AAEA,UAAM,QAAkB;AAAA,MACtB,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MAClC;AAAA,MACA;AAAA,IACF;AAEA,QAAI,WAAW,OAAO,KAAK,OAAO,EAAE,SAAS,GAAG;AAC9C,YAAM,UAAU;AAAA,IAClB;AAGA,YAAQ,OAAO,MAAM,KAAK,UAAU,KAAK,IAAI,IAAI;AAAA,EACnD;AACF;AAOO,IAAM,SAAS,IAAI,OAAO;;;AC3F1B,IAAM,aAAN,MAAiB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKL,gBAAgB,oBAAI,IAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAU5D,YAAY,YAAwB,WAA8B;AAChE,UAAM,WAAW,cAAc,UAAU;AAEzC,UAAM,QAAQ,YAAY;AAAA,MACxB,MAAM;AAAA,MACN,MAAM,SAAS;AAAA,MACf;AAAA,MACA,UAAU;AAAA;AAAA,MACV;AAAA,MACA,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,WAAW;AAAA,IACb,CAAC;AAED,SAAK,cAAc,IAAI,MAAM,IAAI,KAAK;AAEtC,WAAO,KAAK,mBAAmB,SAAS,UAAU,IAAI;AAAA,MACpD,SAAS,MAAM;AAAA,MACf;AAAA,MACA;AAAA,IACF,CAAC;AAED,aAAS,eAAe;AAAA,MACtB,MAAM;AAAA,MACN,SAAS,MAAM;AAAA,MACf,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO,SAAS;AAAA,MAChB;AAAA,IACF,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,qBAAqB,WAAgC;AAEnD,UAAM,YAAY,CAAC,GAAG,KAAK,cAAc,OAAO,CAAC,EAAE;AAAA,MACjD,CAAC,MAAM,EAAE,cAAc;AAAA,IACzB;AAEA,QAAI,UAAU,SAAS,GAAG;AACxB,aAAO;AAAA,IACT;AAGA,WAAO,oBAAoB,SAAS,EAAE;AAAA,MACpC,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,WAAW,eAAe,EAAE,WAAW;AAAA,IACzE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAAiB,UAAwB;AACvC,UAAM,SAAS,KAAK,cAAc,IAAI,QAAQ;AAE9C,gBAAY,UAAU;AAAA,MACpB,QAAQ;AAAA,MACR,aAAa,KAAK,IAAI;AAAA,IACxB,CAAC;AAED,SAAK,cAAc,OAAO,QAAQ;AAElC,WAAO,KAAK,uBAAuB,QAAQ,IAAI;AAAA,MAC7C,SAAS;AAAA,MACT,YAAY,QAAQ;AAAA,IACtB,CAAC;AAED,aAAS,eAAe;AAAA,MACtB,MAAM;AAAA,MACN,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AACF;;;AXtFA,IAAM,sBAAoD;AAAA,EACxD,cAAc;AAAA,IACZ;AAAA,IAAgB;AAAA,IAAU;AAAA,IAAU;AAAA,IAAO;AAAA,IAAc;AAAA,IACzD;AAAA,IAAa;AAAA,IAAY;AAAA,IAAY;AAAA,IAAoB;AAAA,IACzD;AAAA,IAAiB;AAAA,IAAa;AAAA,EAChC;AAAA,EACA,aAAa;AAAA,IACX;AAAA,IAAQ;AAAA,IAAa;AAAA,IAAS;AAAA,IAAW;AAAA,IAAO;AAAA,IAAO;AAAA,IACvD;AAAA,IAAW;AAAA,IAAY;AAAA,IAAS;AAAA,IAAU;AAAA,IAAS;AAAA,IACnD;AAAA,IAAU;AAAA,IAAU;AAAA,IAAU;AAAA,IAAQ;AAAA,IAAY;AAAA,EACpD;AAAA,EACA,IAAI;AAAA,IACF;AAAA,IAAQ;AAAA,IAAW;AAAA,IAAY;AAAA,IAAe;AAAA,IAAS;AAAA,IACvD;AAAA,IAAc;AAAA,IAAa;AAAA,IAAiB;AAAA,IAAY;AAAA,IACxD;AAAA,IAAa;AAAA,IAAO;AAAA,IAAoB;AAAA,EAC1C;AAAA,EACA,SAAS;AAAA,IACP;AAAA,IAAgB;AAAA,IAAQ;AAAA,IAAS;AAAA,IAAY;AAAA,IAC7C;AAAA,IAAa;AAAA,IAAe;AAAA,IAAW;AAAA,IAAS;AAAA,IAChD;AAAA,IAAW;AAAA,IAAO;AAAA,EACpB;AAAA,EACA,UAAU;AAAA,IACR;AAAA,IAAY;AAAA,IAAW;AAAA,IAAe;AAAA,IAAU;AAAA,IAAW;AAAA,IAC3D;AAAA,IAAY;AAAA,IAAa;AAAA,IAAW;AAAA,IAAU;AAAA,IAC9C;AAAA,IAAa;AAAA,EACf;AACF;AAqCO,IAAM,eAAN,MAAmB;AAAA,EACP,aAAa,IAAI,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA,EAM5B;AAAA,EAEjB,YAAY,gBAAyB;AACnC,SAAK,iBAAiB,kBAAkB;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,cAAc,OAAe,QAAgC;AAC3D,UAAM,SAAS,CAAC,OAAO,GAAG,MAAM,EAAE,KAAK,GAAG,EAAE,YAAY;AAExD,UAAM,SAAS,oBAAI,IAAwB;AAE3C,eAAW,CAAC,MAAM,QAAQ,KAAK,OAAO,QAAQ,mBAAmB,GAA+B;AAC9F,UAAI,QAAQ;AACZ,iBAAW,MAAM,UAAU;AACzB,YAAI,OAAO,SAAS,EAAE,GAAG;AACvB;AAAA,QACF;AAAA,MACF;AACA,UAAI,QAAQ,GAAG;AACb,eAAO,IAAI,MAAM,KAAK;AAAA,MACxB;AAAA,IACF;AAEA,QAAI,OAAO,SAAS,GAAG;AAGrB,UAAI,OAAO,UAAU,GAAG;AACtB,eAAO,MAAM,gFAAgF;AAAA,UAC3F,WAAW;AAAA,QACb,CAAC;AACD,eAAO,CAAC,gBAAgB,aAAa;AAAA,MACvC;AACA,aAAO,MAAM,qEAAqE;AAAA,QAChF,WAAW;AAAA,MACb,CAAC;AACD,aAAO,CAAC,aAAa;AAAA,IACvB;AAGA,UAAM,WAAW,CAAC,GAAG,OAAO,QAAQ,CAAC,EAClC,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,EAC1B,IAAI,CAAC,CAAC,IAAI,MAAM,IAAI;AAEvB,WAAO,MAAM,yBAAyB,SAAS,KAAK,IAAI,CAAC,IAAI,EAAE,WAAW,MAAM,CAAC;AAEjF,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,aAAa,MAA+C;AAC1D,UAAM,EAAE,OAAO,OAAO,IAAI;AAC1B,UAAM,cAAc,KAAK,eAAe,KAAK,cAAc,OAAO,MAAM;AAExE,WAAO,KAAK,sBAAsB,KAAK,wBAAwB,YAAY,KAAK,IAAI,CAAC,GAAG;AAGxF,UAAM,YAAYC,QAAO;AACzB,kBAAc;AAAA,MACZ,IAAI;AAAA,MACJ;AAAA,MACA;AAAA,MACA,gBAAgB,YAAY,IAAI,CAAC,MAAM,GAAG,CAAC,SAAS;AAAA,MACpD,aAAa,KAAK;AAAA,MAClB,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,WAAW,KAAK,IAAI;AAAA,MACpB,mBAAmB,KAAK,qBAAqB;AAAA,IAC/C,CAAC;AAED,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,aAAa,MAKU;AACrB,UAAM,kBAAkB,WAAW,KAAK,iBAAiB;AACzD,QAAI,CAAC,iBAAiB;AACpB,YAAM,IAAI,MAAM,+BAA+B,KAAK,iBAAiB,EAAE;AAAA,IACzE;AAEA,UAAM,kBAAkB,oBAAoB,KAAK,iBAAiB;AAClE,QAAI,CAAC,iBAAiB;AACpB,YAAM,IAAI,MAAM,0CAA0C,KAAK,iBAAiB,EAAE;AAAA,IACpF;AAGA,UAAM,gBACJ,0BAA0B,gBAAgB,KAAK,MAAM,KAAK,iBAAiB;AAAA;AAAA;AAAA,EACtC,gBAAgB,OAAO;AAAA;AAAA;AAAA;AAE9D,UAAM,gBAAgB,gBAAgB,KAAK;AAE3C,WAAO;AAAA,MACL,0BAA0B,gBAAgB,KAAK,SAAS,KAAK,KAAK;AAAA,MAClE,EAAE,WAAW,KAAK,kBAAkB;AAAA,IACtC;AAEA,WAAO,KAAK,aAAa;AAAA,MACvB,OAAO;AAAA,MACP,QAAQ,KAAK;AAAA,MACb,aAAa,KAAK;AAAA,MAClB,mBAAmB,KAAK;AAAA,IAC1B,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,YAAgC;AAE9B,UAAM,cAAc,aAAa;AACjC,UAAM,iBAAiB,YAAY;AAAA,MACjC,CAAC,MAAM,CAAC,CAAC,aAAa,aAAa,UAAU,YAAY,WAAW,EAAE,SAAS,EAAE,MAAM;AAAA,IACzF;AAGA,UAAM,kBAAkB,oBAAoB;AAG5C,UAAM,YAAY,aAAa,KAAK,cAAc;AAElD,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA,EAKA,gBAA4B;AAC1B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,QAAgB;AACd,WAAO,KAAK;AAAA,EACd;AACF;;;AD/QO,IAAM,qBAAqB;AAAA,EAChC,OAAO,EAAE,OAAO,EAAE,SAAS,eAAe;AAAA,EAC1C,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,cAAc;AAAA,EACnD,aAAa,EACV,MAAM,EAAE,OAAO,CAAC,EAChB,SAAS,EACT,SAAS,gCAAgC;AAC9C;AAEA,eAAsB,oBAAoB;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AACF,GAI8E;AAC5E,MAAI;AACF,UAAM,eAAe,IAAI,aAAa;AACtC,UAAM,SAAS,aAAa,aAAa;AAAA,MACvC;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;Aa1CA,SAAS,KAAAC,UAAS;AAQX,IAAM,yBAAyB;AAAA,EACpC,WAAWC,GACR,OAAO,EACP,SAAS,EACT,SAAS,6CAA6C;AAC3D;AAEA,eAAsB,wBAAwB;AAAA,EAC5C;AACF,GAE8E;AAC5E,MAAI;AACF,QAAI,WAAW;AACb,YAAM,UAAU,WAAW,SAAS;AACpC,UAAI,CAAC,SAAS;AACZ,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,KAAK;AAAA,gBACT,EAAE,OAAO,sBAAsB,SAAS,GAAG;AAAA,gBAC3C;AAAA,gBACA;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF;AAEA,YAAM,SAAS,oBAAoB,SAAS;AAC5C,YAAM,UAAU,OAAO;AAAA,QAAQ,CAAC,UAC9B,oBAAoB,MAAM,EAAE;AAAA,MAC9B;AAEA,YAAMC,UAAS;AAAA,QACb;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,aAAO;AAAA,QACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAUA,SAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,MACnE;AAAA,IACF;AAGA,UAAM,cAAc,aAAa;AACjC,UAAM,iBAAiB,YAAY;AAAA,MACjC,CAAC,MACC,CAAC,CAAC,aAAa,aAAa,UAAU,YAAY,WAAW,EAAE;AAAA,QAC7D,EAAE;AAAA,MACJ;AAAA,IACJ;AAEA,UAAM,SAAS;AAAA,MACb,eAAe,YAAY;AAAA,MAC3B,gBAAgB,eAAe,IAAI,CAAC,OAAO;AAAA,QACzC,IAAI,EAAE;AAAA,QACN,OAAO,EAAE;AAAA,QACT,QAAQ,EAAE;AAAA,QACV,OAAO,EAAE;AAAA,QACT,WAAW,EAAE;AAAA,MACf,EAAE;AAAA,IACJ;AAEA,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;ACvFA,SAAS,KAAAC,UAAS;AAGX,IAAM,mBAAmB;AAAA,EAC9B,WAAWC,GAAE,OAAO,EAAE,SAAS,YAAY;AAAA,EAC3C,QAAQA,GACL,KAAK,CAAC,QAAQ,WAAW,YAAY,CAAC,EACtC,QAAQ,MAAM,EACd,SAAS,EACT,SAAS,eAAe;AAC7B;AAEA,eAAsB,kBAAkB;AAAA,EACtC;AAAA,EACA;AACF,GAG8E;AAC5E,MAAI;AACF,UAAM,UAAU,oBAAoB,SAAS;AAC7C,QAAI,CAAC,SAAS;AACZ,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK;AAAA,cACT,EAAE,OAAO,iCAAiC,SAAS,GAAG;AAAA,cACtD;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,QACA,SAAS;AAAA,MACX;AAAA,IACF;AAEA,UAAM,kBAAkB,UAAU;AAElC,QAAI;AAEJ,YAAQ,iBAAiB;AAAA,MACvB,KAAK;AACH,iBAAS;AAAA,UACP,IAAI,QAAQ;AAAA,UACZ,WAAW,QAAQ;AAAA,UACnB,QAAQ,QAAQ;AAAA,UAChB,SAAS,QAAQ;AAAA,UACjB,aAAa,QAAQ;AAAA,UACrB,WAAW,QAAQ;AAAA,QACrB;AACA;AAAA,MAEF,KAAK,WAAW;AAEd,cAAM,iBACJ,QAAQ,QAAQ,SAAS,MACrB,QAAQ,QAAQ,MAAM,GAAG,GAAG,IAAI,QAChC,QAAQ;AACd,iBAAS;AAAA,UACP,IAAI,QAAQ;AAAA,UACZ,WAAW,QAAQ;AAAA,UACnB,SAAS;AAAA,UACT,iBAAiB,QAAQ,YAAY;AAAA,UACrC,WAAW,QAAQ;AAAA,QACrB;AACA;AAAA,MACF;AAAA,MAEA,KAAK;AACH,iBAAS;AAAA,UACP,WAAW,QAAQ;AAAA,UACnB,aAAa,QAAQ;AAAA,UACrB,YAAY,QAAQ,YAAY;AAAA,QAClC;AACA;AAAA,IACJ;AAEA,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;AC1FA,SAAS,KAAAC,UAAS;;;ACMlB,SAAS,MAAMC,eAAc;AAU7B,IAAMC,uBAAoD;AAAA,EACxD,cAAc;AAAA,IACZ;AAAA,IAAU;AAAA,IAAU;AAAA,IAAgB;AAAA,IAAa;AAAA,IACjD;AAAA,IAAc;AAAA,IAAiB;AAAA,IAAQ;AAAA,EACzC;AAAA,EACA,aAAa;AAAA,IACX;AAAA,IAAa;AAAA,IAAQ;AAAA,IAAW;AAAA,IAAS;AAAA,IAAY;AAAA,IACrD;AAAA,IAAW;AAAA,IAAU;AAAA,IAAM;AAAA,IAAM;AAAA,EACnC;AAAA,EACA,IAAI;AAAA,IACF;AAAA,IAAQ;AAAA,IAAW;AAAA,IAAY;AAAA,IAAY;AAAA,IAAS;AAAA,IACpD;AAAA,IAAc;AAAA,IAAc;AAAA,IAAO;AAAA,IAAM;AAAA,EAC3C;AAAA,EACA,SAAS;AAAA,IACP;AAAA,IAAe;AAAA,IAAc;AAAA,IAAuB;AAAA,IACpD;AAAA,IAAY;AAAA,IAAW;AAAA,IAAS;AAAA,IAAQ;AAAA,EAC1C;AAAA,EACA,UAAU;AAAA,IACR;AAAA,IAAY;AAAA,IAAW;AAAA,IAAe;AAAA,IAAa;AAAA,IACnD;AAAA,IAAY;AAAA,IAAO;AAAA,IAAa;AAAA,IAAM;AAAA,EACxC;AACF;AAMA,IAAM,oBAA8D;AAAA,EAClE,UAAU;AAAA,IACR;AAAA,IAAY;AAAA,IAAU;AAAA,IAAW;AAAA,IAAY;AAAA,IAAQ;AAAA,IACrD;AAAA,IAAM;AAAA,IAAM;AAAA,EACd;AAAA,EACA,MAAM;AAAA,IACJ;AAAA,IAAiB;AAAA,IAAa;AAAA,IAAQ;AAAA,IAAY;AAAA,IAClD;AAAA,IAAM;AAAA,IAAM;AAAA,EACd;AAAA,EACA,QAAQ;AAAA,IACN;AAAA,IAAU;AAAA,IAAU;AAAA,IAAY;AAAA,IAAM;AAAA,EACxC;AAAA,EACA,KAAK;AAAA,IACH;AAAA,IAAgB;AAAA,IAAgB;AAAA,IAAY;AAAA,IAC5C;AAAA,IAAM;AAAA,IAAM;AAAA,EACd;AACF;AAMA,SAAS,iBAAiB,MAA0B;AAClD,QAAM,QAAQ,KAAK,YAAY;AAC/B,MAAI,WAAuB;AAC3B,MAAI,YAAY;AAEhB,aAAW,CAAC,MAAM,QAAQ,KAAK,OAAO,QAAQA,oBAAmB,GAA+B;AAC9F,UAAM,QAAQ,SAAS;AAAA,MACrB,CAAC,KAAK,OAAO,OAAO,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,IAAI;AAAA,MAC3D;AAAA,IACF;AACA,QAAI,QAAQ,WAAW;AACrB,kBAAY;AACZ,iBAAW;AAAA,IACb;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,eAAe,MAAsC;AAC5D,QAAM,QAAQ,KAAK,YAAY;AAG/B,aAAW,YAAY,CAAC,YAAY,QAAQ,UAAU,KAAK,GAAY;AACrE,UAAM,WAAW,kBAAkB,QAAQ;AAC3C,QAAI,SAAS,KAAK,CAAC,OAAO,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,GAAG;AAC3D,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAEA,IAAM,uBAAmD;AAAA,EACvD,cAAc;AAAA,EACd,aAAa;AAAA,EACb,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,UAAU;AACZ;AAMO,IAAM,YAAN,MAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWrB,MAAM,eACJ,WACA,wBACuB;AACvB,WAAO,KAAK,sBAAsB,EAAE,UAAU,CAAC;AAG/C,UAAM,UAAU,oBAAoB,SAAS;AAC7C,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,iCAAiC,SAAS,EAAE;AAAA,IAC9D;AAGA,UAAM,eAA6B,QAAQ,YAAY,IAAI,CAAC,SAAS;AACnE,YAAM,WAAW,GAAG,KAAK,KAAK,IAAI,KAAK,WAAW,IAAI,0BAA0B,EAAE;AAClF,YAAM,aAAa,iBAAiB,QAAQ;AAC5C,YAAM,WAAW,eAAe,QAAQ;AAExC,aAAO;AAAA,QACL,GAAG;AAAA,QACH,oBAAoB;AAAA,QACpB,cAAc,qBAAqB,UAAU;AAAA,QAC7C;AAAA,MACF;AAAA,IACF,CAAC;AAGD,QAAI,aAAa,WAAW,GAAG;AAC7B,YAAM,YAAY,KAAK,mBAAmB,QAAQ,OAAO;AACzD,mBAAa,KAAK,GAAG,SAAS;AAAA,IAChC;AAGA,UAAM,KAAK,MAAM;AACjB,OAAG,QAAQ,kDAAkD,EAAE;AAAA,MAC7D,KAAK,UAAU,YAAY;AAAA,MAC3B,QAAQ;AAAA,IACV;AAEA,WAAO,KAAK,qBAAqB;AAAA,MAC/B;AAAA,MACA,iBAAiB,aAAa;AAAA,IAChC,CAA4B;AAG5B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAMQ,mBAAmB,SAA+B;AACxD,UAAM,QAAsB,CAAC;AAC7B,UAAM,QAAQ,QAAQ,MAAM,IAAI;AAEhC,eAAW,QAAQ,OAAO;AACxB,YAAM,UAAU,KAAK,KAAK;AAE1B,UACE,QAAQ,WAAW,IAAI,KACvB,QAAQ,SAAS,KACjB,YAAY,YACZ,YAAY,qBACZ,YAAY,kCACZ,YAAY,8BACZ;AACA,cAAM,OAAO,QAAQ,MAAM,CAAC;AAC5B,cAAM,aAAa,iBAAiB,IAAI;AACxC,cAAM,WAAW,eAAe,IAAI;AAEpC,cAAM,KAAK;AAAA,UACT,IAAIC,QAAO;AAAA,UACX,OAAO,KAAK,MAAM,GAAG,EAAE;AAAA,UACvB,aAAa;AAAA,UACb,oBAAoB;AAAA,UACpB,cAAc,qBAAqB,UAAU;AAAA,UAC7C;AAAA,UACA,cAAc,CAAC;AAAA,UACf,oBAAoB,CAAC;AAAA,QACvB,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACF;;;AD5MO,IAAM,uBAAuB;AAAA,EAClC,WAAWC,GAAE,OAAO,EAAE,SAAS,YAAY;AAAA,EAC3C,wBAAwBA,GACrB,OAAO,EACP,SAAS,EACT,SAAS,wCAAwC;AACtD;AAEA,eAAsB,sBAAsB;AAAA,EAC1C;AAAA,EACA;AACF,GAG8E;AAC5E,MAAI;AACF,UAAM,YAAY,IAAI,UAAU;AAChC,UAAM,QAAQ,MAAM,UAAU;AAAA,MAC5B;AAAA,MACA;AAAA,IACF;AAEA,UAAM,SAAS;AAAA,MACb;AAAA,MACA,gBAAgB,MAAM;AAAA,MACtB;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;AE3CA,SAAS,KAAAC,UAAS;AAGX,IAAM,qBAAqB;AAAA,EAChC,WAAWC,GAAE,OAAO,EAAE,SAAS,YAAY;AAAA,EAC3C,SAASA,GACN,MAAMA,GAAE,OAAO,CAAC,EAChB,SAAS,EACT,SAAS,mCAAmC;AACjD;AAEA,eAAsB,oBAAoB;AAAA,EACxC;AAAA,EACA;AACF,GAG8E;AAC5E,MAAI;AACF,UAAM,WAAW,oBAAoB,SAAS;AAE9C,QAAI,SAAS,WAAW,GAAG;AACzB,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK;AAAA,cACT;AAAA,gBACE,OAAO,+BAA+B,SAAS;AAAA,cACjD;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,QACA,SAAS;AAAA,MACX;AAAA,IACF;AAGA,UAAM,iBAAiB,UACnB,SAAS,OAAO,CAAC,MAAM,QAAQ,SAAS,EAAE,EAAE,CAAC,IAC7C;AAEJ,QAAI,eAAe,WAAW,GAAG;AAC/B,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK;AAAA,cACT,EAAE,OAAO,qDAAqD;AAAA,cAC9D;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,QACA,SAAS;AAAA,MACX;AAAA,IACF;AAGA,UAAM,oBAAoB,oBAAI,IAAmC;AACjE,eAAW,QAAQ,gBAAgB;AACjC,YAAM,OAAO,KAAK;AAClB,UAAI,CAAC,kBAAkB,IAAI,IAAI,GAAG;AAChC,0BAAkB,IAAI,MAAM,CAAC,CAAC;AAAA,MAChC;AACA,wBAAkB,IAAI,IAAI,EAAG,KAAK,IAAI;AAAA,IACxC;AAEA,UAAM,cAGD,CAAC;AAEN,eAAW,CAAC,YAAY,KAAK,KAAK,mBAAmB;AACnD,kBAAY,KAAK,EAAE,YAAY,MAAM,CAAC;AAAA,IACxC;AAEA,UAAM,SAAS;AAAA,MACb;AAAA,MACA,YAAY,eAAe;AAAA,MAC3B;AAAA,MACA,cACE;AAAA,IAEJ;AAEA,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;AClGA,eAAsB,sBAGnB;AACD,MAAI;AACF,UAAM,OAAO,aAAa,mBAAmB;AAE7C,UAAM,SAAS;AAAA,MACb,MAAM;AAAA,MACN,WAAW,SAAS;AAAA,IACtB;AAEA,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;AC1BA,SAAS,KAAAC,UAAS;AAIX,IAAM,yBAAyB;AAAA,EACpC,WAAWC,GAAE,OAAO,EAAE,SAAS,iCAAiC;AAAA,EAChE,UAAUA,GAAE,OAAO,EAAE,SAAS,+BAA+B;AAAA,EAC7D,WAAWA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,qCAAqC;AACjF;AAEA,eAAsB,wBAAwB;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AACF,GAI8E;AAC5E,MAAI;AACF,UAAM,UAAU,WAAW,SAAS;AAEpC,QAAI,CAAC,SAAS;AACZ,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK;AAAA,cACT,EAAE,OAAO,sBAAsB,SAAS,GAAG;AAAA,cAC3C;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,QACA,SAAS;AAAA,MACX;AAAA,IACF;AAEA,QAAI,QAAQ,WAAW,YAAY;AACjC,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK;AAAA,cACT,EAAE,OAAO,6BAA6B,SAAS,GAAG;AAAA,cAClD;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,QACA,SAAS;AAAA,MACX;AAAA,IACF;AAEA,UAAM,WAAW,cAAc,WAAW;AAAA,MACxC,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,eAAe,aAAa;AAAA,MAC5B,YAAY,KAAK,IAAI;AAAA,IACvB,CAAC;AAED,aAAS,eAAe;AAAA,MACtB,MAAM;AAAA,MACN;AAAA,MACA;AAAA,IACF,CAAC;AAED,WAAO;AAAA,MACL,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,MAAM,KAAK;AAAA,YACT,EAAE,SAAS,MAAM,SAAS,SAAS;AAAA,YACnC;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;ACxFA,SAAS,KAAAC,UAAS;AAOX,IAAM,oBAAoB;AAAA,EAC/B,QAAQC,GACL,KAAK,CAAC,WAAW,YAAY,KAAK,CAAC,EACnC,QAAQ,SAAS,EACjB,SAAS,EACT,SAAS,2BAA2B;AAAA,EACvC,WAAWA,GACR,OAAO,EACP,SAAS,EACT,SAAS,+BAA+B;AAC7C;AAEA,eAAsB,mBAAmB;AAAA,EACvC;AAAA,EACA;AACF,GAG8E;AAC5E,MAAI;AACF,UAAM,kBAAkB,UAAU;AAClC,QAAI;AAEJ,QAAI,WAAW;AAEb,YAAM,gBAAgB,sBAAsB,SAAS;AACrD,UAAI,oBAAoB,OAAO;AAC7B,mBAAW;AAAA,MACb,OAAO;AACL,mBAAW,cAAc,OAAO,CAAC,MAAM,EAAE,WAAW,eAAe;AAAA,MACrE;AAAA,IACF,WAAW,oBAAoB,WAAW;AACxC,iBAAW,oBAAoB;AAAA,IACjC,WAAW,oBAAoB,YAAY;AAYzC,YAAM,EAAE,OAAAC,OAAM,IAAI,MAAM,OAAO,kBAAkB;AACjD,YAAM,KAAKA,OAAM;AAcjB,YAAM,OAAO,GACV,QAAQ,0EAA0E,EAClF,IAAI;AACP,iBAAW,KAAK,IAAI,CAAC,SAAS;AAAA,QAC5B,IAAI,IAAI;AAAA,QACR,WAAW,IAAI;AAAA,QACf,YAAY,IAAI;AAAA,QAChB,SAAS,IAAI;AAAA,QACb,SAAS,KAAK,MAAM,IAAI,OAAO;AAAA,QAC/B,SAAS,IAAI;AAAA,QACb,QAAQ,IAAI;AAAA,QACZ,cAAc,IAAI;AAAA,QAClB,eAAe,IAAI;AAAA,QACnB,WAAW,IAAI;AAAA,QACf,YAAY,IAAI;AAAA,MAClB,EAAE;AAAA,IACJ,OAAO;AAEL,YAAM,EAAE,OAAAA,OAAM,IAAI,MAAM,OAAO,kBAAkB;AACjD,YAAM,KAAKA,OAAM;AAcjB,YAAM,OAAO,GACV,QAAQ,gDAAgD,EACxD,IAAI;AACP,iBAAW,KAAK,IAAI,CAAC,SAAS;AAAA,QAC5B,IAAI,IAAI;AAAA,QACR,WAAW,IAAI;AAAA,QACf,YAAY,IAAI;AAAA,QAChB,SAAS,IAAI;AAAA,QACb,SAAS,KAAK,MAAM,IAAI,OAAO;AAAA,QAC/B,SAAS,IAAI;AAAA,QACb,QAAQ,IAAI;AAAA,QACZ,cAAc,IAAI;AAAA,QAClB,eAAe,IAAI;AAAA,QACnB,WAAW,IAAI;AAAA,QACf,YAAY,IAAI;AAAA,MAClB,EAAE;AAAA,IACJ;AAEA,UAAM,SAAS;AAAA,MACb,OAAO,SAAS;AAAA,MAChB,QAAQ;AAAA,MACR,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;AAAA,MACjC;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;ACzIA,SAAS,KAAAC,UAAS;AAWX,IAAM,sBAAsB;AAAA,EACjC,WAAWC,GAAE,OAAO,EAAE,SAAS,6BAA6B;AAAA,EAC5D,QAAQA,GAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yBAAyB;AAClE;AAEA,eAAsB,qBAAqB;AAAA,EACzC;AAAA,EACA;AACF,GAG8E;AAC5E,MAAI;AACF,UAAM,UAAU,WAAW,SAAS;AAEpC,QAAI,CAAC,SAAS;AACZ,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK;AAAA,cACT,EAAE,OAAO,sBAAsB,SAAS,GAAG;AAAA,cAC3C;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,QACA,SAAS;AAAA,MACX;AAAA,IACF;AAEA,QAAI,QAAQ,WAAW,eAAe,QAAQ,WAAW,aAAa;AACpE,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK;AAAA,cACT;AAAA,gBACE,OAAO,mDAAmD,QAAQ,MAAM;AAAA,cAC1E;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,QACA,SAAS;AAAA,MACX;AAAA,IACF;AAGA,kBAAc,WAAW,EAAE,QAAQ,aAAa,aAAa,KAAK,IAAI,EAAE,CAAC;AAGzE,UAAM,SAAS,oBAAoB,SAAS;AAC5C,QAAI,kBAAkB;AACtB,QAAI,gBAAgB;AAEpB,eAAW,SAAS,QAAQ;AAC1B,UAAI,MAAM,WAAW,eAAe,MAAM,WAAW,UAAU;AAC7D,oBAAY,MAAM,IAAI,EAAE,QAAQ,aAAa,aAAa,KAAK,IAAI,EAAE,CAAC;AACtE;AAEA,iBAAS,eAAe;AAAA,UACtB,MAAM;AAAA,UACN,SAAS,MAAM;AAAA,UACf,MAAM,MAAM;AAAA,UACZ,IAAI;AAAA,QACN,CAAC;AAAA,MACH;AAGA,YAAM,UAAU,oBAAoB,MAAM,EAAE;AAC5C,iBAAW,UAAU,SAAS;AAC5B,YAAI,OAAO,WAAW,eAAe,OAAO,WAAW,UAAU;AAC/D,uBAAa,OAAO,IAAI;AAAA,YACtB,QAAQ;AAAA,YACR,cAAc,UAAU;AAAA,YACxB,aAAa,KAAK,IAAI;AAAA,UACxB,CAAC;AACD;AAEA,mBAAS,eAAe;AAAA,YACtB,MAAM;AAAA,YACN,SAAS,OAAO;AAAA,YAChB,QAAQ;AAAA,UACV,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAEA,UAAM,SAAS;AAAA,MACb,SAAS;AAAA,MACT;AAAA,MACA,gBAAgB,QAAQ;AAAA,MACxB,QAAQ,UAAU;AAAA,MAClB;AAAA,MACA;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;AC1HA,SAAS,KAAAC,UAAS;AAIX,IAAM,qBAAqB;AAAA,EAChC,QAAQC,GACL,KAAK,CAAC,WAAW,WAAW,aAAa,aAAa,UAAU,KAAK,CAAC,EACtE,QAAQ,KAAK,EACb,SAAS,EACT,SAAS,2BAA2B;AAAA,EACvC,OAAOA,GACJ,OAAO,EACP,QAAQ,EAAE,EACV,SAAS,EACT,SAAS,sCAAsC;AACpD;AAIA,IAAM,mBAAoC;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,eAAsB,oBAAoB;AAAA,EACxC;AAAA,EACA;AACF,GAG8E;AAC5E,MAAI;AACF,UAAM,kBAAkB,UAAU;AAClC,UAAM,iBAAiB,SAAS;AAEhC,QAAI;AAEJ,QAAI,oBAAoB,OAAO;AAC7B,iBAAW,aAAa;AAAA,IAC1B,WAAW,oBAAoB,WAAW;AAExC,YAAM,MAAM,aAAa;AACzB,iBAAW,IAAI,OAAO,CAAC,MAAM,iBAAiB,SAAS,EAAE,MAAM,CAAC;AAAA,IAClE,OAAO;AACL,iBAAW,aAAa,eAAgC;AAAA,IAC1D;AAGA,UAAM,UAAU,SAAS,MAAM,GAAG,cAAc;AAEhD,UAAM,SAAS;AAAA,MACb,OAAO,SAAS;AAAA,MAChB,UAAU,QAAQ;AAAA,MAClB,QAAQ;AAAA,MACR,UAAU,QAAQ,IAAI,CAAC,OAAO;AAAA,QAC5B,IAAI,EAAE;AAAA,QACN,OAAO,EAAE;AAAA,QACT,QAAQ,EAAE;AAAA,QACV,OAAO,EAAE;AAAA,QACT,kBAAkB,EAAE,eAAe;AAAA,QACnC,WAAW,EAAE;AAAA,MACf,EAAE;AAAA,IACJ;AAEA,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;AClFA,SAAS,KAAAC,WAAS;AAQX,IAAM,sBAAsB;AAAA,EACjC,WAAWC,IAAE,OAAO,EAAE,SAAS,4CAA4C;AAC7E;AAEA,eAAsB,qBAAqB;AAAA,EACzC;AACF,GAE8E;AAC5E,MAAI;AACF,UAAM,UAAU,WAAW,SAAS;AACpC,QAAI,CAAC,SAAS;AACZ,aAAO;AAAA,QACL,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK;AAAA,cACT,EAAE,OAAO,sBAAsB,SAAS,GAAG;AAAA,cAC3C;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,QACA,SAAS;AAAA,MACX;AAAA,IACF;AAEA,UAAM,UAAU,oBAAoB,SAAS;AAC7C,UAAM,SAAS,oBAAoB,SAAS;AAG5C,UAAM,uBAeD,CAAC;AAEN,QAAI,iBAAiB;AACrB,QAAI,cAAc;AAClB,QAAI,eAAe;AACnB,QAAI,YAAY;AAEhB,eAAW,SAAS,QAAQ;AAC1B,YAAM,UAAU,oBAAoB,MAAM,EAAE;AAE5C,YAAM,YAAY,QAAQ,OAAO,CAAC,MAAM,EAAE,WAAW,WAAW,EAAE;AAClE,YAAM,SAAS,QAAQ,OAAO,CAAC,MAAM,EAAE,WAAW,QAAQ,EAAE;AAC5D,YAAM,UAAU,QAAQ;AAAA,QACtB,CAAC,MAAM,EAAE,WAAW,aAAa,EAAE,WAAW;AAAA,MAChD,EAAE;AACF,YAAM,WAAW,QAAQ,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,SAAS,CAAC;AAE9D,wBAAkB;AAClB,qBAAe;AACf,sBAAgB;AAChB,mBAAa;AAEb,UAAI,QAAQ,SAAS,GAAG;AACtB,6BAAqB,KAAK;AAAA,UACxB,YAAY,MAAM;AAAA,UAClB,UAAU,MAAM;AAAA,UAChB,YAAY,MAAM;AAAA,UAClB,SAAS,QAAQ,IAAI,CAAC,OAAO;AAAA,YAC3B,IAAI,EAAE;AAAA,YACN,iBAAiB,EAAE;AAAA,YACnB,QAAQ,EAAE;AAAA,YACV,SAAS,EAAE;AAAA,YACX,cAAc,EAAE;AAAA,UAClB,EAAE;AAAA,UACF;AAAA,UACA;AAAA,UACA;AAAA,UACA,WAAW;AAAA,QACb,CAAC;AAAA,MACH;AAAA,IACF;AAEA,UAAM,SAAS;AAAA,MACb;AAAA,MACA,OAAO,QAAQ;AAAA,MACf,QAAQ,QAAQ;AAAA,MAChB,iBAAiB,SAAS,YAAY,UAAU;AAAA,MAChD,SAAS;AAAA,QACP,cAAc,iBAAiB,cAAc;AAAA,QAC7C,WAAW;AAAA,QACX,QAAQ;AAAA,QACR,SAAS;AAAA,QACT;AAAA,MACF;AAAA,MACA,aAAa;AAAA,IACf;AAEA,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;AC3HA,SAAS,KAAAC,WAAS;;;ACQlB,SAAS,cAAc,eAAe,kBAAkB;AACxD,SAAS,QAAAC,aAAY;;;ACTrB,SAAS,iBAAiB;AAC1B,SAAS,eAAe;AACxB,SAAS,YAAY;AAqBrB,SAAS,cAAyB;AAChC,QAAM,WAAW,KAAK,QAAQ,GAAG,gBAAgB;AACjD,SAAO;AAAA,IACL;AAAA,IACA,SAAS,KAAK,UAAU,SAAS;AAAA,IACjC,aAAa,KAAK,UAAU,SAAS;AAAA,IACrC,gBAAgB;AAAA,EAClB;AACF;AAGA,IAAI,UAA4B;AAYzB,SAAS,YAAuB;AACrC,MAAI,CAAC,SAAS;AACZ,cAAU,YAAY;AAAA,EACxB;AACA,SAAO;AACT;AAOO,SAAS,iBAAuB;AACrC,QAAM,SAAS,UAAU;AACzB,YAAU,OAAO,UAAU,EAAE,WAAW,KAAK,CAAC;AAC9C,YAAU,OAAO,aAAa,EAAE,WAAW,KAAK,CAAC;AACnD;;;AD9BA,IAAM,iBAAkD;AAAA,EACtD;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AACF;AAEA,IAAM,kBAAmD;AAAA,EACvD;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,EACZ;AACF;AAMO,IAAM,qBAAN,MAAyB;AAAA,EACtB,eAA6B,CAAC;AAAA,EAC9B;AAAA,EAER,cAAc;AACZ,UAAM,EAAE,SAAS,IAAI,UAAU;AAC/B,SAAK,eAAeC,MAAK,UAAU,eAAe;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAAiC;AAErC,UAAM,WAAyB;AAAA,MAC7B,GAAG;AAAA,MACH,GAAG;AAAA,IACL,EAAE,IAAI,CAAC,SAAS,EAAE,GAAG,KAAK,WAAW,EAAE,EAAE;AAGzC,UAAM,SAAS,KAAK,kBAAkB;AACtC,SAAK,eAAe,CAAC,GAAG,UAAU,GAAG,MAAM;AAC3C,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAS,KAAmD;AAChE,UAAM,QAAoB,EAAE,GAAG,KAAK,WAAW,KAAK,IAAI,EAAE;AAG1D,UAAM,SAAS,KAAK,kBAAkB,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,IAAI,IAAI;AACzE,WAAO,KAAK,KAAK;AACjB,SAAK,mBAAmB,MAAM;AAG9B,UAAM,KAAK,QAAQ;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAW,MAAsB,MAA6B;AAClE,UAAM,SAAS,KAAK,kBAAkB,EAAE;AAAA,MACtC,CAAC,MAAM,EAAE,EAAE,SAAS,QAAQ,EAAE,SAAS;AAAA,IACzC;AACA,SAAK,mBAAmB,MAAM;AAG9B,UAAM,KAAK,QAAQ;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,MAAoC;AAC7C,WAAO,KAAK,aAAa,OAAO,CAAC,MAAM,EAAE,SAAS,IAAI;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,MAAsC;AAC/C,WAAO,KAAK,aAAa,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,MAAuB;AACzB,WAAO,KAAK,aAAa,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAyB;AACvB,UAAM,WAAqB,CAAC;AAE5B,UAAM,QAA0B,CAAC,QAAQ,SAAS,WAAW,SAAS,MAAM;AAC5E,eAAW,QAAQ,OAAO;AACxB,YAAM,OAAO,KAAK,WAAW,IAAI;AACjC,UAAI,KAAK,WAAW,EAAG;AAEvB,YAAM,QAAQ,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC,IAAI;AAC7D,YAAM,QAAQ,KAAK,IAAI,CAAC,MAAM;AAC5B,cAAM,MAAM,EAAE,YAAY,KAAK;AAC/B,eAAO,OAAO,EAAE,IAAI,KAAK,GAAG,WAAM,EAAE,WAAW,cAAc,EAAE,OAAO;AAAA,MACxE,CAAC;AACD,eAAS,KAAK,OAAO,KAAK;AAAA,EAAK,MAAM,KAAK,IAAI,CAAC,EAAE;AAAA,IACnD;AAEA,WAAO,SAAS,KAAK,MAAM;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAMQ,oBAAkC;AACxC,QAAI,CAAC,WAAW,KAAK,YAAY,GAAG;AAClC,aAAO,CAAC;AAAA,IACV;AACA,QAAI;AACF,YAAM,MAAM,aAAa,KAAK,cAAc,OAAO;AACnD,YAAM,SAAkB,KAAK,MAAM,GAAG;AACtC,UAAI,CAAC,MAAM,QAAQ,MAAM,EAAG,QAAO,CAAC;AACpC,aAAO;AAAA,IACT,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA,EAEQ,mBAAmB,SAA6B;AACtD,kBAAc,KAAK,cAAc,KAAK,UAAU,SAAS,MAAM,CAAC,GAAG,OAAO;AAAA,EAC5E;AACF;;;AExPA,SAAS,aAAAC,YAAW,iBAAAC,sBAAqB;AACzC,SAAS,QAAAC,aAAY;AA0BrB,SAAS,aAAa,MAAsB;AAC1C,SAAO,KACJ,YAAY,EACZ,QAAQ,eAAe,GAAG,EAC1B,QAAQ,YAAY,EAAE;AAC3B;AAEA,SAAS,OAAO,SAAkC;AAChD,QAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,SAAO;AAAA,IACL;AAAA,IACA,YAAY,QAAQ,IAAI;AAAA,IACxB,mBAAmB,QAAQ,WAAW;AAAA,IACtC,eAAe,QAAQ,OAAO;AAAA,IAC9B,eAAe,GAAG;AAAA,IAClB;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAEA,SAAS,UAAU,MAA8B;AAC/C,QAAM,EAAE,SAAS,IAAI,UAAU;AAC/B,QAAM,MAAMC,MAAK,UAAU,UAAU,IAAI,GAAG;AAC5C,EAAAC,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAClC,SAAO;AACT;AAMA,SAAS,aAAa,SAAkC;AACtD,SAAO;AAAA,IACL,OAAO,OAAO;AAAA,IACd;AAAA,IACA,mBAAmB,QAAQ,IAAI;AAAA,IAC/B,MAAM,QAAQ,WAAW;AAAA,IACzB;AAAA,IACA,eAAe,QAAQ,OAAO;AAAA,IAC9B,wBAAwB,QAAQ,WAAW;AAAA,IAC3C;AAAA,IACA;AAAA,IACA,0BAA0B,aAAa,QAAQ,IAAI,CAAC;AAAA,IACpD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,wCAAwC,QAAQ,WAAW;AAAA,IAC3D;AAAA,IACA,cAAc,QAAQ,IAAI;AAAA,IAC1B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAEA,SAAS,cAAc,SAAkC;AACvD,SAAO;AAAA,IACL,OAAO,OAAO;AAAA,IACd;AAAA,IACA,oBAAoB,QAAQ,IAAI;AAAA,IAChC,MAAM,QAAQ,WAAW;AAAA,IACzB;AAAA,IACA,eAAe,QAAQ,OAAO;AAAA,IAC9B,wBAAwB,QAAQ,WAAW;AAAA,IAC3C;AAAA,IACA;AAAA,IACA,sBAAsB,aAAa,QAAQ,IAAI,CAAC;AAAA,IAChD;AAAA,IACA;AAAA,IACA;AAAA,IACA,sBAAsB,QAAQ,IAAI;AAAA,IAClC;AAAA,IACA,WAAW,QAAQ,IAAI;AAAA,IACvB;AAAA,IACA,QAAQ,QAAQ,WAAW;AAAA,IAC3B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAEA,SAAS,gBAAgB,SAAkC;AACzD,SAAO;AAAA,IACL,OAAO,OAAO;AAAA,IACd;AAAA,IACA,sBAAsB,QAAQ,IAAI;AAAA,IAClC,MAAM,QAAQ,WAAW;AAAA,IACzB;AAAA,IACA,eAAe,QAAQ,OAAO;AAAA,IAC9B,wBAAwB,QAAQ,WAAW;AAAA,IAC3C;AAAA,IACA;AAAA,IACA,6BAA6B,aAAa,QAAQ,IAAI,CAAC;AAAA,IACvD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,mBAAmB,QAAQ,IAAI;AAAA,IAC/B,uBAAuB,QAAQ,WAAW;AAAA,IAC1C,iBAAiB,QAAQ,IAAI;AAAA,IAC7B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,qBAAqB,QAAQ,IAAI;AAAA,IACjC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAEA,SAAS,cAAc,SAAkC;AAEvD,QAAM,aACJ,kCAAkC,KAAK,QAAQ,IAAI,KACnD,kCAAkC,KAAK,QAAQ,WAAW;AAE5D,MAAI,YAAY;AACd,WAAO;AAAA,MACL;AAAA,MACA,cAAc,QAAQ,IAAI;AAAA,MAC1B,qBAAqB,QAAQ,WAAW;AAAA,MACxC,iBAAiB,QAAQ,OAAO;AAAA,MAChC,kBAAiB,oBAAI,KAAK,GAAE,YAAY,CAAC;AAAA,MACzC;AAAA,MACA,KAAK,QAAQ,IAAI;AAAA,MACjB;AAAA,MACA,GAAG,QAAQ,WAAW;AAAA,MACtB;AAAA,MACA;AAAA,MACA;AAAA,MACA,uBAAuB,QAAQ,WAAW;AAAA,MAC1C;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACb;AAEA,QAAM,OAAO;AAAA,IACX,OAAO;AAAA,MACL,aAAa;AAAA,MACb,MAAM,QAAQ;AAAA,MACd,aAAa,QAAQ;AAAA,MACrB,SAAS,QAAQ;AAAA,MACjB,UAAS,oBAAI,KAAK,GAAE,YAAY;AAAA,MAChC,aAAa,QAAQ;AAAA,IACvB;AAAA,IACA,QAAQ,CAAC;AAAA,EACX;AAEA,SAAO,KAAK,UAAU,MAAM,MAAM,CAAC,IAAI;AACzC;AAEA,SAAS,aAAa,SAAkC;AACtD,SAAO;AAAA,IACL,OAAO,OAAO;AAAA,IACd;AAAA,IACA,mBAAmB,QAAQ,IAAI;AAAA,IAC/B,MAAM,QAAQ,WAAW;AAAA,IACzB;AAAA,IACA,eAAe,QAAQ,OAAO;AAAA,IAC9B,wBAAwB,QAAQ,WAAW;AAAA,IAC3C;AAAA,IACA;AAAA,IACA,0BAA0B,aAAa,QAAQ,IAAI,CAAC;AAAA,IACpD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,iDAAiD,QAAQ,WAAW;AAAA,IACpE;AAAA,IACA,cAAc,QAAQ,IAAI;AAAA,IAC1B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,kBAAkB,QAAQ,IAAI;AAAA,IAC9B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAMA,SAAS,aAAa,KAAqB;AACzC,SAAO,IACJ,MAAM,SAAS,EACf,IAAI,CAAC,SAAS,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC,EAAE,YAAY,CAAC,EACxE,KAAK,EAAE;AACZ;AAYO,SAAS,mBAAmB,SAA0C;AAC3E,QAAM,WAAW,aAAa,QAAQ,IAAI;AAG1C,QAAM,kBACJ,QAAQ,SAAS,YAChB,kCAAkC,KAAK,QAAQ,IAAI,KAClD,kCAAkC,KAAK,QAAQ,WAAW;AAE9D,MAAI;AACJ,MAAI,QAAQ,SAAS,SAAS;AAC5B,UAAM,kBAAkB,QAAQ;AAAA,EAClC,OAAO;AACL,UAAM;AAAA,EACR;AAEA,QAAM,MAAM,UAAU,QAAQ,IAAI;AAClC,QAAM,WAAWD,MAAK,KAAK,GAAG,QAAQ,GAAG,GAAG,EAAE;AAG9C,MAAI;AACJ,UAAQ,QAAQ,MAAM;AAAA,IACpB,KAAK;AACH,aAAO,aAAa,OAAO;AAC3B;AAAA,IACF,KAAK;AACH,aAAO,cAAc,OAAO;AAC5B;AAAA,IACF,KAAK;AACH,aAAO,gBAAgB,OAAO;AAC9B;AAAA,IACF,KAAK;AACH,aAAO,cAAc,OAAO;AAC5B;AAAA,IACF,KAAK;AACH,aAAO,aAAa,OAAO;AAC3B;AAAA,EACJ;AAGA,EAAAE,eAAc,UAAU,MAAM,OAAO;AAErC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,eAAe;AAAA,MACb,MAAM,QAAQ;AAAA,MACd,MAAM,QAAQ;AAAA,MACd,aAAa,QAAQ;AAAA,MACrB,SAAS,QAAQ;AAAA,MACjB,WAAW;AAAA,MACX;AAAA,IACF;AAAA,EACF;AACF;;;AC3VA,SAAS,gBAAAC,eAAc,iBAAAC,sBAAqB;AAC5C,SAAS,QAAAC,aAAY;AAcrB,eAAsB,kBACpB,UACe;AACf,QAAM,EAAE,SAAS,IAAI,UAAU;AAC/B,QAAM,YAAYC,MAAK,UAAU,iBAAiB;AAElD,QAAM,aAAa,SAAS,eAAe;AAE3C,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AAEX,EAAAC,eAAc,WAAW,OAAO,OAAO;AACzC;;;ACrBA,IAAM,gBAA+B;AAAA,EACnC;AAAA,IACE,MAAM;AAAA,IACN,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAMO,IAAM,mBAAN,MAAuB;AAAA,EACpB;AAAA,EAER,cAAc;AACZ,SAAK,WAAW,IAAI,mBAAmB;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAsB;AAC1B,UAAM,KAAK,SAAS,QAAQ;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,eAAe,SAA0C;AAE7D,UAAM,aAAa,QAAQ,YAAY,EAAE,KAAK;AAE9C,eAAW,OAAO,MAAM,KAAK,SAAS,QAAQ,GAAG;AAC/C,UAAI,WAAW,SAAS,IAAI,KAAK,YAAY,CAAC,GAAG;AAC/C,eAAO,EAAE,oBAAoB,MAAM;AAAA,MACrC;AAAA,IACF;AAGA,eAAW,QAAQ,eAAe;AAChC,iBAAW,WAAW,KAAK,UAAU;AACnC,YAAI,QAAQ,KAAK,OAAO,GAAG;AACzB,gBAAM,gBAAgB,YAAY,OAAO;AACzC,iBAAO;AAAA,YACL,oBAAoB;AAAA,YACpB,eAAe,KAAK;AAAA,YACpB,eAAe;AAAA,YACf,sBAAsB,QAAQ,MAAM,GAAG,GAAG;AAAA,YAC1C,kBAAkB,eAAe,SAAS,KAAK,IAAI;AAAA,UACrD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,WAAO;AAAA,MACL,oBAAoB;AAAA,MACpB,eAAe;AAAA,MACf,eAAe,YAAY,OAAO;AAAA,MAClC,sBAAsB,QAAQ,MAAM,GAAG,GAAG;AAAA,MAC1C,kBAAkB;AAAA,IACpB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAiB,SAAiD;AAEtE,UAAM,SAAS,mBAAmB,OAAO;AAGzC,UAAM,KAAK,SAAS,SAAS,OAAO,aAAa;AAGjD,UAAM,kBAAkB,KAAK,QAAQ;AAGrC,UAAM,aAAyB;AAAA,MAC7B,GAAG,OAAO;AAAA,MACV,WAAW,KAAK,IAAI;AAAA,IACtB;AAEA,UAAM,UACJ,WAAW,QAAQ,IAAI,KAAK,QAAQ,IAAI,MAAM,QAAQ,WAAW,WACxD,OAAO,QAAQ;AAE1B,WAAO,EAAE,YAAY,UAAU,OAAO,UAAU,QAAQ;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBAA0C;AAC9C,WAAO,KAAK,SAAS,QAAQ;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,iBAAiB,MAA6B;AAClD,UAAM,MAAM,KAAK,SAAS,WAAW,IAAI;AACzC,QAAI,CAAC,KAAK;AACR,YAAM,IAAI,MAAM,yBAAyB,IAAI,EAAE;AAAA,IACjD;AACA,QAAI,IAAI,WAAW;AACjB,YAAM,IAAI,MAAM,sCAAsC,IAAI,EAAE;AAAA,IAC9D;AAEA,UAAM,KAAK,SAAS,WAAW,IAAI,MAAM,IAAI;AAG7C,UAAM,kBAAkB,KAAK,QAAQ;AAAA,EACvC;AACF;AASA,SAAS,YAAY,SAAyB;AAE5C,QAAM,aAAa,QAAQ,MAAM,cAAc;AAC/C,MAAI,WAAY,QAAO,WAAW,CAAC;AAGnC,QAAM,QAAQ,QACX,QAAQ,oBAAoB,EAAE,EAC9B,MAAM,KAAK,EACX,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,EAC1B,MAAM,GAAG,CAAC;AAEb,SAAO,MAAM,KAAK,GAAG,EAAE,YAAY,KAAK;AAC1C;AAKA,SAAS,eAAe,SAAiB,MAA8B;AACrE,UAAQ,MAAM;AAAA,IACZ,KAAK,QAAQ;AACX,YAAM,cAAc,QAAQ,MAAM,4BAA4B;AAC9D,UAAI,YAAa,QAAO,UAAU,YAAY,CAAC,EAAE,KAAK,CAAC;AACvD,YAAM,aAAa,QAAQ,MAAM,2BAA2B;AAC5D,UAAI,WAAY,QAAO,SAAS,WAAW,CAAC,EAAE,KAAK,CAAC;AACpD,YAAM,YAAY,QAAQ,MAAM,0BAA0B;AAC1D,UAAI,UAAW,QAAO,QAAQ,UAAU,CAAC,EAAE,KAAK,CAAC;AACjD,aAAO;AAAA,IACT;AAAA,IACA,KAAK;AACH,aAAO,IAAI,YAAY,OAAO,CAAC;AAAA,IACjC,KAAK,QAAQ;AACX,YAAM,aAAa,QAAQ,MAAM,oBAAoB;AACrD,UAAI,WAAY,QAAO,SAAS,WAAW,CAAC,EAAE,KAAK,CAAC;AACpD,aAAO;AAAA,IACT;AAAA,IACA,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,EACX;AACF;;;ALzPO,IAAM,yBAAyB;AAAA,EACpC,MAAMC,IACH,KAAK,CAAC,QAAQ,SAAS,WAAW,SAAS,MAAM,CAAC,EAClD,SAAS,8BAA8B;AAAA,EAC1C,MAAMA,IAAE,OAAO,EAAE,SAAS,6BAA6B;AAAA,EACvD,aAAaA,IAAE,OAAO,EAAE,SAAS,0BAA0B;AAAA,EAC3D,SAASA,IAAE,OAAO,EAAE,SAAS,yCAAyC;AAAA,EACtE,aAAaA,IACV,OAAO,EACP,SAAS,EACT,SAAS,+CAA+C;AAC7D;AAEA,eAAsB,wBAAwB;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAM8E;AAC5E,MAAI;AACF,UAAM,UAAU,IAAI,iBAAiB;AACrC,UAAM,QAAQ,KAAK;AAEnB,UAAM,UAA2B;AAAA,MAC/B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa,eAAe;AAAA,IAC9B;AAEA,UAAM,SAAS,MAAM,QAAQ,iBAAiB,OAAO;AAErD,UAAM,SAAS;AAAA,MACb,QAAQ;AAAA,MACR,YAAY;AAAA,QACV,MAAM,OAAO,WAAW;AAAA,QACxB,MAAM,OAAO,WAAW;AAAA,QACxB,aAAa,OAAO,WAAW;AAAA,QAC/B,SAAS,OAAO,WAAW;AAAA,QAC3B,WAAW,OAAO,WAAW;AAAA,MAC/B;AAAA,MACA,UAAU,OAAO;AAAA,MACjB,SAAS,OAAO;AAAA,IAClB;AAEA,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;AMtEA,SAAS,KAAAC,WAAS;;;AC8BX,IAAM,cAAN,MAAkB;AAAA,EACf,iBAAgC;AAAA,EAChC,UAAuB,CAAC;AAAA;AAAA,EAGhC,UAAU,UAAwB;AAChC,SAAK,iBAAiB;AAAA,EACxB;AAAA;AAAA,EAGA,WAAW,SAAiB,WAAmB,SAAuB;AACpE,SAAK,QAAQ,KAAK;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,MACA,YAAY,KAAK,IAAI;AAAA,IACvB,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,WAAW,WAAiC;AAC1C,UAAM,YAAoC,CAAC;AAC3C,UAAM,eAAuC,CAAC;AAC9C,UAAM,SAAiC,CAAC;AACxC,QAAI,WAAW;AAGf,QAAI;AACF,YAAM,KAAK,MAAM;AASjB,UAAI;AACJ,UAAI,WAAW;AACb,oBAAY,GACT,QAAQ,gFAAgF,EACxF,IAAI,SAAS;AAAA,MAClB,OAAO;AACL,oBAAY,GACT,QAAQ,2DAA2D,EACnE,IAAI;AAAA,MACT;AAEA,iBAAW,OAAO,WAAW;AAC3B,cAAM,OAAO,IAAI,YAAY;AAC7B,YAAI,SAAS,EAAG;AAEhB,oBAAY;AACZ,cAAM,MAAM,IAAI,cAAc;AAC9B,kBAAU,GAAG,KAAK,UAAU,GAAG,KAAK,KAAK;AACzC,qBAAa,IAAI,UAAU,KAAK,aAAa,IAAI,UAAU,KAAK,KAAK;AACrE,eAAO,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,KAAK;AAAA,MAC/C;AASA,UAAI;AACJ,UAAI,WAAW;AACb,qBAAa,GACV,QAAQ,0EAA0E,EAClF,IAAI,SAAS;AAAA,MAClB,OAAO;AACL,qBAAa,GACV,QAAQ,qDAAqD,EAC7D,IAAI;AAAA,MACT;AAEA,iBAAW,OAAO,YAAY;AAC5B,cAAM,OAAO,IAAI,YAAY;AAC7B,YAAI,SAAS,EAAG;AAEhB,oBAAY;AACZ,kBAAU,IAAI,UAAU,KAAK,UAAU,IAAI,UAAU,KAAK,KAAK;AAC/D,eAAO,QAAQ,KAAK,OAAO,QAAQ,KAAK,KAAK;AAI7C,cAAM,SAAS,GACZ,QAAQ,4CAA4C,EACpD,IAAI,IAAI,SAAS;AACpB,YAAI,QAAQ;AACV,uBAAa,OAAO,UAAU,KAAK,aAAa,OAAO,UAAU,KAAK,KAAK;AAAA,QAC7E;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAGA,UAAM,kBAAkB,YACpB,KAAK,QAAQ,OAAO,CAAC,MAAM,EAAE,cAAc,SAAS,IACpD,KAAK;AAET,eAAW,SAAS,iBAAiB;AACnC,kBAAY,MAAM;AAClB,gBAAU,MAAM,SAAS,KAAK,UAAU,MAAM,SAAS,KAAK,KAAK,MAAM;AAAA,IACzE;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa,KAAK;AAAA,MAClB,iBAAiB,KAAK,mBAAmB,OAAO,KAAK,iBAAiB,WAAW;AAAA,IACnF;AAAA,EACF;AAAA;AAAA,EAGA,cAA6B;AAC3B,QAAI,KAAK,mBAAmB,KAAM,QAAO;AAEzC,UAAM,UAAU,KAAK,WAAW;AAChC,QAAI,QAAQ,YAAY,KAAK,gBAAgB;AAC3C,aAAO,qBAAqB,QAAQ,SAAS,QAAQ,CAAC,CAAC,cAAc,KAAK,eAAe,QAAQ,CAAC,CAAC;AAAA,IACrG;AAEA,UAAM,YAAY,KAAK,iBAAiB,QAAQ;AAChD,QAAI,YAAY,KAAK,iBAAiB,KAAK;AACzC,aAAO,oBAAoB,QAAQ,SAAS,QAAQ,CAAC,CAAC,iBAAiB,UAAU,QAAQ,CAAC,CAAC,kBAAkB,KAAK,eAAe,QAAQ,CAAC,CAAC;AAAA,IAC7I;AAEA,WAAO;AAAA,EACT;AACF;AAGO,IAAM,cAAc,IAAI,YAAY;;;ADpKpC,IAAM,uBAAuB;AAAA,EAClC,WAAWC,IAAE,OAAO,EAAE,SAAS,EAAE,SAAS,qCAAqC;AACjF;AAEA,eAAsB,sBAAsB;AAAA,EAC1C;AACF,GAE8E;AAC5E,MAAI;AACF,UAAM,UAAU,YAAY,WAAW,SAAS;AAChD,UAAM,gBAAgB,YAAY,YAAY;AAE9C,UAAM,SAAkC;AAAA,MACtC,GAAG;AAAA,IACL;AAEA,QAAI,eAAe;AACjB,aAAO,gBAAgB;AAAA,IACzB;AAEA,QAAI,WAAW;AACb,aAAO,oBAAoB;AAAA,IAC7B;AAEA,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;AExCA,SAAS,KAAAC,WAAS;AAIX,IAAM,qBAAqB;AAAA,EAChC,mBAAmBC,IAAE,OAAO,EAAE,SAAS,0CAA0C;AAAA,EACjF,OAAOA,IAAE,OAAO,EAAE,SAAS,mCAAmC;AAAA,EAC9D,QAAQA,IAAE,MAAMA,IAAE,OAAO,CAAC,EAAE,SAAS,kCAAkC;AAAA,EACvE,aAAaA,IACV,MAAMA,IAAE,OAAO,CAAC,EAChB,SAAS,EACT,SAAS,gCAAgC;AAC9C;AAEA,eAAsB,oBAAoB;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAK8E;AAC5E,MAAI;AACF,UAAM,eAAe,IAAI,aAAa;AACtC,UAAM,SAAS,aAAa,aAAa;AAAA,MACvC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;AC9CA,SAAS,KAAAC,WAAS;;;ACmBlB,SAAS,sBACP,WACA,WACA,aACA,iBACA,aACA,SACiB;AACjB,QAAM,KAAK,MAAM;AACjB,QAAM,MAAM,KAAK,IAAI;AACrB,QAAM,aAAa,KAAK,KAAK,QAAQ,SAAS,CAAC;AAE/C,QAAM,SAAS,GACZ;AAAA,IACC;AAAA;AAAA;AAAA,EAGF,EACC,IAAI,WAAW,WAAW,aAAa,iBAAiB,aAAa,SAAS,YAAY,GAAG;AAEhG,SAAO;AAAA,IACL,IAAI,OAAO,OAAO,eAAe;AAAA,IACjC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,EACb;AACF;AAEA,SAAS,cAAc,WAAsC;AAC3D,QAAM,KAAK,MAAM;AAYjB,QAAM,OAAO,GACV,QAAQ,+EAA+E,EACvF,IAAI,SAAS;AAEhB,SAAO,KAAK,IAAI,CAAC,OAAO;AAAA,IACtB,IAAI,EAAE;AAAA,IACN,WAAW,EAAE;AAAA,IACb,WAAW,EAAE;AAAA,IACb,aAAa,EAAE;AAAA,IACf,iBAAiB,EAAE;AAAA,IACnB,aAAa,EAAE;AAAA,IACf,SAAS,EAAE;AAAA,IACX,YAAY,EAAE;AAAA,IACd,WAAW,EAAE;AAAA,EACf,EAAE;AACJ;AAUO,IAAM,gBAAN,MAAoB;AAAA,EACR;AAAA,EAEjB,YAAY,WAAmB;AAC7B,SAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,cACE,aACA,iBACA,aACA,SACiB;AACjB,UAAM,UAAU,WAAW,KAAK,SAAS;AACzC,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,sBAAsB,KAAK,SAAS,EAAE;AAAA,IACxD;AAGA,UAAM,QAAQ;AAAA,MACZ,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,WAAO,MAAM,qBAAqB,WAAW,UAAU,eAAe,WAAW,WAAW,KAAK;AAAA,MAC/F,WAAW,KAAK;AAAA,IAClB,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,kBAAmC;AACvC,UAAM,UAAU,WAAW,KAAK,SAAS;AACzC,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,sBAAsB,KAAK,SAAS,EAAE;AAAA,IACxD;AAGA,kBAAc,KAAK,WAAW;AAAA,MAC5B,OAAO;AAAA,MACP,QAAQ;AAAA,IACV,CAAC;AAED,UAAM,aAAa,cAAc,KAAK,SAAS;AAI/C,UAAM,WAAqB,CAAC;AAG5B,UAAM,eAAe,CAAC,GAAG,IAAI,IAAI,WAAW,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAEtE,aAAS,KAAK,mBAAmB;AACjC,aAAS,KAAK,aAAa,QAAQ,KAAK,EAAE;AAC1C,aAAS,KAAK,aAAY,oBAAI,KAAK,GAAE,YAAY,CAAC,EAAE;AACpD,aAAS,KAAK,oBAAoB,aAAa,KAAK,IAAI,CAAC,EAAE;AAC3D,aAAS,KAAK,EAAE;AAGhB,aAAS,KAAK,WAAW;AACzB,YAAQ,OAAO,QAAQ,CAAC,MAAM,MAAM;AAClC,eAAS,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE;AAAA,IACnC,CAAC;AACD,aAAS,KAAK,EAAE;AAGhB,UAAM,iBAAiB,WAAW,OAAO,CAAC,MAAM,EAAE,oBAAoB,EAAE;AACxE,QAAI,eAAe,SAAS,GAAG;AAC7B,eAAS,KAAK,uBAAuB;AACrC,iBAAW,SAAS,gBAAgB;AAClC,iBAAS,KAAK,OAAO,MAAM,WAAW,EAAE;AACxC,iBAAS,KAAK,MAAM,OAAO;AAC3B,iBAAS,KAAK,EAAE;AAAA,MAClB;AAAA,IACF;AAGA,aAAS,IAAI,GAAG,IAAI,QAAQ,OAAO,QAAQ,KAAK;AAC9C,YAAM,cAAc,WAAW,OAAO,CAAC,MAAM,EAAE,oBAAoB,CAAC;AACpE,UAAI,YAAY,SAAS,GAAG;AAC1B,iBAAS,KAAK,kBAAkB,QAAQ,OAAO,CAAC,CAAC,EAAE;AACnD,mBAAW,SAAS,aAAa;AAC/B,mBAAS,KAAK,KAAK,MAAM,WAAW,aAAa,MAAM,WAAW,IAAI;AACtE,mBAAS,KAAK,MAAM,OAAO;AAC3B,mBAAS,KAAK,EAAE;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AAGA,UAAM,mBAAmB,WAAW,OAAO,CAAC,MAAM,EAAE,oBAAoB,EAAE;AAC1E,QAAI,iBAAiB,SAAS,GAAG;AAC/B,eAAS,KAAK,oBAAoB;AAClC,iBAAW,SAAS,kBAAkB;AACpC,iBAAS,KAAK,OAAO,MAAM,WAAW,EAAE;AACxC,iBAAS,KAAK,MAAM,OAAO;AAC3B,iBAAS,KAAK,EAAE;AAAA,MAClB;AAAA,IACF;AAEA,UAAM,UAAU,SAAS,KAAK,IAAI;AAIlC,UAAM,cAA4B,aAAa,IAAI,CAAC,MAAM,SAAS;AAAA,MACjE,IAAI,UAAU,KAAK,SAAS,IAAI,GAAG;AAAA,MACnC,OAAO,GAAG,IAAI;AAAA,MACd,aAAa,6BAA6B,IAAI;AAAA,MAC9C,oBAAoB;AAAA;AAAA,MACpB,cAAc;AAAA,MACd,UAAU;AAAA,MACV,cAAc,CAAC;AAAA,MACf,oBAAoB,CAAC,oDAAoD;AAAA,IAC3E,EAAE;AAEF,UAAM,gBAAgB,cAAc;AAAA,MAClC,WAAW,KAAK;AAAA,MAChB,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,IACF,CAAC;AAGD,kBAAc,KAAK,WAAW;AAAA,MAC5B,QAAQ;AAAA,MACR,aAAa,KAAK,IAAI;AAAA,IACxB,CAAC;AAED,WAAO,KAAK,qBAAqB,EAAE,WAAW,KAAK,UAAU,CAAC;AAE9D,WAAO,cAAc;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAsB;AACpB,UAAM,UAAU,WAAW,KAAK,SAAS;AACzC,QAAI,CAAC,QAAS,QAAO;AACrB,WAAO,CAAC,aAAa,aAAa,UAAU,EAAE,SAAS,QAAQ,MAAM;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBAAmC;AACjC,WAAO,cAAc,KAAK,SAAS;AAAA,EACrC;AACF;;;AD/PO,IAAM,sBAAsB;AAAA,EACjC,WAAWC,IAAE,OAAO,EAAE,SAAS,YAAY;AAAA,EAC3C,aAAaA,IAAE,OAAO,EAAE,SAAS,oEAAoE;AAAA,EACrG,iBAAiBA,IACd,OAAO,EACP,SAAS,8EAA8E;AAAA,EAC1F,aAAaA,IAAE,OAAO,EAAE,SAAS,mDAAmD;AAAA,EACpF,SAASA,IAAE,OAAO,EAAE,SAAS,yCAAyC;AACxE;AAEA,eAAsB,qBAAqB;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAM8E;AAC5E,MAAI;AACF,UAAM,SAAS,IAAI,cAAc,SAAS;AAC1C,UAAM,QAAQ,OAAO,cAAc,aAAa,iBAAiB,aAAa,OAAO;AAErF,UAAM,SAAS;AAAA,MACb,SAAS;AAAA,MACT,SAAS,MAAM;AAAA,MACf;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;AEnDA,SAAS,KAAAC,WAAS;AAIX,IAAM,wBAAwB;AAAA,EACnC,WAAWC,IAAE,OAAO,EAAE,SAAS,oCAAoC;AACrE;AAEA,eAAsB,uBAAuB;AAAA,EAC3C;AACF,GAE8E;AAC5E,MAAI;AACF,UAAM,SAAS,IAAI,cAAc,SAAS;AAC1C,UAAM,YAAY,MAAM,OAAO,gBAAgB;AAG/C,UAAM,UAAU,oBAAoB,SAAS;AAE7C,UAAM,SAAS;AAAA,MACb;AAAA,MACA;AAAA,MACA,SAAS,SAAS,WAAW;AAAA,IAC/B;AAEA,WAAO;AAAA,MACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,CAAC;AAAA,IACnE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,WAAO;AAAA,MACL,SAAS;AAAA,QACP,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,QAAQ,GAAG,MAAM,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;ApCHO,SAAS,eAA0B;AACxC,QAAM,SAAS,IAAI,UAAU;AAAA,IAC3B,MAAM;AAAA,IACN,SAAS;AAAA,EACX,CAAC;AAGD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AACT;;;AqCzKA,SAAS,gBAAgB,wBAAwB;AACjD,SAAS,iBAAiB,aAAAC,kBAAiB;;;ACOpC,SAAS,mBAA2B;AACzC;AAAA;AAAA,IAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA4xCpB;;;AC5xCA,SAAS,gBAAAC,qBAAoB;AA+BtB,IAAM,cAAN,cAA0BC,cAAa;AAAA,EACpC,WAAW,oBAAI,IAA0B;AAAA,EACzC,iBAAiB,oBAAI,IAA4B;AAAA,EACjD,gBAAgB,oBAAI,IAA0B;AAAA;AAAA;AAAA;AAAA,EAMtD,gBAAgB,MAIL;AACT,UAAM,cAAc,KAAK,qBAAqB,KAAK,WAAW;AAE9D,SAAK,SAAS,IAAI,KAAK,WAAW;AAAA,MAChC,aAAa,KAAK;AAAA,MAClB;AAAA,MACA,aAAa,KAAK;AAAA,MAClB,UAAU;AAAA,MACV,QAAQ,oBAAI,IAAI;AAAA,MAChB,OAAO,CAAC;AAAA,MACR,SAAS;AAAA,MACT,WAAW;AAAA,MACX,UAAU,CAAC;AAAA,IACb,CAAC;AAED,WAAO,KAAK,uBAAuB,WAAW,KAAK,KAAK,SAAS,GAAG;AAGpE,SAAK;AAAA,MACH;AAAA,MACA,KAAK,UAAU;AAAA,QACb,MAAM;AAAA,QACN,WAAW,KAAK;AAAA,QAChB;AAAA,QACA,aAAa,KAAK;AAAA,MACpB,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,kBAAkB,WAAyB;AACzC,UAAM,UAAU,KAAK,SAAS,IAAI,SAAS;AAC3C,QAAI,SAAS;AACX,cAAQ,WAAW;AACnB,aAAO,KAAK,wBAAwB,QAAQ,WAAW,EAAE;AAGzD,WAAK;AAAA,QACH;AAAA,QACA,KAAK,UAAU;AAAA,UACb,MAAM;AAAA,UACN;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,mBAAmB,WAAmB,OAAyB;AAC7D,UAAM,UAAU,KAAK,SAAS,IAAI,SAAS;AAC3C,QAAI,CAAC,QAAS;AAGd,SAAK,WAAW,SAAS,KAAK;AAG9B,QAAI,CAAC,KAAK,cAAc,IAAI,SAAS,GAAG;AACtC,WAAK,cAAc,IAAI,WAAW,CAAC,CAAC;AAAA,IACtC;AACA,SAAK,cAAc,IAAI,SAAS,EAAG,KAAK,KAAK;AAG7C,QAAI,CAAC,KAAK,eAAe,IAAI,SAAS,GAAG;AACvC,WAAK,eAAe;AAAA,QAClB;AAAA,QACA,WAAW,MAAM;AACf,eAAK,YAAY,SAAS;AAC1B,eAAK,eAAe,OAAO,SAAS;AAAA,QACtC,GAAG,GAAG;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,cAAoC;AAClC,WAAO;AAAA,MACL,MAAM;AAAA,MACN,UAAU,MAAM,KAAK,KAAK,SAAS,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,WAAW,CAAC,OAAO;AAAA,QACrE;AAAA,QACA,aAAa,EAAE;AAAA,QACf,aAAa,EAAE;AAAA,QACf,UAAU,EAAE;AAAA,QACZ,UAAU;AAAA,UACR,QAAQ,MAAM,KAAK,EAAE,OAAO,OAAO,CAAC;AAAA,UACpC,OAAO,CAAC,GAAG,EAAE,KAAK;AAAA,UAClB,SAAS,EAAE;AAAA,UACX,WAAW,EAAE;AAAA,QACf;AAAA,MACF,EAAE;AAAA,IACJ;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMQ,qBAAqB,aAA6B;AACxD,UAAM,WAAW,MAAM,KAAK,KAAK,SAAS,OAAO,CAAC,EAAE;AAAA,MAClD,CAAC,MAAM,EAAE;AAAA,IACX;AACA,QAAI,CAAC,SAAS,SAAS,WAAW,EAAG,QAAO;AAC5C,QAAI,IAAI;AACR,WAAO,SAAS,SAAS,GAAG,WAAW,KAAK,CAAC,GAAG,EAAG;AACnD,WAAO,GAAG,WAAW,KAAK,CAAC;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAMQ,WAAW,SAAuB,OAAyB;AACjE,YAAQ,SAAS,KAAK,EAAE,WAAW,KAAK,IAAI,GAAG,MAAM,CAAC;AAEtD,QAAI,QAAQ,SAAS,SAAS,IAAK,SAAQ,SAAS,MAAM;AAE1D,YAAQ,MAAM,MAAM;AAAA,MAClB,KAAK,iBAAiB;AACpB,cAAM,QAAoB;AAAA,UACxB,IAAI,MAAM;AAAA,UACV,MAAM,MAAM;AAAA,UACZ,OAAO,MAAM;AAAA,UACb,QAAQ;AAAA,UACR,UAAU,MAAM;AAAA,UAChB,YAAY,MAAM;AAAA,UAClB,aAAa;AAAA,UACb,SAAS;AAAA,QACX;AACA,gBAAQ,OAAO,IAAI,MAAM,SAAS,KAAK;AAEvC,YAAI,MAAM,UAAU;AAClB,kBAAQ,MAAM,KAAK;AAAA,YACjB,IAAI,QAAQ,MAAM,QAAQ,IAAI,MAAM,OAAO;AAAA,YAC3C,QAAQ,MAAM;AAAA,YACd,QAAQ,MAAM;AAAA,YACd,UAAU;AAAA,YACV,QAAQ;AAAA,YACR,OAAO;AAAA,UACT,CAAC;AAAA,QACH;AACA;AAAA,MACF;AAAA,MAEA,KAAK,mBAAmB;AACtB,gBAAQ,OAAO,OAAO,MAAM,OAAO;AACnC,gBAAQ,QAAQ,QAAQ,MAAM;AAAA,UAC5B,CAAC,MAAM,EAAE,WAAW,MAAM,WAAW,EAAE,WAAW,MAAM;AAAA,QAC1D;AACA;AAAA,MACF;AAAA,MAEA,KAAK,iBAAiB;AACpB,cAAM,IAAI,QAAQ,OAAO,IAAI,MAAM,OAAO;AAC1C,YAAI,EAAG,GAAE,SAAS,MAAM;AACxB;AAAA,MACF;AAAA,MAEA,KAAK,iBAAiB;AACpB,cAAM,IAAI,QAAQ,OAAO,IAAI,MAAM,OAAO;AAC1C,YAAI,GAAG;AACL,YAAE,cAAc,MAAM;AACtB,YAAE,SAAS;AAAA,QACb;AACA;AAAA,MACF;AAAA,MAEA,KAAK,kBAAkB;AACrB,cAAM,IAAI,QAAQ,OAAO,IAAI,MAAM,OAAO;AAC1C,YAAI,GAAG;AACL,YAAE,cAAc;AAChB,YAAE,SAAS,MAAM,WAAW,YAAY,cAAc;AAAA,QACxD;AACA;AAAA,MACF;AAAA,MAEA,KAAK,gBAAgB;AACnB,cAAM,SAAS,OAAO,MAAM,MAAM,IAAI,MAAM,IAAI,IAAI,KAAK,IAAI,CAAC;AAC9D,gBAAQ,MAAM,KAAK;AAAA,UACjB,IAAI;AAAA,UACJ,QAAQ,MAAM;AAAA,UACd,QAAQ,MAAM;AAAA,UACd,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,OAAO,MAAM;AAAA,QACf,CAAC;AAED,mBAAW,MAAM;AACf,kBAAQ,QAAQ,QAAQ,MAAM,OAAO,CAAC,MAAM,EAAE,OAAO,MAAM;AAAA,QAC7D,GAAG,GAAK;AACR;AAAA,MACF;AAAA,MAEA,KAAK;AAAA,MACL,KAAK;AAEH;AAAA,MAEF,KAAK,eAAe;AAClB,gBAAQ,YAAY,MAAM;AAC1B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMQ,YAAY,WAAyB;AAC3C,UAAM,SAAS,KAAK,cAAc,IAAI,SAAS;AAC/C,UAAM,UAAU,KAAK,SAAS,IAAI,SAAS;AAC3C,QAAI,CAAC,UAAU,CAAC,WAAW,OAAO,WAAW,EAAG;AAEhD,UAAM,QAAsB;AAAA,MAC1B,MAAM;AAAA,MACN;AAAA,MACA,aAAa,QAAQ;AAAA,MACrB,WAAW,KAAK,IAAI;AAAA,MACpB,QAAQ,CAAC,GAAG,MAAM;AAAA,IACpB;AAEA,SAAK,KAAK,aAAa,KAAK,UAAU,KAAK,CAAC;AAC5C,SAAK,cAAc,IAAI,WAAW,CAAC,CAAC;AAAA,EACtC;AACF;;;AC3RA,OAAO,eAAe;AAKf,IAAM,kBAAN,MAAsB;AAAA,EACnB,KAAuB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,WAAmB,aAAqB,aAAqB;AACvE,SAAK,YAAY;AACjB,SAAK,cAAc;AACnB,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,QAAQ,MAAoB;AAC1B,SAAK,KAAK,IAAI,UAAU,kBAAkB,IAAI,EAAE;AAEhD,SAAK,GAAG,GAAG,QAAQ,MAAM;AACvB,aAAO,KAAK,8CAA8C,KAAK,SAAS,GAAG;AAE3E,YAAM,MAAuB;AAAA,QAC3B,MAAM;AAAA,QACN,WAAW,KAAK;AAAA,QAChB,aAAa,KAAK;AAAA,QAClB,aAAa,KAAK;AAAA,MACpB;AACA,WAAK,GAAI,KAAK,KAAK,UAAU,GAAG,CAAC;AAGjC,eAAS,GAAG,eAAe,CAAC,UAAsB;AAChD,YAAI,KAAK,IAAI,eAAe,UAAU,MAAM;AAC1C,gBAAM,aAAkC;AAAA,YACtC,MAAM;AAAA,YACN,WAAW,KAAK;AAAA,YAChB;AAAA,UACF;AACA,eAAK,GAAG,KAAK,KAAK,UAAU,UAAU,CAAC;AAAA,QACzC;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAED,SAAK,GAAG,GAAG,SAAS,CAAC,QAAQ;AAC3B,aAAO,KAAK,2BAA2B,IAAI,OAAO,EAAE;AAAA,IACtD,CAAC;AAED,SAAK,GAAG,GAAG,SAAS,MAAM;AACxB,aAAO,KAAK,+BAA+B;AAAA,IAC7C,CAAC;AAAA,EACH;AAAA,EAEA,aAAmB;AACjB,QAAI,KAAK,MAAM,KAAK,GAAG,eAAe,UAAU,MAAM;AACpD,YAAM,MAAyB;AAAA,QAC7B,MAAM;AAAA,QACN,WAAW,KAAK;AAAA,MAClB;AACA,WAAK,GAAG,KAAK,KAAK,UAAU,GAAG,CAAC;AAChC,WAAK,GAAG,MAAM;AAAA,IAChB;AACA,SAAK,KAAK;AAAA,EACZ;AACF;;;AH3CO,SAAS,eAAe,SAAqD;AAClF,QAAM,OAAO,UAAU,EAAE;AAEzB,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,aAAa,iBAAiB,CAAC,KAAK,QAAQ;AAChD,UAAI,IAAI,QAAQ,OAAO,IAAI,QAAQ,eAAe;AAChD,YAAI,UAAU,KAAK,EAAE,gBAAgB,2BAA2B,CAAC;AACjE,YAAI,IAAI,iBAAiB,CAAC;AAAA,MAC5B,OAAO;AACL,YAAI,UAAU,GAAG;AACjB,YAAI,IAAI,WAAW;AAAA,MACrB;AAAA,IACF,CAAC;AAED,eAAW,GAAG,SAAS,CAAC,QAA+B;AACrD,UAAI,IAAI,SAAS,cAAc;AAE7B,eAAO,KAAK,kBAAkB,IAAI,qCAAgC;AAClE,cAAM,SAAS,IAAI,gBAAgB,QAAQ,WAAW,QAAQ,aAAa,QAAQ,WAAW;AAC9F,eAAO,QAAQ,IAAI;AACnB,gBAAQ;AAAA,UACN,SAAS;AAAA,UACT,OAAO,MAAM,OAAO,WAAW;AAAA,QACjC,CAAC;AAAA,MACH,OAAO;AACL,eAAO,MAAM,oBAAoB,IAAI,OAAO,EAAE;AAC9C,gBAAQ,EAAE,SAAS,OAAO,OAAO,MAAM;AAAA,QAAC,EAAE,CAAC;AAAA,MAC7C;AAAA,IACF,CAAC;AAED,eAAW,OAAO,MAAM,aAAa,MAAM;AACzC,aAAO,KAAK,sDAAiD,IAAI,EAAE;AAEnE,YAAM,MAAM,IAAI,gBAAgB,EAAE,QAAQ,WAAW,CAAC;AACtD,YAAM,SAAS,IAAI,YAAY;AAG/B,YAAM,cAAc,OAAO,gBAAgB;AAAA,QACzC,WAAW,QAAQ;AAAA,QACnB,aAAa,QAAQ;AAAA,QACrB,aAAa,QAAQ;AAAA,MACvB,CAAC;AACD,aAAO,KAAK,2BAA2B,WAAW,EAAE;AAGpD,eAAS,GAAG,eAAe,CAAC,UAAsB;AAChD,eAAO,mBAAmB,QAAQ,WAAW,KAAK;AAAA,MACpD,CAAC;AAGD,UAAI,GAAG,cAAc,CAAC,OAAkB;AAEtC,WAAG,KAAK,KAAK,UAAU,OAAO,YAAY,CAAC,CAAC;AAE5C,WAAG,GAAG,WAAW,CAAC,SAAiB;AACjC,cAAI;AACF,kBAAM,MAAqB,KAAK,MAAM,KAAK,SAAS,CAAC;AAErD,gBAAI,IAAI,SAAS,YAAY;AAC3B,oBAAM,OAAO,OAAO,gBAAgB;AAAA,gBAClC,WAAW,IAAI;AAAA,gBACf,aAAa,IAAI;AAAA,gBACjB,aAAa,IAAI;AAAA,cACnB,CAAC;AAED,oBAAM,eAAe,KAAK,UAAU;AAAA,gBAClC,MAAM;AAAA,gBACN,WAAW,IAAI;AAAA,gBACf,aAAa;AAAA,gBACb,aAAa,IAAI;AAAA,cACnB,CAAC;AACD,kBAAI,QAAQ,QAAQ,CAAC,MAAM;AACzB,oBAAI,MAAM,MAAM,EAAE,eAAeC,WAAU,KAAM,GAAE,KAAK,YAAY;AAAA,cACtE,CAAC;AAAA,YACH,WAAW,IAAI,SAAS,iBAAiB;AACvC,qBAAO,mBAAmB,IAAI,WAAW,IAAI,KAAK;AAAA,YACpD,WAAW,IAAI,SAAS,cAAc;AACpC,qBAAO,kBAAkB,IAAI,SAAS;AACtC,oBAAM,eAAe,KAAK,UAAU;AAAA,gBAClC,MAAM;AAAA,gBACN,WAAW,IAAI;AAAA,cACjB,CAAC;AACD,kBAAI,QAAQ,QAAQ,CAAC,MAAM;AACzB,oBAAI,EAAE,eAAeA,WAAU,KAAM,GAAE,KAAK,YAAY;AAAA,cAC1D,CAAC;AAAA,YACH,WAAY,IAAY,SAAS,QAAQ;AACvC,iBAAG,KAAK,KAAK,UAAU,EAAE,MAAM,OAAO,CAAC,CAAC;AAAA,YAC1C;AAAA,UACF,QAAQ;AAAA,UAER;AAAA,QACF,CAAC;AAAA,MACH,CAAC;AAGD,aAAO,GAAG,aAAa,CAAC,SAAiB;AACvC,YAAI,QAAQ,QAAQ,CAAC,MAAM;AACzB,cAAI,EAAE,eAAeA,WAAU,KAAM,GAAE,KAAK,IAAI;AAAA,QAClD,CAAC;AAAA,MACH,CAAC;AAED,cAAQ;AAAA,QACN,SAAS;AAAA,QACT,OAAO,MAAM;AACX,iBAAO,kBAAkB,QAAQ,SAAS;AAC1C,cAAI,MAAM;AACV,qBAAW,MAAM;AAAA,QACnB;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH,CAAC;AACH;;;AtC9HA,eAAe,OAAO;AACpB,iBAAe;AAGf,QAAM,mBAAmB,QAAQ,IAAI,oBAAoB,MAAM;AAE/D,MAAI,CAAC,kBAAkB;AACrB,UAAM,YAAY,WAAW;AAC7B,UAAM,cAAc,QAAQ,IAAI;AAChC,UAAM,cAAc,YAAY,MAAM,GAAG,EAAE,IAAI,KAAK;AACpD,mBAAe,EAAE,WAAW,aAAa,YAAY,CAAC,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EACxE;AAEA,QAAM,SAAS,aAAa;AAC5B,QAAM,YAAY,IAAI,qBAAqB;AAC3C,QAAM,OAAO,QAAQ,SAAS;AAChC;AAEA,KAAK,EAAE,MAAM,CAAC,UAAU;AACtB,UAAQ,MAAM,gBAAgB,KAAK;AACnC,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["uuidv4","uuidv4","uuidv4","uuidv4","uuidv4","uuidv4","uuidv4","uuidv4","z","z","result","z","z","z","uuidv4","DEPARTMENT_KEYWORDS","uuidv4","z","z","z","z","z","z","z","getDb","z","z","z","z","z","z","z","join","join","mkdirSync","writeFileSync","join","join","mkdirSync","writeFileSync","readFileSync","writeFileSync","join","join","writeFileSync","z","z","z","z","z","z","z","z","z","WebSocket","EventEmitter","EventEmitter","WebSocket"]}