squads-cli 0.1.2 → 0.3.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/README.md +164 -21
- package/dist/chunk-266URT5W.js +915 -0
- package/dist/chunk-266URT5W.js.map +1 -0
- package/dist/chunk-7OCVIDC7.js +12 -0
- package/dist/chunk-7OCVIDC7.js.map +1 -0
- package/dist/chunk-FUHBEL3L.js +203 -0
- package/dist/chunk-FUHBEL3L.js.map +1 -0
- package/dist/cli.js +2118 -1017
- package/dist/cli.js.map +1 -1
- package/dist/memory-4PVUKIDK.js +19 -0
- package/dist/memory-4PVUKIDK.js.map +1 -0
- package/dist/sessions-UR3YGSLR.js +15 -0
- package/dist/sessions-UR3YGSLR.js.map +1 -0
- package/docker/.env.example +17 -0
- package/docker/README.md +92 -0
- package/docker/docker-compose.engram.yml +289 -0
- package/docker/docker-compose.yml +194 -0
- package/docker/init-db.sql +399 -0
- package/docker/init-engram-db.sql +148 -0
- package/docker/init-langfuse-db.sh +10 -0
- package/docker/otel-collector.yaml +34 -0
- package/docker/squads-bridge/Dockerfile +14 -0
- package/docker/squads-bridge/Dockerfile.proxy +14 -0
- package/docker/squads-bridge/anthropic_proxy.py +313 -0
- package/docker/squads-bridge/requirements.txt +7 -0
- package/docker/squads-bridge/squads_bridge.py +1457 -0
- package/docker/telemetry-ping/Dockerfile +10 -0
- package/docker/telemetry-ping/deploy.sh +69 -0
- package/docker/telemetry-ping/main.py +136 -0
- package/docker/telemetry-ping/requirements.txt +3 -0
- package/package.json +12 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/sessions.ts","../src/lib/terminal.ts","../src/commands/sessions.ts"],"sourcesContent":["/**\n * Session tracking for active Claude Code sessions\n * Provides heartbeat-based session state management\n *\n * Storage:\n * - Active sessions: .agents/sessions/active/{id}.json (quick lookup)\n * - Event history: .agents/sessions/history.jsonl (analytics)\n */\n\nimport { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync, unlinkSync, appendFileSync, createReadStream } from 'fs';\nimport { join, dirname } from 'path';\nimport { randomBytes } from 'crypto';\nimport { createInterface } from 'readline';\nimport { execSync } from 'child_process';\n\nexport interface SessionState {\n sessionId: string;\n squad: string | null;\n startedAt: string;\n lastHeartbeat: string;\n cwd: string;\n pid: number;\n}\n\nexport interface SessionSummary {\n totalSessions: number;\n bySquad: Record<string, number>;\n squadCount: number;\n byTool?: Record<string, number>; // Optional: breakdown by AI tool\n}\n\n// Event types for JSONL history\nexport type SessionEventType = 'start' | 'heartbeat' | 'stop' | 'stale_cleanup';\n\nexport interface SessionEvent {\n type: SessionEventType;\n sessionId: string;\n squad: string | null;\n ts: string;\n cwd?: string;\n pid?: number;\n durationMs?: number; // For stop events\n}\n\nexport interface SessionHistoryStats {\n totalSessions: number;\n totalDurationMs: number;\n avgDurationMs: number;\n bySquad: Record<string, { count: number; durationMs: number }>;\n byDate: Record<string, number>; // YYYY-MM-DD -> count\n peakConcurrent: number;\n}\n\n// Live AI coding assistant process info\nexport interface AIProcess {\n pid: number;\n tty: string;\n cwd: string;\n squad: string | null;\n tool: string; // 'claude', 'cursor', 'aider', 'gemini', etc.\n}\n\n// Supported AI coding tools (process names to detect)\nconst AI_TOOL_PATTERNS: { pattern: RegExp; name: string }[] = [\n { pattern: /^claude$/, name: 'claude' },\n { pattern: /^cursor$/i, name: 'cursor' },\n { pattern: /^aider$/, name: 'aider' },\n { pattern: /^gemini$/i, name: 'gemini' },\n { pattern: /^copilot$/i, name: 'copilot' },\n { pattern: /^cody$/i, name: 'cody' },\n { pattern: /^continue$/i, name: 'continue' },\n];\n\n// Session is stale after 5 minutes without heartbeat\nconst STALE_THRESHOLD_MS = 5 * 60 * 1000;\n\n// History file name\nconst HISTORY_FILE = 'history.jsonl';\n\n// Active sessions subdirectory\nconst ACTIVE_DIR = 'active';\n\n// Directory mapping for squad detection\nconst SQUAD_DIR_MAP: Record<string, string> = {\n 'hq': 'company',\n 'agents-squads-web': 'website',\n 'company': 'company',\n 'product': 'product',\n 'engineering': 'engineering',\n 'research': 'research',\n 'intelligence': 'intelligence',\n 'customer': 'customer',\n 'finance': 'finance',\n 'marketing': 'marketing',\n};\n\n/**\n * Find the .agents directory (sessions live at .agents/sessions/)\n */\nexport function findAgentsDir(): string | null {\n let dir = process.cwd();\n\n for (let i = 0; i < 5; i++) {\n const agentsPath = join(dir, '.agents');\n if (existsSync(agentsPath)) {\n return agentsPath;\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n\n return null;\n}\n\n/**\n * Get the sessions base directory\n */\nexport function getSessionsBaseDir(): string | null {\n const agentsDir = findAgentsDir();\n if (!agentsDir) return null;\n\n const sessionsDir = join(agentsDir, 'sessions');\n if (!existsSync(sessionsDir)) {\n mkdirSync(sessionsDir, { recursive: true });\n }\n return sessionsDir;\n}\n\n/**\n * Get the active sessions directory, creating it if needed\n */\nexport function getSessionsDir(): string | null {\n const baseDir = getSessionsBaseDir();\n if (!baseDir) return null;\n\n const activeDir = join(baseDir, ACTIVE_DIR);\n if (!existsSync(activeDir)) {\n mkdirSync(activeDir, { recursive: true });\n }\n return activeDir;\n}\n\n/**\n * Get the history file path\n */\nexport function getHistoryFilePath(): string | null {\n const baseDir = getSessionsBaseDir();\n if (!baseDir) return null;\n return join(baseDir, HISTORY_FILE);\n}\n\n/**\n * Append an event to the history JSONL file\n */\nfunction appendEvent(event: SessionEvent): void {\n const historyPath = getHistoryFilePath();\n if (!historyPath) return;\n\n try {\n const line = JSON.stringify(event) + '\\n';\n appendFileSync(historyPath, line);\n } catch {\n // Silently fail - history is optional\n }\n}\n\n/**\n * Detect which squad based on current working directory\n */\nexport function detectSquad(cwd: string = process.cwd()): string | null {\n // Pattern: .../agents-squads/{domain}/...\n const match = cwd.match(/agents-squads\\/([^/]+)/);\n if (match) {\n const dir = match[1];\n return SQUAD_DIR_MAP[dir] || dir;\n }\n return null;\n}\n\n/**\n * Detect running AI coding assistant processes (real-time process detection)\n * Supports: Claude, Cursor, Aider, Gemini, Copilot, Cody, Continue\n */\nexport function detectAIProcesses(): AIProcess[] {\n const processes: AIProcess[] = [];\n\n try {\n // Get all processes - we'll filter for AI tools\n const psOutput = execSync('ps -eo pid,tty,comm 2>/dev/null', {\n encoding: 'utf-8',\n timeout: 5000,\n }).trim();\n\n if (!psOutput) return [];\n\n const lines = psOutput.split('\\n').filter(line => line.trim());\n\n for (const line of lines) {\n const parts = line.trim().split(/\\s+/);\n if (parts.length < 3) continue;\n\n const pid = parseInt(parts[0], 10);\n const tty = parts[1];\n const comm = parts.slice(2).join(' '); // Process name (may have spaces)\n\n if (isNaN(pid)) continue;\n\n // Check if this is an AI coding tool\n let toolName: string | null = null;\n for (const { pattern, name } of AI_TOOL_PATTERNS) {\n if (pattern.test(comm)) {\n toolName = name;\n break;\n }\n }\n\n if (!toolName) continue;\n\n // Get the working directory for this process\n let cwd = '';\n try {\n const lsofOutput = execSync(`lsof -p ${pid} 2>/dev/null | grep cwd | awk '{print $NF}'`, {\n encoding: 'utf-8',\n timeout: 3000,\n }).trim();\n cwd = lsofOutput || '';\n } catch {\n // Can't get cwd, use empty string\n cwd = '';\n }\n\n // Detect squad from working directory\n const squad = detectSquad(cwd);\n\n processes.push({\n pid,\n tty,\n cwd,\n squad,\n tool: toolName,\n });\n }\n } catch {\n // Process detection failed (command not found, timeout, etc.)\n // Return empty array - graceful degradation\n }\n\n return processes;\n}\n\n// Backwards compatibility alias\nexport const detectClaudeProcesses = detectAIProcesses;\n\n/**\n * Get live session summary using real process detection\n */\nexport function getLiveSessionSummary(): SessionSummary {\n const processes = detectAIProcesses();\n const bySquad: Record<string, number> = {};\n const byTool: Record<string, number> = {};\n\n for (const proc of processes) {\n const squad = proc.squad || 'unknown';\n bySquad[squad] = (bySquad[squad] || 0) + 1;\n byTool[proc.tool] = (byTool[proc.tool] || 0) + 1;\n }\n\n return {\n totalSessions: processes.length,\n bySquad,\n squadCount: Object.keys(bySquad).length,\n byTool,\n };\n}\n\n/**\n * Generate a unique session ID\n */\nfunction generateSessionId(): string {\n return randomBytes(8).toString('hex');\n}\n\n/**\n * Get current session ID from environment or generate new one\n */\nlet currentSessionId: string | null = null;\n\nexport function getSessionId(): string {\n if (currentSessionId) return currentSessionId;\n\n // Check if we have a session file for this PID\n const sessionsDir = getSessionsDir();\n if (sessionsDir) {\n const pid = process.pid;\n const files = readdirSync(sessionsDir).filter(f => f.endsWith('.json'));\n\n for (const file of files) {\n try {\n const content = readFileSync(join(sessionsDir, file), 'utf-8');\n const session = JSON.parse(content) as SessionState;\n if (session.pid === pid) {\n currentSessionId = session.sessionId;\n return currentSessionId;\n }\n } catch {\n // Ignore parse errors\n }\n }\n }\n\n // Generate new session ID\n currentSessionId = generateSessionId();\n return currentSessionId;\n}\n\n/**\n * Start a new session (write initial state file and log event)\n */\nexport function startSession(squad?: string): SessionState | null {\n const sessionsDir = getSessionsDir();\n if (!sessionsDir) return null;\n\n const sessionId = getSessionId();\n const now = new Date().toISOString();\n const cwd = process.cwd();\n const detectedSquad = squad || detectSquad(cwd);\n\n const session: SessionState = {\n sessionId,\n squad: detectedSquad,\n startedAt: now,\n lastHeartbeat: now,\n cwd,\n pid: process.pid,\n };\n\n const sessionPath = join(sessionsDir, `${sessionId}.json`);\n writeFileSync(sessionPath, JSON.stringify(session, null, 2));\n\n // Log start event to history\n appendEvent({\n type: 'start',\n sessionId,\n squad: detectedSquad,\n ts: now,\n cwd,\n pid: process.pid,\n });\n\n return session;\n}\n\n/**\n * Update heartbeat for current session\n */\nexport function updateHeartbeat(): boolean {\n const sessionsDir = getSessionsDir();\n if (!sessionsDir) return false;\n\n const sessionId = getSessionId();\n const sessionPath = join(sessionsDir, `${sessionId}.json`);\n\n if (!existsSync(sessionPath)) {\n // Session doesn't exist, start a new one\n startSession();\n return true;\n }\n\n try {\n const content = readFileSync(sessionPath, 'utf-8');\n const session = JSON.parse(content) as SessionState;\n session.lastHeartbeat = new Date().toISOString();\n writeFileSync(sessionPath, JSON.stringify(session, null, 2));\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Stop current session (remove state file and log event)\n */\nexport function stopSession(): boolean {\n const sessionsDir = getSessionsDir();\n if (!sessionsDir) return false;\n\n const sessionId = getSessionId();\n const sessionPath = join(sessionsDir, `${sessionId}.json`);\n\n if (existsSync(sessionPath)) {\n // Read session to get start time and squad for duration calculation\n let squad: string | null = null;\n let durationMs: number | undefined;\n\n try {\n const content = readFileSync(sessionPath, 'utf-8');\n const session = JSON.parse(content) as SessionState;\n squad = session.squad;\n durationMs = Date.now() - new Date(session.startedAt).getTime();\n } catch {\n // Ignore parse errors\n }\n\n unlinkSync(sessionPath);\n currentSessionId = null;\n\n // Log stop event to history\n appendEvent({\n type: 'stop',\n sessionId,\n squad,\n ts: new Date().toISOString(),\n durationMs,\n });\n\n return true;\n }\n\n return false;\n}\n\n/**\n * Get all active sessions (non-stale)\n */\nexport function getActiveSessions(): SessionState[] {\n const sessionsDir = getSessionsDir();\n if (!sessionsDir) return [];\n\n const now = Date.now();\n const sessions: SessionState[] = [];\n\n try {\n const files = readdirSync(sessionsDir).filter(f => f.endsWith('.json'));\n\n for (const file of files) {\n try {\n const filePath = join(sessionsDir, file);\n const content = readFileSync(filePath, 'utf-8');\n const session = JSON.parse(content) as SessionState;\n\n // Check if session is stale\n const lastHeartbeat = new Date(session.lastHeartbeat).getTime();\n if (now - lastHeartbeat < STALE_THRESHOLD_MS) {\n sessions.push(session);\n }\n } catch {\n // Ignore parse errors\n }\n }\n } catch {\n // Directory read error\n }\n\n return sessions;\n}\n\n/**\n * Get session summary for dashboard\n */\nexport function getSessionSummary(): SessionSummary {\n const sessions = getActiveSessions();\n const bySquad: Record<string, number> = {};\n\n for (const session of sessions) {\n const squad = session.squad || 'unknown';\n bySquad[squad] = (bySquad[squad] || 0) + 1;\n }\n\n return {\n totalSessions: sessions.length,\n bySquad,\n squadCount: Object.keys(bySquad).length,\n };\n}\n\n/**\n * Clean up stale sessions (older than threshold) and log events\n */\nexport function cleanupStaleSessions(): number {\n const sessionsDir = getSessionsDir();\n if (!sessionsDir) return 0;\n\n const now = Date.now();\n const nowIso = new Date().toISOString();\n let cleaned = 0;\n\n try {\n const files = readdirSync(sessionsDir).filter(f => f.endsWith('.json'));\n\n for (const file of files) {\n try {\n const filePath = join(sessionsDir, file);\n const content = readFileSync(filePath, 'utf-8');\n const session = JSON.parse(content) as SessionState;\n\n const lastHeartbeat = new Date(session.lastHeartbeat).getTime();\n if (now - lastHeartbeat >= STALE_THRESHOLD_MS) {\n const durationMs = now - new Date(session.startedAt).getTime();\n\n unlinkSync(filePath);\n cleaned++;\n\n // Log stale cleanup event\n appendEvent({\n type: 'stale_cleanup',\n sessionId: session.sessionId,\n squad: session.squad,\n ts: nowIso,\n durationMs,\n });\n }\n } catch {\n // If we can't parse, remove the file\n try {\n unlinkSync(join(sessionsDir, file));\n cleaned++;\n } catch {\n // Ignore\n }\n }\n }\n } catch {\n // Directory read error\n }\n\n return cleaned;\n}\n\n/**\n * Read all events from history file\n */\nexport async function readSessionHistory(options: {\n since?: Date;\n until?: Date;\n squad?: string;\n type?: SessionEventType;\n limit?: number;\n} = {}): Promise<SessionEvent[]> {\n const historyPath = getHistoryFilePath();\n if (!historyPath || !existsSync(historyPath)) return [];\n\n const events: SessionEvent[] = [];\n const sinceMs = options.since?.getTime() || 0;\n const untilMs = options.until?.getTime() || Date.now();\n\n return new Promise((resolve) => {\n const rl = createInterface({\n input: createReadStream(historyPath),\n crlfDelay: Infinity,\n });\n\n rl.on('line', (line) => {\n if (!line.trim()) return;\n\n try {\n const event = JSON.parse(line) as SessionEvent;\n const eventMs = new Date(event.ts).getTime();\n\n // Apply filters\n if (eventMs < sinceMs || eventMs > untilMs) return;\n if (options.squad && event.squad !== options.squad) return;\n if (options.type && event.type !== options.type) return;\n\n events.push(event);\n } catch {\n // Ignore parse errors\n }\n });\n\n rl.on('close', () => {\n // Apply limit (from end, most recent first)\n if (options.limit && events.length > options.limit) {\n resolve(events.slice(-options.limit));\n } else {\n resolve(events);\n }\n });\n\n rl.on('error', () => {\n resolve([]);\n });\n });\n}\n\n/**\n * Get session history statistics\n */\nexport async function getSessionHistoryStats(options: {\n since?: Date;\n until?: Date;\n squad?: string;\n} = {}): Promise<SessionHistoryStats> {\n const events = await readSessionHistory(options);\n\n const stats: SessionHistoryStats = {\n totalSessions: 0,\n totalDurationMs: 0,\n avgDurationMs: 0,\n bySquad: {},\n byDate: {},\n peakConcurrent: 0,\n };\n\n // Track active sessions for peak concurrent calculation\n const activeSessions = new Map<string, { squad: string | null; startTs: number }>();\n let currentConcurrent = 0;\n\n for (const event of events) {\n const squad = event.squad || 'unknown';\n const date = event.ts.split('T')[0]; // YYYY-MM-DD\n\n if (event.type === 'start') {\n stats.totalSessions++;\n stats.byDate[date] = (stats.byDate[date] || 0) + 1;\n\n if (!stats.bySquad[squad]) {\n stats.bySquad[squad] = { count: 0, durationMs: 0 };\n }\n stats.bySquad[squad].count++;\n\n // Track for concurrent calculation\n activeSessions.set(event.sessionId, {\n squad: event.squad,\n startTs: new Date(event.ts).getTime(),\n });\n currentConcurrent++;\n stats.peakConcurrent = Math.max(stats.peakConcurrent, currentConcurrent);\n }\n\n if (event.type === 'stop' || event.type === 'stale_cleanup') {\n const duration = event.durationMs || 0;\n stats.totalDurationMs += duration;\n\n if (stats.bySquad[squad]) {\n stats.bySquad[squad].durationMs += duration;\n }\n\n // Remove from concurrent tracking\n if (activeSessions.has(event.sessionId)) {\n activeSessions.delete(event.sessionId);\n currentConcurrent = Math.max(0, currentConcurrent - 1);\n }\n }\n }\n\n // Calculate average duration\n const completedSessions = events.filter(e => e.type === 'stop' || e.type === 'stale_cleanup').length;\n if (completedSessions > 0) {\n stats.avgDurationMs = Math.round(stats.totalDurationMs / completedSessions);\n }\n\n return stats;\n}\n\n/**\n * Get recent session events (for display)\n */\nexport async function getRecentSessions(limit: number = 20): Promise<SessionEvent[]> {\n const events = await readSessionHistory({ limit: limit * 3 }); // Get more to filter\n\n // Group by session and get start/stop pairs\n const sessionEvents = new Map<string, SessionEvent[]>();\n for (const event of events) {\n if (!sessionEvents.has(event.sessionId)) {\n sessionEvents.set(event.sessionId, []);\n }\n sessionEvents.get(event.sessionId)!.push(event);\n }\n\n // Get the most recent start events\n const startEvents = events\n .filter(e => e.type === 'start')\n .slice(-limit);\n\n return startEvents.reverse(); // Most recent first\n}\n","// Terminal utilities - Bun-style approach\n// Raw ANSI for performance, no heavy deps\n\n// ANSI escape codes\nexport const ESC = '\\x1b[';\nexport const RESET = `${ESC}0m`;\n\n// Colors (256-color mode for gradients)\nexport const rgb = (r: number, g: number, b: number) => `${ESC}38;2;${r};${g};${b}m`;\nexport const bgRgb = (r: number, g: number, b: number) => `${ESC}48;2;${r};${g};${b}m`;\n\n// Named colors (our brand palette)\nexport const colors = {\n purple: rgb(168, 85, 247), // #a855f7\n pink: rgb(236, 72, 153), // #ec4899\n cyan: rgb(6, 182, 212), // #06b6d4\n green: rgb(16, 185, 129), // #10b981\n yellow: rgb(234, 179, 8), // #eab308\n red: rgb(239, 68, 68), // #ef4444\n gray: rgb(107, 114, 128), // #6b7280\n dim: rgb(75, 85, 99), // #4b5563\n white: rgb(255, 255, 255),\n};\n\n// Styles\nexport const bold = `${ESC}1m`;\nexport const dim = `${ESC}2m`;\n\n// Cursor control\nexport const cursor = {\n hide: `${ESC}?25l`,\n show: `${ESC}?25h`,\n up: (n = 1) => `${ESC}${n}A`,\n down: (n = 1) => `${ESC}${n}B`,\n left: (n = 1) => `${ESC}${n}D`,\n right: (n = 1) => `${ESC}${n}C`,\n to: (x: number, y: number) => `${ESC}${y};${x}H`,\n save: `${ESC}s`,\n restore: `${ESC}u`,\n};\n\n// Clear\nexport const clear = {\n line: `${ESC}2K`,\n toEnd: `${ESC}0K`,\n screen: `${ESC}2J${ESC}0;0H`,\n};\n\n// Gradient text (purple → pink → cyan)\nexport function gradient(text: string): string {\n const stops = [\n [168, 85, 247], // purple\n [192, 132, 252], // purple-light\n [232, 121, 249], // pink\n [244, 114, 182], // pink-light\n [251, 113, 133], // rose\n ];\n\n let result = '';\n for (let i = 0; i < text.length; i++) {\n const t = i / Math.max(text.length - 1, 1);\n const stopIndex = t * (stops.length - 1);\n const lower = Math.floor(stopIndex);\n const upper = Math.min(lower + 1, stops.length - 1);\n const blend = stopIndex - lower;\n\n const r = Math.round(stops[lower][0] + (stops[upper][0] - stops[lower][0]) * blend);\n const g = Math.round(stops[lower][1] + (stops[upper][1] - stops[lower][1]) * blend);\n const b = Math.round(stops[lower][2] + (stops[upper][2] - stops[lower][2]) * blend);\n\n result += rgb(r, g, b) + text[i];\n }\n return result + RESET;\n}\n\n// Progress bar with gradient fill\nexport function progressBar(percent: number, width = 20): string {\n const filled = Math.round((percent / 100) * width);\n const empty = width - filled;\n\n let bar = '';\n for (let i = 0; i < filled; i++) {\n const t = i / Math.max(filled - 1, 1);\n const r = Math.round(16 + (168 - 16) * t);\n const g = Math.round(185 + (85 - 185) * t);\n const b = Math.round(129 + (247 - 129) * t);\n bar += rgb(r, g, b) + '━';\n }\n\n bar += colors.dim + '━'.repeat(empty) + RESET;\n return bar;\n}\n\n// Box drawing\nexport const box = {\n topLeft: '┌',\n topRight: '┐',\n bottomLeft: '└',\n bottomRight: '┘',\n horizontal: '─',\n vertical: '│',\n teeRight: '├',\n teeLeft: '┤',\n};\n\n// Format helpers\nexport function padEnd(str: string, len: number): string {\n // Strip ANSI codes for length calculation\n const visible = str.replace(/\\x1b\\[[0-9;]*m/g, '');\n const pad = Math.max(0, len - visible.length);\n return str + ' '.repeat(pad);\n}\n\nexport function truncate(str: string, len: number): string {\n const visible = str.replace(/\\x1b\\[[0-9;]*m/g, '');\n if (visible.length <= len) return str;\n\n // Simple truncation (won't handle mid-ANSI truncation perfectly)\n let result = '';\n let count = 0;\n let i = 0;\n\n while (i < str.length && count < len - 1) {\n if (str[i] === '\\x1b') {\n const end = str.indexOf('m', i);\n if (end !== -1) {\n result += str.slice(i, end + 1);\n i = end + 1;\n continue;\n }\n }\n result += str[i];\n count++;\n i++;\n }\n\n return result + colors.dim + '…' + RESET;\n}\n\n// Spinner frames\nexport const spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n\n// Status icons\nexport const icons = {\n success: `${colors.green}●${RESET}`,\n warning: `${colors.yellow}○${RESET}`,\n error: `${colors.red}●${RESET}`,\n pending: `${colors.dim}○${RESET}`,\n active: `${colors.green}●${RESET}`,\n progress: `${colors.cyan}◆${RESET}`,\n empty: `${colors.dim}◇${RESET}`,\n};\n\n// Write without newline\nexport function write(str: string): void {\n process.stdout.write(str);\n}\n\n// Write line\nexport function writeLine(str = ''): void {\n process.stdout.write(str + '\\n');\n}\n\n// Sparkline chart using block characters\nexport function sparkline(values: number[], width?: number): string {\n if (values.length === 0) return '';\n\n const blocks = ['▁', '▂', '▃', '▄', '▅', '▆', '▇', '█'];\n const max = Math.max(...values, 1);\n\n let result = '';\n for (const val of values) {\n const normalized = val / max;\n const blockIndex = Math.min(Math.floor(normalized * blocks.length), blocks.length - 1);\n const intensity = normalized;\n\n // Color gradient from dim to cyan to green based on value\n if (normalized === 0) {\n result += colors.dim + blocks[0];\n } else if (normalized < 0.5) {\n result += colors.cyan + blocks[blockIndex];\n } else {\n result += colors.green + blocks[blockIndex];\n }\n }\n\n return result + RESET;\n}\n\n// Bar chart (horizontal)\nexport function barChart(value: number, max: number, width: number = 20, label?: string): string {\n const filled = Math.round((value / max) * width);\n const empty = width - filled;\n\n let bar = '';\n for (let i = 0; i < filled; i++) {\n const t = i / Math.max(filled - 1, 1);\n // Green to cyan gradient\n const r = Math.round(16 + (6 - 16) * t);\n const g = Math.round(185 + (182 - 185) * t);\n const b = Math.round(129 + (212 - 129) * t);\n bar += rgb(r, g, b) + '━';\n }\n\n bar += colors.dim + '━'.repeat(empty) + RESET;\n\n if (label) {\n return `${bar} ${label}`;\n }\n return bar;\n}\n","/**\n * List active Claude Code sessions across squads\n */\n\nimport {\n getActiveSessions,\n getSessionSummary,\n cleanupStaleSessions,\n getSessionHistoryStats,\n getRecentSessions,\n SessionState,\n SessionEvent,\n} from '../lib/sessions.js';\nimport {\n colors,\n bold,\n RESET,\n gradient,\n box,\n padEnd,\n icons,\n writeLine,\n} from '../lib/terminal.js';\n\ninterface SessionsOptions {\n verbose?: boolean;\n json?: boolean;\n}\n\nexport async function sessionsCommand(\n options: SessionsOptions = {}\n): Promise<void> {\n // Clean up stale sessions first\n cleanupStaleSessions();\n\n const sessions = getActiveSessions();\n const summary = getSessionSummary();\n\n // JSON output for scripts\n if (options.json) {\n console.log(JSON.stringify({ sessions, summary }, null, 2));\n return;\n }\n\n writeLine();\n writeLine(` ${gradient('squads')} ${colors.dim}sessions${RESET}`);\n writeLine();\n\n if (sessions.length === 0) {\n writeLine(` ${colors.dim}No active sessions${RESET}`);\n writeLine();\n writeLine(` ${colors.dim}Sessions are tracked automatically when Claude Code runs.${RESET}`);\n writeLine(` ${colors.dim}Each session updates its heartbeat via squads CLI commands.${RESET}`);\n writeLine();\n return;\n }\n\n // Summary line\n const squadText = summary.squadCount === 1 ? 'squad' : 'squads';\n const sessionText = summary.totalSessions === 1 ? 'session' : 'sessions';\n writeLine(` ${colors.green}${summary.totalSessions}${RESET} active ${sessionText} ${colors.dim}across${RESET} ${colors.cyan}${summary.squadCount}${RESET} ${squadText}`);\n writeLine();\n\n // Group by squad\n const bySquad: Record<string, SessionState[]> = {};\n for (const session of sessions) {\n const squad = session.squad || 'unknown';\n if (!bySquad[squad]) bySquad[squad] = [];\n bySquad[squad].push(session);\n }\n\n // Table\n const w = { squad: 16, sessions: 10, activity: 14 };\n const tableWidth = w.squad + w.sessions + w.activity + 4;\n\n writeLine(` ${colors.purple}${box.topLeft}${colors.dim}${box.horizontal.repeat(tableWidth)}${colors.purple}${box.topRight}${RESET}`);\n\n const header = ` ${colors.purple}${box.vertical}${RESET} ` +\n `${bold}${padEnd('SQUAD', w.squad)}${RESET}` +\n `${bold}${padEnd('SESSIONS', w.sessions)}${RESET}` +\n `${bold}LAST ACTIVITY${RESET}` +\n ` ${colors.purple}${box.vertical}${RESET}`;\n writeLine(header);\n\n writeLine(` ${colors.purple}${box.teeRight}${colors.dim}${box.horizontal.repeat(tableWidth)}${colors.purple}${box.teeLeft}${RESET}`);\n\n for (const [squad, squadSessions] of Object.entries(bySquad).sort()) {\n // Find most recent activity\n let mostRecent = 0;\n for (const session of squadSessions) {\n const ts = new Date(session.lastHeartbeat).getTime();\n if (ts > mostRecent) mostRecent = ts;\n }\n\n const lastActivity = formatTimeAgo(mostRecent);\n const activityColor = getActivityColor(mostRecent);\n\n const row = ` ${colors.purple}${box.vertical}${RESET} ` +\n `${colors.cyan}${padEnd(squad, w.squad)}${RESET}` +\n `${padEnd(String(squadSessions.length), w.sessions)}` +\n `${padEnd(`${activityColor}${lastActivity}${RESET}`, w.activity)}` +\n `${colors.purple}${box.vertical}${RESET}`;\n\n writeLine(row);\n }\n\n writeLine(` ${colors.purple}${box.bottomLeft}${colors.dim}${box.horizontal.repeat(tableWidth)}${colors.purple}${box.bottomRight}${RESET}`);\n\n // Verbose: show individual sessions\n if (options.verbose) {\n writeLine();\n writeLine(` ${bold}Session Details${RESET}`);\n writeLine();\n\n for (const session of sessions) {\n const squad = session.squad || 'unknown';\n const ago = formatTimeAgo(new Date(session.lastHeartbeat).getTime());\n\n writeLine(` ${icons.active} ${colors.white}${session.sessionId}${RESET}`);\n writeLine(` ${colors.dim}squad: ${squad} | pid: ${session.pid} | heartbeat: ${ago}${RESET}`);\n writeLine(` ${colors.dim}cwd: ${session.cwd}${RESET}`);\n }\n }\n\n writeLine();\n writeLine(` ${colors.dim}$${RESET} squads sessions -v ${colors.dim}Show session details${RESET}`);\n writeLine();\n}\n\n/**\n * Format timestamp as \"Xm ago\" or \"Xs ago\"\n */\nfunction formatTimeAgo(timestamp: number): string {\n const now = Date.now();\n const diff = now - timestamp;\n\n const seconds = Math.floor(diff / 1000);\n const minutes = Math.floor(seconds / 60);\n\n if (minutes >= 1) {\n return `${minutes}m ago`;\n }\n return `${seconds}s ago`;\n}\n\n/**\n * Get color based on how recent the activity is\n */\nfunction getActivityColor(timestamp: number): string {\n const now = Date.now();\n const diff = now - timestamp;\n\n const minutes = Math.floor(diff / (1000 * 60));\n\n if (minutes < 1) return colors.green;\n if (minutes < 3) return colors.yellow;\n return colors.dim;\n}\n\ninterface HistoryOptions {\n days?: number;\n squad?: string;\n json?: boolean;\n}\n\ninterface SummaryOptions {\n json?: boolean;\n}\n\nexport interface SessionSummaryData {\n squads: Array<{\n name: string;\n actions: string;\n outputs: string;\n }>;\n decisions?: Array<{\n question: string;\n answer: string;\n }>;\n customer?: {\n vertical: string;\n persona: string;\n painPoints: string[];\n };\n nextActions?: Array<{\n squad: string;\n action: string;\n }>;\n filesUpdated?: string[];\n targets?: {\n metric: string;\n value: string;\n }[];\n model?: string; // e.g., \"Claude Opus 4.5\"\n duration?: string; // e.g., \"45m\"\n}\n\n/**\n * Show a pretty summary of session work\n */\nexport async function sessionsSummaryCommand(\n data: SessionSummaryData,\n options: SummaryOptions = {}\n): Promise<void> {\n if (options.json) {\n console.log(JSON.stringify(data, null, 2));\n return;\n }\n\n writeLine();\n writeLine(` ${gradient('squads')} ${colors.dim}session summary${RESET}`);\n writeLine();\n\n // Squads table\n if (data.squads.length > 0) {\n const w = { squad: 14, actions: 26, outputs: 36 };\n const tableWidth = w.squad + w.actions + w.outputs + 6;\n\n // Helper to truncate text\n const truncate = (text: string, max: number) =>\n text.length > max ? text.substring(0, max - 1) + '…' : text;\n\n writeLine(` ${colors.green}${icons.active}${RESET} ${bold}${data.squads.length} Squads Active${RESET}`);\n writeLine();\n\n writeLine(` ${colors.purple}${box.topLeft}${colors.dim}${box.horizontal.repeat(tableWidth)}${colors.purple}${box.topRight}${RESET}`);\n\n const header = ` ${colors.purple}${box.vertical}${RESET} ` +\n `${bold}${padEnd('SQUAD', w.squad)}${RESET}` +\n `${bold}${padEnd('ACTIONS', w.actions)}${RESET}` +\n `${bold}${padEnd('KEY OUTPUTS', w.outputs)}${RESET}` +\n `${colors.purple}${box.vertical}${RESET}`;\n writeLine(header);\n\n writeLine(` ${colors.purple}${box.teeRight}${colors.dim}${box.horizontal.repeat(tableWidth)}${colors.purple}${box.teeLeft}${RESET}`);\n\n for (const squad of data.squads) {\n const row = ` ${colors.purple}${box.vertical}${RESET} ` +\n `${colors.cyan}${padEnd(truncate(squad.name, w.squad - 1), w.squad)}${RESET}` +\n `${padEnd(truncate(squad.actions, w.actions - 1), w.actions)}` +\n `${padEnd(truncate(squad.outputs, w.outputs - 1), w.outputs)}` +\n `${colors.purple}${box.vertical}${RESET}`;\n writeLine(row);\n }\n\n writeLine(` ${colors.purple}${box.bottomLeft}${colors.dim}${box.horizontal.repeat(tableWidth)}${colors.purple}${box.bottomRight}${RESET}`);\n }\n\n // Decisions\n if (data.decisions && data.decisions.length > 0) {\n writeLine();\n writeLine(` ${bold}Strategic Decisions${RESET}`);\n writeLine();\n\n const w = { question: 16, answer: 50 };\n const tableWidth = w.question + w.answer + 4;\n\n writeLine(` ${colors.purple}${box.topLeft}${colors.dim}${box.horizontal.repeat(tableWidth)}${colors.purple}${box.topRight}${RESET}`);\n\n for (const decision of data.decisions) {\n const row = ` ${colors.purple}${box.vertical}${RESET} ` +\n `${colors.yellow}${padEnd(decision.question, w.question)}${RESET}` +\n `${padEnd(decision.answer, w.answer)}` +\n `${colors.purple}${box.vertical}${RESET}`;\n writeLine(row);\n }\n\n writeLine(` ${colors.purple}${box.bottomLeft}${colors.dim}${box.horizontal.repeat(tableWidth)}${colors.purple}${box.bottomRight}${RESET}`);\n }\n\n // Target customer\n if (data.customer) {\n writeLine();\n writeLine(` ${bold}Target Customer${RESET}`);\n writeLine();\n writeLine(` ${colors.dim}Vertical:${RESET} ${colors.cyan}${data.customer.vertical}${RESET}`);\n writeLine(` ${colors.dim}Persona:${RESET} ${colors.white}${data.customer.persona}${RESET}`);\n writeLine(` ${colors.dim}Pain:${RESET} ${data.customer.painPoints.join(', ')}`);\n }\n\n // Next actions\n if (data.nextActions && data.nextActions.length > 0) {\n writeLine();\n writeLine(` ${bold}Next Actions${RESET}`);\n writeLine();\n\n for (const action of data.nextActions) {\n writeLine(` ${colors.cyan}${padEnd(action.squad, 14)}${RESET}${colors.dim}→${RESET} ${action.action}`);\n }\n }\n\n // Q1 Targets\n if (data.targets && data.targets.length > 0) {\n writeLine();\n writeLine(` ${bold}Q1 Targets${RESET}`);\n writeLine();\n\n for (const target of data.targets) {\n writeLine(` ${colors.dim}•${RESET} ${target.metric}: ${colors.green}${target.value}${RESET}`);\n }\n }\n\n // Files updated\n if (data.filesUpdated && data.filesUpdated.length > 0) {\n writeLine();\n writeLine(` ${colors.dim}Files updated:${RESET}`);\n for (const file of data.filesUpdated) {\n writeLine(` ${colors.dim} •${RESET} ${colors.cyan}${file}${RESET}`);\n }\n }\n\n writeLine();\n\n // Footer with model attribution\n const modelText = data.model ? data.model : 'Claude';\n const durationText = data.duration ? ` ${colors.dim}(${data.duration})${RESET}` : '';\n writeLine(` ${colors.dim}Generated by${RESET} ${colors.purple}${modelText}${RESET}${durationText}`);\n writeLine();\n}\n\n/**\n * Build summary from current session by detecting recent activity\n */\nexport async function buildCurrentSessionSummary(): Promise<SessionSummaryData> {\n const { existsSync, readdirSync, statSync, readFileSync } = await import('fs');\n const { join } = await import('path');\n const { findMemoryDir } = await import('../lib/memory.js');\n\n const memoryDir = findMemoryDir();\n const squads: SessionSummaryData['squads'] = [];\n const filesUpdated: string[] = [];\n\n // Look for files modified in last 2 hours (current session window)\n const sessionWindow = 2 * 60 * 60 * 1000; // 2 hours\n const now = Date.now();\n\n if (memoryDir && existsSync(memoryDir)) {\n const squadDirs = readdirSync(memoryDir, { withFileTypes: true })\n .filter(d => d.isDirectory());\n\n for (const squadDir of squadDirs) {\n const squadPath = join(memoryDir, squadDir.name);\n let squadModified = false;\n let stateContent = '';\n let executionContent = '';\n\n try {\n const agentDirs = readdirSync(squadPath, { withFileTypes: true })\n .filter(d => d.isDirectory());\n\n for (const agentDir of agentDirs) {\n const agentPath = join(squadPath, agentDir.name);\n const files = readdirSync(agentPath).filter(f => f.endsWith('.md'));\n\n for (const file of files) {\n const filePath = join(agentPath, file);\n const stats = statSync(filePath);\n\n if (now - stats.mtimeMs < sessionWindow) {\n squadModified = true;\n const relativePath = `${squadDir.name}/${agentDir.name}/${file}`;\n filesUpdated.push(relativePath);\n\n // Read content for summary\n if (file === 'state.md') {\n stateContent = readFileSync(filePath, 'utf-8');\n } else if (file === 'executions.md') {\n executionContent = readFileSync(filePath, 'utf-8');\n }\n }\n }\n }\n\n if (squadModified) {\n // Extract summary from state/execution content\n let actions = 'State updated';\n let outputs = 'Memory refreshed';\n\n // Try to extract info from execution log\n if (executionContent) {\n const lines = executionContent.split('\\n').filter(l => l.trim());\n const recentEntry = lines.slice(-10).join(' ');\n if (recentEntry.includes('completed')) {\n actions = 'Execution completed';\n }\n // Extract key points\n const keyMatch = recentEntry.match(/Key (?:findings|decisions|outputs)?:?\\s*([^.]+)/i);\n if (keyMatch) {\n outputs = keyMatch[1].substring(0, 50);\n }\n }\n\n // Try to extract from state header\n if (stateContent) {\n const updatedMatch = stateContent.match(/Updated:\\s*([^\\n]+)/);\n if (updatedMatch) {\n actions = `Updated ${updatedMatch[1]}`;\n }\n }\n\n squads.push({\n name: squadDir.name.charAt(0).toUpperCase() + squadDir.name.slice(1),\n actions,\n outputs: outputs.length > 44 ? outputs.substring(0, 41) + '...' : outputs,\n });\n }\n } catch {\n // Skip if can't read\n }\n }\n }\n\n // If no recent activity found\n if (squads.length === 0) {\n squads.push({\n name: 'No recent activity',\n actions: '—',\n outputs: 'Run squads to see activity here',\n });\n }\n\n return {\n squads,\n filesUpdated: filesUpdated.length > 0 ? filesUpdated : undefined,\n model: process.env.ANTHROPIC_MODEL || 'Claude',\n };\n}\n\n/**\n * Show session history and statistics\n */\nexport async function sessionsHistoryCommand(\n options: HistoryOptions = {}\n): Promise<void> {\n const days = options.days || 7;\n const since = new Date(Date.now() - days * 24 * 60 * 60 * 1000);\n\n const stats = await getSessionHistoryStats({\n since,\n squad: options.squad,\n });\n\n const recentSessions = await getRecentSessions(10);\n\n // JSON output\n if (options.json) {\n console.log(JSON.stringify({ stats, recentSessions }, null, 2));\n return;\n }\n\n writeLine();\n writeLine(` ${gradient('squads')} ${colors.dim}sessions history${RESET} ${colors.dim}(${days}d)${RESET}`);\n writeLine();\n\n if (stats.totalSessions === 0) {\n writeLine(` ${colors.dim}No session history found${RESET}`);\n writeLine();\n writeLine(` ${colors.dim}Session events are logged to .agents/sessions/history.jsonl${RESET}`);\n writeLine();\n return;\n }\n\n // Summary stats\n const avgMinutes = Math.round(stats.avgDurationMs / 60000);\n const totalHours = Math.round(stats.totalDurationMs / 3600000 * 10) / 10;\n\n writeLine(` ${bold}Summary${RESET}`);\n writeLine(` ${colors.cyan}${stats.totalSessions}${RESET} sessions ${colors.dim}│${RESET} ${colors.green}${totalHours}h${RESET} total ${colors.dim}│${RESET} ${colors.yellow}${avgMinutes}m${RESET} avg ${colors.dim}│${RESET} ${colors.purple}${stats.peakConcurrent}${RESET} peak`);\n writeLine();\n\n // By squad table\n const squads = Object.entries(stats.bySquad).sort((a, b) => b[1].count - a[1].count);\n\n if (squads.length > 0) {\n const w = { squad: 16, sessions: 10, duration: 12 };\n const tableWidth = w.squad + w.sessions + w.duration + 4;\n\n writeLine(` ${bold}By Squad${RESET}`);\n writeLine();\n writeLine(` ${colors.purple}${box.topLeft}${colors.dim}${box.horizontal.repeat(tableWidth)}${colors.purple}${box.topRight}${RESET}`);\n\n const header = ` ${colors.purple}${box.vertical}${RESET} ` +\n `${bold}${padEnd('SQUAD', w.squad)}${RESET}` +\n `${bold}${padEnd('SESSIONS', w.sessions)}${RESET}` +\n `${bold}DURATION${RESET}` +\n ` ${colors.purple}${box.vertical}${RESET}`;\n writeLine(header);\n\n writeLine(` ${colors.purple}${box.teeRight}${colors.dim}${box.horizontal.repeat(tableWidth)}${colors.purple}${box.teeLeft}${RESET}`);\n\n for (const [squad, data] of squads) {\n const hours = Math.round(data.durationMs / 3600000 * 10) / 10;\n\n const row = ` ${colors.purple}${box.vertical}${RESET} ` +\n `${colors.cyan}${padEnd(squad, w.squad)}${RESET}` +\n `${padEnd(String(data.count), w.sessions)}` +\n `${padEnd(`${hours}h`, w.duration)}` +\n `${colors.purple}${box.vertical}${RESET}`;\n\n writeLine(row);\n }\n\n writeLine(` ${colors.purple}${box.bottomLeft}${colors.dim}${box.horizontal.repeat(tableWidth)}${colors.purple}${box.bottomRight}${RESET}`);\n }\n\n // Recent sessions\n if (recentSessions.length > 0) {\n writeLine();\n writeLine(` ${bold}Recent Sessions${RESET}`);\n writeLine();\n\n for (const event of recentSessions.slice(0, 5)) {\n const squad = event.squad || 'unknown';\n const date = new Date(event.ts);\n const timeStr = date.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' });\n const dateStr = date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });\n\n writeLine(` ${colors.dim}${dateStr} ${timeStr}${RESET} ${colors.cyan}${squad}${RESET} ${colors.dim}${event.sessionId.slice(0, 8)}${RESET}`);\n }\n }\n\n // By date (last 7 days)\n const dates = Object.entries(stats.byDate)\n .sort((a, b) => b[0].localeCompare(a[0]))\n .slice(0, 7);\n\n if (dates.length > 1) {\n writeLine();\n writeLine(` ${bold}Daily Activity${RESET}`);\n writeLine();\n\n for (const [date, count] of dates) {\n const bar = '█'.repeat(Math.min(count, 20));\n writeLine(` ${colors.dim}${date}${RESET} ${colors.green}${bar}${RESET} ${count}`);\n }\n }\n\n writeLine();\n writeLine(` ${colors.dim}$${RESET} squads sessions history --days 30 ${colors.dim}Longer history${RESET}`);\n writeLine(` ${colors.dim}$${RESET} squads sessions history -s website ${colors.dim}Filter by squad${RESET}`);\n writeLine();\n}\n"],"mappings":";;;AASA,SAAS,YAAY,WAAW,aAAa,cAAc,eAAe,YAAY,gBAAgB,wBAAwB;AAC9H,SAAS,MAAM,eAAe;AAC9B,SAAS,mBAAmB;AAC5B,SAAS,uBAAuB;AAChC,SAAS,gBAAgB;AAkDzB,IAAM,mBAAwD;AAAA,EAC5D,EAAE,SAAS,YAAY,MAAM,SAAS;AAAA,EACtC,EAAE,SAAS,aAAa,MAAM,SAAS;AAAA,EACvC,EAAE,SAAS,WAAW,MAAM,QAAQ;AAAA,EACpC,EAAE,SAAS,aAAa,MAAM,SAAS;AAAA,EACvC,EAAE,SAAS,cAAc,MAAM,UAAU;AAAA,EACzC,EAAE,SAAS,WAAW,MAAM,OAAO;AAAA,EACnC,EAAE,SAAS,eAAe,MAAM,WAAW;AAC7C;AAGA,IAAM,qBAAqB,IAAI,KAAK;AAGpC,IAAM,eAAe;AAGrB,IAAM,aAAa;AAGnB,IAAM,gBAAwC;AAAA,EAC5C,MAAM;AAAA,EACN,qBAAqB;AAAA,EACrB,WAAW;AAAA,EACX,WAAW;AAAA,EACX,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,aAAa;AACf;AAKO,SAAS,gBAA+B;AAC7C,MAAI,MAAM,QAAQ,IAAI;AAEtB,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,UAAM,aAAa,KAAK,KAAK,SAAS;AACtC,QAAI,WAAW,UAAU,GAAG;AAC1B,aAAO;AAAA,IACT;AACA,UAAM,SAAS,QAAQ,GAAG;AAC1B,QAAI,WAAW,IAAK;AACpB,UAAM;AAAA,EACR;AAEA,SAAO;AACT;AAKO,SAAS,qBAAoC;AAClD,QAAM,YAAY,cAAc;AAChC,MAAI,CAAC,UAAW,QAAO;AAEvB,QAAM,cAAc,KAAK,WAAW,UAAU;AAC9C,MAAI,CAAC,WAAW,WAAW,GAAG;AAC5B,cAAU,aAAa,EAAE,WAAW,KAAK,CAAC;AAAA,EAC5C;AACA,SAAO;AACT;AAKO,SAAS,iBAAgC;AAC9C,QAAM,UAAU,mBAAmB;AACnC,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,YAAY,KAAK,SAAS,UAAU;AAC1C,MAAI,CAAC,WAAW,SAAS,GAAG;AAC1B,cAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,EAC1C;AACA,SAAO;AACT;AAKO,SAAS,qBAAoC;AAClD,QAAM,UAAU,mBAAmB;AACnC,MAAI,CAAC,QAAS,QAAO;AACrB,SAAO,KAAK,SAAS,YAAY;AACnC;AAKA,SAAS,YAAY,OAA2B;AAC9C,QAAM,cAAc,mBAAmB;AACvC,MAAI,CAAC,YAAa;AAElB,MAAI;AACF,UAAM,OAAO,KAAK,UAAU,KAAK,IAAI;AACrC,mBAAe,aAAa,IAAI;AAAA,EAClC,QAAQ;AAAA,EAER;AACF;AAKO,SAAS,YAAY,MAAc,QAAQ,IAAI,GAAkB;AAEtE,QAAM,QAAQ,IAAI,MAAM,wBAAwB;AAChD,MAAI,OAAO;AACT,UAAM,MAAM,MAAM,CAAC;AACnB,WAAO,cAAc,GAAG,KAAK;AAAA,EAC/B;AACA,SAAO;AACT;AAMO,SAAS,oBAAiC;AAC/C,QAAM,YAAyB,CAAC;AAEhC,MAAI;AAEF,UAAM,WAAW,SAAS,mCAAmC;AAAA,MAC3D,UAAU;AAAA,MACV,SAAS;AAAA,IACX,CAAC,EAAE,KAAK;AAER,QAAI,CAAC,SAAU,QAAO,CAAC;AAEvB,UAAM,QAAQ,SAAS,MAAM,IAAI,EAAE,OAAO,UAAQ,KAAK,KAAK,CAAC;AAE7D,eAAW,QAAQ,OAAO;AACxB,YAAM,QAAQ,KAAK,KAAK,EAAE,MAAM,KAAK;AACrC,UAAI,MAAM,SAAS,EAAG;AAEtB,YAAM,MAAM,SAAS,MAAM,CAAC,GAAG,EAAE;AACjC,YAAM,MAAM,MAAM,CAAC;AACnB,YAAM,OAAO,MAAM,MAAM,CAAC,EAAE,KAAK,GAAG;AAEpC,UAAI,MAAM,GAAG,EAAG;AAGhB,UAAI,WAA0B;AAC9B,iBAAW,EAAE,SAAS,KAAK,KAAK,kBAAkB;AAChD,YAAI,QAAQ,KAAK,IAAI,GAAG;AACtB,qBAAW;AACX;AAAA,QACF;AAAA,MACF;AAEA,UAAI,CAAC,SAAU;AAGf,UAAI,MAAM;AACV,UAAI;AACF,cAAM,aAAa,SAAS,WAAW,GAAG,+CAA+C;AAAA,UACvF,UAAU;AAAA,UACV,SAAS;AAAA,QACX,CAAC,EAAE,KAAK;AACR,cAAM,cAAc;AAAA,MACtB,QAAQ;AAEN,cAAM;AAAA,MACR;AAGA,YAAM,QAAQ,YAAY,GAAG;AAE7B,gBAAU,KAAK;AAAA,QACb;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,MAAM;AAAA,MACR,CAAC;AAAA,IACH;AAAA,EACF,QAAQ;AAAA,EAGR;AAEA,SAAO;AACT;AAQO,SAAS,wBAAwC;AACtD,QAAM,YAAY,kBAAkB;AACpC,QAAM,UAAkC,CAAC;AACzC,QAAM,SAAiC,CAAC;AAExC,aAAW,QAAQ,WAAW;AAC5B,UAAM,QAAQ,KAAK,SAAS;AAC5B,YAAQ,KAAK,KAAK,QAAQ,KAAK,KAAK,KAAK;AACzC,WAAO,KAAK,IAAI,KAAK,OAAO,KAAK,IAAI,KAAK,KAAK;AAAA,EACjD;AAEA,SAAO;AAAA,IACL,eAAe,UAAU;AAAA,IACzB;AAAA,IACA,YAAY,OAAO,KAAK,OAAO,EAAE;AAAA,IACjC;AAAA,EACF;AACF;AAKA,SAAS,oBAA4B;AACnC,SAAO,YAAY,CAAC,EAAE,SAAS,KAAK;AACtC;AAKA,IAAI,mBAAkC;AAE/B,SAAS,eAAuB;AACrC,MAAI,iBAAkB,QAAO;AAG7B,QAAM,cAAc,eAAe;AACnC,MAAI,aAAa;AACf,UAAM,MAAM,QAAQ;AACpB,UAAM,QAAQ,YAAY,WAAW,EAAE,OAAO,OAAK,EAAE,SAAS,OAAO,CAAC;AAEtE,eAAW,QAAQ,OAAO;AACxB,UAAI;AACF,cAAM,UAAU,aAAa,KAAK,aAAa,IAAI,GAAG,OAAO;AAC7D,cAAM,UAAU,KAAK,MAAM,OAAO;AAClC,YAAI,QAAQ,QAAQ,KAAK;AACvB,6BAAmB,QAAQ;AAC3B,iBAAO;AAAA,QACT;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAGA,qBAAmB,kBAAkB;AACrC,SAAO;AACT;AAKO,SAAS,aAAa,OAAqC;AAChE,QAAM,cAAc,eAAe;AACnC,MAAI,CAAC,YAAa,QAAO;AAEzB,QAAM,YAAY,aAAa;AAC/B,QAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,gBAAgB,SAAS,YAAY,GAAG;AAE9C,QAAM,UAAwB;AAAA,IAC5B;AAAA,IACA,OAAO;AAAA,IACP,WAAW;AAAA,IACX,eAAe;AAAA,IACf;AAAA,IACA,KAAK,QAAQ;AAAA,EACf;AAEA,QAAM,cAAc,KAAK,aAAa,GAAG,SAAS,OAAO;AACzD,gBAAc,aAAa,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAG3D,cAAY;AAAA,IACV,MAAM;AAAA,IACN;AAAA,IACA,OAAO;AAAA,IACP,IAAI;AAAA,IACJ;AAAA,IACA,KAAK,QAAQ;AAAA,EACf,CAAC;AAED,SAAO;AACT;AAKO,SAAS,kBAA2B;AACzC,QAAM,cAAc,eAAe;AACnC,MAAI,CAAC,YAAa,QAAO;AAEzB,QAAM,YAAY,aAAa;AAC/B,QAAM,cAAc,KAAK,aAAa,GAAG,SAAS,OAAO;AAEzD,MAAI,CAAC,WAAW,WAAW,GAAG;AAE5B,iBAAa;AACb,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,UAAU,aAAa,aAAa,OAAO;AACjD,UAAM,UAAU,KAAK,MAAM,OAAO;AAClC,YAAQ,iBAAgB,oBAAI,KAAK,GAAE,YAAY;AAC/C,kBAAc,aAAa,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAC3D,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKO,SAAS,cAAuB;AACrC,QAAM,cAAc,eAAe;AACnC,MAAI,CAAC,YAAa,QAAO;AAEzB,QAAM,YAAY,aAAa;AAC/B,QAAM,cAAc,KAAK,aAAa,GAAG,SAAS,OAAO;AAEzD,MAAI,WAAW,WAAW,GAAG;AAE3B,QAAI,QAAuB;AAC3B,QAAI;AAEJ,QAAI;AACF,YAAM,UAAU,aAAa,aAAa,OAAO;AACjD,YAAM,UAAU,KAAK,MAAM,OAAO;AAClC,cAAQ,QAAQ;AAChB,mBAAa,KAAK,IAAI,IAAI,IAAI,KAAK,QAAQ,SAAS,EAAE,QAAQ;AAAA,IAChE,QAAQ;AAAA,IAER;AAEA,eAAW,WAAW;AACtB,uBAAmB;AAGnB,gBAAY;AAAA,MACV,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,KAAI,oBAAI,KAAK,GAAE,YAAY;AAAA,MAC3B;AAAA,IACF,CAAC;AAED,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAKO,SAAS,oBAAoC;AAClD,QAAM,cAAc,eAAe;AACnC,MAAI,CAAC,YAAa,QAAO,CAAC;AAE1B,QAAM,MAAM,KAAK,IAAI;AACrB,QAAM,WAA2B,CAAC;AAElC,MAAI;AACF,UAAM,QAAQ,YAAY,WAAW,EAAE,OAAO,OAAK,EAAE,SAAS,OAAO,CAAC;AAEtE,eAAW,QAAQ,OAAO;AACxB,UAAI;AACF,cAAM,WAAW,KAAK,aAAa,IAAI;AACvC,cAAM,UAAU,aAAa,UAAU,OAAO;AAC9C,cAAM,UAAU,KAAK,MAAM,OAAO;AAGlC,cAAM,gBAAgB,IAAI,KAAK,QAAQ,aAAa,EAAE,QAAQ;AAC9D,YAAI,MAAM,gBAAgB,oBAAoB;AAC5C,mBAAS,KAAK,OAAO;AAAA,QACvB;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;AAKO,SAAS,oBAAoC;AAClD,QAAM,WAAW,kBAAkB;AACnC,QAAM,UAAkC,CAAC;AAEzC,aAAW,WAAW,UAAU;AAC9B,UAAM,QAAQ,QAAQ,SAAS;AAC/B,YAAQ,KAAK,KAAK,QAAQ,KAAK,KAAK,KAAK;AAAA,EAC3C;AAEA,SAAO;AAAA,IACL,eAAe,SAAS;AAAA,IACxB;AAAA,IACA,YAAY,OAAO,KAAK,OAAO,EAAE;AAAA,EACnC;AACF;AAKO,SAAS,uBAA+B;AAC7C,QAAM,cAAc,eAAe;AACnC,MAAI,CAAC,YAAa,QAAO;AAEzB,QAAM,MAAM,KAAK,IAAI;AACrB,QAAM,UAAS,oBAAI,KAAK,GAAE,YAAY;AACtC,MAAI,UAAU;AAEd,MAAI;AACF,UAAM,QAAQ,YAAY,WAAW,EAAE,OAAO,OAAK,EAAE,SAAS,OAAO,CAAC;AAEtE,eAAW,QAAQ,OAAO;AACxB,UAAI;AACF,cAAM,WAAW,KAAK,aAAa,IAAI;AACvC,cAAM,UAAU,aAAa,UAAU,OAAO;AAC9C,cAAM,UAAU,KAAK,MAAM,OAAO;AAElC,cAAM,gBAAgB,IAAI,KAAK,QAAQ,aAAa,EAAE,QAAQ;AAC9D,YAAI,MAAM,iBAAiB,oBAAoB;AAC7C,gBAAM,aAAa,MAAM,IAAI,KAAK,QAAQ,SAAS,EAAE,QAAQ;AAE7D,qBAAW,QAAQ;AACnB;AAGA,sBAAY;AAAA,YACV,MAAM;AAAA,YACN,WAAW,QAAQ;AAAA,YACnB,OAAO,QAAQ;AAAA,YACf,IAAI;AAAA,YACJ;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF,QAAQ;AAEN,YAAI;AACF,qBAAW,KAAK,aAAa,IAAI,CAAC;AAClC;AAAA,QACF,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;AAKA,eAAsB,mBAAmB,UAMrC,CAAC,GAA4B;AAC/B,QAAM,cAAc,mBAAmB;AACvC,MAAI,CAAC,eAAe,CAAC,WAAW,WAAW,EAAG,QAAO,CAAC;AAEtD,QAAM,SAAyB,CAAC;AAChC,QAAM,UAAU,QAAQ,OAAO,QAAQ,KAAK;AAC5C,QAAM,UAAU,QAAQ,OAAO,QAAQ,KAAK,KAAK,IAAI;AAErD,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,KAAK,gBAAgB;AAAA,MACzB,OAAO,iBAAiB,WAAW;AAAA,MACnC,WAAW;AAAA,IACb,CAAC;AAED,OAAG,GAAG,QAAQ,CAAC,SAAS;AACtB,UAAI,CAAC,KAAK,KAAK,EAAG;AAElB,UAAI;AACF,cAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,cAAM,UAAU,IAAI,KAAK,MAAM,EAAE,EAAE,QAAQ;AAG3C,YAAI,UAAU,WAAW,UAAU,QAAS;AAC5C,YAAI,QAAQ,SAAS,MAAM,UAAU,QAAQ,MAAO;AACpD,YAAI,QAAQ,QAAQ,MAAM,SAAS,QAAQ,KAAM;AAEjD,eAAO,KAAK,KAAK;AAAA,MACnB,QAAQ;AAAA,MAER;AAAA,IACF,CAAC;AAED,OAAG,GAAG,SAAS,MAAM;AAEnB,UAAI,QAAQ,SAAS,OAAO,SAAS,QAAQ,OAAO;AAClD,gBAAQ,OAAO,MAAM,CAAC,QAAQ,KAAK,CAAC;AAAA,MACtC,OAAO;AACL,gBAAQ,MAAM;AAAA,MAChB;AAAA,IACF,CAAC;AAED,OAAG,GAAG,SAAS,MAAM;AACnB,cAAQ,CAAC,CAAC;AAAA,IACZ,CAAC;AAAA,EACH,CAAC;AACH;AAKA,eAAsB,uBAAuB,UAIzC,CAAC,GAAiC;AACpC,QAAM,SAAS,MAAM,mBAAmB,OAAO;AAE/C,QAAM,QAA6B;AAAA,IACjC,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,eAAe;AAAA,IACf,SAAS,CAAC;AAAA,IACV,QAAQ,CAAC;AAAA,IACT,gBAAgB;AAAA,EAClB;AAGA,QAAM,iBAAiB,oBAAI,IAAuD;AAClF,MAAI,oBAAoB;AAExB,aAAW,SAAS,QAAQ;AAC1B,UAAM,QAAQ,MAAM,SAAS;AAC7B,UAAM,OAAO,MAAM,GAAG,MAAM,GAAG,EAAE,CAAC;AAElC,QAAI,MAAM,SAAS,SAAS;AAC1B,YAAM;AACN,YAAM,OAAO,IAAI,KAAK,MAAM,OAAO,IAAI,KAAK,KAAK;AAEjD,UAAI,CAAC,MAAM,QAAQ,KAAK,GAAG;AACzB,cAAM,QAAQ,KAAK,IAAI,EAAE,OAAO,GAAG,YAAY,EAAE;AAAA,MACnD;AACA,YAAM,QAAQ,KAAK,EAAE;AAGrB,qBAAe,IAAI,MAAM,WAAW;AAAA,QAClC,OAAO,MAAM;AAAA,QACb,SAAS,IAAI,KAAK,MAAM,EAAE,EAAE,QAAQ;AAAA,MACtC,CAAC;AACD;AACA,YAAM,iBAAiB,KAAK,IAAI,MAAM,gBAAgB,iBAAiB;AAAA,IACzE;AAEA,QAAI,MAAM,SAAS,UAAU,MAAM,SAAS,iBAAiB;AAC3D,YAAM,WAAW,MAAM,cAAc;AACrC,YAAM,mBAAmB;AAEzB,UAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,cAAM,QAAQ,KAAK,EAAE,cAAc;AAAA,MACrC;AAGA,UAAI,eAAe,IAAI,MAAM,SAAS,GAAG;AACvC,uBAAe,OAAO,MAAM,SAAS;AACrC,4BAAoB,KAAK,IAAI,GAAG,oBAAoB,CAAC;AAAA,MACvD;AAAA,IACF;AAAA,EACF;AAGA,QAAM,oBAAoB,OAAO,OAAO,OAAK,EAAE,SAAS,UAAU,EAAE,SAAS,eAAe,EAAE;AAC9F,MAAI,oBAAoB,GAAG;AACzB,UAAM,gBAAgB,KAAK,MAAM,MAAM,kBAAkB,iBAAiB;AAAA,EAC5E;AAEA,SAAO;AACT;AAKA,eAAsB,kBAAkB,QAAgB,IAA6B;AACnF,QAAM,SAAS,MAAM,mBAAmB,EAAE,OAAO,QAAQ,EAAE,CAAC;AAG5D,QAAM,gBAAgB,oBAAI,IAA4B;AACtD,aAAW,SAAS,QAAQ;AAC1B,QAAI,CAAC,cAAc,IAAI,MAAM,SAAS,GAAG;AACvC,oBAAc,IAAI,MAAM,WAAW,CAAC,CAAC;AAAA,IACvC;AACA,kBAAc,IAAI,MAAM,SAAS,EAAG,KAAK,KAAK;AAAA,EAChD;AAGA,QAAM,cAAc,OACjB,OAAO,OAAK,EAAE,SAAS,OAAO,EAC9B,MAAM,CAAC,KAAK;AAEf,SAAO,YAAY,QAAQ;AAC7B;;;AChqBO,IAAM,MAAM;AACZ,IAAM,QAAQ,GAAG,GAAG;AAGpB,IAAM,MAAM,CAAC,GAAW,GAAW,MAAc,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;AAI1E,IAAM,SAAS;AAAA,EACpB,QAAQ,IAAI,KAAK,IAAI,GAAG;AAAA;AAAA,EACxB,MAAM,IAAI,KAAK,IAAI,GAAG;AAAA;AAAA,EACtB,MAAM,IAAI,GAAG,KAAK,GAAG;AAAA;AAAA,EACrB,OAAO,IAAI,IAAI,KAAK,GAAG;AAAA;AAAA,EACvB,QAAQ,IAAI,KAAK,KAAK,CAAC;AAAA;AAAA,EACvB,KAAK,IAAI,KAAK,IAAI,EAAE;AAAA;AAAA,EACpB,MAAM,IAAI,KAAK,KAAK,GAAG;AAAA;AAAA,EACvB,KAAK,IAAI,IAAI,IAAI,EAAE;AAAA;AAAA,EACnB,OAAO,IAAI,KAAK,KAAK,GAAG;AAC1B;AAGO,IAAM,OAAO,GAAG,GAAG;AACnB,IAAM,MAAM,GAAG,GAAG;AAGlB,IAAM,SAAS;AAAA,EACpB,MAAM,GAAG,GAAG;AAAA,EACZ,MAAM,GAAG,GAAG;AAAA,EACZ,IAAI,CAAC,IAAI,MAAM,GAAG,GAAG,GAAG,CAAC;AAAA,EACzB,MAAM,CAAC,IAAI,MAAM,GAAG,GAAG,GAAG,CAAC;AAAA,EAC3B,MAAM,CAAC,IAAI,MAAM,GAAG,GAAG,GAAG,CAAC;AAAA,EAC3B,OAAO,CAAC,IAAI,MAAM,GAAG,GAAG,GAAG,CAAC;AAAA,EAC5B,IAAI,CAAC,GAAW,MAAc,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC;AAAA,EAC7C,MAAM,GAAG,GAAG;AAAA,EACZ,SAAS,GAAG,GAAG;AACjB;AAGO,IAAM,QAAQ;AAAA,EACnB,MAAM,GAAG,GAAG;AAAA,EACZ,OAAO,GAAG,GAAG;AAAA,EACb,QAAQ,GAAG,GAAG,KAAK,GAAG;AACxB;AAGO,SAAS,SAAS,MAAsB;AAC7C,QAAM,QAAQ;AAAA,IACZ,CAAC,KAAK,IAAI,GAAG;AAAA;AAAA,IACb,CAAC,KAAK,KAAK,GAAG;AAAA;AAAA,IACd,CAAC,KAAK,KAAK,GAAG;AAAA;AAAA,IACd,CAAC,KAAK,KAAK,GAAG;AAAA;AAAA,IACd,CAAC,KAAK,KAAK,GAAG;AAAA;AAAA,EAChB;AAEA,MAAI,SAAS;AACb,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,IAAI,IAAI,KAAK,IAAI,KAAK,SAAS,GAAG,CAAC;AACzC,UAAM,YAAY,KAAK,MAAM,SAAS;AACtC,UAAM,QAAQ,KAAK,MAAM,SAAS;AAClC,UAAM,QAAQ,KAAK,IAAI,QAAQ,GAAG,MAAM,SAAS,CAAC;AAClD,UAAM,QAAQ,YAAY;AAE1B,UAAM,IAAI,KAAK,MAAM,MAAM,KAAK,EAAE,CAAC,KAAK,MAAM,KAAK,EAAE,CAAC,IAAI,MAAM,KAAK,EAAE,CAAC,KAAK,KAAK;AAClF,UAAM,IAAI,KAAK,MAAM,MAAM,KAAK,EAAE,CAAC,KAAK,MAAM,KAAK,EAAE,CAAC,IAAI,MAAM,KAAK,EAAE,CAAC,KAAK,KAAK;AAClF,UAAM,IAAI,KAAK,MAAM,MAAM,KAAK,EAAE,CAAC,KAAK,MAAM,KAAK,EAAE,CAAC,IAAI,MAAM,KAAK,EAAE,CAAC,KAAK,KAAK;AAElF,cAAU,IAAI,GAAG,GAAG,CAAC,IAAI,KAAK,CAAC;AAAA,EACjC;AACA,SAAO,SAAS;AAClB;AAGO,SAAS,YAAY,SAAiB,QAAQ,IAAY;AAC/D,QAAM,SAAS,KAAK,MAAO,UAAU,MAAO,KAAK;AACjD,QAAM,QAAQ,QAAQ;AAEtB,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,UAAM,IAAI,IAAI,KAAK,IAAI,SAAS,GAAG,CAAC;AACpC,UAAM,IAAI,KAAK,MAAM,MAAM,MAAM,MAAM,CAAC;AACxC,UAAM,IAAI,KAAK,MAAM,OAAO,KAAK,OAAO,CAAC;AACzC,UAAM,IAAI,KAAK,MAAM,OAAO,MAAM,OAAO,CAAC;AAC1C,WAAO,IAAI,GAAG,GAAG,CAAC,IAAI;AAAA,EACxB;AAEA,SAAO,OAAO,MAAM,SAAI,OAAO,KAAK,IAAI;AACxC,SAAO;AACT;AAGO,IAAM,MAAM;AAAA,EACjB,SAAS;AAAA,EACT,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,UAAU;AAAA,EACV,SAAS;AACX;AAGO,SAAS,OAAO,KAAa,KAAqB;AAEvD,QAAM,UAAU,IAAI,QAAQ,mBAAmB,EAAE;AACjD,QAAM,MAAM,KAAK,IAAI,GAAG,MAAM,QAAQ,MAAM;AAC5C,SAAO,MAAM,IAAI,OAAO,GAAG;AAC7B;AAEO,SAAS,SAAS,KAAa,KAAqB;AACzD,QAAM,UAAU,IAAI,QAAQ,mBAAmB,EAAE;AACjD,MAAI,QAAQ,UAAU,IAAK,QAAO;AAGlC,MAAI,SAAS;AACb,MAAI,QAAQ;AACZ,MAAI,IAAI;AAER,SAAO,IAAI,IAAI,UAAU,QAAQ,MAAM,GAAG;AACxC,QAAI,IAAI,CAAC,MAAM,QAAQ;AACrB,YAAM,MAAM,IAAI,QAAQ,KAAK,CAAC;AAC9B,UAAI,QAAQ,IAAI;AACd,kBAAU,IAAI,MAAM,GAAG,MAAM,CAAC;AAC9B,YAAI,MAAM;AACV;AAAA,MACF;AAAA,IACF;AACA,cAAU,IAAI,CAAC;AACf;AACA;AAAA,EACF;AAEA,SAAO,SAAS,OAAO,MAAM,WAAM;AACrC;AAMO,IAAM,QAAQ;AAAA,EACnB,SAAS,GAAG,OAAO,KAAK,SAAI,KAAK;AAAA,EACjC,SAAS,GAAG,OAAO,MAAM,SAAI,KAAK;AAAA,EAClC,OAAO,GAAG,OAAO,GAAG,SAAI,KAAK;AAAA,EAC7B,SAAS,GAAG,OAAO,GAAG,SAAI,KAAK;AAAA,EAC/B,QAAQ,GAAG,OAAO,KAAK,SAAI,KAAK;AAAA,EAChC,UAAU,GAAG,OAAO,IAAI,SAAI,KAAK;AAAA,EACjC,OAAO,GAAG,OAAO,GAAG,SAAI,KAAK;AAC/B;AAQO,SAAS,UAAU,MAAM,IAAU;AACxC,UAAQ,OAAO,MAAM,MAAM,IAAI;AACjC;AAGO,SAAS,UAAU,QAAkB,OAAwB;AAClE,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,QAAM,SAAS,CAAC,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,QAAG;AACtD,QAAM,MAAM,KAAK,IAAI,GAAG,QAAQ,CAAC;AAEjC,MAAI,SAAS;AACb,aAAW,OAAO,QAAQ;AACxB,UAAM,aAAa,MAAM;AACzB,UAAM,aAAa,KAAK,IAAI,KAAK,MAAM,aAAa,OAAO,MAAM,GAAG,OAAO,SAAS,CAAC;AACrF,UAAM,YAAY;AAGlB,QAAI,eAAe,GAAG;AACpB,gBAAU,OAAO,MAAM,OAAO,CAAC;AAAA,IACjC,WAAW,aAAa,KAAK;AAC3B,gBAAU,OAAO,OAAO,OAAO,UAAU;AAAA,IAC3C,OAAO;AACL,gBAAU,OAAO,QAAQ,OAAO,UAAU;AAAA,IAC5C;AAAA,EACF;AAEA,SAAO,SAAS;AAClB;AAGO,SAAS,SAAS,OAAe,KAAa,QAAgB,IAAI,OAAwB;AAC/F,QAAM,SAAS,KAAK,MAAO,QAAQ,MAAO,KAAK;AAC/C,QAAM,QAAQ,QAAQ;AAEtB,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,UAAM,IAAI,IAAI,KAAK,IAAI,SAAS,GAAG,CAAC;AAEpC,UAAM,IAAI,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC;AACtC,UAAM,IAAI,KAAK,MAAM,OAAO,MAAM,OAAO,CAAC;AAC1C,UAAM,IAAI,KAAK,MAAM,OAAO,MAAM,OAAO,CAAC;AAC1C,WAAO,IAAI,GAAG,GAAG,CAAC,IAAI;AAAA,EACxB;AAEA,SAAO,OAAO,MAAM,SAAI,OAAO,KAAK,IAAI;AAExC,MAAI,OAAO;AACT,WAAO,GAAG,GAAG,IAAI,KAAK;AAAA,EACxB;AACA,SAAO;AACT;;;ACrLA,eAAsB,gBACpB,UAA2B,CAAC,GACb;AAEf,uBAAqB;AAErB,QAAM,WAAW,kBAAkB;AACnC,QAAM,UAAU,kBAAkB;AAGlC,MAAI,QAAQ,MAAM;AAChB,YAAQ,IAAI,KAAK,UAAU,EAAE,UAAU,QAAQ,GAAG,MAAM,CAAC,CAAC;AAC1D;AAAA,EACF;AAEA,YAAU;AACV,YAAU,KAAK,SAAS,QAAQ,CAAC,IAAI,OAAO,GAAG,WAAW,KAAK,EAAE;AACjE,YAAU;AAEV,MAAI,SAAS,WAAW,GAAG;AACzB,cAAU,KAAK,OAAO,GAAG,qBAAqB,KAAK,EAAE;AACrD,cAAU;AACV,cAAU,KAAK,OAAO,GAAG,4DAA4D,KAAK,EAAE;AAC5F,cAAU,KAAK,OAAO,GAAG,8DAA8D,KAAK,EAAE;AAC9F,cAAU;AACV;AAAA,EACF;AAGA,QAAM,YAAY,QAAQ,eAAe,IAAI,UAAU;AACvD,QAAM,cAAc,QAAQ,kBAAkB,IAAI,YAAY;AAC9D,YAAU,KAAK,OAAO,KAAK,GAAG,QAAQ,aAAa,GAAG,KAAK,WAAW,WAAW,IAAI,OAAO,GAAG,SAAS,KAAK,IAAI,OAAO,IAAI,GAAG,QAAQ,UAAU,GAAG,KAAK,IAAI,SAAS,EAAE;AACxK,YAAU;AAGV,QAAM,UAA0C,CAAC;AACjD,aAAW,WAAW,UAAU;AAC9B,UAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAI,CAAC,QAAQ,KAAK,EAAG,SAAQ,KAAK,IAAI,CAAC;AACvC,YAAQ,KAAK,EAAE,KAAK,OAAO;AAAA,EAC7B;AAGA,QAAM,IAAI,EAAE,OAAO,IAAI,UAAU,IAAI,UAAU,GAAG;AAClD,QAAM,aAAa,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW;AAEvD,YAAU,KAAK,OAAO,MAAM,GAAG,IAAI,OAAO,GAAG,OAAO,GAAG,GAAG,IAAI,WAAW,OAAO,UAAU,CAAC,GAAG,OAAO,MAAM,GAAG,IAAI,QAAQ,GAAG,KAAK,EAAE;AAEpI,QAAM,SAAS,KAAK,OAAO,MAAM,GAAG,IAAI,QAAQ,GAAG,KAAK,IACnD,IAAI,GAAG,OAAO,SAAS,EAAE,KAAK,CAAC,GAAG,KAAK,GACvC,IAAI,GAAG,OAAO,YAAY,EAAE,QAAQ,CAAC,GAAG,KAAK,GAC7C,IAAI,gBAAgB,KAAK,IACxB,OAAO,MAAM,GAAG,IAAI,QAAQ,GAAG,KAAK;AAC1C,YAAU,MAAM;AAEhB,YAAU,KAAK,OAAO,MAAM,GAAG,IAAI,QAAQ,GAAG,OAAO,GAAG,GAAG,IAAI,WAAW,OAAO,UAAU,CAAC,GAAG,OAAO,MAAM,GAAG,IAAI,OAAO,GAAG,KAAK,EAAE;AAEpI,aAAW,CAAC,OAAO,aAAa,KAAK,OAAO,QAAQ,OAAO,EAAE,KAAK,GAAG;AAEnE,QAAI,aAAa;AACjB,eAAW,WAAW,eAAe;AACnC,YAAM,KAAK,IAAI,KAAK,QAAQ,aAAa,EAAE,QAAQ;AACnD,UAAI,KAAK,WAAY,cAAa;AAAA,IACpC;AAEA,UAAM,eAAe,cAAc,UAAU;AAC7C,UAAM,gBAAgB,iBAAiB,UAAU;AAEjD,UAAM,MAAM,KAAK,OAAO,MAAM,GAAG,IAAI,QAAQ,GAAG,KAAK,IAChD,OAAO,IAAI,GAAG,OAAO,OAAO,EAAE,KAAK,CAAC,GAAG,KAAK,GAC5C,OAAO,OAAO,cAAc,MAAM,GAAG,EAAE,QAAQ,CAAC,GAChD,OAAO,GAAG,aAAa,GAAG,YAAY,GAAG,KAAK,IAAI,EAAE,QAAQ,CAAC,GAC7D,OAAO,MAAM,GAAG,IAAI,QAAQ,GAAG,KAAK;AAEzC,cAAU,GAAG;AAAA,EACf;AAEA,YAAU,KAAK,OAAO,MAAM,GAAG,IAAI,UAAU,GAAG,OAAO,GAAG,GAAG,IAAI,WAAW,OAAO,UAAU,CAAC,GAAG,OAAO,MAAM,GAAG,IAAI,WAAW,GAAG,KAAK,EAAE;AAG1I,MAAI,QAAQ,SAAS;AACnB,cAAU;AACV,cAAU,KAAK,IAAI,kBAAkB,KAAK,EAAE;AAC5C,cAAU;AAEV,eAAW,WAAW,UAAU;AAC9B,YAAM,QAAQ,QAAQ,SAAS;AAC/B,YAAM,MAAM,cAAc,IAAI,KAAK,QAAQ,aAAa,EAAE,QAAQ,CAAC;AAEnE,gBAAU,KAAK,MAAM,MAAM,IAAI,OAAO,KAAK,GAAG,QAAQ,SAAS,GAAG,KAAK,EAAE;AACzE,gBAAU,OAAO,OAAO,GAAG,UAAU,KAAK,WAAW,QAAQ,GAAG,iBAAiB,GAAG,GAAG,KAAK,EAAE;AAC9F,gBAAU,OAAO,OAAO,GAAG,QAAQ,QAAQ,GAAG,GAAG,KAAK,EAAE;AAAA,IAC1D;AAAA,EACF;AAEA,YAAU;AACV,YAAU,KAAK,OAAO,GAAG,IAAI,KAAK,0BAA0B,OAAO,GAAG,uBAAuB,KAAK,EAAE;AACpG,YAAU;AACZ;AAKA,SAAS,cAAc,WAA2B;AAChD,QAAM,MAAM,KAAK,IAAI;AACrB,QAAM,OAAO,MAAM;AAEnB,QAAM,UAAU,KAAK,MAAM,OAAO,GAAI;AACtC,QAAM,UAAU,KAAK,MAAM,UAAU,EAAE;AAEvC,MAAI,WAAW,GAAG;AAChB,WAAO,GAAG,OAAO;AAAA,EACnB;AACA,SAAO,GAAG,OAAO;AACnB;AAKA,SAAS,iBAAiB,WAA2B;AACnD,QAAM,MAAM,KAAK,IAAI;AACrB,QAAM,OAAO,MAAM;AAEnB,QAAM,UAAU,KAAK,MAAM,QAAQ,MAAO,GAAG;AAE7C,MAAI,UAAU,EAAG,QAAO,OAAO;AAC/B,MAAI,UAAU,EAAG,QAAO,OAAO;AAC/B,SAAO,OAAO;AAChB;AA2CA,eAAsB,uBACpB,MACA,UAA0B,CAAC,GACZ;AACf,MAAI,QAAQ,MAAM;AAChB,YAAQ,IAAI,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AACzC;AAAA,EACF;AAEA,YAAU;AACV,YAAU,KAAK,SAAS,QAAQ,CAAC,IAAI,OAAO,GAAG,kBAAkB,KAAK,EAAE;AACxE,YAAU;AAGV,MAAI,KAAK,OAAO,SAAS,GAAG;AAC1B,UAAM,IAAI,EAAE,OAAO,IAAI,SAAS,IAAI,SAAS,GAAG;AAChD,UAAM,aAAa,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU;AAGrD,UAAMA,YAAW,CAAC,MAAc,QAC9B,KAAK,SAAS,MAAM,KAAK,UAAU,GAAG,MAAM,CAAC,IAAI,WAAM;AAEzD,cAAU,KAAK,OAAO,KAAK,GAAG,MAAM,MAAM,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,OAAO,MAAM,iBAAiB,KAAK,EAAE;AACvG,cAAU;AAEV,cAAU,KAAK,OAAO,MAAM,GAAG,IAAI,OAAO,GAAG,OAAO,GAAG,GAAG,IAAI,WAAW,OAAO,UAAU,CAAC,GAAG,OAAO,MAAM,GAAG,IAAI,QAAQ,GAAG,KAAK,EAAE;AAEpI,UAAM,SAAS,KAAK,OAAO,MAAM,GAAG,IAAI,QAAQ,GAAG,KAAK,IACnD,IAAI,GAAG,OAAO,SAAS,EAAE,KAAK,CAAC,GAAG,KAAK,GACvC,IAAI,GAAG,OAAO,WAAW,EAAE,OAAO,CAAC,GAAG,KAAK,GAC3C,IAAI,GAAG,OAAO,eAAe,EAAE,OAAO,CAAC,GAAG,KAAK,GAC/C,OAAO,MAAM,GAAG,IAAI,QAAQ,GAAG,KAAK;AACzC,cAAU,MAAM;AAEhB,cAAU,KAAK,OAAO,MAAM,GAAG,IAAI,QAAQ,GAAG,OAAO,GAAG,GAAG,IAAI,WAAW,OAAO,UAAU,CAAC,GAAG,OAAO,MAAM,GAAG,IAAI,OAAO,GAAG,KAAK,EAAE;AAEpI,eAAW,SAAS,KAAK,QAAQ;AAC/B,YAAM,MAAM,KAAK,OAAO,MAAM,GAAG,IAAI,QAAQ,GAAG,KAAK,IAChD,OAAO,IAAI,GAAG,OAAOA,UAAS,MAAM,MAAM,EAAE,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,KAAK,GACxE,OAAOA,UAAS,MAAM,SAAS,EAAE,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,GACzD,OAAOA,UAAS,MAAM,SAAS,EAAE,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,GACzD,OAAO,MAAM,GAAG,IAAI,QAAQ,GAAG,KAAK;AACzC,gBAAU,GAAG;AAAA,IACf;AAEA,cAAU,KAAK,OAAO,MAAM,GAAG,IAAI,UAAU,GAAG,OAAO,GAAG,GAAG,IAAI,WAAW,OAAO,UAAU,CAAC,GAAG,OAAO,MAAM,GAAG,IAAI,WAAW,GAAG,KAAK,EAAE;AAAA,EAC5I;AAGA,MAAI,KAAK,aAAa,KAAK,UAAU,SAAS,GAAG;AAC/C,cAAU;AACV,cAAU,KAAK,IAAI,sBAAsB,KAAK,EAAE;AAChD,cAAU;AAEV,UAAM,IAAI,EAAE,UAAU,IAAI,QAAQ,GAAG;AACrC,UAAM,aAAa,EAAE,WAAW,EAAE,SAAS;AAE3C,cAAU,KAAK,OAAO,MAAM,GAAG,IAAI,OAAO,GAAG,OAAO,GAAG,GAAG,IAAI,WAAW,OAAO,UAAU,CAAC,GAAG,OAAO,MAAM,GAAG,IAAI,QAAQ,GAAG,KAAK,EAAE;AAEpI,eAAW,YAAY,KAAK,WAAW;AACrC,YAAM,MAAM,KAAK,OAAO,MAAM,GAAG,IAAI,QAAQ,GAAG,KAAK,IAChD,OAAO,MAAM,GAAG,OAAO,SAAS,UAAU,EAAE,QAAQ,CAAC,GAAG,KAAK,GAC7D,OAAO,SAAS,QAAQ,EAAE,MAAM,CAAC,GACjC,OAAO,MAAM,GAAG,IAAI,QAAQ,GAAG,KAAK;AACzC,gBAAU,GAAG;AAAA,IACf;AAEA,cAAU,KAAK,OAAO,MAAM,GAAG,IAAI,UAAU,GAAG,OAAO,GAAG,GAAG,IAAI,WAAW,OAAO,UAAU,CAAC,GAAG,OAAO,MAAM,GAAG,IAAI,WAAW,GAAG,KAAK,EAAE;AAAA,EAC5I;AAGA,MAAI,KAAK,UAAU;AACjB,cAAU;AACV,cAAU,KAAK,IAAI,kBAAkB,KAAK,EAAE;AAC5C,cAAU;AACV,cAAU,KAAK,OAAO,GAAG,YAAY,KAAK,IAAI,OAAO,IAAI,GAAG,KAAK,SAAS,QAAQ,GAAG,KAAK,EAAE;AAC5F,cAAU,KAAK,OAAO,GAAG,WAAW,KAAK,KAAK,OAAO,KAAK,GAAG,KAAK,SAAS,OAAO,GAAG,KAAK,EAAE;AAC5F,cAAU,KAAK,OAAO,GAAG,QAAQ,KAAK,QAAQ,KAAK,SAAS,WAAW,KAAK,IAAI,CAAC,EAAE;AAAA,EACrF;AAGA,MAAI,KAAK,eAAe,KAAK,YAAY,SAAS,GAAG;AACnD,cAAU;AACV,cAAU,KAAK,IAAI,eAAe,KAAK,EAAE;AACzC,cAAU;AAEV,eAAW,UAAU,KAAK,aAAa;AACrC,gBAAU,KAAK,OAAO,IAAI,GAAG,OAAO,OAAO,OAAO,EAAE,CAAC,GAAG,KAAK,GAAG,OAAO,GAAG,SAAI,KAAK,IAAI,OAAO,MAAM,EAAE;AAAA,IACxG;AAAA,EACF;AAGA,MAAI,KAAK,WAAW,KAAK,QAAQ,SAAS,GAAG;AAC3C,cAAU;AACV,cAAU,KAAK,IAAI,aAAa,KAAK,EAAE;AACvC,cAAU;AAEV,eAAW,UAAU,KAAK,SAAS;AACjC,gBAAU,KAAK,OAAO,GAAG,SAAI,KAAK,IAAI,OAAO,MAAM,KAAK,OAAO,KAAK,GAAG,OAAO,KAAK,GAAG,KAAK,EAAE;AAAA,IAC/F;AAAA,EACF;AAGA,MAAI,KAAK,gBAAgB,KAAK,aAAa,SAAS,GAAG;AACrD,cAAU;AACV,cAAU,KAAK,OAAO,GAAG,iBAAiB,KAAK,EAAE;AACjD,eAAW,QAAQ,KAAK,cAAc;AACpC,gBAAU,KAAK,OAAO,GAAG,WAAM,KAAK,IAAI,OAAO,IAAI,GAAG,IAAI,GAAG,KAAK,EAAE;AAAA,IACtE;AAAA,EACF;AAEA,YAAU;AAGV,QAAM,YAAY,KAAK,QAAQ,KAAK,QAAQ;AAC5C,QAAM,eAAe,KAAK,WAAW,IAAI,OAAO,GAAG,IAAI,KAAK,QAAQ,IAAI,KAAK,KAAK;AAClF,YAAU,KAAK,OAAO,GAAG,eAAe,KAAK,IAAI,OAAO,MAAM,GAAG,SAAS,GAAG,KAAK,GAAG,YAAY,EAAE;AACnG,YAAU;AACZ;AAKA,eAAsB,6BAA0D;AAC9E,QAAM,EAAE,YAAAC,aAAY,aAAAC,cAAa,UAAU,cAAAC,cAAa,IAAI,MAAM,OAAO,IAAI;AAC7E,QAAM,EAAE,MAAAC,MAAK,IAAI,MAAM,OAAO,MAAM;AACpC,QAAM,EAAE,cAAc,IAAI,MAAM,OAAO,sBAAkB;AAEzD,QAAM,YAAY,cAAc;AAChC,QAAM,SAAuC,CAAC;AAC9C,QAAM,eAAyB,CAAC;AAGhC,QAAM,gBAAgB,IAAI,KAAK,KAAK;AACpC,QAAM,MAAM,KAAK,IAAI;AAErB,MAAI,aAAaH,YAAW,SAAS,GAAG;AACtC,UAAM,YAAYC,aAAY,WAAW,EAAE,eAAe,KAAK,CAAC,EAC7D,OAAO,OAAK,EAAE,YAAY,CAAC;AAE9B,eAAW,YAAY,WAAW;AAChC,YAAM,YAAYE,MAAK,WAAW,SAAS,IAAI;AAC/C,UAAI,gBAAgB;AACpB,UAAI,eAAe;AACnB,UAAI,mBAAmB;AAEvB,UAAI;AACF,cAAM,YAAYF,aAAY,WAAW,EAAE,eAAe,KAAK,CAAC,EAC7D,OAAO,OAAK,EAAE,YAAY,CAAC;AAE9B,mBAAW,YAAY,WAAW;AAChC,gBAAM,YAAYE,MAAK,WAAW,SAAS,IAAI;AAC/C,gBAAM,QAAQF,aAAY,SAAS,EAAE,OAAO,OAAK,EAAE,SAAS,KAAK,CAAC;AAElE,qBAAW,QAAQ,OAAO;AACxB,kBAAM,WAAWE,MAAK,WAAW,IAAI;AACrC,kBAAM,QAAQ,SAAS,QAAQ;AAE/B,gBAAI,MAAM,MAAM,UAAU,eAAe;AACvC,8BAAgB;AAChB,oBAAM,eAAe,GAAG,SAAS,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI;AAC9D,2BAAa,KAAK,YAAY;AAG9B,kBAAI,SAAS,YAAY;AACvB,+BAAeD,cAAa,UAAU,OAAO;AAAA,cAC/C,WAAW,SAAS,iBAAiB;AACnC,mCAAmBA,cAAa,UAAU,OAAO;AAAA,cACnD;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,YAAI,eAAe;AAEjB,cAAI,UAAU;AACd,cAAI,UAAU;AAGd,cAAI,kBAAkB;AACpB,kBAAM,QAAQ,iBAAiB,MAAM,IAAI,EAAE,OAAO,OAAK,EAAE,KAAK,CAAC;AAC/D,kBAAM,cAAc,MAAM,MAAM,GAAG,EAAE,KAAK,GAAG;AAC7C,gBAAI,YAAY,SAAS,WAAW,GAAG;AACrC,wBAAU;AAAA,YACZ;AAEA,kBAAM,WAAW,YAAY,MAAM,kDAAkD;AACrF,gBAAI,UAAU;AACZ,wBAAU,SAAS,CAAC,EAAE,UAAU,GAAG,EAAE;AAAA,YACvC;AAAA,UACF;AAGA,cAAI,cAAc;AAChB,kBAAM,eAAe,aAAa,MAAM,qBAAqB;AAC7D,gBAAI,cAAc;AAChB,wBAAU,WAAW,aAAa,CAAC,CAAC;AAAA,YACtC;AAAA,UACF;AAEA,iBAAO,KAAK;AAAA,YACV,MAAM,SAAS,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,SAAS,KAAK,MAAM,CAAC;AAAA,YACnE;AAAA,YACA,SAAS,QAAQ,SAAS,KAAK,QAAQ,UAAU,GAAG,EAAE,IAAI,QAAQ;AAAA,UACpE,CAAC;AAAA,QACH;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,WAAW,GAAG;AACvB,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL;AAAA,IACA,cAAc,aAAa,SAAS,IAAI,eAAe;AAAA,IACvD,OAAO,QAAQ,IAAI,mBAAmB;AAAA,EACxC;AACF;AAKA,eAAsB,uBACpB,UAA0B,CAAC,GACZ;AACf,QAAM,OAAO,QAAQ,QAAQ;AAC7B,QAAM,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,KAAK,GAAI;AAE9D,QAAM,QAAQ,MAAM,uBAAuB;AAAA,IACzC;AAAA,IACA,OAAO,QAAQ;AAAA,EACjB,CAAC;AAED,QAAM,iBAAiB,MAAM,kBAAkB,EAAE;AAGjD,MAAI,QAAQ,MAAM;AAChB,YAAQ,IAAI,KAAK,UAAU,EAAE,OAAO,eAAe,GAAG,MAAM,CAAC,CAAC;AAC9D;AAAA,EACF;AAEA,YAAU;AACV,YAAU,KAAK,SAAS,QAAQ,CAAC,IAAI,OAAO,GAAG,mBAAmB,KAAK,IAAI,OAAO,GAAG,IAAI,IAAI,KAAK,KAAK,EAAE;AACzG,YAAU;AAEV,MAAI,MAAM,kBAAkB,GAAG;AAC7B,cAAU,KAAK,OAAO,GAAG,2BAA2B,KAAK,EAAE;AAC3D,cAAU;AACV,cAAU,KAAK,OAAO,GAAG,8DAA8D,KAAK,EAAE;AAC9F,cAAU;AACV;AAAA,EACF;AAGA,QAAM,aAAa,KAAK,MAAM,MAAM,gBAAgB,GAAK;AACzD,QAAM,aAAa,KAAK,MAAM,MAAM,kBAAkB,OAAU,EAAE,IAAI;AAEtE,YAAU,KAAK,IAAI,UAAU,KAAK,EAAE;AACpC,YAAU,KAAK,OAAO,IAAI,GAAG,MAAM,aAAa,GAAG,KAAK,cAAc,OAAO,GAAG,SAAI,KAAK,KAAK,OAAO,KAAK,GAAG,UAAU,IAAI,KAAK,WAAW,OAAO,GAAG,SAAI,KAAK,KAAK,OAAO,MAAM,GAAG,UAAU,IAAI,KAAK,SAAS,OAAO,GAAG,SAAI,KAAK,KAAK,OAAO,MAAM,GAAG,MAAM,cAAc,GAAG,KAAK,OAAO;AAC1R,YAAU;AAGV,QAAM,SAAS,OAAO,QAAQ,MAAM,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,KAAK;AAEnF,MAAI,OAAO,SAAS,GAAG;AACrB,UAAM,IAAI,EAAE,OAAO,IAAI,UAAU,IAAI,UAAU,GAAG;AAClD,UAAM,aAAa,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW;AAEvD,cAAU,KAAK,IAAI,WAAW,KAAK,EAAE;AACrC,cAAU;AACV,cAAU,KAAK,OAAO,MAAM,GAAG,IAAI,OAAO,GAAG,OAAO,GAAG,GAAG,IAAI,WAAW,OAAO,UAAU,CAAC,GAAG,OAAO,MAAM,GAAG,IAAI,QAAQ,GAAG,KAAK,EAAE;AAEpI,UAAM,SAAS,KAAK,OAAO,MAAM,GAAG,IAAI,QAAQ,GAAG,KAAK,IACnD,IAAI,GAAG,OAAO,SAAS,EAAE,KAAK,CAAC,GAAG,KAAK,GACvC,IAAI,GAAG,OAAO,YAAY,EAAE,QAAQ,CAAC,GAAG,KAAK,GAC7C,IAAI,WAAW,KAAK,IACnB,OAAO,MAAM,GAAG,IAAI,QAAQ,GAAG,KAAK;AAC1C,cAAU,MAAM;AAEhB,cAAU,KAAK,OAAO,MAAM,GAAG,IAAI,QAAQ,GAAG,OAAO,GAAG,GAAG,IAAI,WAAW,OAAO,UAAU,CAAC,GAAG,OAAO,MAAM,GAAG,IAAI,OAAO,GAAG,KAAK,EAAE;AAEpI,eAAW,CAAC,OAAO,IAAI,KAAK,QAAQ;AAClC,YAAM,QAAQ,KAAK,MAAM,KAAK,aAAa,OAAU,EAAE,IAAI;AAE3D,YAAM,MAAM,KAAK,OAAO,MAAM,GAAG,IAAI,QAAQ,GAAG,KAAK,IAChD,OAAO,IAAI,GAAG,OAAO,OAAO,EAAE,KAAK,CAAC,GAAG,KAAK,GAC5C,OAAO,OAAO,KAAK,KAAK,GAAG,EAAE,QAAQ,CAAC,GACtC,OAAO,GAAG,KAAK,KAAK,EAAE,QAAQ,CAAC,GAC/B,OAAO,MAAM,GAAG,IAAI,QAAQ,GAAG,KAAK;AAEzC,gBAAU,GAAG;AAAA,IACf;AAEA,cAAU,KAAK,OAAO,MAAM,GAAG,IAAI,UAAU,GAAG,OAAO,GAAG,GAAG,IAAI,WAAW,OAAO,UAAU,CAAC,GAAG,OAAO,MAAM,GAAG,IAAI,WAAW,GAAG,KAAK,EAAE;AAAA,EAC5I;AAGA,MAAI,eAAe,SAAS,GAAG;AAC7B,cAAU;AACV,cAAU,KAAK,IAAI,kBAAkB,KAAK,EAAE;AAC5C,cAAU;AAEV,eAAW,SAAS,eAAe,MAAM,GAAG,CAAC,GAAG;AAC9C,YAAM,QAAQ,MAAM,SAAS;AAC7B,YAAM,OAAO,IAAI,KAAK,MAAM,EAAE;AAC9B,YAAM,UAAU,KAAK,mBAAmB,SAAS,EAAE,MAAM,WAAW,QAAQ,UAAU,CAAC;AACvF,YAAM,UAAU,KAAK,mBAAmB,SAAS,EAAE,OAAO,SAAS,KAAK,UAAU,CAAC;AAEnF,gBAAU,KAAK,OAAO,GAAG,GAAG,OAAO,IAAI,OAAO,GAAG,KAAK,KAAK,OAAO,IAAI,GAAG,KAAK,GAAG,KAAK,KAAK,OAAO,GAAG,GAAG,MAAM,UAAU,MAAM,GAAG,CAAC,CAAC,GAAG,KAAK,EAAE;AAAA,IAC/I;AAAA,EACF;AAGA,QAAM,QAAQ,OAAO,QAAQ,MAAM,MAAM,EACtC,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,EACvC,MAAM,GAAG,CAAC;AAEb,MAAI,MAAM,SAAS,GAAG;AACpB,cAAU;AACV,cAAU,KAAK,IAAI,iBAAiB,KAAK,EAAE;AAC3C,cAAU;AAEV,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO;AACjC,YAAM,MAAM,SAAI,OAAO,KAAK,IAAI,OAAO,EAAE,CAAC;AAC1C,gBAAU,KAAK,OAAO,GAAG,GAAG,IAAI,GAAG,KAAK,KAAK,OAAO,KAAK,GAAG,GAAG,GAAG,KAAK,IAAI,KAAK,EAAE;AAAA,IACpF;AAAA,EACF;AAEA,YAAU;AACV,YAAU,KAAK,OAAO,GAAG,IAAI,KAAK,wCAAwC,OAAO,GAAG,iBAAiB,KAAK,EAAE;AAC5G,YAAU,KAAK,OAAO,GAAG,IAAI,KAAK,wCAAwC,OAAO,GAAG,kBAAkB,KAAK,EAAE;AAC7G,YAAU;AACZ;","names":["truncate","existsSync","readdirSync","readFileSync","join"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
3
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
4
|
+
}) : x)(function(x) {
|
|
5
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
6
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
__require
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=chunk-7OCVIDC7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
__require
|
|
4
|
+
} from "./chunk-7OCVIDC7.js";
|
|
5
|
+
|
|
6
|
+
// src/lib/memory.ts
|
|
7
|
+
import { readFileSync, writeFileSync, existsSync, readdirSync, mkdirSync } from "fs";
|
|
8
|
+
import { join, dirname } from "path";
|
|
9
|
+
function findMemoryDir() {
|
|
10
|
+
let dir = process.cwd();
|
|
11
|
+
for (let i = 0; i < 5; i++) {
|
|
12
|
+
const memoryPath = join(dir, ".agents", "memory");
|
|
13
|
+
if (existsSync(memoryPath)) {
|
|
14
|
+
return memoryPath;
|
|
15
|
+
}
|
|
16
|
+
const parent = join(dir, "..");
|
|
17
|
+
if (parent === dir) break;
|
|
18
|
+
dir = parent;
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
function listMemoryEntries(memoryDir) {
|
|
23
|
+
const entries = [];
|
|
24
|
+
const squads = readdirSync(memoryDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
25
|
+
for (const squad of squads) {
|
|
26
|
+
const squadPath = join(memoryDir, squad);
|
|
27
|
+
const agents = readdirSync(squadPath, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
28
|
+
for (const agent of agents) {
|
|
29
|
+
const agentPath = join(squadPath, agent);
|
|
30
|
+
const files = readdirSync(agentPath).filter((f) => f.endsWith(".md"));
|
|
31
|
+
for (const file of files) {
|
|
32
|
+
const filePath = join(agentPath, file);
|
|
33
|
+
const type = file.replace(".md", "");
|
|
34
|
+
entries.push({
|
|
35
|
+
squad,
|
|
36
|
+
agent,
|
|
37
|
+
type,
|
|
38
|
+
content: readFileSync(filePath, "utf-8"),
|
|
39
|
+
path: filePath
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return entries;
|
|
45
|
+
}
|
|
46
|
+
var SEMANTIC_EXPANSIONS = {
|
|
47
|
+
"pricing": ["price", "cost", "$", "revenue", "fee", "rate"],
|
|
48
|
+
"price": ["pricing", "cost", "$", "fee"],
|
|
49
|
+
"revenue": ["income", "sales", "mrr", "arr", "$"],
|
|
50
|
+
"cost": ["expense", "spend", "budget", "$", "price"],
|
|
51
|
+
"customer": ["client", "lead", "prospect", "user"],
|
|
52
|
+
"client": ["customer", "lead", "prospect"],
|
|
53
|
+
"lead": ["prospect", "customer", "client", "pipeline"],
|
|
54
|
+
"agent": ["squad", "bot", "ai"],
|
|
55
|
+
"squad": ["team", "agent", "group"],
|
|
56
|
+
"status": ["state", "progress", "health"],
|
|
57
|
+
"bug": ["issue", "error", "problem", "fix"],
|
|
58
|
+
"feature": ["capability", "function", "ability"]
|
|
59
|
+
};
|
|
60
|
+
function expandQuery(query) {
|
|
61
|
+
const words = query.toLowerCase().split(/\s+/);
|
|
62
|
+
const expanded = new Set(words);
|
|
63
|
+
for (const word of words) {
|
|
64
|
+
if (SEMANTIC_EXPANSIONS[word]) {
|
|
65
|
+
SEMANTIC_EXPANSIONS[word].forEach((syn) => expanded.add(syn));
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return Array.from(expanded);
|
|
69
|
+
}
|
|
70
|
+
function getFileAge(filePath) {
|
|
71
|
+
try {
|
|
72
|
+
const { statSync } = __require("fs");
|
|
73
|
+
const stats = statSync(filePath);
|
|
74
|
+
const ageMs = Date.now() - stats.mtimeMs;
|
|
75
|
+
const ageDays = ageMs / (1e3 * 60 * 60 * 24);
|
|
76
|
+
return ageDays;
|
|
77
|
+
} catch {
|
|
78
|
+
return 999;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function searchMemory(query, memoryDir) {
|
|
82
|
+
const dir = memoryDir || findMemoryDir();
|
|
83
|
+
if (!dir) return [];
|
|
84
|
+
const entries = listMemoryEntries(dir);
|
|
85
|
+
const results = [];
|
|
86
|
+
const queryLower = query.toLowerCase();
|
|
87
|
+
const expandedTerms = expandQuery(queryLower);
|
|
88
|
+
for (const entry of entries) {
|
|
89
|
+
const contentLower = entry.content.toLowerCase();
|
|
90
|
+
const lines = entry.content.split("\n");
|
|
91
|
+
const matches = [];
|
|
92
|
+
let score = 0;
|
|
93
|
+
let directHits = 0;
|
|
94
|
+
let expandedHits = 0;
|
|
95
|
+
const directWords = queryLower.split(/\s+/);
|
|
96
|
+
for (const word of directWords) {
|
|
97
|
+
if (contentLower.includes(word)) {
|
|
98
|
+
directHits += 1;
|
|
99
|
+
score += 2;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
for (const term of expandedTerms) {
|
|
103
|
+
if (contentLower.includes(term)) {
|
|
104
|
+
expandedHits += 1;
|
|
105
|
+
score += 0.5;
|
|
106
|
+
for (let i = 0; i < lines.length; i++) {
|
|
107
|
+
const line = lines[i];
|
|
108
|
+
if (line.toLowerCase().includes(term) && line.trim() && !matches.includes(line.trim())) {
|
|
109
|
+
matches.push(line.trim());
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (contentLower.includes(queryLower)) {
|
|
115
|
+
score += 5;
|
|
116
|
+
}
|
|
117
|
+
const ageDays = getFileAge(entry.path);
|
|
118
|
+
if (ageDays < 1) {
|
|
119
|
+
score *= 1.5;
|
|
120
|
+
} else if (ageDays < 7) {
|
|
121
|
+
score *= 1.2;
|
|
122
|
+
} else if (ageDays > 30) {
|
|
123
|
+
score *= 0.8;
|
|
124
|
+
}
|
|
125
|
+
const typeWeights = {
|
|
126
|
+
"state": 1.2,
|
|
127
|
+
// Current state slightly preferred
|
|
128
|
+
"learnings": 1.1,
|
|
129
|
+
// Learnings are valuable
|
|
130
|
+
"output": 1,
|
|
131
|
+
// Recent outputs
|
|
132
|
+
"feedback": 0.9
|
|
133
|
+
// Feedback less commonly needed
|
|
134
|
+
};
|
|
135
|
+
score *= typeWeights[entry.type] || 1;
|
|
136
|
+
if (score > 0 && (directHits > 0 || expandedHits > 1)) {
|
|
137
|
+
results.push({ entry, matches: matches.slice(0, 7), score });
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return results.sort((a, b) => b.score - a.score);
|
|
141
|
+
}
|
|
142
|
+
function getSquadState(squadName) {
|
|
143
|
+
const memoryDir = findMemoryDir();
|
|
144
|
+
if (!memoryDir) return [];
|
|
145
|
+
const squadPath = join(memoryDir, squadName);
|
|
146
|
+
if (!existsSync(squadPath)) return [];
|
|
147
|
+
const entries = [];
|
|
148
|
+
const agents = readdirSync(squadPath, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
149
|
+
for (const agent of agents) {
|
|
150
|
+
const statePath = join(squadPath, agent, "state.md");
|
|
151
|
+
if (existsSync(statePath)) {
|
|
152
|
+
entries.push({
|
|
153
|
+
squad: squadName,
|
|
154
|
+
agent,
|
|
155
|
+
type: "state",
|
|
156
|
+
content: readFileSync(statePath, "utf-8"),
|
|
157
|
+
path: statePath
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return entries;
|
|
162
|
+
}
|
|
163
|
+
function updateMemory(squadName, agentName, type, content) {
|
|
164
|
+
const memoryDir = findMemoryDir();
|
|
165
|
+
if (!memoryDir) {
|
|
166
|
+
throw new Error("No .agents/memory directory found");
|
|
167
|
+
}
|
|
168
|
+
const filePath = join(memoryDir, squadName, agentName, `${type}.md`);
|
|
169
|
+
const dir = dirname(filePath);
|
|
170
|
+
if (!existsSync(dir)) {
|
|
171
|
+
mkdirSync(dir, { recursive: true });
|
|
172
|
+
}
|
|
173
|
+
writeFileSync(filePath, content);
|
|
174
|
+
}
|
|
175
|
+
function appendToMemory(squadName, agentName, type, addition) {
|
|
176
|
+
const memoryDir = findMemoryDir();
|
|
177
|
+
if (!memoryDir) {
|
|
178
|
+
throw new Error("No .agents/memory directory found");
|
|
179
|
+
}
|
|
180
|
+
const filePath = join(memoryDir, squadName, agentName, `${type}.md`);
|
|
181
|
+
let existing = "";
|
|
182
|
+
if (existsSync(filePath)) {
|
|
183
|
+
existing = readFileSync(filePath, "utf-8");
|
|
184
|
+
}
|
|
185
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
186
|
+
const newContent = existing + `
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
_Added: ${timestamp}_
|
|
190
|
+
|
|
191
|
+
${addition}`;
|
|
192
|
+
updateMemory(squadName, agentName, type, newContent.trim());
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export {
|
|
196
|
+
findMemoryDir,
|
|
197
|
+
listMemoryEntries,
|
|
198
|
+
searchMemory,
|
|
199
|
+
getSquadState,
|
|
200
|
+
updateMemory,
|
|
201
|
+
appendToMemory
|
|
202
|
+
};
|
|
203
|
+
//# sourceMappingURL=chunk-FUHBEL3L.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/memory.ts"],"sourcesContent":["import { readFileSync, writeFileSync, existsSync, readdirSync, mkdirSync } from 'fs';\nimport { join, dirname } from 'path';\n\nexport interface MemoryEntry {\n squad: string;\n agent: string;\n type: 'state' | 'output' | 'learnings' | 'feedback';\n content: string;\n path: string;\n lastUpdated?: string;\n}\n\nexport interface SearchResult {\n entry: MemoryEntry;\n matches: string[];\n score: number;\n}\n\nexport function findMemoryDir(): string | null {\n let dir = process.cwd();\n\n for (let i = 0; i < 5; i++) {\n const memoryPath = join(dir, '.agents', 'memory');\n if (existsSync(memoryPath)) {\n return memoryPath;\n }\n const parent = join(dir, '..');\n if (parent === dir) break;\n dir = parent;\n }\n\n return null;\n}\n\nexport function listMemoryEntries(memoryDir: string): MemoryEntry[] {\n const entries: MemoryEntry[] = [];\n\n const squads = readdirSync(memoryDir, { withFileTypes: true })\n .filter(e => e.isDirectory())\n .map(e => e.name);\n\n for (const squad of squads) {\n const squadPath = join(memoryDir, squad);\n const agents = readdirSync(squadPath, { withFileTypes: true })\n .filter(e => e.isDirectory())\n .map(e => e.name);\n\n for (const agent of agents) {\n const agentPath = join(squadPath, agent);\n const files = readdirSync(agentPath).filter(f => f.endsWith('.md'));\n\n for (const file of files) {\n const filePath = join(agentPath, file);\n const type = file.replace('.md', '') as MemoryEntry['type'];\n\n entries.push({\n squad,\n agent,\n type,\n content: readFileSync(filePath, 'utf-8'),\n path: filePath\n });\n }\n }\n }\n\n return entries;\n}\n\n// Semantic expansions for common business terms\nconst SEMANTIC_EXPANSIONS: Record<string, string[]> = {\n 'pricing': ['price', 'cost', '$', 'revenue', 'fee', 'rate'],\n 'price': ['pricing', 'cost', '$', 'fee'],\n 'revenue': ['income', 'sales', 'mrr', 'arr', '$'],\n 'cost': ['expense', 'spend', 'budget', '$', 'price'],\n 'customer': ['client', 'lead', 'prospect', 'user'],\n 'client': ['customer', 'lead', 'prospect'],\n 'lead': ['prospect', 'customer', 'client', 'pipeline'],\n 'agent': ['squad', 'bot', 'ai'],\n 'squad': ['team', 'agent', 'group'],\n 'status': ['state', 'progress', 'health'],\n 'bug': ['issue', 'error', 'problem', 'fix'],\n 'feature': ['capability', 'function', 'ability'],\n};\n\nfunction expandQuery(query: string): string[] {\n const words = query.toLowerCase().split(/\\s+/);\n const expanded = new Set(words);\n\n for (const word of words) {\n if (SEMANTIC_EXPANSIONS[word]) {\n SEMANTIC_EXPANSIONS[word].forEach(syn => expanded.add(syn));\n }\n }\n\n return Array.from(expanded);\n}\n\nfunction getFileAge(filePath: string): number {\n try {\n const { statSync } = require('fs');\n const stats = statSync(filePath);\n const ageMs = Date.now() - stats.mtimeMs;\n const ageDays = ageMs / (1000 * 60 * 60 * 24);\n return ageDays;\n } catch {\n return 999;\n }\n}\n\nexport function searchMemory(query: string, memoryDir?: string): SearchResult[] {\n const dir = memoryDir || findMemoryDir();\n if (!dir) return [];\n\n const entries = listMemoryEntries(dir);\n const results: SearchResult[] = [];\n const queryLower = query.toLowerCase();\n const expandedTerms = expandQuery(queryLower);\n\n for (const entry of entries) {\n const contentLower = entry.content.toLowerCase();\n const lines = entry.content.split('\\n');\n const matches: string[] = [];\n let score = 0;\n let directHits = 0;\n let expandedHits = 0;\n\n // Check direct query words first\n const directWords = queryLower.split(/\\s+/);\n for (const word of directWords) {\n if (contentLower.includes(word)) {\n directHits += 1;\n score += 2; // Direct matches worth more\n }\n }\n\n // Check expanded terms\n for (const term of expandedTerms) {\n if (contentLower.includes(term)) {\n expandedHits += 1;\n score += 0.5; // Expanded matches worth less but still count\n\n // Find matching lines with context\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (line.toLowerCase().includes(term) && line.trim() && !matches.includes(line.trim())) {\n matches.push(line.trim());\n }\n }\n }\n }\n\n // Boost score for exact phrase match\n if (contentLower.includes(queryLower)) {\n score += 5;\n }\n\n // Recency boost - files updated recently are more relevant\n const ageDays = getFileAge(entry.path);\n if (ageDays < 1) {\n score *= 1.5; // Updated today\n } else if (ageDays < 7) {\n score *= 1.2; // Updated this week\n } else if (ageDays > 30) {\n score *= 0.8; // Stale data penalty\n }\n\n // Type weighting - balanced across types\n const typeWeights: Record<string, number> = {\n 'state': 1.2, // Current state slightly preferred\n 'learnings': 1.1, // Learnings are valuable\n 'output': 1.0, // Recent outputs\n 'feedback': 0.9, // Feedback less commonly needed\n };\n score *= typeWeights[entry.type] || 1.0;\n\n if (score > 0 && (directHits > 0 || expandedHits > 1)) {\n results.push({ entry, matches: matches.slice(0, 7), score });\n }\n }\n\n // Sort by score descending\n return results.sort((a, b) => b.score - a.score);\n}\n\nexport function getSquadState(squadName: string): MemoryEntry[] {\n const memoryDir = findMemoryDir();\n if (!memoryDir) return [];\n\n const squadPath = join(memoryDir, squadName);\n if (!existsSync(squadPath)) return [];\n\n const entries: MemoryEntry[] = [];\n const agents = readdirSync(squadPath, { withFileTypes: true })\n .filter(e => e.isDirectory())\n .map(e => e.name);\n\n for (const agent of agents) {\n const statePath = join(squadPath, agent, 'state.md');\n if (existsSync(statePath)) {\n entries.push({\n squad: squadName,\n agent,\n type: 'state',\n content: readFileSync(statePath, 'utf-8'),\n path: statePath\n });\n }\n }\n\n return entries;\n}\n\nexport function updateMemory(\n squadName: string,\n agentName: string,\n type: MemoryEntry['type'],\n content: string\n): void {\n const memoryDir = findMemoryDir();\n if (!memoryDir) {\n throw new Error('No .agents/memory directory found');\n }\n\n const filePath = join(memoryDir, squadName, agentName, `${type}.md`);\n const dir = dirname(filePath);\n\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n writeFileSync(filePath, content);\n}\n\nexport function appendToMemory(\n squadName: string,\n agentName: string,\n type: MemoryEntry['type'],\n addition: string\n): void {\n const memoryDir = findMemoryDir();\n if (!memoryDir) {\n throw new Error('No .agents/memory directory found');\n }\n\n const filePath = join(memoryDir, squadName, agentName, `${type}.md`);\n\n let existing = '';\n if (existsSync(filePath)) {\n existing = readFileSync(filePath, 'utf-8');\n }\n\n const timestamp = new Date().toISOString().split('T')[0];\n const newContent = existing + `\\n\\n---\\n_Added: ${timestamp}_\\n\\n${addition}`;\n\n updateMemory(squadName, agentName, type, newContent.trim());\n}\n"],"mappings":"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","names":[]}
|