@yishiguji/tokenarena 0.7.1

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/parsers/claude-code.ts","../src/domain/aggregator.ts","../src/domain/token-usage.ts","../src/domain/session-extractor.ts","../src/infrastructure/fs/utils.ts","../src/parsers/registry.ts","../src/parsers/codex.ts","../src/parsers/gsd.ts","../src/parsers/gemini-cli.ts","../src/parsers/hermes.ts","../src/infrastructure/sqlite.ts","../src/parsers/copilot-cli.ts","../src/parsers/oh-my-pi.ts","../src/parsers/opencode.ts","../src/parsers/openclaw.ts","../src/parsers/qwen-code.ts","../src/parsers/kimi-code.ts","../src/parsers/droid.ts","../src/parsers/pi-coding-agent.ts","../src/parsers/qwenpaw.ts","../src/parsers/cline.ts","../src/parsers/kiro.ts","../src/parsers/roo-code.ts","../src/parsers/cursor.ts","../src/parsers/zcode.ts","../src/cli.ts","../src/infrastructure/config/manager.ts","../src/infrastructure/xdg.ts","../src/infrastructure/ui/format.ts","../src/infrastructure/ui/prompts.ts","../src/utils/logger.ts","../src/commands/config.ts","../src/services/sync-service.ts","../src/domain/project-identity.ts","../src/domain/upload-manifest.ts","../src/infrastructure/api/client.ts","../src/infrastructure/runtime/lock.ts","../src/infrastructure/runtime/paths.ts","../src/infrastructure/runtime/state.ts","../src/infrastructure/runtime/upload-manifest.ts","../src/services/parser-service.ts","../src/commands/init.ts","../src/infrastructure/service/index.ts","../src/infrastructure/service/linux-systemd.ts","../src/utils/command.ts","../src/infrastructure/service/utils.ts","../src/infrastructure/service/macos-launchd.ts","../src/commands/daemon.ts","../src/domain/local-usage-summary.ts","../src/infrastructure/runtime/cli-version.ts","../src/infrastructure/ui/local-usage-dashboard.ts","../src/commands/status.ts","../src/commands/sync.ts","../src/commands/uninstall.ts","../src/commands/home.ts","../src/commands/service.ts","../src/infrastructure/runtime/main-module.ts","../src/index.ts"],"sourcesContent":["import { existsSync, realpathSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, sep } from \"node:path\";\nimport { aggregateToBuckets } from \"../domain/aggregator\";\nimport { extractSessions } from \"../domain/session-extractor\";\nimport type {\n ParseResult,\n SessionEvent,\n TokenUsageEntry,\n} from \"../domain/types\";\nimport {\n extractSessionId,\n findJsonlFiles,\n readFileSafe,\n} from \"../infrastructure/fs/utils\";\nimport { registerParser } from \"./registry\";\nimport type { IParser, ToolDefinition } from \"./types\";\n\nconst TOOL: ToolDefinition = {\n id: \"claude-code\",\n name: \"Claude Code\",\n dataDir: join(homedir(), \".claude\", \"projects\"),\n};\n\nfunction getClaudeRoots(): string[] {\n const roots = [join(homedir(), \".claude\")];\n\n const cfg = process.env.CLAUDE_CONFIG_DIR?.trim();\n if (cfg) {\n let custom = cfg;\n if (custom.startsWith(\"~\")) custom = join(homedir(), custom.slice(1));\n custom = custom.replace(/[/\\\\]+$/, \"\") || custom;\n roots.push(custom);\n }\n\n const seen = new Set<string>();\n const unique: string[] = [];\n for (const r of roots) {\n let key = r;\n try {\n key = realpathSync(r);\n } catch {\n // dir may not exist yet\n }\n if (seen.has(key)) continue;\n seen.add(key);\n unique.push(r);\n }\n return unique;\n}\n\nfunction projectRelativePath(\n filePath: string,\n projectsDir: string,\n): string | null {\n const prefix = projectsDir + sep;\n return filePath.startsWith(prefix) ? filePath.slice(prefix.length) : null;\n}\n\nfunction extractProject(filePath: string, projectsDir: string): string {\n const relative = projectRelativePath(filePath, projectsDir);\n if (!relative) return \"unknown\";\n const firstSegment = relative.split(sep)[0];\n if (!firstSegment) return \"unknown\";\n const parts = firstSegment.split(\"-\").filter(Boolean);\n return parts.length > 0 ? parts[parts.length - 1] : \"unknown\";\n}\n\nclass ClaudeCodeParser implements IParser {\n readonly tool = TOOL;\n\n async parse(): Promise<ParseResult> {\n const entries: TokenUsageEntry[] = [];\n const sessionEvents: SessionEvent[] = [];\n const seenUuids = new Set<string>();\n const seenSessionIds = new Set<string>();\n const seenProjectFiles = new Set<string>();\n\n const roots = getClaudeRoots();\n\n for (const root of roots) {\n const projectsDir = join(root, \"projects\");\n const projectFiles = findJsonlFiles(projectsDir);\n\n for (const filePath of projectFiles) {\n const relative = projectRelativePath(filePath, projectsDir);\n if (relative !== null) {\n if (seenProjectFiles.has(relative)) continue;\n seenProjectFiles.add(relative);\n }\n\n const content = readFileSafe(filePath);\n if (!content) continue;\n\n const project = extractProject(filePath, projectsDir);\n const sessionId = extractSessionId(filePath);\n seenSessionIds.add(sessionId);\n\n for (const line of content.split(\"\\n\")) {\n if (!line.trim()) continue;\n try {\n const obj = JSON.parse(line);\n const timestamp = obj.timestamp;\n if (!timestamp) continue;\n\n const parsedTimestamp = new Date(timestamp);\n if (Number.isNaN(parsedTimestamp.getTime())) continue;\n\n if (\n obj.type === \"user\" ||\n obj.type === \"assistant\" ||\n obj.type === \"tool_use\" ||\n obj.type === \"tool_result\"\n ) {\n sessionEvents.push({\n sessionId,\n source: \"claude-code\",\n project,\n timestamp: parsedTimestamp,\n role: obj.type === \"user\" ? \"user\" : \"assistant\",\n });\n }\n\n if (obj.type !== \"assistant\") continue;\n const message = obj.message;\n if (!message?.usage) continue;\n\n const usage = message.usage;\n if (usage.input_tokens == null && usage.output_tokens == null) {\n continue;\n }\n\n const uuid = obj.uuid;\n if (uuid) {\n if (seenUuids.has(uuid)) continue;\n seenUuids.add(uuid);\n }\n\n entries.push({\n sessionId,\n source: \"claude-code\",\n model: message.model || \"unknown\",\n project,\n timestamp: parsedTimestamp,\n inputTokens: usage.input_tokens || 0,\n outputTokens: usage.output_tokens || 0,\n reasoningTokens: 0,\n cachedTokens: usage.cache_read_input_tokens || 0,\n });\n } catch {\n // Ignore malformed lines and continue scanning the session log.\n }\n }\n }\n }\n\n for (const root of roots) {\n for (const transcriptsDir of [\"transcripts\", \"sessions\"]) {\n const transcriptFiles = findJsonlFiles(join(root, transcriptsDir));\n\n for (const filePath of transcriptFiles) {\n const sessionId = extractSessionId(filePath);\n if (seenSessionIds.has(sessionId)) continue;\n seenSessionIds.add(sessionId);\n\n const content = readFileSafe(filePath);\n if (!content) continue;\n\n for (const line of content.split(\"\\n\")) {\n if (!line.trim()) continue;\n try {\n const obj = JSON.parse(line);\n const timestamp = obj.timestamp;\n if (!timestamp) continue;\n\n const parsedTimestamp = new Date(timestamp);\n if (Number.isNaN(parsedTimestamp.getTime())) continue;\n\n if (\n obj.type === \"user\" ||\n obj.type === \"assistant\" ||\n obj.type === \"tool_use\" ||\n obj.type === \"tool_result\"\n ) {\n sessionEvents.push({\n sessionId,\n source: \"claude-code\",\n project: \"unknown\",\n timestamp: parsedTimestamp,\n role: obj.type === \"user\" ? \"user\" : \"assistant\",\n });\n }\n } catch {\n // Ignore malformed lines and continue scanning the transcript log.\n }\n }\n }\n }\n }\n\n return {\n buckets: aggregateToBuckets(entries),\n sessions: extractSessions(sessionEvents, entries),\n };\n }\n\n isInstalled(): boolean {\n const roots = getClaudeRoots();\n return roots.some(\n (root) =>\n existsSync(join(root, \"projects\")) ||\n existsSync(join(root, \"transcripts\")) ||\n existsSync(join(root, \"sessions\")),\n );\n }\n}\n\nregisterParser(new ClaudeCodeParser());\n","import { hostname } from \"node:os\";\nimport { hasInvalidTokenCounts } from \"./token-usage\";\nimport type { TokenBucket, TokenUsageEntry } from \"./types\";\n\n/**\n * Round a date down to the nearest 30-minute bucket\n */\nexport function roundToHalfHour(date: Date): Date {\n const d = new Date(date);\n d.setMinutes(d.getMinutes() < 30 ? 0 : 30, 0, 0);\n return d;\n}\n\n/**\n * Aggregate raw token usage entries into 30-minute buckets\n */\nexport function aggregateToBuckets(entries: TokenUsageEntry[]): TokenBucket[] {\n const map = new Map<string, TokenBucket>();\n const host = hostname().replace(/\\.local$/, \"\");\n\n for (const e of entries) {\n if (hasInvalidTokenCounts(e)) {\n continue;\n }\n\n const bucketStart = roundToHalfHour(e.timestamp).toISOString();\n const key = `${e.source}|${e.model}|${e.project}|${bucketStart}`;\n\n if (!map.has(key)) {\n map.set(key, {\n source: e.source,\n model: e.model,\n project: e.project,\n bucketStart,\n hostname: host,\n inputTokens: 0,\n outputTokens: 0,\n reasoningTokens: 0,\n cachedTokens: 0,\n totalTokens: 0,\n });\n }\n\n const b = map.get(key);\n if (!b) continue;\n b.inputTokens += e.inputTokens || 0;\n b.outputTokens += e.outputTokens || 0;\n b.reasoningTokens += e.reasoningTokens || 0;\n b.cachedTokens += e.cachedTokens || 0;\n b.totalTokens +=\n (e.inputTokens || 0) +\n (e.outputTokens || 0) +\n (e.reasoningTokens || 0) +\n (e.cachedTokens || 0);\n }\n\n return Array.from(map.values());\n}\n\n/**\n * Add hostname to buckets after privacy filtering\n */\nexport function addHostname(buckets: TokenBucket[]): void {\n const host = hostname().replace(/\\.local$/, \"\");\n for (const b of buckets) {\n b.hostname = host;\n }\n}\n","import type { TokenUsageEntry } from \"./types\";\n\nconst TOKEN_COUNT_KEYS = [\n \"inputTokens\",\n \"outputTokens\",\n \"reasoningTokens\",\n \"cachedTokens\",\n] as const;\n\nexport function hasInvalidTokenCounts(\n entry: Pick<TokenUsageEntry, (typeof TOKEN_COUNT_KEYS)[number]>,\n): boolean {\n return TOKEN_COUNT_KEYS.some((key) => {\n const value = entry[key];\n return !Number.isSafeInteger(value) || value < 0;\n });\n}\n","import { createHash } from \"node:crypto\";\nimport { hostname } from \"node:os\";\nimport { hasInvalidTokenCounts } from \"./token-usage\";\nimport type {\n SessionEvent,\n SessionMetadata,\n SessionModelUsage,\n TokenUsageEntry,\n} from \"./types\";\n\nfunction toEntryTotalTokens(entry: TokenUsageEntry) {\n return (\n entry.inputTokens +\n entry.outputTokens +\n entry.reasoningTokens +\n entry.cachedTokens\n );\n}\n\nfunction buildSessionUsage(entries: TokenUsageEntry[]) {\n const usageBySession = new Map<string, Map<string, SessionModelUsage>>();\n\n for (const entry of entries) {\n if (!entry.sessionId) {\n continue;\n }\n\n if (hasInvalidTokenCounts(entry)) {\n continue;\n }\n\n let byModel = usageBySession.get(entry.sessionId);\n if (!byModel) {\n byModel = new Map<string, SessionModelUsage>();\n usageBySession.set(entry.sessionId, byModel);\n }\n\n const existing = byModel.get(entry.model);\n if (existing) {\n existing.inputTokens += entry.inputTokens;\n existing.outputTokens += entry.outputTokens;\n existing.reasoningTokens += entry.reasoningTokens;\n existing.cachedTokens += entry.cachedTokens;\n existing.totalTokens += toEntryTotalTokens(entry);\n continue;\n }\n\n byModel.set(entry.model, {\n model: entry.model,\n inputTokens: entry.inputTokens,\n outputTokens: entry.outputTokens,\n reasoningTokens: entry.reasoningTokens,\n cachedTokens: entry.cachedTokens,\n totalTokens: toEntryTotalTokens(entry),\n });\n }\n\n return usageBySession;\n}\n\n/**\n * Extract session metadata from timing events.\n *\n * Turn = first AI response → last AI response before next user prompt.\n * activeSeconds = sum(generation durations), excluding queue/TTFT wait.\n * durationSeconds = wall clock from first to last message.\n */\nexport function extractSessions(\n events: SessionEvent[],\n entries: TokenUsageEntry[] = [],\n): SessionMetadata[] {\n const groups = new Map<string, SessionEvent[]>();\n for (const e of events) {\n if (!groups.has(e.sessionId)) groups.set(e.sessionId, []);\n groups.get(e.sessionId)?.push(e);\n }\n\n const sessions: SessionMetadata[] = [];\n const host = hostname().replace(/\\.local$/, \"\");\n const usageBySession = buildSessionUsage(entries);\n\n for (const [sessionId, sessionEvents] of groups) {\n sessionEvents.sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());\n\n const first = sessionEvents[0];\n const last = sessionEvents[sessionEvents.length - 1];\n const durationSeconds = Math.round(\n (last.timestamp.getTime() - first.timestamp.getTime()) / 1000,\n );\n\n let activeSeconds = 0;\n let turnStart: Date | null = null;\n let turnEnd: Date | null = null;\n let waitingForFirstResponse = false;\n\n for (const event of sessionEvents) {\n if (event.role === \"user\") {\n if (turnStart !== null && turnEnd !== null && turnEnd > turnStart) {\n activeSeconds += Math.round(\n (turnEnd.getTime() - turnStart.getTime()) / 1000,\n );\n }\n turnStart = null;\n turnEnd = null;\n waitingForFirstResponse = true;\n } else if (waitingForFirstResponse) {\n turnStart = event.timestamp;\n turnEnd = event.timestamp;\n waitingForFirstResponse = false;\n } else if (turnStart !== null) {\n turnEnd = event.timestamp;\n }\n }\n if (turnStart !== null && turnEnd !== null && turnEnd > turnStart) {\n activeSeconds += Math.round(\n (turnEnd.getTime() - turnStart.getTime()) / 1000,\n );\n }\n\n const userPromptHours = new Array(24).fill(0);\n let userMessageCount = 0;\n for (const event of sessionEvents) {\n if (event.role === \"user\") {\n userMessageCount++;\n userPromptHours[event.timestamp.getUTCHours()]++;\n }\n }\n\n const modelUsages = Array.from(\n usageBySession.get(sessionId)?.values() ?? [],\n ).sort((left, right) => {\n if (right.totalTokens !== left.totalTokens) {\n return right.totalTokens - left.totalTokens;\n }\n\n return left.model.localeCompare(right.model);\n });\n const inputTokens = modelUsages.reduce(\n (sum, usage) => sum + usage.inputTokens,\n 0,\n );\n const outputTokens = modelUsages.reduce(\n (sum, usage) => sum + usage.outputTokens,\n 0,\n );\n const reasoningTokens = modelUsages.reduce(\n (sum, usage) => sum + usage.reasoningTokens,\n 0,\n );\n const cachedTokens = modelUsages.reduce(\n (sum, usage) => sum + usage.cachedTokens,\n 0,\n );\n const totalTokens = modelUsages.reduce(\n (sum, usage) => sum + usage.totalTokens,\n 0,\n );\n const primaryModel = modelUsages[0]?.model ?? \"\";\n\n const sessionHash = createHash(\"sha256\")\n .update(sessionId)\n .digest(\"hex\")\n .slice(0, 16);\n\n sessions.push({\n source: first.source,\n project: first.project || \"unknown\",\n sessionHash,\n hostname: host,\n firstMessageAt: first.timestamp.toISOString(),\n lastMessageAt: last.timestamp.toISOString(),\n durationSeconds,\n activeSeconds,\n messageCount: sessionEvents.length,\n userMessageCount,\n userPromptHours,\n inputTokens,\n outputTokens,\n reasoningTokens,\n cachedTokens,\n totalTokens,\n primaryModel,\n modelUsages,\n });\n }\n\n return sessions;\n}\n\n/**\n * Add hostname to sessions after privacy filtering\n */\nexport function addHostnameToSessions(sessions: SessionMetadata[]): void {\n const host = hostname().replace(/\\.local$/, \"\");\n for (const s of sessions) {\n s.hostname = host;\n }\n}\n","import { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { basename, join, sep } from \"node:path\";\n\n/**\n * Recursively find all .jsonl files under a directory\n */\nexport function findJsonlFiles(dir: string): string[] {\n const results: string[] = [];\n if (!existsSync(dir)) return results;\n\n try {\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const fullPath = join(dir, entry.name);\n if (entry.isDirectory()) {\n results.push(...findJsonlFiles(fullPath));\n } else if (entry.name.endsWith(\".jsonl\")) {\n results.push(fullPath);\n }\n }\n } catch {\n // ignore unreadable directories\n }\n return results;\n}\n\n/**\n * Find all JSON files matching a pattern in a directory (non-recursive)\n */\nexport function findJsonFiles(dir: string, pattern: RegExp): string[] {\n const results: string[] = [];\n if (!existsSync(dir)) return results;\n\n try {\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (entry.isFile() && pattern.test(entry.name)) {\n results.push(join(dir, entry.name));\n }\n }\n } catch {\n // ignore unreadable directories\n }\n return results;\n}\n\n/**\n * Read file contents, return null on error\n */\nexport function readFileSafe(filePath: string): string | null {\n try {\n return readFileSync(filePath, \"utf-8\");\n } catch {\n return null;\n }\n}\n\n/**\n * Parse JSONL file into array of objects\n */\nexport function parseJsonl<T>(content: string): T[] {\n const results: T[] = [];\n for (const line of content.split(\"\\n\")) {\n if (!line.trim()) continue;\n try {\n results.push(JSON.parse(line) as T);\n } catch {\n // skip malformed lines\n }\n }\n return results;\n}\n\n/**\n * Extract project name from a Claude-style encoded path\n * Path format: ~/.claude/projects/{encodedProjectPath}/{sessionId}.jsonl\n */\nexport function extractProjectFromPath(\n filePath: string,\n projectsDir: string,\n): string {\n const prefix = projectsDir + sep;\n if (!filePath.startsWith(prefix)) return \"unknown\";\n const relative = filePath.slice(prefix.length);\n const firstSeg = relative.split(sep)[0];\n if (!firstSeg) return \"unknown\";\n const parts = firstSeg.split(\"-\").filter(Boolean);\n return parts.length > 0 ? parts[parts.length - 1] : \"unknown\";\n}\n\n/**\n * Extract session ID from file path (basename without extension)\n */\nexport function extractSessionId(filePath: string): string {\n return basename(filePath, \".jsonl\");\n}\n","import { existsSync } from \"node:fs\";\nimport type { IParser, ToolDefinition } from \"./types\";\n\nexport const TOOLS: ToolDefinition[] = [];\n\nconst parsers = new Map<string, IParser>();\n\nexport function registerParser(parser: IParser): void {\n parsers.set(parser.tool.id, parser);\n if (!TOOLS.find((tool) => tool.id === parser.tool.id)) {\n TOOLS.push(parser.tool);\n }\n}\n\nexport function getParser(toolId: string): IParser | undefined {\n return parsers.get(toolId);\n}\n\nexport function getAllParsers(): IParser[] {\n return Array.from(parsers.values());\n}\n\nexport function isToolInstalled(toolId: string): boolean {\n const parser = parsers.get(toolId);\n if (parser?.isInstalled) {\n return parser.isInstalled();\n }\n\n const tool = TOOLS.find((candidate) => candidate.id === toolId);\n return tool ? existsSync(tool.dataDir) : false;\n}\n\nexport function detectInstalledTools(): ToolDefinition[] {\n return TOOLS.filter((tool) => isToolInstalled(tool.id));\n}\n\nexport function getAllTools(): ToolDefinition[] {\n return TOOLS;\n}\n","import { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { aggregateToBuckets } from \"../domain/aggregator\";\nimport { extractSessions } from \"../domain/session-extractor\";\nimport type {\n ParseResult,\n SessionEvent,\n TokenUsageEntry,\n} from \"../domain/types\";\nimport { findJsonlFiles, readFileSafe } from \"../infrastructure/fs/utils\";\nimport { registerParser } from \"./registry\";\nimport type { IParser, ToolDefinition } from \"./types\";\n\nconst TOOL_ID = \"codex\";\nconst TOOL_NAME = \"Codex CLI\";\nconst DEFAULT_DATA_DIR = join(homedir(), \".codex\", \"sessions\");\n\nfunction createToolDefinition(dataDir: string): ToolDefinition {\n return {\n id: TOOL_ID,\n name: TOOL_NAME,\n dataDir,\n };\n}\n\nfunction toSafeNumber(value: unknown): number {\n const numberValue = Number(value);\n return Number.isFinite(numberValue) ? numberValue : 0;\n}\n\nfunction toNonNegativeDelta(current: unknown, previous: unknown): number {\n return Math.max(0, toSafeNumber(current) - toSafeNumber(previous));\n}\n\ninterface CodexEvent {\n type: string;\n timestamp?: string;\n payload?: {\n type?: string;\n model?: string;\n cwd?: string;\n git?: {\n repository_url?: string;\n };\n info?: {\n model?: string;\n last_token_usage?: {\n input_tokens?: number;\n output_tokens?: number;\n cached_input_tokens?: number;\n reasoning_output_tokens?: number;\n };\n total_token_usage?: {\n input_tokens?: number;\n output_tokens?: number;\n cached_input_tokens?: number;\n reasoning_output_tokens?: number;\n };\n };\n };\n}\n\nfunction getPathLeaf(value: string): string {\n const normalized = value.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n const leaf = normalized.split(\"/\").filter(Boolean).pop();\n return leaf || \"unknown\";\n}\n\nexport function resolveCodexProject(payload?: CodexEvent[\"payload\"]): string {\n if (!payload) {\n return \"unknown\";\n }\n\n const repositoryUrl = payload.git?.repository_url;\n if (repositoryUrl) {\n const match = repositoryUrl.match(/([^/]+\\/[^/]+?)(?:\\.git)?$/);\n if (match) {\n return match[1];\n }\n }\n\n if (payload.cwd) {\n return getPathLeaf(payload.cwd);\n }\n\n return \"unknown\";\n}\n\nexport class CodexParser implements IParser {\n readonly tool: ToolDefinition;\n\n constructor(private readonly dataDir = DEFAULT_DATA_DIR) {\n this.tool = createToolDefinition(dataDir);\n }\n\n async parse(): Promise<ParseResult> {\n const entries: TokenUsageEntry[] = [];\n const sessionEvents: SessionEvent[] = [];\n const files = findJsonlFiles(this.dataDir);\n\n if (files.length === 0) {\n return { buckets: [], sessions: [] };\n }\n\n for (const filePath of files) {\n const content = readFileSafe(filePath);\n if (!content) continue;\n\n let sessionProject = \"unknown\";\n const sessionModel = \"unknown\";\n for (const line of content.split(\"\\n\")) {\n if (!line.trim()) continue;\n try {\n const obj = JSON.parse(line) as CodexEvent;\n if (obj.type === \"session_meta\") {\n sessionProject = resolveCodexProject(obj.payload);\n break;\n }\n } catch {\n break;\n }\n }\n\n let turnContextModel = \"unknown\";\n type TokenUsage = {\n input_tokens?: number;\n output_tokens?: number;\n cached_input_tokens?: number;\n reasoning_output_tokens?: number;\n };\n const prevTotal = new Map<string, TokenUsage>();\n\n for (const line of content.split(\"\\n\")) {\n if (!line.trim()) continue;\n try {\n const obj = JSON.parse(line) as CodexEvent;\n\n if (obj.type === \"turn_context\" && obj.timestamp) {\n const eventTimestamp = new Date(obj.timestamp);\n if (!Number.isNaN(eventTimestamp.getTime())) {\n sessionEvents.push({\n sessionId: filePath,\n source: TOOL_ID,\n project: sessionProject,\n timestamp: eventTimestamp,\n role: \"user\",\n });\n }\n }\n\n if (obj.type === \"turn_context\" && obj.payload?.model) {\n turnContextModel = obj.payload.model;\n continue;\n }\n\n if (obj.type !== \"event_msg\") continue;\n\n const payload = obj.payload;\n if (!payload || payload.type !== \"token_count\") continue;\n\n const info = payload.info;\n if (!info) continue;\n\n const timestamp = obj.timestamp ? new Date(obj.timestamp) : null;\n if (!timestamp || Number.isNaN(timestamp.getTime())) continue;\n\n sessionEvents.push({\n sessionId: filePath,\n source: TOOL_ID,\n project: sessionProject,\n timestamp,\n role: \"assistant\",\n });\n\n let usage = info.last_token_usage;\n if (!usage && info.total_token_usage) {\n const totalKey = `${info.model || payload.model || turnContextModel || \"\"}`;\n const prev = prevTotal.get(totalKey);\n const curr = info.total_token_usage;\n if (prev) {\n usage = {\n input_tokens: toNonNegativeDelta(\n curr.input_tokens,\n prev.input_tokens,\n ),\n output_tokens: toNonNegativeDelta(\n curr.output_tokens,\n prev.output_tokens,\n ),\n cached_input_tokens: toNonNegativeDelta(\n curr.cached_input_tokens,\n prev.cached_input_tokens,\n ),\n reasoning_output_tokens: toNonNegativeDelta(\n curr.reasoning_output_tokens,\n prev.reasoning_output_tokens,\n ),\n };\n } else {\n usage = curr;\n }\n prevTotal.set(totalKey, { ...curr });\n }\n if (!usage) continue;\n\n const model =\n info.model || payload.model || turnContextModel || sessionModel;\n const cachedInput = toSafeNumber(usage.cached_input_tokens);\n const reasoningTokens = toSafeNumber(usage.reasoning_output_tokens);\n const inputTokens = Math.max(\n 0,\n toSafeNumber(usage.input_tokens) - cachedInput,\n );\n const outputTokens = Math.max(\n 0,\n toSafeNumber(usage.output_tokens) - reasoningTokens,\n );\n\n if (\n inputTokens === 0 &&\n outputTokens === 0 &&\n reasoningTokens === 0 &&\n cachedInput === 0\n ) {\n continue;\n }\n\n entries.push({\n sessionId: filePath,\n source: TOOL_ID,\n model,\n project: sessionProject,\n timestamp,\n inputTokens,\n outputTokens,\n reasoningTokens,\n cachedTokens: cachedInput,\n });\n } catch {\n // Ignore malformed lines and continue scanning the session log.\n }\n }\n }\n\n return {\n buckets: aggregateToBuckets(entries),\n sessions: extractSessions(sessionEvents, entries),\n };\n }\n}\n\nregisterParser(new CodexParser());\n","import { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { aggregateToBuckets } from \"../domain/aggregator\";\nimport { extractSessions } from \"../domain/session-extractor\";\nimport type {\n ParseResult,\n SessionEvent,\n TokenUsageEntry,\n} from \"../domain/types\";\nimport {\n findJsonlFiles,\n parseJsonl,\n readFileSafe,\n} from \"../infrastructure/fs/utils\";\nimport { registerParser } from \"./registry\";\nimport type { IParser, ToolDefinition } from \"./types\";\n\nconst TOOL_ID = \"gsd\";\nconst TOOL_NAME = \"GSD-2\";\nconst DEFAULT_SESSIONS_DIR = join(homedir(), \".gsd\", \"sessions\");\n\ninterface GsdUsage {\n input?: number;\n inputTokens?: number;\n output?: number;\n outputTokens?: number;\n cacheRead?: number;\n cacheReadTokens?: number;\n cache_read?: number;\n reasoningOutputTokens?: number;\n thinkingTokens?: number;\n thoughts?: number;\n}\n\ninterface GsdEvent {\n type?: string;\n id?: string;\n timestamp?: string;\n cwd?: string;\n message?: {\n role?: string;\n timestamp?: string;\n model?: string;\n usage?: GsdUsage;\n };\n}\n\nfunction createToolDefinition(dataDir: string): ToolDefinition {\n return {\n id: TOOL_ID,\n name: TOOL_NAME,\n dataDir,\n };\n}\n\nfunction toSafeNumber(value: unknown): number {\n const numberValue = Number(value);\n return Number.isFinite(numberValue) ? numberValue : 0;\n}\n\nfunction getPathLeaf(value: string): string {\n const normalized = value.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n const leaf = normalized.split(\"/\").filter(Boolean).pop();\n return leaf || \"unknown\";\n}\n\nfunction normalizeForPrefix(value: string): string {\n return value.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n}\n\nfunction getUsageNumber(\n usage: GsdUsage,\n ...keys: Array<keyof GsdUsage>\n): number {\n for (const key of keys) {\n const value = usage[key];\n const numberValue = toSafeNumber(value);\n if (numberValue > 0) {\n return numberValue;\n }\n }\n\n return 0;\n}\n\nexport function extractGsdProjectFromCwd(cwd: string): string {\n return getPathLeaf(cwd);\n}\n\nexport function extractGsdProjectFromDir(\n filePath: string,\n sessionsDir = DEFAULT_SESSIONS_DIR,\n): string {\n const normalizedFilePath = normalizeForPrefix(filePath);\n const normalizedSessionsDir = normalizeForPrefix(sessionsDir);\n const prefix = `${normalizedSessionsDir}/`;\n\n if (!normalizedFilePath.startsWith(prefix)) {\n return \"unknown\";\n }\n\n const relativePath = normalizedFilePath.slice(prefix.length);\n const firstSegment = relativePath.split(\"/\")[0];\n if (!firstSegment) {\n return \"unknown\";\n }\n\n try {\n const decoded = decodeURIComponent(firstSegment);\n if (decoded.includes(\"/\") || decoded.includes(\"\\\\\")) {\n return getPathLeaf(decoded);\n }\n } catch {\n // Fall back to slug parsing when the segment is not URI-encoded.\n }\n\n const slugParts = firstSegment.split(\"-\").filter(Boolean);\n return slugParts.length > 0 ? slugParts[slugParts.length - 1] : \"unknown\";\n}\n\nexport class GsdParser implements IParser {\n readonly tool: ToolDefinition;\n\n constructor(private readonly sessionsDir = DEFAULT_SESSIONS_DIR) {\n this.tool = createToolDefinition(sessionsDir);\n }\n\n async parse(): Promise<ParseResult> {\n const sessionFiles = findJsonlFiles(this.sessionsDir);\n if (sessionFiles.length === 0) {\n return { buckets: [], sessions: [] };\n }\n\n const entries: TokenUsageEntry[] = [];\n const sessionEvents: SessionEvent[] = [];\n const seenEntryIds = new Set<string>();\n\n for (const filePath of sessionFiles) {\n const content = readFileSafe(filePath);\n if (!content) continue;\n\n const rows = parseJsonl<GsdEvent>(content);\n if (rows.length === 0) continue;\n\n let sessionId = filePath;\n let project = extractGsdProjectFromDir(filePath, this.sessionsDir);\n\n for (const row of rows) {\n if (row.type !== \"session\") continue;\n if (row.id) {\n sessionId = row.id;\n }\n if (row.cwd) {\n project = extractGsdProjectFromCwd(row.cwd);\n }\n break;\n }\n\n for (const row of rows) {\n if (row.type !== \"message\") continue;\n\n const message = row.message;\n if (!message) continue;\n\n const rawTimestamp = row.timestamp || message.timestamp;\n if (!rawTimestamp) continue;\n\n const timestamp = new Date(rawTimestamp);\n if (Number.isNaN(timestamp.getTime())) continue;\n\n if (message.role === \"user\" || message.role === \"assistant\") {\n sessionEvents.push({\n sessionId,\n source: TOOL_ID,\n project,\n timestamp,\n role: message.role,\n });\n }\n\n if (message.role !== \"assistant\") continue;\n\n const usage = message.usage;\n if (!usage) continue;\n\n const inputTokens = getUsageNumber(usage, \"input\", \"inputTokens\");\n const outputTokens = getUsageNumber(usage, \"output\", \"outputTokens\");\n const cachedTokens = getUsageNumber(\n usage,\n \"cacheRead\",\n \"cacheReadTokens\",\n \"cache_read\",\n );\n const reasoningTokens = getUsageNumber(\n usage,\n \"reasoningOutputTokens\",\n \"thinkingTokens\",\n \"thoughts\",\n );\n\n if (\n inputTokens === 0 &&\n outputTokens === 0 &&\n cachedTokens === 0 &&\n reasoningTokens === 0\n ) {\n continue;\n }\n\n if (row.id) {\n if (seenEntryIds.has(row.id)) continue;\n seenEntryIds.add(row.id);\n }\n\n entries.push({\n sessionId,\n source: TOOL_ID,\n model: message.model || \"unknown\",\n project,\n timestamp,\n inputTokens,\n outputTokens,\n reasoningTokens,\n cachedTokens,\n });\n }\n }\n\n return {\n buckets: aggregateToBuckets(entries),\n sessions: extractSessions(sessionEvents, entries),\n };\n }\n\n isInstalled(): boolean {\n return existsSync(this.sessionsDir);\n }\n}\n\nregisterParser(new GsdParser());\n","import { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { basename, join } from \"node:path\";\nimport { aggregateToBuckets } from \"../domain/aggregator\";\nimport { extractSessions } from \"../domain/session-extractor\";\nimport type {\n ParseResult,\n SessionEvent,\n TokenUsageEntry,\n} from \"../domain/types\";\nimport { registerParser } from \"./registry\";\nimport type { IParser, ToolDefinition } from \"./types\";\n\nconst TOOL: ToolDefinition = {\n id: \"gemini-cli\",\n name: \"Gemini CLI\",\n dataDir: join(homedir(), \".gemini\", \"tmp\"),\n};\n\n// Gemini CLI session storage:\n// ~/.gemini/tmp/<hash>/chats/session-<ts>-<id>.jsonl (current, v0.39+)\n// ~/.gemini/tmp/<hash>/chats/session-<ts>-<id>.json (legacy single-object)\n// ~/.gemini/tmp/<hash>/chats/<parent>/<sub>.jsonl (nested subagent sessions)\n// The .jsonl migration (PR #23749, ~v0.39.0) means a .json-only glob misses every\n// new session — collect both extensions and descend one level for subagent files.\nfunction findSessionFiles(baseDir: string): string[] {\n const results: string[] = [];\n if (!existsSync(baseDir)) return results;\n\n let projectDirs: import(\"node:fs\").Dirent[];\n try {\n projectDirs = readdirSync(baseDir, { withFileTypes: true });\n } catch {\n return results;\n }\n for (const entry of projectDirs) {\n if (!entry.isDirectory()) continue;\n collectChatFiles(join(baseDir, entry.name, \"chats\"), results, 0);\n }\n return results;\n}\n\nfunction collectChatFiles(dir: string, out: string[], depth: number): void {\n if (depth > 2) return; // chats/ + nested subagent dir is as deep as it goes\n let entries: import(\"node:fs\").Dirent[];\n try {\n entries = readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n for (const e of entries) {\n const full = join(dir, e.name);\n if (e.isDirectory()) {\n collectChatFiles(full, out, depth + 1);\n } else if (e.name.endsWith(\".jsonl\") || e.name.endsWith(\".json\")) {\n out.push(full);\n }\n }\n}\n\ninterface GeminiMessage {\n type?: string;\n role?: string;\n timestamp?: string;\n createTime?: string;\n model?: string;\n tokens?: {\n input?: number;\n output?: number;\n cached?: number;\n thoughts?: number;\n };\n usage?: {\n promptTokenCount?: number;\n candidatesTokenCount?: number;\n cachedContentTokenCount?: number;\n thoughtsTokenCount?: number;\n input_tokens?: number;\n output_tokens?: number;\n };\n usageMetadata?: GeminiMessage[\"usage\"];\n token_count?: GeminiMessage[\"usage\"];\n}\n\ninterface GeminiRecord {\n messages: GeminiMessage[];\n directories: string[] | null;\n model: string | null;\n createTime: string | null;\n}\n\n// .jsonl: line 1 is session metadata (carries `directories`), each following line\n// is one event record identified by `type` or `role`. .json: single ConversationRecord.\nfunction readRecord(filePath: string): GeminiRecord | null {\n let raw: string;\n try {\n raw = readFileSync(filePath, \"utf-8\");\n } catch {\n return null;\n }\n\n if (filePath.endsWith(\".jsonl\")) {\n const messages: GeminiMessage[] = [];\n let directories: string[] | null = null;\n let model: string | null = null;\n let createTime: string | null = null;\n for (const line of raw.split(\"\\n\")) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n let obj: Record<string, unknown>;\n try {\n obj = JSON.parse(trimmed);\n } catch {\n continue;\n }\n if (!directories && Array.isArray(obj.directories)) {\n directories = obj.directories as string[];\n if (typeof obj.model === \"string\") model = obj.model;\n if (typeof obj.createTime === \"string\") createTime = obj.createTime;\n continue;\n }\n if (typeof obj.type === \"string\" || typeof obj.role === \"string\") {\n messages.push(obj as GeminiMessage);\n }\n }\n return { messages, directories, model, createTime };\n }\n\n let data: {\n messages?: GeminiMessage[];\n history?: GeminiMessage[];\n directories?: string[];\n model?: string;\n createTime?: string;\n };\n try {\n data = JSON.parse(raw);\n } catch {\n return null;\n }\n return {\n messages: Array.isArray(data?.messages)\n ? data.messages\n : Array.isArray(data?.history)\n ? data.history\n : [],\n directories: Array.isArray(data?.directories) ? data.directories : null,\n model: typeof data?.model === \"string\" ? data.model : null,\n createTime: typeof data?.createTime === \"string\" ? data.createTime : null,\n };\n}\n\n// .jsonl format records assistant turns as `type: 'gemini'`; legacy .json uses\n// `role: 'assistant'`. Accept both, plus the raw API `role: 'model'`.\nfunction classifyRole(msg: GeminiMessage): \"user\" | \"assistant\" | null {\n const t = msg.type ?? msg.role;\n if (t === \"user\") return \"user\";\n if (t === \"gemini\" || t === \"model\" || t === \"assistant\") return \"assistant\";\n return null;\n}\n\nfunction projectFromDirectories(directories: string[] | null): string {\n if (!directories || directories.length === 0) return \"unknown\";\n const first = directories[0];\n if (!first) return \"unknown\";\n return basename(String(first).replace(/[\\\\/]+$/, \"\")) || \"unknown\";\n}\n\nclass GeminiCliParser implements IParser {\n readonly tool = TOOL;\n\n async parse(): Promise<ParseResult> {\n const sessionFiles = findSessionFiles(TOOL.dataDir);\n if (sessionFiles.length === 0) {\n return { buckets: [], sessions: [] };\n }\n\n const entries: TokenUsageEntry[] = [];\n const sessionEvents: SessionEvent[] = [];\n\n for (const filePath of sessionFiles) {\n const record = readRecord(filePath);\n if (!record) continue;\n\n const project = projectFromDirectories(record.directories);\n\n for (const msg of record.messages) {\n const role = classifyRole(msg);\n if (!role) continue;\n\n const timestamp = msg.timestamp || msg.createTime || record.createTime;\n if (!timestamp) continue;\n const ts = new Date(timestamp);\n if (Number.isNaN(ts.getTime())) continue;\n\n sessionEvents.push({\n sessionId: filePath,\n source: \"gemini-cli\",\n project,\n timestamp: ts,\n role,\n });\n\n const tokens = msg.tokens;\n const usage = msg.usage || msg.usageMetadata || msg.token_count;\n if (!tokens && !usage) continue;\n\n // Gemini's `output` already includes thoughts and `input` already\n // includes cached — subtract to avoid double-counting reasoning/cached.\n if (tokens) {\n const cached = tokens.cached || 0;\n const thoughts = tokens.thoughts || 0;\n entries.push({\n sessionId: filePath,\n source: \"gemini-cli\",\n model: msg.model || record.model || \"unknown\",\n project,\n timestamp: ts,\n inputTokens: (tokens.input || 0) - cached,\n outputTokens: (tokens.output || 0) - thoughts,\n reasoningTokens: thoughts,\n cachedTokens: cached,\n });\n } else if (usage) {\n const cached = usage.cachedContentTokenCount || 0;\n const thoughts = usage.thoughtsTokenCount || 0;\n entries.push({\n sessionId: filePath,\n source: \"gemini-cli\",\n model: msg.model || record.model || \"unknown\",\n project,\n timestamp: ts,\n inputTokens:\n (usage.promptTokenCount || usage.input_tokens || 0) - cached,\n outputTokens:\n (usage.candidatesTokenCount || usage.output_tokens || 0) -\n thoughts,\n reasoningTokens: thoughts,\n cachedTokens: cached,\n });\n }\n }\n }\n\n return {\n buckets: aggregateToBuckets(entries),\n sessions: extractSessions(sessionEvents, entries),\n };\n }\n}\n\nregisterParser(new GeminiCliParser());\n","import { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { aggregateToBuckets } from \"../domain/aggregator\";\nimport { extractSessions } from \"../domain/session-extractor\";\nimport type {\n ParseResult,\n SessionEvent,\n TokenUsageEntry,\n} from \"../domain/types\";\nimport { readSqliteRows, type SqliteQueryRows } from \"../infrastructure/sqlite\";\nimport { registerParser } from \"./registry\";\nimport type { IParser, ToolDefinition } from \"./types\";\n\nconst TOOL_ID = \"hermes\";\nconst TOOL_NAME = \"Hermes Agent\";\nconst DEFAULT_DB_PATH = join(homedir(), \".hermes\", \"state.db\");\n\nconst SESSIONS_QUERY = `SELECT\n id,\n model,\n started_at as startedAt,\n input_tokens as inputTokens,\n output_tokens as outputTokens,\n cache_read_tokens as cacheReadTokens,\n reasoning_tokens as reasoningTokens\n FROM sessions\n WHERE input_tokens > 0\n OR output_tokens > 0\n OR cache_read_tokens > 0\n OR reasoning_tokens > 0`;\n\nconst MESSAGES_QUERY = `SELECT\n session_id as sessionId,\n role,\n timestamp\n FROM messages\n WHERE role IN ('user', 'assistant')\n ORDER BY timestamp`;\n\ninterface HermesSessionRow {\n id?: unknown;\n model?: unknown;\n startedAt?: unknown;\n inputTokens?: unknown;\n outputTokens?: unknown;\n cacheReadTokens?: unknown;\n reasoningTokens?: unknown;\n}\n\ninterface HermesMessageRow {\n sessionId?: unknown;\n role?: unknown;\n timestamp?: unknown;\n}\n\nexport interface HermesParserOptions {\n dbPath?: string;\n queryRows?: SqliteQueryRows;\n}\n\nfunction createToolDefinition(dbPath: string): ToolDefinition {\n return {\n id: TOOL_ID,\n name: TOOL_NAME,\n dataDir: dirname(dbPath),\n };\n}\n\nfunction toSafeNumber(value: unknown): number {\n const numberValue = Number(value);\n return Number.isFinite(numberValue) ? numberValue : 0;\n}\n\nfunction parseUnixTimestamp(value: unknown): Date | null {\n const numberValue = Number(value);\n if (!Number.isFinite(numberValue)) {\n return null;\n }\n\n const timestamp = new Date(numberValue * 1000);\n return Number.isNaN(timestamp.getTime()) ? null : timestamp;\n}\n\nexport class HermesParser implements IParser {\n readonly tool: ToolDefinition;\n private readonly dbPath: string;\n private readonly queryRows: SqliteQueryRows;\n\n constructor(options: HermesParserOptions = {}) {\n this.dbPath = options.dbPath || DEFAULT_DB_PATH;\n this.queryRows = options.queryRows || readSqliteRows;\n this.tool = createToolDefinition(this.dbPath);\n }\n\n async parse(): Promise<ParseResult> {\n if (!existsSync(this.dbPath)) {\n return { buckets: [], sessions: [] };\n }\n\n const sessionRows = await this.queryRows<HermesSessionRow>(\n this.dbPath,\n SESSIONS_QUERY,\n );\n\n const entries: TokenUsageEntry[] = [];\n for (const row of sessionRows) {\n const sessionId =\n typeof row.id === \"string\" && row.id.length > 0 ? row.id : null;\n if (!sessionId) continue;\n\n const timestamp = parseUnixTimestamp(row.startedAt);\n if (!timestamp) continue;\n\n const inputTokens = toSafeNumber(row.inputTokens);\n const outputTokens = toSafeNumber(row.outputTokens);\n const cachedTokens = toSafeNumber(row.cacheReadTokens);\n const reasoningTokens = toSafeNumber(row.reasoningTokens);\n\n if (\n inputTokens === 0 &&\n outputTokens === 0 &&\n cachedTokens === 0 &&\n reasoningTokens === 0\n ) {\n continue;\n }\n\n entries.push({\n sessionId,\n source: TOOL_ID,\n model:\n typeof row.model === \"string\" && row.model.length > 0\n ? row.model\n : \"unknown\",\n project: \"unknown\",\n timestamp,\n inputTokens,\n outputTokens,\n reasoningTokens,\n cachedTokens,\n });\n }\n\n let messageRows: HermesMessageRow[];\n try {\n messageRows = await this.queryRows<HermesMessageRow>(\n this.dbPath,\n MESSAGES_QUERY,\n );\n } catch {\n return {\n buckets: aggregateToBuckets(entries),\n sessions: [],\n };\n }\n\n const sessionEvents: SessionEvent[] = [];\n for (const row of messageRows) {\n const sessionId =\n typeof row.sessionId === \"string\" && row.sessionId.length > 0\n ? row.sessionId\n : null;\n if (!sessionId) continue;\n\n const role =\n row.role === \"user\" || row.role === \"assistant\" ? row.role : null;\n if (!role) continue;\n\n const timestamp = parseUnixTimestamp(row.timestamp);\n if (!timestamp) continue;\n\n sessionEvents.push({\n sessionId,\n source: TOOL_ID,\n project: \"unknown\",\n timestamp,\n role,\n });\n }\n\n return {\n buckets: aggregateToBuckets(entries),\n sessions: extractSessions(sessionEvents, entries),\n };\n }\n\n isInstalled(): boolean {\n return existsSync(this.dbPath);\n }\n}\n\nregisterParser(new HermesParser());\n","import { execFileSync } from \"node:child_process\";\nimport { pathToFileURL } from \"node:url\";\n\ntype SqliteDatabaseSync<TRow> = {\n close(): void;\n prepare(sql: string): {\n all(): TRow[];\n };\n};\n\nexport type SqliteQueryRows = <TRow>(\n dbPath: string,\n query: string,\n) => Promise<TRow[]>;\n\nfunction withSuppressedSqliteWarning<T>(fn: () => Promise<T>): Promise<T> {\n const originalEmitWarning = process.emitWarning;\n\n process.emitWarning = ((\n warning: string | Error,\n ...args: unknown[]\n ): void => {\n const warningName =\n typeof warning === \"string\"\n ? typeof args[0] === \"string\"\n ? args[0]\n : \"\"\n : warning.name;\n const warningMessage =\n typeof warning === \"string\" ? warning : warning.message;\n\n if (\n warningName === \"ExperimentalWarning\" &&\n warningMessage.includes(\"SQLite\")\n ) {\n return;\n }\n\n (\n originalEmitWarning as (\n warning: string | Error,\n ...warningArgs: unknown[]\n ) => void\n ).call(process, warning, ...args);\n }) as typeof process.emitWarning;\n\n return fn().finally(() => {\n process.emitWarning = originalEmitWarning;\n });\n}\n\nasync function readSqliteRowsWithBuiltin<TRow>(\n dbPath: string,\n query: string,\n): Promise<TRow[] | null> {\n try {\n return await withSuppressedSqliteWarning(async () => {\n const sqliteModuleId = \"node:sqlite\";\n const sqlite = (await import(sqliteModuleId)) as {\n DatabaseSync: new (location: string) => SqliteDatabaseSync<TRow>;\n };\n\n const locations = [\n dbPath,\n `${pathToFileURL(dbPath).href}?mode=ro&immutable=1`,\n ];\n let lastError: unknown = null;\n\n for (const location of locations) {\n let db: SqliteDatabaseSync<TRow> | null = null;\n try {\n db = new sqlite.DatabaseSync(location);\n return db.prepare(query).all() as TRow[];\n } catch (err) {\n lastError = err;\n const error = err as NodeJS.ErrnoException;\n const message = (err as Error).message;\n if (\n error.code === \"ERR_SQLITE_ERROR\" &&\n message.includes(\"unable to open database file\")\n ) {\n continue;\n }\n\n throw err;\n } finally {\n db?.close();\n }\n }\n\n throw lastError;\n });\n } catch (err) {\n const error = err as NodeJS.ErrnoException;\n const message = (err as Error).message;\n if (\n error.code === \"ERR_UNKNOWN_BUILTIN_MODULE\" ||\n message.includes(\"node:sqlite\")\n ) {\n return null;\n }\n\n throw err;\n }\n}\n\nfunction readSqliteRowsWithCli<TRow>(dbPath: string, query: string): TRow[] {\n const candidates = [\n process.env.TOKEN_ARENA_SQLITE3,\n \"sqlite3\",\n \"sqlite3.exe\",\n ].filter((value): value is string => Boolean(value));\n\n let lastError: Error | null = null;\n\n for (const command of candidates) {\n try {\n const output = execFileSync(command, [\"-json\", dbPath, query], {\n encoding: \"utf-8\",\n maxBuffer: 100 * 1024 * 1024,\n timeout: 30000,\n windowsHide: true,\n }).trim();\n\n if (!output || output === \"[]\") {\n return [];\n }\n\n return JSON.parse(output) as TRow[];\n } catch (err) {\n lastError = err as Error;\n const nodeError = err as NodeJS.ErrnoException & { status?: number };\n if (nodeError.status === 127 || nodeError.message?.includes(\"ENOENT\")) {\n continue;\n }\n\n throw err;\n }\n }\n\n throw new Error(\n `sqlite3 CLI not found. Install sqlite3 or set TOKEN_ARENA_SQLITE3 to its full path. Last error: ${lastError?.message || \"not found\"}`,\n );\n}\n\nexport async function readSqliteRows<TRow>(\n dbPath: string,\n query: string,\n): Promise<TRow[]> {\n const builtinRows = await readSqliteRowsWithBuiltin<TRow>(dbPath, query);\n return builtinRows ?? readSqliteRowsWithCli<TRow>(dbPath, query);\n}\n","import { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { basename, dirname, join } from \"node:path\";\nimport { aggregateToBuckets } from \"../domain/aggregator\";\nimport { extractSessions } from \"../domain/session-extractor\";\nimport type {\n ParseResult,\n SessionEvent,\n TokenUsageEntry,\n} from \"../domain/types\";\nimport { registerParser } from \"./registry\";\nimport type { IParser, ToolDefinition } from \"./types\";\n\nconst ROOT_DIR = join(homedir(), \".copilot\");\n\nconst TOOL: ToolDefinition = {\n id: \"copilot-cli\",\n name: \"GitHub Copilot CLI\",\n dataDir: ROOT_DIR,\n};\n\ninterface CopilotEvent {\n type: string;\n timestamp?: string;\n data?: {\n context?: {\n gitRoot?: string;\n cwd?: string;\n };\n modelMetrics?: Record<\n string,\n {\n usage?: {\n inputTokens?: number;\n outputTokens?: number;\n cacheReadTokens?: number;\n cacheWriteTokens?: number;\n };\n }\n >;\n };\n}\n\nfunction collectEventFiles(\n dir: string,\n results: { filePath: string; sessionId: string }[],\n visited: Set<string>,\n): void {\n if (!existsSync(dir) || visited.has(dir)) {\n return;\n }\n\n visited.add(dir);\n\n try {\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const fullPath = join(dir, entry.name);\n\n if (entry.isDirectory()) {\n collectEventFiles(fullPath, results, visited);\n continue;\n }\n\n if (entry.isFile() && entry.name === \"events.jsonl\") {\n results.push({\n filePath: fullPath,\n sessionId: basename(dirname(fullPath)),\n });\n }\n }\n } catch {\n // Ignore unreadable directories and keep scanning.\n }\n}\n\nfunction findEventFiles(\n baseDir: string,\n): { filePath: string; sessionId: string }[] {\n const results: { filePath: string; sessionId: string }[] = [];\n collectEventFiles(baseDir, results, new Set<string>());\n return results;\n}\n\nfunction getProjectFromContext(\n context: { gitRoot?: string; cwd?: string } | undefined,\n): string {\n const projectPath = context?.gitRoot || context?.cwd;\n if (!projectPath) return \"unknown\";\n return basename(projectPath.replace(/[\\\\/]+$/, \"\")) || \"unknown\";\n}\n\nclass CopilotCliParser implements IParser {\n readonly tool = TOOL;\n\n async parse(): Promise<ParseResult> {\n const eventFiles = findEventFiles(ROOT_DIR);\n if (eventFiles.length === 0) {\n return { buckets: [], sessions: [] };\n }\n\n const entries: TokenUsageEntry[] = [];\n const sessionEvents: SessionEvent[] = [];\n\n for (const { filePath, sessionId } of eventFiles) {\n let content: string;\n try {\n content = readFileSync(filePath, \"utf-8\");\n } catch {\n continue;\n }\n\n let currentProject = \"unknown\";\n\n for (const line of content.split(\"\\n\")) {\n if (!line.trim()) continue;\n\n try {\n const obj = JSON.parse(line) as CopilotEvent;\n const timestamp = obj.timestamp ? new Date(obj.timestamp) : null;\n const hasTimestamp = timestamp && !Number.isNaN(timestamp.getTime());\n\n if (obj.type === \"session.start\" || obj.type === \"session.resume\") {\n currentProject = getProjectFromContext(obj.data?.context);\n }\n\n if (hasTimestamp && timestamp && obj.type === \"user.message\") {\n sessionEvents.push({\n sessionId,\n source: \"copilot-cli\",\n project: currentProject,\n timestamp,\n role: \"user\",\n });\n }\n\n if (hasTimestamp && timestamp && obj.type === \"assistant.message\") {\n sessionEvents.push({\n sessionId,\n source: \"copilot-cli\",\n project: currentProject,\n timestamp,\n role: \"assistant\",\n });\n }\n\n if (obj.type !== \"session.shutdown\" || !hasTimestamp || !timestamp) {\n continue;\n }\n\n const modelMetrics = obj.data?.modelMetrics || {};\n for (const [model, metrics] of Object.entries(modelMetrics)) {\n const usage = metrics?.usage;\n if (!usage) continue;\n\n const totalInput = usage.inputTokens || 0;\n const cachedRead = usage.cacheReadTokens || 0;\n const output = usage.outputTokens || 0;\n\n if (totalInput === 0 && cachedRead === 0 && output === 0) {\n continue;\n }\n\n entries.push({\n sessionId,\n source: \"copilot-cli\",\n model,\n project: currentProject,\n timestamp,\n inputTokens: Math.max(0, totalInput - cachedRead),\n outputTokens: output,\n reasoningTokens: 0,\n cachedTokens: cachedRead,\n });\n }\n } catch {\n // Ignore malformed lines and continue scanning the event log.\n }\n }\n }\n\n return {\n buckets: aggregateToBuckets(entries),\n sessions: extractSessions(sessionEvents, entries),\n };\n }\n\n isInstalled(): boolean {\n return existsSync(ROOT_DIR);\n }\n}\n\nregisterParser(new CopilotCliParser());\n","import { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { aggregateToBuckets } from \"../domain/aggregator\";\nimport { extractSessions } from \"../domain/session-extractor\";\nimport type {\n ParseResult,\n SessionEvent,\n TokenUsageEntry,\n} from \"../domain/types\";\nimport {\n findJsonlFiles,\n parseJsonl,\n readFileSafe,\n} from \"../infrastructure/fs/utils\";\nimport { registerParser } from \"./registry\";\nimport type { IParser, ToolDefinition } from \"./types\";\n\nconst TOOL_ID = \"oh-my-pi\";\nconst TOOL_NAME = \"omp\";\nconst DEFAULT_SESSIONS_DIR = join(homedir(), \".omp\", \"agent\", \"sessions\");\n\ninterface OhMyPiUsage {\n input?: number;\n inputTokens?: number;\n output?: number;\n outputTokens?: number;\n cacheRead?: number;\n cacheReadTokens?: number;\n cache_read?: number;\n reasoningOutputTokens?: number;\n thinkingTokens?: number;\n thoughts?: number;\n}\n\ninterface OhMyPiEvent {\n type?: string;\n id?: string;\n timestamp?: string;\n cwd?: string;\n message?: {\n role?: string;\n timestamp?: string;\n model?: string;\n usage?: OhMyPiUsage;\n };\n}\n\nfunction createToolDefinition(dataDir: string): ToolDefinition {\n return {\n id: TOOL_ID,\n name: TOOL_NAME,\n dataDir,\n };\n}\n\nfunction toSafeNumber(value: unknown): number {\n const numberValue = Number(value);\n return Number.isFinite(numberValue) ? numberValue : 0;\n}\n\nfunction getPathLeaf(value: string): string {\n const normalized = value.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n const leaf = normalized.split(\"/\").filter(Boolean).pop();\n return leaf || \"unknown\";\n}\n\nfunction normalizeForPrefix(value: string): string {\n return value.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n}\n\nfunction getUsageNumber(\n usage: OhMyPiUsage,\n ...keys: Array<keyof OhMyPiUsage>\n): number {\n for (const key of keys) {\n const value = usage[key];\n const numberValue = toSafeNumber(value);\n if (numberValue > 0) {\n return numberValue;\n }\n }\n\n return 0;\n}\n\nexport function extractOhMyPiProjectFromCwd(cwd: string): string {\n return getPathLeaf(cwd);\n}\n\nexport function extractOhMyPiProjectFromDir(\n filePath: string,\n sessionsDir = DEFAULT_SESSIONS_DIR,\n): string {\n const normalizedFilePath = normalizeForPrefix(filePath);\n const normalizedSessionsDir = normalizeForPrefix(sessionsDir);\n const prefix = `${normalizedSessionsDir}/`;\n\n if (!normalizedFilePath.startsWith(prefix)) {\n return \"unknown\";\n }\n\n const relativePath = normalizedFilePath.slice(prefix.length);\n const firstSegment = relativePath.split(\"/\")[0];\n if (!firstSegment) {\n return \"unknown\";\n }\n\n try {\n const decoded = decodeURIComponent(firstSegment);\n if (decoded.includes(\"/\") || decoded.includes(\"\\\\\")) {\n return getPathLeaf(decoded);\n }\n } catch {\n // Fall back to slug parsing when the segment is not URI-encoded.\n }\n\n const slugParts = firstSegment.split(\"-\").filter(Boolean);\n return slugParts.length > 0 ? slugParts[slugParts.length - 1] : \"unknown\";\n}\n\nexport class OhMyPiParser implements IParser {\n readonly tool: ToolDefinition;\n\n constructor(private readonly sessionsDir = DEFAULT_SESSIONS_DIR) {\n this.tool = createToolDefinition(sessionsDir);\n }\n\n async parse(): Promise<ParseResult> {\n const sessionFiles = findJsonlFiles(this.sessionsDir);\n if (sessionFiles.length === 0) {\n return { buckets: [], sessions: [] };\n }\n\n const entries: TokenUsageEntry[] = [];\n const sessionEvents: SessionEvent[] = [];\n const seenEntryIds = new Set<string>();\n\n for (const filePath of sessionFiles) {\n const content = readFileSafe(filePath);\n if (!content) continue;\n\n const rows = parseJsonl<OhMyPiEvent>(content);\n if (rows.length === 0) continue;\n\n let sessionId = filePath;\n let project = extractOhMyPiProjectFromDir(filePath, this.sessionsDir);\n\n for (const row of rows) {\n if (row.type !== \"session\") continue;\n if (row.id) {\n sessionId = row.id;\n }\n if (row.cwd) {\n project = extractOhMyPiProjectFromCwd(row.cwd);\n }\n break;\n }\n\n for (const row of rows) {\n if (row.type !== \"message\") continue;\n\n const message = row.message;\n if (!message) continue;\n\n const rawTimestamp = row.timestamp || message.timestamp;\n if (!rawTimestamp) continue;\n\n const timestamp = new Date(rawTimestamp);\n if (Number.isNaN(timestamp.getTime())) continue;\n\n if (message.role === \"user\" || message.role === \"assistant\") {\n sessionEvents.push({\n sessionId,\n source: TOOL_ID,\n project,\n timestamp,\n role: message.role,\n });\n }\n\n if (message.role !== \"assistant\") continue;\n\n const usage = message.usage;\n if (!usage) continue;\n\n const inputTokens = getUsageNumber(usage, \"input\", \"inputTokens\");\n const outputTokens = getUsageNumber(usage, \"output\", \"outputTokens\");\n const cachedTokens = getUsageNumber(\n usage,\n \"cacheRead\",\n \"cacheReadTokens\",\n \"cache_read\",\n );\n const reasoningTokens = getUsageNumber(\n usage,\n \"reasoningOutputTokens\",\n \"thinkingTokens\",\n \"thoughts\",\n );\n\n if (\n inputTokens === 0 &&\n outputTokens === 0 &&\n cachedTokens === 0 &&\n reasoningTokens === 0\n ) {\n continue;\n }\n\n if (row.id) {\n if (seenEntryIds.has(row.id)) continue;\n seenEntryIds.add(row.id);\n }\n\n entries.push({\n sessionId,\n source: TOOL_ID,\n model: message.model || \"unknown\",\n project,\n timestamp,\n inputTokens,\n outputTokens,\n reasoningTokens,\n cachedTokens,\n });\n }\n }\n\n return {\n buckets: aggregateToBuckets(entries),\n sessions: extractSessions(sessionEvents, entries),\n };\n }\n\n isInstalled(): boolean {\n return existsSync(this.sessionsDir);\n }\n}\n\nregisterParser(new OhMyPiParser());\n","import { execFileSync } from \"node:child_process\";\nimport { type Dirent, existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { basename, join } from \"node:path\";\nimport { aggregateToBuckets } from \"../domain/aggregator\";\nimport { extractSessions } from \"../domain/session-extractor\";\nimport type {\n ParseResult,\n SessionEvent,\n TokenUsageEntry,\n} from \"../domain/types\";\nimport { registerParser } from \"./registry\";\nimport type { IParser, ToolDefinition } from \"./types\";\n\nconst DEFAULT_DATA_DIR = join(homedir(), \".local\", \"share\", \"opencode\");\n\nconst TOOL: ToolDefinition = {\n id: \"opencode\",\n name: \"OpenCode\",\n dataDir: DEFAULT_DATA_DIR,\n};\n\ninterface OpenCodeMessage {\n sessionID?: string;\n role?: string;\n created?: string;\n modelID?: string;\n tokens?: {\n input?: number;\n output?: number;\n cache?: {\n read?: number;\n };\n reasoning?: number;\n };\n path?: {\n root?: string;\n };\n time?: {\n created?: string;\n };\n}\n\ninterface SqliteRow {\n sessionID: string;\n role: string;\n created: string;\n modelID: string | null;\n tokens: string | null;\n rootPath: string | null;\n}\n\nfunction getOpenCodeDataDirs(env: NodeJS.ProcessEnv = process.env): string[] {\n const dirs = [\n env.TOKEN_ARENA_OPENCODE_DIR,\n env.XDG_DATA_HOME ? join(env.XDG_DATA_HOME, \"opencode\") : undefined,\n DEFAULT_DATA_DIR,\n env.LOCALAPPDATA ? join(env.LOCALAPPDATA, \"opencode\") : undefined,\n env.APPDATA ? join(env.APPDATA, \"opencode\") : undefined,\n ].filter((value): value is string => Boolean(value));\n\n return Array.from(new Set(dirs));\n}\n\nasync function withSuppressedSqliteWarning<T>(\n fn: () => Promise<T>,\n): Promise<T> {\n const originalEmitWarning = process.emitWarning;\n\n process.emitWarning = ((\n warning: string | Error,\n ...args: unknown[]\n ): void => {\n const warningName =\n typeof warning === \"string\"\n ? typeof args[0] === \"string\"\n ? args[0]\n : \"\"\n : warning.name;\n const warningMessage =\n typeof warning === \"string\" ? warning : warning.message;\n\n if (\n warningName === \"ExperimentalWarning\" &&\n warningMessage.includes(\"SQLite\")\n ) {\n return;\n }\n\n (\n originalEmitWarning as (\n warning: string | Error,\n ...warningArgs: unknown[]\n ) => void\n ).call(process, warning, ...args);\n }) as typeof process.emitWarning;\n\n try {\n return await fn();\n } finally {\n process.emitWarning = originalEmitWarning;\n }\n}\n\nasync function readSqliteRowsWithBuiltin(\n dbPath: string,\n query: string,\n): Promise<SqliteRow[] | null> {\n try {\n return await withSuppressedSqliteWarning(async () => {\n const sqliteModuleId = \"node:sqlite\";\n const sqlite = (await import(sqliteModuleId)) as {\n DatabaseSync: new (\n location: string,\n ) => {\n close(): void;\n prepare(sql: string): {\n all(): SqliteRow[];\n };\n };\n };\n const db = new sqlite.DatabaseSync(dbPath);\n\n try {\n return db.prepare(query).all() as SqliteRow[];\n } finally {\n db.close();\n }\n });\n } catch (err) {\n const error = err as NodeJS.ErrnoException;\n const message = (err as Error).message;\n if (\n error.code === \"ERR_UNKNOWN_BUILTIN_MODULE\" ||\n message.includes(\"node:sqlite\")\n ) {\n return null;\n }\n\n throw err;\n }\n}\n\nfunction readSqliteRowsWithCli(dbPath: string, query: string): SqliteRow[] {\n const candidates = [\n process.env.TOKEN_ARENA_SQLITE3,\n \"sqlite3\",\n \"sqlite3.exe\",\n ].filter((value): value is string => Boolean(value));\n\n let lastError: Error | null = null;\n\n for (const command of candidates) {\n try {\n const output = execFileSync(command, [\"-json\", dbPath, query], {\n encoding: \"utf-8\",\n maxBuffer: 100 * 1024 * 1024,\n timeout: 30000,\n windowsHide: true,\n }).trim();\n\n if (!output || output === \"[]\") {\n return [];\n }\n\n return JSON.parse(output) as SqliteRow[];\n } catch (err) {\n lastError = err as Error;\n const nodeError = err as NodeJS.ErrnoException & { status?: number };\n if (nodeError.status === 127 || nodeError.message?.includes(\"ENOENT\")) {\n continue;\n }\n\n throw err;\n }\n }\n\n throw new Error(\n `sqlite3 CLI not found. Install sqlite3 or set TOKEN_ARENA_SQLITE3 to its full path. Last error: ${lastError?.message || \"not found\"}`,\n );\n}\n\nexport class OpenCodeParser implements IParser {\n readonly tool = TOOL;\n\n constructor(\n private readonly resolveRoots: () => string[] = getOpenCodeDataDirs,\n ) {}\n\n async parse(): Promise<ParseResult> {\n const buckets: ParseResult[\"buckets\"] = [];\n const sessions: ParseResult[\"sessions\"] = [];\n\n for (const rootDir of this.resolveRoots()) {\n const result = await this.parseRoot(rootDir);\n if (result.buckets.length > 0) {\n buckets.push(...result.buckets);\n }\n if (result.sessions.length > 0) {\n sessions.push(...result.sessions);\n }\n }\n\n return { buckets, sessions };\n }\n\n isInstalled(): boolean {\n return this.resolveRoots().some((dir) => existsSync(dir));\n }\n\n private async parseRoot(rootDir: string): Promise<ParseResult> {\n const dbPath = join(rootDir, \"opencode.db\");\n const messagesDir = join(rootDir, \"storage\", \"message\");\n\n if (existsSync(dbPath)) {\n try {\n return await this.parseFromSqlite(dbPath);\n } catch (err) {\n process.stderr.write(\n `warn: opencode sqlite parse failed (${(err as Error).message}), trying legacy json...\\n`,\n );\n }\n }\n\n return this.parseFromJson(messagesDir);\n }\n\n private async parseFromSqlite(dbPath: string): Promise<ParseResult> {\n const query = `SELECT\n session_id as sessionID,\n json_extract(data, '$.role') as role,\n json_extract(data, '$.time.created') as created,\n json_extract(data, '$.modelID') as modelID,\n json_extract(data, '$.tokens') as tokens,\n json_extract(data, '$.path.root') as rootPath\n FROM message`;\n\n const builtinRows = await readSqliteRowsWithBuiltin(dbPath, query);\n const rows = builtinRows ?? readSqliteRowsWithCli(dbPath, query);\n\n if (rows.length === 0) {\n return { buckets: [], sessions: [] };\n }\n\n const entries: TokenUsageEntry[] = [];\n const sessionEvents: SessionEvent[] = [];\n\n for (const row of rows) {\n const timestamp = new Date(row.created);\n if (Number.isNaN(timestamp.getTime())) continue;\n\n const project = row.rootPath ? basename(row.rootPath) : \"unknown\";\n const sessionId = row.sessionID || \"unknown\";\n if (row.role !== \"user\" && row.role !== \"assistant\") continue;\n\n sessionEvents.push({\n sessionId,\n source: \"opencode\",\n project,\n timestamp,\n role: row.role === \"user\" ? \"user\" : \"assistant\",\n });\n\n if (!row.modelID) continue;\n\n let tokens: OpenCodeMessage[\"tokens\"];\n try {\n tokens =\n typeof row.tokens === \"string\" ? JSON.parse(row.tokens) : row.tokens;\n } catch {\n continue;\n }\n if (!tokens || (!tokens.input && !tokens.output)) continue;\n\n entries.push({\n sessionId,\n source: \"opencode\",\n model: row.modelID || \"unknown\",\n project,\n timestamp,\n inputTokens: tokens.input || 0,\n outputTokens: tokens.output || 0,\n reasoningTokens: tokens.reasoning || 0,\n cachedTokens: tokens.cache?.read || 0,\n });\n }\n\n return {\n buckets: aggregateToBuckets(entries),\n sessions: extractSessions(sessionEvents, entries),\n };\n }\n\n private parseFromJson(messagesDir: string): ParseResult {\n if (!existsSync(messagesDir)) return { buckets: [], sessions: [] };\n\n const entries: TokenUsageEntry[] = [];\n const sessionEvents: SessionEvent[] = [];\n\n let sessionDirs: Dirent[];\n try {\n sessionDirs = readdirSync(messagesDir, { withFileTypes: true }).filter(\n (dirent) => dirent.isDirectory() && dirent.name.startsWith(\"ses_\"),\n );\n } catch {\n return { buckets: [], sessions: [] };\n }\n\n for (const sessionDir of sessionDirs) {\n const sessionPath = join(messagesDir, sessionDir.name);\n let messageFiles: string[];\n try {\n messageFiles = readdirSync(sessionPath).filter((file) =>\n file.endsWith(\".json\"),\n );\n } catch {\n continue;\n }\n\n for (const file of messageFiles) {\n const filePath = join(sessionPath, file);\n\n let data: OpenCodeMessage;\n try {\n data = JSON.parse(readFileSync(filePath, \"utf-8\"));\n } catch {\n continue;\n }\n\n const created = data.time?.created ?? data.created;\n if (!created) continue;\n const timestamp = new Date(created);\n if (Number.isNaN(timestamp.getTime())) continue;\n\n const rootPath = data.path?.root;\n const project = rootPath ? basename(rootPath) : \"unknown\";\n if (data.role !== \"user\" && data.role !== \"assistant\") continue;\n\n sessionEvents.push({\n sessionId: sessionDir.name,\n source: \"opencode\",\n project,\n timestamp,\n role: data.role === \"user\" ? \"user\" : \"assistant\",\n });\n\n if (!data.modelID) continue;\n const tokens = data.tokens;\n if (!tokens || (!tokens.input && !tokens.output)) continue;\n\n entries.push({\n sessionId: sessionDir.name,\n source: \"opencode\",\n model: data.modelID || \"unknown\",\n project,\n timestamp,\n inputTokens: tokens.input || 0,\n outputTokens: tokens.output || 0,\n reasoningTokens: tokens.reasoning || 0,\n cachedTokens: tokens.cache?.read || 0,\n });\n }\n }\n\n return {\n buckets: aggregateToBuckets(entries),\n sessions: extractSessions(sessionEvents, entries),\n };\n }\n}\n\nregisterParser(new OpenCodeParser());\n","import { type Dirent, existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { aggregateToBuckets } from \"../domain/aggregator\";\nimport { extractSessions } from \"../domain/session-extractor\";\nimport type {\n ParseResult,\n SessionEvent,\n TokenUsageEntry,\n} from \"../domain/types\";\nimport { registerParser } from \"./registry\";\nimport type { IParser, ToolDefinition } from \"./types\";\n\nconst TOOL_ID = \"openclaw\";\nconst TOOL_NAME = \"OpenClaw\";\nconst DEFAULT_DATA_DIR = join(homedir(), \".openclaw\");\nconst LEGACY_ROOT_NAMES = [\".clawdbot\", \".moltbot\", \".moldbot\"];\n\nconst TOOL: ToolDefinition = {\n id: TOOL_ID,\n name: TOOL_NAME,\n dataDir: DEFAULT_DATA_DIR,\n};\n\ninterface OpenClawMessage {\n type?: string;\n timestamp?: string | number;\n message?: {\n role?: string;\n timestamp?: string | number;\n model?: string;\n usage?: {\n input?: number;\n inputTokens?: number;\n input_tokens?: number;\n promptTokens?: number;\n prompt_tokens?: number;\n output?: number;\n outputTokens?: number;\n output_tokens?: number;\n completionTokens?: number;\n completion_tokens?: number;\n cacheRead?: number;\n cache_read?: number;\n cache_read_input_tokens?: number;\n };\n };\n model?: string;\n}\n\n/** Normalize usage fields — OpenClaw supports multiple naming conventions */\nfunction getTokens(\n usage: NonNullable<OpenClawMessage[\"message\"]>[\"usage\"],\n ...keys: string[]\n): number {\n for (const key of keys) {\n const value = (usage as Record<string, unknown>)[key];\n if (typeof value === \"number\" && value > 0) return value;\n }\n return 0;\n}\n\nexport function getOpenClawRoots(homeDir = homedir()): string[] {\n const roots = [join(homeDir, \".openclaw\")];\n\n try {\n const profileRoots = readdirSync(homeDir, { withFileTypes: true })\n .filter(\n (entry) => entry.isDirectory() && /^\\.openclaw-.+/.test(entry.name),\n )\n .map((entry) => join(homeDir, entry.name))\n .sort((left, right) => left.localeCompare(right));\n\n roots.push(...profileRoots);\n } catch {\n // Ignore unreadable home directories and fall back to well-known roots.\n }\n\n roots.push(...LEGACY_ROOT_NAMES.map((name) => join(homeDir, name)));\n\n return Array.from(new Set(roots));\n}\n\nexport class OpenClawParser implements IParser {\n readonly tool = TOOL;\n\n constructor(\n private readonly resolveRoots: () => string[] = getOpenClawRoots,\n ) {}\n\n async parse(): Promise<ParseResult> {\n const entries: TokenUsageEntry[] = [];\n const sessionEvents: SessionEvent[] = [];\n\n for (const root of this.resolveRoots()) {\n const agentsDir = join(root, \"agents\");\n if (!existsSync(agentsDir)) continue;\n\n let agentDirs: Dirent[];\n try {\n agentDirs = readdirSync(agentsDir, { withFileTypes: true }).filter(\n (d) => d.isDirectory(),\n );\n } catch {\n continue;\n }\n\n for (const agentDir of agentDirs) {\n const project = agentDir.name;\n const sessionsDir = join(agentsDir, agentDir.name, \"sessions\");\n if (!existsSync(sessionsDir)) continue;\n\n let files: string[];\n try {\n files = readdirSync(sessionsDir).filter((f) => f.endsWith(\".jsonl\"));\n } catch {\n continue;\n }\n\n for (const file of files) {\n const filePath = join(sessionsDir, file);\n\n let content: string;\n try {\n content = readFileSync(filePath, \"utf-8\");\n } catch {\n continue;\n }\n\n for (const line of content.split(\"\\n\")) {\n if (!line.trim()) continue;\n try {\n const obj = JSON.parse(line) as OpenClawMessage;\n\n if (obj.type !== \"message\") continue;\n const msg = obj.message;\n if (!msg) continue;\n\n const timestamp = obj.timestamp || msg.timestamp;\n if (!timestamp) continue;\n const ts = new Date(\n typeof timestamp === \"number\" ? timestamp : timestamp,\n );\n if (Number.isNaN(ts.getTime())) continue;\n if (msg.role !== \"user\" && msg.role !== \"assistant\") continue;\n\n sessionEvents.push({\n sessionId: filePath,\n source: TOOL_ID,\n project,\n timestamp: ts,\n role: msg.role === \"user\" ? \"user\" : \"assistant\",\n });\n\n if (msg.role !== \"assistant\") continue;\n const usage = msg.usage;\n if (!usage) continue;\n\n entries.push({\n sessionId: filePath,\n source: TOOL_ID,\n model: msg.model || obj.model || \"unknown\",\n project,\n timestamp: ts,\n inputTokens: getTokens(\n usage,\n \"input\",\n \"inputTokens\",\n \"input_tokens\",\n \"promptTokens\",\n \"prompt_tokens\",\n ),\n outputTokens: getTokens(\n usage,\n \"output\",\n \"outputTokens\",\n \"output_tokens\",\n \"completionTokens\",\n \"completion_tokens\",\n ),\n reasoningTokens: 0,\n cachedTokens: getTokens(\n usage,\n \"cacheRead\",\n \"cache_read\",\n \"cache_read_input_tokens\",\n ),\n });\n } catch {}\n }\n }\n }\n }\n\n return {\n buckets: aggregateToBuckets(entries),\n sessions: extractSessions(sessionEvents, entries),\n };\n }\n\n isInstalled(): boolean {\n return this.resolveRoots().some((root) => existsSync(join(root, \"agents\")));\n }\n}\n\nregisterParser(new OpenClawParser());\n","import { existsSync, readdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { aggregateToBuckets } from \"../domain/aggregator\";\nimport { extractSessions } from \"../domain/session-extractor\";\nimport type {\n ParseResult,\n SessionEvent,\n TokenUsageEntry,\n} from \"../domain/types\";\nimport { readFileSafe } from \"../infrastructure/fs/utils\";\nimport { registerParser } from \"./registry\";\nimport type { IParser, ToolDefinition } from \"./types\";\n\nconst TOOL_ID = \"qwen-code\";\nconst TOOL_NAME = \"Qwen Code\";\nconst DEFAULT_DATA_DIR = join(homedir(), \".qwen\", \"tmp\");\n\ninterface QwenUsage {\n promptTokenCount?: number;\n candidatesTokenCount?: number;\n cachedContentTokenCount?: number;\n thoughtsTokenCount?: number;\n input_tokens?: number;\n output_tokens?: number;\n}\n\ninterface QwenEvent {\n type?: string;\n timestamp?: string;\n cwd?: string;\n uuid?: string;\n model?: string;\n usageMetadata?: QwenUsage;\n usage?: QwenUsage;\n}\n\nexport interface QwenCodeParserOptions {\n dataDir?: string;\n}\n\nfunction createToolDefinition(dataDir: string): ToolDefinition {\n return {\n id: TOOL_ID,\n name: TOOL_NAME,\n dataDir,\n };\n}\n\nfunction toSafeNumber(value: unknown): number {\n const numberValue = Number(value);\n return Number.isFinite(numberValue) ? numberValue : 0;\n}\n\nfunction getPathLeaf(value: string): string {\n const normalized = value.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n const leaf = normalized.split(\"/\").filter(Boolean).pop();\n return leaf || \"unknown\";\n}\n\nfunction normalizeForPrefix(value: string): string {\n return value.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n}\n\nfunction findSessionFiles(baseDir: string): string[] {\n const results: string[] = [];\n if (!existsSync(baseDir)) return results;\n\n try {\n for (const entry of readdirSync(baseDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue;\n\n const chatsDir = join(baseDir, entry.name, \"chats\");\n if (!existsSync(chatsDir)) continue;\n\n try {\n for (const file of readdirSync(chatsDir)) {\n if (file.endsWith(\".jsonl\")) {\n results.push(join(chatsDir, file));\n }\n }\n } catch {\n // Ignore unreadable chat directories and keep scanning.\n }\n }\n } catch {\n return results;\n }\n\n return results;\n}\n\nexport function resolveQwenProject(\n cwd: string | undefined,\n filePath: string,\n dataDir = DEFAULT_DATA_DIR,\n): string {\n if (cwd) {\n return getPathLeaf(cwd);\n }\n\n const normalizedFilePath = normalizeForPrefix(filePath);\n const normalizedDataDir = normalizeForPrefix(dataDir);\n const prefix = `${normalizedDataDir}/`;\n\n if (!normalizedFilePath.startsWith(prefix)) {\n return \"unknown\";\n }\n\n const relativePath = normalizedFilePath.slice(prefix.length);\n const projectId = relativePath.split(\"/\")[0];\n return projectId || \"unknown\";\n}\n\nexport class QwenCodeParser implements IParser {\n readonly tool: ToolDefinition;\n\n constructor(private readonly dataDir = DEFAULT_DATA_DIR) {\n this.tool = createToolDefinition(dataDir);\n }\n\n async parse(): Promise<ParseResult> {\n const sessionFiles = findSessionFiles(this.dataDir);\n if (sessionFiles.length === 0) {\n return { buckets: [], sessions: [] };\n }\n\n const entries: TokenUsageEntry[] = [];\n const sessionEvents: SessionEvent[] = [];\n const seenUuids = new Set<string>();\n\n for (const filePath of sessionFiles) {\n const content = readFileSafe(filePath);\n if (!content) continue;\n\n const sessionId = filePath;\n\n for (const line of content.split(\"\\n\")) {\n if (!line.trim()) continue;\n\n try {\n const obj = JSON.parse(line) as QwenEvent;\n if (!obj.timestamp) continue;\n\n const timestamp = new Date(obj.timestamp);\n if (Number.isNaN(timestamp.getTime())) continue;\n\n const project = resolveQwenProject(obj.cwd, filePath, this.dataDir);\n\n if (obj.type === \"user\" || obj.type === \"assistant\") {\n sessionEvents.push({\n sessionId,\n source: TOOL_ID,\n project,\n timestamp,\n role: obj.type,\n });\n }\n\n if (obj.type !== \"assistant\") continue;\n\n const usage = obj.usageMetadata || obj.usage;\n if (!usage) continue;\n\n const totalInput =\n toSafeNumber(usage.promptTokenCount) ||\n toSafeNumber(usage.input_tokens);\n const totalOutput =\n toSafeNumber(usage.candidatesTokenCount) ||\n toSafeNumber(usage.output_tokens);\n const cachedTokens = toSafeNumber(usage.cachedContentTokenCount);\n const reasoningTokens = toSafeNumber(usage.thoughtsTokenCount);\n\n if (\n totalInput === 0 &&\n totalOutput === 0 &&\n cachedTokens === 0 &&\n reasoningTokens === 0\n ) {\n continue;\n }\n\n if (obj.uuid) {\n if (seenUuids.has(obj.uuid)) continue;\n seenUuids.add(obj.uuid);\n }\n\n entries.push({\n sessionId,\n source: TOOL_ID,\n model: obj.model || \"unknown\",\n project,\n timestamp,\n inputTokens: Math.max(0, totalInput - cachedTokens),\n outputTokens: Math.max(0, totalOutput - reasoningTokens),\n reasoningTokens,\n cachedTokens,\n });\n } catch {\n // Ignore malformed lines and continue scanning the session log.\n }\n }\n }\n\n return {\n buckets: aggregateToBuckets(entries),\n sessions: extractSessions(sessionEvents, entries),\n };\n }\n\n isInstalled(): boolean {\n return existsSync(this.dataDir);\n }\n}\n\nregisterParser(new QwenCodeParser());\n","import { existsSync, readdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { aggregateToBuckets } from \"../domain/aggregator\";\nimport { extractSessions } from \"../domain/session-extractor\";\nimport type {\n ParseResult,\n SessionEvent,\n TokenUsageEntry,\n} from \"../domain/types\";\nimport { readFileSafe } from \"../infrastructure/fs/utils\";\nimport { registerParser } from \"./registry\";\nimport type { IParser, ToolDefinition } from \"./types\";\n\nconst TOOL_ID = \"kimi-code\";\nconst TOOL_NAME = \"Kimi Code\";\nconst DEFAULT_SESSIONS_DIR = join(homedir(), \".kimi\", \"sessions\");\nconst DEFAULT_CONFIG_PATH = join(homedir(), \".kimi\", \"kimi.json\");\n\nconst USER_EVENT_TYPES = new Set([\"UserMessage\", \"user_message\", \"Input\"]);\nconst ASSISTANT_EVENT_TYPES = new Set([\n \"AssistantMessage\",\n \"assistant_message\",\n \"Output\",\n \"ModelOutput\",\n \"AssistantOutput\",\n]);\n\ninterface KimiTokenUsage {\n input_other?: unknown;\n output?: unknown;\n input_cache_read?: unknown;\n input_cache_creation?: unknown;\n}\n\ninterface KimiPayload {\n timestamp?: string | number;\n model?: string;\n role?: string;\n token_usage?: KimiTokenUsage;\n message_id?: string;\n}\n\ninterface KimiEvent {\n type?: string;\n timestamp?: string | number;\n payload?: KimiPayload;\n}\n\nexport interface KimiCodeParserOptions {\n sessionsDir?: string;\n configPath?: string;\n}\n\nfunction createToolDefinition(dataDir: string): ToolDefinition {\n return {\n id: TOOL_ID,\n name: TOOL_NAME,\n dataDir,\n };\n}\n\nfunction toSafeNumber(value: unknown): number {\n const numberValue = Number(value);\n return Number.isFinite(numberValue) ? numberValue : 0;\n}\n\nfunction getPathLeaf(value: string): string {\n const normalized = value.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n const leaf = normalized.split(\"/\").filter(Boolean).pop();\n return leaf || \"unknown\";\n}\n\nfunction findWireFiles(\n baseDir: string,\n): Array<{ filePath: string; workDirHash: string }> {\n const results: Array<{ filePath: string; workDirHash: string }> = [];\n if (!existsSync(baseDir)) return results;\n\n try {\n for (const workDir of readdirSync(baseDir, { withFileTypes: true })) {\n if (!workDir.isDirectory()) continue;\n\n const workDirPath = join(baseDir, workDir.name);\n try {\n for (const session of readdirSync(workDirPath, {\n withFileTypes: true,\n })) {\n if (!session.isDirectory()) continue;\n\n const wireFile = join(workDirPath, session.name, \"wire.jsonl\");\n if (existsSync(wireFile)) {\n results.push({ filePath: wireFile, workDirHash: workDir.name });\n }\n }\n } catch {\n // Ignore unreadable session directories and keep scanning.\n }\n }\n } catch {\n return results;\n }\n\n return results;\n}\n\nfunction parseTimestamp(value: string | number | undefined): Date | null {\n if (value == null) return null;\n const timestamp = new Date(value);\n return Number.isNaN(timestamp.getTime()) ? null : timestamp;\n}\n\nfunction classifyKimiRole(\n type: string | undefined,\n payload: KimiPayload | undefined,\n): SessionEvent[\"role\"] | null {\n if (payload?.role === \"user\" || payload?.role === \"assistant\") {\n return payload.role;\n }\n\n if (type && USER_EVENT_TYPES.has(type)) {\n return \"user\";\n }\n\n if (type && ASSISTANT_EVENT_TYPES.has(type)) {\n return \"assistant\";\n }\n\n if (type?.toLowerCase().includes(\"assistant\")) {\n return \"assistant\";\n }\n\n return null;\n}\n\nfunction loadProjectMap(configPath: string): Map<string, string> {\n const projectMap = new Map<string, string>();\n const content = readFileSafe(configPath);\n if (!content) return projectMap;\n\n try {\n const config = JSON.parse(content) as {\n workspaces?: Record<string, string | { path?: string; dir?: string }>;\n projects?: Record<string, string | { path?: string; dir?: string }>;\n };\n\n const workspaces = config.workspaces || config.projects || {};\n for (const [hash, info] of Object.entries(workspaces)) {\n const pathValue =\n typeof info === \"string\" ? info : info.path || info.dir || undefined;\n if (!pathValue) continue;\n\n projectMap.set(hash, getPathLeaf(pathValue));\n }\n } catch {\n // Ignore unreadable config and fall back to work-dir hashes.\n }\n\n return projectMap;\n}\n\nexport class KimiCodeParser implements IParser {\n readonly tool: ToolDefinition;\n private readonly sessionsDir: string;\n private readonly configPath: string;\n\n constructor(options: KimiCodeParserOptions = {}) {\n this.sessionsDir = options.sessionsDir || DEFAULT_SESSIONS_DIR;\n this.configPath = options.configPath || DEFAULT_CONFIG_PATH;\n this.tool = createToolDefinition(this.sessionsDir);\n }\n\n async parse(): Promise<ParseResult> {\n const wireFiles = findWireFiles(this.sessionsDir);\n if (wireFiles.length === 0) {\n return { buckets: [], sessions: [] };\n }\n\n const projectMap = loadProjectMap(this.configPath);\n const entries: TokenUsageEntry[] = [];\n const sessionEvents: SessionEvent[] = [];\n const seenMessageIds = new Set<string>();\n\n for (const { filePath, workDirHash } of wireFiles) {\n const content = readFileSafe(filePath);\n if (!content) continue;\n\n const sessionId = filePath;\n const project = projectMap.get(workDirHash) || workDirHash;\n let currentModel = \"unknown\";\n let lastTimestampRaw: string | number | undefined;\n\n for (const line of content.split(\"\\n\")) {\n if (!line.trim()) continue;\n\n let obj: KimiEvent;\n try {\n obj = JSON.parse(line) as KimiEvent;\n } catch {\n continue;\n }\n\n const payload = obj.payload;\n if (!payload) continue;\n\n if (payload.model) {\n currentModel = payload.model;\n }\n\n const timestampValue =\n payload.timestamp ?? obj.timestamp ?? lastTimestampRaw;\n const timestamp = parseTimestamp(timestampValue);\n if (payload.timestamp != null) {\n lastTimestampRaw = payload.timestamp;\n } else if (obj.timestamp != null) {\n lastTimestampRaw = obj.timestamp;\n }\n\n const role = classifyKimiRole(obj.type, payload);\n if (role && timestamp) {\n sessionEvents.push({\n sessionId,\n source: TOOL_ID,\n project,\n timestamp,\n role,\n });\n }\n\n if (obj.type !== \"StatusUpdate\") continue;\n\n const tokenUsage = payload.token_usage;\n if (!tokenUsage || !timestamp) continue;\n\n const inputTokens = toSafeNumber(tokenUsage.input_other);\n const outputTokens = toSafeNumber(tokenUsage.output);\n const cachedTokens = toSafeNumber(tokenUsage.input_cache_read);\n const cacheCreateTokens = toSafeNumber(tokenUsage.input_cache_creation);\n\n if (\n inputTokens === 0 &&\n outputTokens === 0 &&\n cachedTokens === 0 &&\n cacheCreateTokens === 0\n ) {\n continue;\n }\n\n if (payload.message_id) {\n if (seenMessageIds.has(payload.message_id)) continue;\n seenMessageIds.add(payload.message_id);\n }\n\n if (!role) {\n sessionEvents.push({\n sessionId,\n source: TOOL_ID,\n project,\n timestamp,\n role: \"assistant\",\n });\n }\n\n entries.push({\n sessionId,\n source: TOOL_ID,\n model: currentModel,\n project,\n timestamp,\n inputTokens,\n outputTokens,\n reasoningTokens: 0,\n cachedTokens,\n });\n }\n }\n\n return {\n buckets: aggregateToBuckets(entries),\n sessions: extractSessions(sessionEvents, entries),\n };\n }\n\n isInstalled(): boolean {\n return existsSync(this.sessionsDir);\n }\n}\n\nregisterParser(new KimiCodeParser());\n","import { existsSync, readdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { basename, dirname, join } from \"node:path\";\nimport { aggregateToBuckets } from \"../domain/aggregator\";\nimport { extractSessions } from \"../domain/session-extractor\";\nimport type {\n ParseResult,\n SessionEvent,\n TokenUsageEntry,\n} from \"../domain/types\";\nimport { readFileSafe } from \"../infrastructure/fs/utils\";\nimport { registerParser } from \"./registry\";\nimport type { IParser, ToolDefinition } from \"./types\";\n\nconst TOOL_ID = \"droid\";\nconst TOOL_NAME = \"Droid\";\nconst DEFAULT_DATA_DIR = join(homedir(), \".factory\", \"sessions\");\n\ninterface DroidMessageEvent {\n type?: string;\n timestamp?: string;\n message?: {\n role?: string;\n };\n}\n\ninterface DroidSettings {\n model?: string;\n tokenUsage?: {\n inputTokens?: unknown;\n outputTokens?: unknown;\n cacheReadTokens?: unknown;\n thinkingTokens?: unknown;\n };\n}\n\nfunction createToolDefinition(dataDir: string): ToolDefinition {\n return {\n id: TOOL_ID,\n name: TOOL_NAME,\n dataDir,\n };\n}\n\nfunction findSessionFiles(dir: string): string[] {\n const results: string[] = [];\n if (!existsSync(dir)) return results;\n\n try {\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const fullPath = join(dir, entry.name);\n if (entry.isDirectory()) {\n results.push(...findSessionFiles(fullPath));\n } else if (\n entry.isFile() &&\n entry.name.endsWith(\".jsonl\") &&\n !entry.name.endsWith(\".settings.json\")\n ) {\n results.push(fullPath);\n }\n }\n } catch {\n // Ignore unreadable directories and keep scanning.\n }\n\n return results;\n}\n\nexport function extractDroidProject(slug: string): string {\n const parts = slug.split(\"-\").filter(Boolean);\n return parts.length > 0 ? parts[parts.length - 1] : \"unknown\";\n}\n\nfunction toSafeNumber(value: unknown): number {\n const numberValue = Number(value);\n return Number.isFinite(numberValue) ? numberValue : 0;\n}\n\nexport class DroidParser implements IParser {\n readonly tool: ToolDefinition;\n\n constructor(private readonly dataDir = DEFAULT_DATA_DIR) {\n this.tool = createToolDefinition(dataDir);\n }\n\n async parse(): Promise<ParseResult> {\n const sessionFiles = findSessionFiles(this.dataDir);\n if (sessionFiles.length === 0) {\n return { buckets: [], sessions: [] };\n }\n\n const entries: TokenUsageEntry[] = [];\n const sessionEvents: SessionEvent[] = [];\n\n for (const filePath of sessionFiles) {\n const sessionId = filePath;\n const project = extractDroidProject(basename(dirname(filePath)));\n let firstMessageTimestamp: Date | null = null;\n\n const content = readFileSafe(filePath);\n if (!content) continue;\n\n for (const line of content.split(\"\\n\")) {\n if (!line.trim()) continue;\n\n let obj: DroidMessageEvent;\n try {\n obj = JSON.parse(line) as DroidMessageEvent;\n } catch {\n continue;\n }\n\n if (obj.type !== \"message\" || !obj.timestamp) continue;\n\n const timestamp = new Date(obj.timestamp);\n if (Number.isNaN(timestamp.getTime())) continue;\n\n const role = obj.message?.role;\n if (role !== \"user\" && role !== \"assistant\") continue;\n\n if (firstMessageTimestamp === null) {\n firstMessageTimestamp = timestamp;\n }\n\n sessionEvents.push({\n sessionId,\n source: TOOL_ID,\n project,\n timestamp,\n role,\n });\n }\n\n const settingsPath = join(\n dirname(filePath),\n `${basename(filePath, \".jsonl\")}.settings.json`,\n );\n const settingsContent = readFileSafe(settingsPath);\n if (!settingsContent || firstMessageTimestamp === null) continue;\n\n let settings: DroidSettings;\n try {\n settings = JSON.parse(settingsContent) as DroidSettings;\n } catch {\n continue;\n }\n\n const tokenUsage = settings.tokenUsage;\n if (!tokenUsage) continue;\n\n const cachedTokens = toSafeNumber(tokenUsage.cacheReadTokens);\n const reasoningTokens = toSafeNumber(tokenUsage.thinkingTokens);\n const inputTokens = Math.max(\n 0,\n toSafeNumber(tokenUsage.inputTokens) - cachedTokens,\n );\n const outputTokens = Math.max(\n 0,\n toSafeNumber(tokenUsage.outputTokens) - reasoningTokens,\n );\n\n if (\n inputTokens === 0 &&\n outputTokens === 0 &&\n cachedTokens === 0 &&\n reasoningTokens === 0\n ) {\n continue;\n }\n\n entries.push({\n sessionId,\n source: TOOL_ID,\n model: settings.model || \"unknown\",\n project,\n timestamp: firstMessageTimestamp,\n inputTokens,\n outputTokens,\n reasoningTokens,\n cachedTokens,\n });\n }\n\n return {\n buckets: aggregateToBuckets(entries),\n sessions: extractSessions(sessionEvents, entries),\n };\n }\n\n isInstalled(): boolean {\n return existsSync(this.dataDir);\n }\n}\n\nregisterParser(new DroidParser());\n","import { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { aggregateToBuckets } from \"../domain/aggregator\";\nimport { extractSessions } from \"../domain/session-extractor\";\nimport type {\n ParseResult,\n SessionEvent,\n TokenUsageEntry,\n} from \"../domain/types\";\nimport {\n findJsonlFiles,\n parseJsonl,\n readFileSafe,\n} from \"../infrastructure/fs/utils\";\nimport { registerParser } from \"./registry\";\nimport type { IParser, ToolDefinition } from \"./types\";\n\nconst TOOL_ID = \"pi-coding-agent\";\nconst TOOL_NAME = \"pi\";\nconst DEFAULT_SESSIONS_DIR = join(homedir(), \".pi\", \"agent\", \"sessions\");\n\ninterface PiUsage {\n input?: number;\n inputTokens?: number;\n output?: number;\n outputTokens?: number;\n cacheRead?: number;\n cacheReadTokens?: number;\n cache_read?: number;\n reasoningOutputTokens?: number;\n thinkingTokens?: number;\n thoughts?: number;\n}\n\ninterface PiEvent {\n type?: string;\n id?: string;\n timestamp?: string;\n cwd?: string;\n message?: {\n role?: string;\n timestamp?: string;\n model?: string;\n usage?: PiUsage;\n };\n}\n\nfunction createToolDefinition(dataDir: string): ToolDefinition {\n return {\n id: TOOL_ID,\n name: TOOL_NAME,\n dataDir,\n };\n}\n\nfunction toSafeNumber(value: unknown): number {\n const numberValue = Number(value);\n return Number.isFinite(numberValue) ? numberValue : 0;\n}\n\nfunction getPathLeaf(value: string): string {\n const normalized = value.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n const leaf = normalized.split(\"/\").filter(Boolean).pop();\n return leaf || \"unknown\";\n}\n\nfunction normalizeForPrefix(value: string): string {\n return value.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n}\n\nfunction getUsageNumber(usage: PiUsage, ...keys: Array<keyof PiUsage>): number {\n for (const key of keys) {\n const value = usage[key];\n const numberValue = toSafeNumber(value);\n if (numberValue > 0) {\n return numberValue;\n }\n }\n\n return 0;\n}\n\nexport function extractPiProjectFromCwd(cwd: string): string {\n return getPathLeaf(cwd);\n}\n\nexport function extractPiProjectFromDir(\n filePath: string,\n sessionsDir = DEFAULT_SESSIONS_DIR,\n): string {\n const normalizedFilePath = normalizeForPrefix(filePath);\n const normalizedSessionsDir = normalizeForPrefix(sessionsDir);\n const prefix = `${normalizedSessionsDir}/`;\n\n if (!normalizedFilePath.startsWith(prefix)) {\n return \"unknown\";\n }\n\n const relativePath = normalizedFilePath.slice(prefix.length);\n const firstSegment = relativePath.split(\"/\")[0];\n if (!firstSegment) {\n return \"unknown\";\n }\n\n try {\n const decoded = decodeURIComponent(firstSegment);\n if (decoded.includes(\"/\") || decoded.includes(\"\\\\\")) {\n return getPathLeaf(decoded);\n }\n } catch {\n // Fall back to slug parsing when the segment is not URI-encoded.\n }\n\n const slugParts = firstSegment.split(\"-\").filter(Boolean);\n return slugParts.length > 0 ? slugParts[slugParts.length - 1] : \"unknown\";\n}\n\nexport class PiCodingAgentParser implements IParser {\n readonly tool: ToolDefinition;\n\n constructor(private readonly sessionsDir = DEFAULT_SESSIONS_DIR) {\n this.tool = createToolDefinition(sessionsDir);\n }\n\n async parse(): Promise<ParseResult> {\n const sessionFiles = findJsonlFiles(this.sessionsDir);\n if (sessionFiles.length === 0) {\n return { buckets: [], sessions: [] };\n }\n\n const entries: TokenUsageEntry[] = [];\n const sessionEvents: SessionEvent[] = [];\n const seenEntryIds = new Set<string>();\n\n for (const filePath of sessionFiles) {\n const content = readFileSafe(filePath);\n if (!content) continue;\n\n const rows = parseJsonl<PiEvent>(content);\n if (rows.length === 0) continue;\n\n let sessionId = filePath;\n let project = extractPiProjectFromDir(filePath, this.sessionsDir);\n\n for (const row of rows) {\n if (row.type !== \"session\") continue;\n if (row.id) {\n sessionId = row.id;\n }\n if (row.cwd) {\n project = extractPiProjectFromCwd(row.cwd);\n }\n break;\n }\n\n for (const row of rows) {\n if (row.type !== \"message\") continue;\n\n const message = row.message;\n if (!message) continue;\n\n const rawTimestamp = row.timestamp || message.timestamp;\n if (!rawTimestamp) continue;\n\n const timestamp = new Date(rawTimestamp);\n if (Number.isNaN(timestamp.getTime())) continue;\n\n if (message.role === \"user\" || message.role === \"assistant\") {\n sessionEvents.push({\n sessionId,\n source: TOOL_ID,\n project,\n timestamp,\n role: message.role,\n });\n }\n\n if (message.role !== \"assistant\") continue;\n\n const usage = message.usage;\n if (!usage) continue;\n\n const inputTokens = getUsageNumber(usage, \"input\", \"inputTokens\");\n const outputTokens = getUsageNumber(usage, \"output\", \"outputTokens\");\n const cachedTokens = getUsageNumber(\n usage,\n \"cacheRead\",\n \"cacheReadTokens\",\n \"cache_read\",\n );\n const reasoningTokens = getUsageNumber(\n usage,\n \"reasoningOutputTokens\",\n \"thinkingTokens\",\n \"thoughts\",\n );\n\n if (\n inputTokens === 0 &&\n outputTokens === 0 &&\n cachedTokens === 0 &&\n reasoningTokens === 0\n ) {\n continue;\n }\n\n if (row.id) {\n if (seenEntryIds.has(row.id)) continue;\n seenEntryIds.add(row.id);\n }\n\n entries.push({\n sessionId,\n source: TOOL_ID,\n model: message.model || \"unknown\",\n project,\n timestamp,\n inputTokens,\n outputTokens,\n reasoningTokens,\n cachedTokens,\n });\n }\n }\n\n return {\n buckets: aggregateToBuckets(entries),\n sessions: extractSessions(sessionEvents, entries),\n };\n }\n\n isInstalled(): boolean {\n return existsSync(this.sessionsDir);\n }\n}\n\nregisterParser(new PiCodingAgentParser());\n","import { existsSync, readdirSync } from \"node:fs\";\nimport { homedir, hostname } from \"node:os\";\nimport { join } from \"node:path\";\nimport { aggregateToBuckets } from \"../domain/aggregator\";\nimport type {\n ParseResult,\n SessionEvent,\n SessionMetadata,\n SessionModelUsage,\n TokenUsageEntry,\n} from \"../domain/types\";\nimport { readFileSafe } from \"../infrastructure/fs/utils\";\nimport { registerParser } from \"./registry\";\nimport type { IParser, ToolDefinition } from \"./types\";\n\nconst TOOL_ID = \"qwenpaw\";\nconst TOOL_NAME = \"QwenPaw\";\nconst DEFAULT_USAGE_PATH = join(homedir(), \".qwenpaw\", \"token_usage.json\");\nconst DEFAULT_WORKSPACE_PATH = join(homedir(), \".qwenpaw\", \"workspace\");\n\ninterface QwenPawUsageRecord {\n provider_id?: unknown;\n model_name?: unknown;\n prompt_tokens?: unknown;\n completion_tokens?: unknown;\n call_count?: unknown;\n}\n\ntype QwenPawUsageFile = Record<string, Record<string, QwenPawUsageRecord>>;\n\ninterface QwenPawChatRecord {\n channel: string;\n created_at: string;\n id: string;\n name: string;\n session_id: string;\n user_id: string;\n status: string;\n updated_at: string;\n}\n\ninterface QwenPawChatsFile {\n chats: QwenPawChatRecord[];\n version: number;\n}\n\ninterface QwenPawSessionContent {\n type: string;\n text?: string;\n thinking?: string;\n input?: unknown;\n output?: unknown;\n}\n\ninterface QwenPawMessage {\n id: string;\n name: string;\n role: \"user\" | \"assistant\" | \"system\";\n content: QwenPawSessionContent[];\n timestamp: string;\n metadata?: Record<string, unknown>;\n}\n\ninterface QwenPawAgentData {\n memory?: {\n content: Array<[QwenPawMessage, unknown]>;\n };\n}\n\ninterface QwenPawSessionFile {\n agent: QwenPawAgentData;\n}\n\nexport interface QwenPawParserOptions {\n usagePath?: string;\n workspacePath?: string;\n}\n\nfunction createToolDefinition(usagePath: string): ToolDefinition {\n return {\n id: TOOL_ID,\n name: TOOL_NAME,\n dataDir: usagePath,\n };\n}\n\nfunction toSafeNumber(value: unknown): number {\n const numberValue = Number(value);\n return Number.isFinite(numberValue) && numberValue > 0 ? numberValue : 0;\n}\n\nfunction parseUsageDate(value: string): Date | null {\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(value)) {\n return null;\n }\n\n const timestamp = new Date(`${value}T00:00:00.000Z`);\n return Number.isNaN(timestamp.getTime()) ? null : timestamp;\n}\n\nfunction getString(value: unknown): string | null {\n return typeof value === \"string\" && value.length > 0 ? value : null;\n}\n\nfunction resolveModel(recordKey: string, record: QwenPawUsageRecord): string {\n const providerId = getString(record.provider_id);\n const modelName = getString(record.model_name);\n\n if (providerId && modelName) {\n return `${providerId}:${modelName}`;\n }\n\n return modelName || recordKey || \"unknown\";\n}\n\nexport class QwenPawParser implements IParser {\n readonly tool: ToolDefinition;\n private readonly usagePath: string;\n private readonly workspacePath: string;\n\n constructor(options: QwenPawParserOptions = {}) {\n this.usagePath = options.usagePath || DEFAULT_USAGE_PATH;\n this.workspacePath = options.workspacePath || DEFAULT_WORKSPACE_PATH;\n this.tool = createToolDefinition(this.usagePath);\n }\n\n async parse(): Promise<ParseResult> {\n const entries: TokenUsageEntry[] = [];\n const sessionEvents: SessionEvent[] = [];\n\n const content = readFileSafe(this.usagePath);\n if (content) {\n try {\n const usageFile = JSON.parse(content) as QwenPawUsageFile;\n\n for (const [dateKey, recordsByModel] of Object.entries(usageFile)) {\n const timestamp = parseUsageDate(dateKey);\n if (!timestamp || typeof recordsByModel !== \"object\") {\n continue;\n }\n\n for (const [recordKey, record] of Object.entries(recordsByModel)) {\n if (!record || typeof record !== \"object\") {\n continue;\n }\n\n const inputTokens = toSafeNumber(record.prompt_tokens);\n const outputTokens = toSafeNumber(record.completion_tokens);\n if (inputTokens === 0 && outputTokens === 0) {\n continue;\n }\n\n entries.push({\n source: TOOL_ID,\n model: resolveModel(recordKey, record),\n project: \"unknown\",\n timestamp,\n inputTokens,\n outputTokens,\n reasoningTokens: 0,\n cachedTokens: 0,\n });\n }\n }\n } catch {}\n }\n\n const workspaceSessions = await this.parseWorkspaceSessions();\n sessionEvents.push(...workspaceSessions);\n\n return {\n buckets: aggregateToBuckets(entries),\n sessions: this.aggregateSessions(sessionEvents),\n };\n }\n\n private async parseWorkspaceSessions(): Promise<SessionEvent[]> {\n const events: SessionEvent[] = [];\n\n if (!existsSync(this.workspacePath)) {\n return events;\n }\n\n try {\n const workspaceDirs = readdirSync(this.workspacePath);\n\n for (const workspaceDir of workspaceDirs) {\n const workspacePath = join(this.workspacePath, workspaceDir);\n const chatsPath = join(workspacePath, \"chats.json\");\n const sessionsPath = join(workspacePath, \"sessions\");\n\n // Parse chats.json to get session metadata\n const chatsContent = readFileSafe(chatsPath);\n if (!chatsContent) {\n continue;\n }\n\n let chatsFile: QwenPawChatsFile;\n try {\n chatsFile = JSON.parse(chatsContent) as QwenPawChatsFile;\n } catch {\n continue;\n }\n\n if (!chatsFile.chats || !Array.isArray(chatsFile.chats)) {\n continue;\n }\n\n // Parse individual session files\n const sessionFiles = this.getSessionFiles(sessionsPath);\n\n for (const chat of chatsFile.chats) {\n const sessionFileContent = sessionFiles.get(chat.session_id);\n if (!sessionFileContent) {\n continue;\n }\n\n try {\n const sessionData = JSON.parse(\n sessionFileContent,\n ) as QwenPawSessionFile;\n const sessionMessages = this.extractMessages(sessionData);\n\n for (const msg of sessionMessages) {\n events.push({\n sessionId: chat.session_id,\n source: TOOL_ID,\n project: workspaceDir,\n timestamp: new Date(msg.timestamp),\n role: msg.role as \"user\" | \"assistant\",\n });\n }\n } catch {}\n }\n }\n } catch {\n // If workspace directory can't be read, just return empty events\n }\n\n return events;\n }\n\n private getSessionFiles(sessionsPath: string): Map<string, string> {\n const files = new Map<string, string>();\n\n if (!existsSync(sessionsPath)) {\n return files;\n }\n\n try {\n const sessionFileNames = readdirSync(sessionsPath);\n\n for (const fileName of sessionFileNames) {\n if (!fileName.endsWith(\".json\")) {\n continue;\n }\n\n const filePath = join(sessionsPath, fileName);\n const content = readFileSafe(filePath);\n if (content) {\n // Extract session_id from filename: format is \"{channel}_{session_id}.json\"\n const sessionId = fileName\n .replace(/^[^_]+_/, \"\")\n .replace(\".json\", \"\");\n files.set(sessionId, content);\n }\n }\n } catch {\n // If sessions directory can't be read, return empty map\n }\n\n return files;\n }\n\n private extractMessages(sessionData: QwenPawSessionFile): QwenPawMessage[] {\n const messages: QwenPawMessage[] = [];\n\n if (!sessionData.agent?.memory?.content) {\n return messages;\n }\n\n for (const [messageData] of sessionData.agent.memory.content) {\n if (!messageData || typeof messageData !== \"object\") {\n continue;\n }\n\n const msg = messageData as unknown as QwenPawMessage;\n\n // Only include user and assistant messages (skip system messages)\n if ((msg.role === \"user\" || msg.role === \"assistant\") && msg.timestamp) {\n messages.push(msg);\n }\n }\n\n return messages;\n }\n\n private aggregateSessions(events: SessionEvent[]): SessionMetadata[] {\n const sessionMap = new Map<\n string,\n {\n source: string;\n project: string;\n firstMessageAt: Date;\n lastMessageAt: Date;\n messageCount: number;\n userMessageCount: number;\n modelUsages: Map<string, { inputTokens: number; outputTokens: number }>;\n }\n >();\n\n for (const event of events) {\n const key = `${event.sessionId}|${event.source}|${event.project}`;\n\n if (!sessionMap.has(key)) {\n sessionMap.set(key, {\n source: event.source,\n project: event.project,\n firstMessageAt: event.timestamp,\n lastMessageAt: event.timestamp,\n messageCount: 0,\n userMessageCount: 0,\n modelUsages: new Map(),\n });\n }\n\n const session = sessionMap.get(key);\n if (!session) continue;\n\n session.lastMessageAt =\n event.timestamp > session.lastMessageAt\n ? event.timestamp\n : session.lastMessageAt;\n session.messageCount++;\n\n if (event.role === \"user\") {\n session.userMessageCount++;\n }\n }\n\n return Array.from(sessionMap.entries()).map(([sessionKey, sessionData]) => {\n const [sessionHash] = sessionKey.split(\"|\");\n const firstMessageAt = sessionData.firstMessageAt.toISOString();\n const lastMessageAt = sessionData.lastMessageAt.toISOString();\n const durationSeconds = Math.floor(\n (sessionData.lastMessageAt.getTime() -\n sessionData.firstMessageAt.getTime()) /\n 1000,\n );\n\n // For now, we don't have token data from sessions, so set to 0\n const inputTokens = 0;\n const outputTokens = 0;\n const reasoningTokens = 0;\n const cachedTokens = 0;\n const totalTokens = 0;\n\n // Build model usages array (empty for now as we don't have model data)\n const modelUsages: SessionModelUsage[] = Array.from(\n sessionData.modelUsages.entries(),\n ).map(([model, usage]) => ({\n model,\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n reasoningTokens: 0,\n cachedTokens: 0,\n totalTokens: usage.inputTokens + usage.outputTokens,\n }));\n\n return {\n source: sessionData.source,\n project: sessionData.project,\n sessionHash,\n hostname: hostname().replace(/\\.local$/, \"\"),\n firstMessageAt,\n lastMessageAt,\n durationSeconds,\n activeSeconds: durationSeconds, // Assume all time is active for now\n messageCount: sessionData.messageCount,\n userMessageCount: sessionData.userMessageCount,\n userPromptHours: [], // No hourly data available\n inputTokens,\n outputTokens,\n reasoningTokens,\n cachedTokens,\n totalTokens,\n primaryModel: \"unknown\", // No model data available from session files\n modelUsages,\n };\n });\n }\n\n isInstalled(): boolean {\n return existsSync(this.usagePath) || existsSync(this.workspacePath);\n }\n}\n\nregisterParser(new QwenPawParser());\n","import { readFileSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { basename, join } from \"node:path\";\nimport { aggregateToBuckets } from \"../domain/aggregator\";\nimport { extractSessions } from \"../domain/session-extractor\";\nimport type {\n ParseResult,\n SessionEvent,\n TokenUsageEntry,\n} from \"../domain/types\";\nimport { registerParser } from \"./registry\";\nimport type { IParser, ToolDefinition } from \"./types\";\n\nconst EXTENSION_ID = \"saoudrizwan.claude-dev\";\n\nconst HOSTS = [\n \"Code\",\n \"Cursor\",\n \"Windsurf\",\n \"VSCodium\",\n \"Code - Insiders\",\n \"Trae\",\n \"Trae CN\",\n];\n\nconst TOOL: ToolDefinition = {\n id: \"cline\",\n name: \"Cline\",\n dataDir: join(homedir(), \".cline\"),\n};\n\nfunction getHostRoots(): string[] {\n const out: string[] = [];\n if (process.platform === \"darwin\") {\n const base = join(homedir(), \"Library\", \"Application Support\");\n for (const h of HOSTS) out.push(join(base, h));\n } else if (process.platform === \"win32\") {\n const appData =\n process.env.APPDATA?.trim() || join(homedir(), \"AppData\", \"Roaming\");\n for (const h of HOSTS) out.push(join(appData, h));\n } else {\n const xdg =\n process.env.XDG_CONFIG_HOME?.trim() || join(homedir(), \".config\");\n for (const h of HOSTS) out.push(join(xdg, h));\n }\n return out;\n}\n\nfunction findClineExtensionDirs(): string[] {\n const dirs: string[] = [];\n for (const root of getHostRoots()) {\n const ext = join(root, \"User\", \"globalStorage\", EXTENSION_ID);\n try {\n if (statSync(ext).isDirectory()) dirs.push(ext);\n } catch {\n // not installed in this host; skip\n }\n }\n return dirs;\n}\n\nfunction readJsonSafe(path: string): unknown {\n try {\n return JSON.parse(readFileSync(path, \"utf-8\"));\n } catch {\n return null;\n }\n}\n\nfunction projectFromPath(absPath: unknown): string {\n if (!absPath || typeof absPath !== \"string\") return \"unknown\";\n const trimmed = absPath.replace(/[\\\\/]+$/, \"\");\n const name = basename(trimmed);\n return name || \"unknown\";\n}\n\nclass ClineParser implements IParser {\n readonly tool = TOOL;\n\n isInstalled(): boolean {\n return findClineExtensionDirs().length > 0;\n }\n\n async parse(): Promise<ParseResult> {\n const extDirs = findClineExtensionDirs();\n if (extDirs.length === 0) return { buckets: [], sessions: [] };\n\n const entries: TokenUsageEntry[] = [];\n const sessionEvents: SessionEvent[] = [];\n\n for (const extDir of extDirs) {\n const history = readJsonSafe(join(extDir, \"state\", \"taskHistory.json\"));\n if (!Array.isArray(history)) continue;\n\n for (const item of history) {\n try {\n if (!item || typeof item !== \"object\" || !item.id) continue;\n const taskId = String(item.id);\n const project = projectFromPath(\n (item as Record<string, unknown>).cwdOnTaskInitialization ||\n (item as Record<string, unknown>).shadowGitConfigWorkTree,\n );\n const fallbackModel =\n ((item as Record<string, unknown>).modelId &&\n String((item as Record<string, unknown>).modelId).trim()) ||\n \"cline-unknown\";\n\n const messages = readJsonSafe(\n join(extDir, \"tasks\", taskId, \"ui_messages.json\"),\n );\n if (!Array.isArray(messages)) continue;\n\n for (const msg of messages) {\n if (!msg || typeof msg !== \"object\") continue;\n const ts = Number((msg as Record<string, unknown>).ts);\n if (!Number.isFinite(ts)) continue;\n const timestamp = new Date(ts);\n\n const msgType = (msg as Record<string, unknown>).type;\n const msgSay = (msg as Record<string, unknown>).say;\n\n if (msgType === \"say\" && msgSay === \"api_req_started\") {\n let info: Record<string, unknown> | null = null;\n try {\n const text = (msg as Record<string, unknown>).text;\n if (typeof text === \"string\") info = JSON.parse(text);\n } catch {\n /* skip */\n }\n if (!info) continue;\n\n const inputTokens = Math.max(0, Number(info.tokensIn) || 0);\n const outputTokens = Math.max(0, Number(info.tokensOut) || 0);\n const cacheWrites = Math.max(0, Number(info.cacheWrites) || 0);\n const cacheReads = Math.max(0, Number(info.cacheReads) || 0);\n if (inputTokens + outputTokens + cacheWrites + cacheReads === 0)\n continue;\n\n const model =\n (info.model && String(info.model).trim()) || fallbackModel;\n if (typeof model !== \"string\") continue;\n\n entries.push({\n source: \"cline\",\n model,\n project,\n timestamp,\n inputTokens: inputTokens + cacheWrites,\n outputTokens,\n reasoningTokens: 0,\n cachedTokens: cacheReads,\n });\n }\n\n if (\n msgType === \"ask\" ||\n (msgType === \"say\" && msgSay === \"user_feedback\")\n ) {\n sessionEvents.push({\n sessionId: taskId,\n source: \"cline\",\n project,\n timestamp,\n role: \"user\",\n });\n } else if (msgType === \"say\" && msgSay === \"api_req_started\") {\n sessionEvents.push({\n sessionId: taskId,\n source: \"cline\",\n project,\n timestamp,\n role: \"assistant\",\n });\n }\n }\n } catch {\n // Skip this task; keep going for the rest of the history.\n }\n }\n }\n\n return {\n buckets: aggregateToBuckets(entries),\n sessions: extractSessions(sessionEvents, entries),\n };\n }\n}\n\nregisterParser(new ClineParser());\n","import { execFileSync } from \"node:child_process\";\nimport {\n copyFileSync,\n existsSync,\n mkdtempSync,\n readdirSync,\n readFileSync,\n rmSync,\n statSync,\n} from \"node:fs\";\nimport { homedir, tmpdir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport { aggregateToBuckets } from \"../domain/aggregator\";\nimport type { ParseResult, TokenUsageEntry } from \"../domain/types\";\nimport { registerParser } from \"./registry\";\nimport type { IParser, ToolDefinition } from \"./types\";\n\nconst KIROAGENT_RELATIVE = join(\"User\", \"globalStorage\", \"kiro.kiroagent\");\n\nfunction getDefaultBasePath(): string {\n if (process.platform === \"darwin\") {\n return join(\n homedir(),\n \"Library\",\n \"Application Support\",\n \"Kiro\",\n KIROAGENT_RELATIVE,\n );\n }\n if (process.platform === \"win32\") {\n const appData =\n process.env.APPDATA?.trim() || join(homedir(), \"AppData\", \"Roaming\");\n return join(appData, \"Kiro\", KIROAGENT_RELATIVE);\n }\n const xdgConfigHome =\n process.env.XDG_CONFIG_HOME?.trim() || join(homedir(), \".config\");\n return join(xdgConfigHome, \"Kiro\", KIROAGENT_RELATIVE);\n}\n\nconst TOOL: ToolDefinition = {\n id: \"kiro\",\n name: \"Kiro\",\n dataDir: getDefaultBasePath(),\n};\n\nfunction getKiroBasePath(): string | null {\n const explicit = process.env.KIRO_BASE_PATH?.trim();\n if (explicit) {\n const r = resolve(explicit);\n return existsSync(r) ? r : null;\n }\n const def = getDefaultBasePath();\n return existsSync(def) ? def : null;\n}\n\nfunction isLockError(err: unknown): boolean {\n return (\n err instanceof Error &&\n typeof err.message === \"string\" &&\n /database is locked/i.test(err.message)\n );\n}\n\nconst TOKENS_SQL =\n \"SELECT id, model, tokens_prompt, tokens_generated, timestamp \" +\n \"FROM tokens_generated \" +\n \"WHERE tokens_prompt > 0 OR tokens_generated > 0 \" +\n \"ORDER BY id ASC\";\n\nfunction queryDb(dbPath: string, sql: string): unknown[] {\n const out = execFileSync(\"sqlite3\", [\"-json\", dbPath, sql], {\n encoding: \"utf-8\",\n maxBuffer: 100 * 1024 * 1024,\n timeout: 30000,\n });\n const trimmed = out.trim();\n if (!trimmed || trimmed === \"[]\") return [];\n return JSON.parse(trimmed) as unknown[];\n}\n\ninterface DbRow {\n id: number;\n model: string;\n tokens_prompt: number;\n tokens_generated: number;\n timestamp: string;\n}\n\nfunction readDb(dbPath: string): DbRow[] {\n try {\n return queryDb(dbPath, TOKENS_SQL) as DbRow[];\n } catch (err) {\n if (!isLockError(err)) throw err;\n const snapshotDir = mkdtempSync(join(tmpdir(), \"vibe-usage-kiro-\"));\n const queryPath = join(snapshotDir, \"devdata.sqlite\");\n copyFileSync(dbPath, queryPath);\n for (const suffix of [\"-shm\", \"-wal\"]) {\n const companion = `${dbPath}${suffix}`;\n if (existsSync(companion))\n copyFileSync(companion, `${queryPath}${suffix}`);\n }\n try {\n return queryDb(queryPath, TOKENS_SQL) as DbRow[];\n } finally {\n rmSync(snapshotDir, { recursive: true, force: true });\n }\n }\n}\n\ninterface JsonlRow {\n model?: string;\n promptTokens?: number;\n generatedTokens?: number;\n}\n\nfunction readJsonl(jsonlPath: string): DbRow[] {\n let raw: string;\n try {\n raw = readFileSync(jsonlPath, \"utf-8\");\n } catch {\n return [];\n }\n const lines = raw\n .split(\"\\n\")\n .map((l) => l.trim())\n .filter(Boolean);\n if (lines.length === 0) return [];\n\n let mtime: Date;\n try {\n mtime = statSync(jsonlPath).mtime;\n } catch {\n mtime = new Date();\n }\n const ts = mtime\n .toISOString()\n .replace(\"T\", \" \")\n .replace(\"Z\", \"\")\n .slice(0, 19);\n\n const rows: DbRow[] = [];\n for (let i = 0; i < lines.length; i++) {\n try {\n const obj = JSON.parse(lines[i]) as JsonlRow;\n rows.push({\n id: i + 1,\n model: obj.model || \"agent\",\n tokens_prompt: obj.promptTokens || 0,\n tokens_generated: obj.generatedTokens || 0,\n timestamp: ts,\n });\n } catch {\n // skip malformed lines\n }\n }\n return rows;\n}\n\ninterface ModelWindow {\n startMs: number;\n endMs: number;\n model: string;\n}\n\nfunction buildModelTimeline(base: string): ModelWindow[] {\n const timeline: ModelWindow[] = [];\n let entries: import(\"node:fs\").Dirent[];\n try {\n entries = readdirSync(base, { withFileTypes: true });\n } catch {\n return timeline;\n }\n\n for (const entry of entries) {\n if (!entry.isDirectory() || entry.name === \"dev_data\") continue;\n const dirPath = join(base, entry.name);\n let files: string[];\n try {\n files = readdirSync(dirPath).filter((f) => f.endsWith(\".chat\"));\n } catch {\n continue;\n }\n for (const file of files) {\n try {\n const data = JSON.parse(readFileSync(join(dirPath, file), \"utf-8\"));\n const meta = data?.metadata;\n if (!meta?.modelId || !meta?.startTime) continue;\n const startMs = Number(meta.startTime);\n const endMs = Number(meta.endTime || meta.startTime);\n if (!Number.isFinite(startMs) || !Number.isFinite(endMs)) continue;\n timeline.push({ startMs, endMs, model: String(meta.modelId) });\n } catch {\n // skip unreadable / malformed chat files\n }\n }\n }\n timeline.sort((a, b) => a.startMs - b.startMs);\n return timeline;\n}\n\nfunction resolveModel(timeline: ModelWindow[], ts: Date): string | null {\n if (!timeline.length) return null;\n const t = ts.getTime();\n if (!Number.isFinite(t)) return null;\n\n let best: string | null = null;\n let bestDist = Infinity;\n for (const e of timeline) {\n if (t >= e.startMs && t <= e.endMs) return e.model;\n const d = Math.min(Math.abs(t - e.startMs), Math.abs(t - e.endMs));\n if (d < bestDist) {\n bestDist = d;\n best = e.model;\n }\n }\n return bestDist < 10 * 60 * 1000 ? best : null;\n}\n\nfunction normalizeModelName(raw: string | null | undefined): string | null {\n if (!raw || typeof raw !== \"string\") return null;\n const trimmed = raw.trim();\n if (!trimmed) return null;\n if (trimmed === trimmed.toLowerCase() && trimmed.includes(\"-\"))\n return trimmed;\n const cleaned = trimmed\n .replace(/_\\d{8}_V\\d+_\\d+$/i, \"\")\n .replace(/_V\\d+$/i, \"\")\n .toLowerCase()\n .replace(/_/g, \"-\");\n return cleaned || null;\n}\n\nfunction parseDbTimestamp(value: string | null | undefined): Date | null {\n if (!value) return null;\n const d = new Date(`${String(value).trim().replace(\" \", \"T\")}Z`);\n return Number.isNaN(d.getTime()) ? null : d;\n}\n\nclass KiroParser implements IParser {\n readonly tool = TOOL;\n\n async parse(): Promise<ParseResult> {\n const base = getKiroBasePath();\n if (!base) return { buckets: [], sessions: [] };\n\n const dbPath = join(base, \"dev_data\", \"devdata.sqlite\");\n const jsonlPath = join(base, \"dev_data\", \"tokens_generated.jsonl\");\n\n let rows: DbRow[];\n try {\n if (existsSync(dbPath)) {\n rows = readDb(dbPath);\n } else if (existsSync(jsonlPath)) {\n rows = readJsonl(jsonlPath);\n } else {\n return { buckets: [], sessions: [] };\n }\n } catch (err) {\n if (\n err instanceof Error &&\n typeof err.message === \"string\" &&\n err.message.includes(\"ENOENT\")\n ) {\n throw new Error(\n \"sqlite3 CLI not found. Install sqlite3 to sync Kiro data.\",\n );\n }\n throw err;\n }\n\n if (!rows.length) return { buckets: [], sessions: [] };\n\n const timeline = buildModelTimeline(base);\n const entries: TokenUsageEntry[] = [];\n\n for (const row of rows) {\n const inputTokens = Math.max(0, Number(row.tokens_prompt) || 0);\n const outputTokens = Math.max(0, Number(row.tokens_generated) || 0);\n if (inputTokens === 0 && outputTokens === 0) continue;\n const timestamp = parseDbTimestamp(row.timestamp);\n if (!timestamp) continue;\n\n let model = normalizeModelName(resolveModel(timeline, timestamp));\n if (!model) {\n const literal = (row.model || \"\").trim();\n if (literal && literal.toLowerCase() !== \"agent\") {\n model = normalizeModelName(literal);\n }\n }\n if (!model) model = \"kiro-agent\";\n\n entries.push({\n source: \"kiro\",\n model,\n project: \"unknown\",\n timestamp,\n inputTokens,\n outputTokens,\n reasoningTokens: 0,\n cachedTokens: 0,\n });\n }\n\n return { buckets: aggregateToBuckets(entries), sessions: [] };\n }\n\n isInstalled(): boolean {\n return getKiroBasePath() !== null;\n }\n}\n\nregisterParser(new KiroParser());\n","import { readdirSync, readFileSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { basename, join } from \"node:path\";\nimport { aggregateToBuckets } from \"../domain/aggregator\";\nimport { extractSessions } from \"../domain/session-extractor\";\nimport type {\n ParseResult,\n SessionEvent,\n TokenUsageEntry,\n} from \"../domain/types\";\nimport { registerParser } from \"./registry\";\nimport type { IParser, ToolDefinition } from \"./types\";\n\nconst EXTENSION_ID = \"rooveterinaryinc.roo-cline\";\n\nconst HOSTS = [\n \"Code\",\n \"Cursor\",\n \"Windsurf\",\n \"VSCodium\",\n \"Code - Insiders\",\n \"Trae\",\n \"Trae CN\",\n];\n\nfunction getHostRoots(): string[] {\n const out: string[] = [];\n let roots: string[];\n if (process.platform === \"darwin\") {\n roots = [join(homedir(), \"Library\", \"Application Support\")];\n } else if (process.platform === \"win32\") {\n roots = [\n process.env.APPDATA?.trim() || join(homedir(), \"AppData\", \"Roaming\"),\n ];\n } else {\n roots = [process.env.XDG_CONFIG_HOME?.trim() || join(homedir(), \".config\")];\n }\n for (const root of roots) {\n for (const h of HOSTS) {\n out.push(join(root, h));\n }\n }\n return out;\n}\n\nfunction findExtensionDirs(): string[] {\n const dirs: string[] = [];\n for (const root of getHostRoots()) {\n const ext = join(root, \"User\", \"globalStorage\", EXTENSION_ID);\n try {\n if (statSync(ext).isDirectory()) dirs.push(ext);\n } catch {\n // not installed in this host; skip\n }\n }\n return dirs;\n}\n\nfunction readJsonSafe<T>(path: string): T | null {\n try {\n return JSON.parse(readFileSync(path, \"utf-8\")) as T;\n } catch {\n return null;\n }\n}\n\nfunction projectFromPath(absPath: string | undefined): string {\n if (!absPath || typeof absPath !== \"string\") return \"unknown\";\n const trimmed = absPath.replace(/[\\\\/]+$/, \"\");\n const name = basename(trimmed);\n return name || \"unknown\";\n}\n\ninterface HistoryItem {\n id: string | number;\n workspace?: string;\n apiConfigName?: string;\n}\n\ninterface UiMessage {\n type?: string;\n say?: string;\n ts?: number;\n text?: string;\n}\n\nfunction readHistoryItems(extDir: string): HistoryItem[] {\n const tasksDir = join(extDir, \"tasks\");\n const index = readJsonSafe<{ entries?: HistoryItem[] }>(\n join(tasksDir, \"_index.json\"),\n );\n if (index?.entries && Array.isArray(index.entries)) return index.entries;\n\n const items: HistoryItem[] = [];\n let names: import(\"node:fs\").Dirent[];\n try {\n names = readdirSync(tasksDir, { withFileTypes: true });\n } catch {\n return items;\n }\n for (const entry of names) {\n if (\n !entry.isDirectory() ||\n entry.name.startsWith(\"_\") ||\n entry.name.startsWith(\".\")\n )\n continue;\n const item = readJsonSafe<HistoryItem>(\n join(tasksDir, entry.name, \"history_item.json\"),\n );\n if (item && typeof item === \"object\") items.push(item);\n }\n return items;\n}\n\nconst TOOL: ToolDefinition = {\n id: \"roo-code\",\n name: \"Roo Code\",\n dataDir: getHostRoots()[0] ?? \"\",\n};\n\nclass RooCodeParser implements IParser {\n readonly tool = TOOL;\n\n async parse(): Promise<ParseResult> {\n const extDirs = findExtensionDirs();\n if (extDirs.length === 0) return { buckets: [], sessions: [] };\n\n const entries: TokenUsageEntry[] = [];\n const events: SessionEvent[] = [];\n\n for (const extDir of extDirs) {\n const items = readHistoryItems(extDir);\n if (!items.length) continue;\n\n for (const item of items) {\n if (!item || typeof item !== \"object\" || !item.id) continue;\n const taskId = String(item.id);\n const project = projectFromPath(item.workspace);\n const fallbackModel =\n (item.apiConfigName && String(item.apiConfigName).trim()) ||\n \"roo-unknown\";\n\n const messages = readJsonSafe<UiMessage[]>(\n join(extDir, \"tasks\", taskId, \"ui_messages.json\"),\n );\n if (!Array.isArray(messages)) continue;\n\n for (const msg of messages) {\n if (!msg || typeof msg !== \"object\") continue;\n const ts = Number(msg.ts);\n if (!Number.isFinite(ts)) continue;\n const timestamp = new Date(ts);\n\n if (msg.type === \"say\" && msg.say === \"api_req_started\") {\n let info: {\n tokensIn?: number;\n tokensOut?: number;\n cacheWrites?: number;\n cacheReads?: number;\n model?: string;\n } | null = null;\n try {\n info = JSON.parse(msg.text ?? \"\");\n } catch {\n // skip\n }\n if (!info) continue;\n\n const inputTokens = Math.max(0, Number(info.tokensIn) || 0);\n const outputTokens = Math.max(0, Number(info.tokensOut) || 0);\n const cacheWrites = Math.max(0, Number(info.cacheWrites) || 0);\n const cacheReads = Math.max(0, Number(info.cacheReads) || 0);\n if (inputTokens + outputTokens + cacheWrites + cacheReads === 0)\n continue;\n\n const model =\n (info.model && String(info.model).trim()) || fallbackModel;\n\n entries.push({\n sessionId: taskId,\n source: \"roo-code\",\n model,\n project,\n timestamp,\n inputTokens: inputTokens + cacheWrites,\n outputTokens,\n reasoningTokens: 0,\n cachedTokens: cacheReads,\n });\n events.push({\n sessionId: taskId,\n source: \"roo-code\",\n project,\n timestamp,\n role: \"assistant\",\n });\n } else if (\n msg.type === \"ask\" ||\n (msg.type === \"say\" && msg.say === \"user_feedback\")\n ) {\n events.push({\n sessionId: taskId,\n source: \"roo-code\",\n project,\n timestamp,\n role: \"user\",\n });\n }\n }\n }\n }\n\n return {\n buckets: aggregateToBuckets(entries),\n sessions: extractSessions(events, entries),\n };\n }\n\n isInstalled(): boolean {\n return findExtensionDirs().length > 0;\n }\n}\n\nregisterParser(new RooCodeParser());\n","import { execFileSync } from \"node:child_process\";\nimport { copyFileSync, existsSync, mkdtempSync, rmSync } from \"node:fs\";\nimport { homedir, tmpdir } from \"node:os\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { aggregateToBuckets } from \"../domain/aggregator\";\nimport type { ParseResult, TokenUsageEntry } from \"../domain/types\";\nimport { registerParser } from \"./registry\";\nimport type { IParser, ToolDefinition } from \"./types\";\n\nconst TOOL_ID = \"cursor\";\nconst TOOL_NAME = \"Cursor\";\nconst STATE_DB_RELATIVE = join(\"User\", \"globalStorage\", \"state.vscdb\");\nconst ACCESS_TOKEN_KEY = \"cursorAuth/accessToken\";\nconst SESSION_COOKIE = \"WorkosCursorSessionToken\";\nconst FETCH_TIMEOUT_MS = 10_000;\n\nfunction getDefaultStateDbPath(): string {\n if (process.platform === \"darwin\") {\n return join(\n homedir(),\n \"Library\",\n \"Application Support\",\n \"Cursor\",\n STATE_DB_RELATIVE,\n );\n }\n if (process.platform === \"win32\") {\n const appData =\n process.env.APPDATA?.trim() || join(homedir(), \"AppData\", \"Roaming\");\n return join(appData, \"Cursor\", STATE_DB_RELATIVE);\n }\n const xdgConfigHome =\n process.env.XDG_CONFIG_HOME?.trim() || join(homedir(), \".config\");\n return join(xdgConfigHome, \"Cursor\", STATE_DB_RELATIVE);\n}\n\nfunction getCursorStateDbPath(): string | null {\n const explicit = process.env.CURSOR_STATE_DB_PATH?.trim();\n if (explicit) {\n const resolved = resolve(explicit);\n return existsSync(resolved) ? resolved : null;\n }\n\n const configDirs = process.env.CURSOR_CONFIG_DIR?.trim();\n const candidates = configDirs\n ? configDirs\n .split(\",\")\n .map((v) => v.trim())\n .filter(Boolean)\n .map((v) => {\n const r = resolve(v);\n return r.endsWith(\".vscdb\") ? r : join(r, STATE_DB_RELATIVE);\n })\n : [getDefaultStateDbPath()];\n\n for (const c of candidates) {\n if (existsSync(c)) return c;\n }\n return null;\n}\n\nfunction queryAccessToken(dbPath: string): string | null {\n const sql = `SELECT value FROM ItemTable WHERE key = '${ACCESS_TOKEN_KEY}' LIMIT 1`;\n const candidates = [\n process.env.TOKEN_ARENA_SQLITE3,\n \"sqlite3\",\n \"sqlite3.exe\",\n ].filter((value): value is string => Boolean(value));\n\n for (const command of candidates) {\n try {\n const out = execFileSync(command, [\"-json\", dbPath, sql], {\n encoding: \"utf-8\",\n maxBuffer: 4 * 1024 * 1024,\n timeout: 15000,\n windowsHide: true,\n }).trim();\n\n if (!out || out === \"[]\") continue;\n const rows = JSON.parse(out) as Array<{ value?: string }>;\n const value = rows[0]?.value;\n if (typeof value !== \"string\") continue;\n const token = value.trim();\n if (token) return token;\n } catch (err) {\n const nodeError = err as NodeJS.ErrnoException & { status?: number };\n if (nodeError.status === 127 || nodeError.message?.includes(\"ENOENT\")) {\n continue;\n }\n throw err;\n }\n }\n return null;\n}\n\nfunction readAccessToken(dbPath: string): string | null {\n try {\n return queryAccessToken(dbPath);\n } catch (err) {\n if (!isLockError(err)) throw err;\n\n const snapshotDir = mkdtempSync(join(tmpdir(), \"tokenarena-cursor-\"));\n const queryPath = join(snapshotDir, \"state.vscdb\");\n try {\n copyFileSync(dbPath, queryPath);\n for (const suffix of [\"-shm\", \"-wal\"]) {\n const companion = `${dbPath}${suffix}`;\n if (existsSync(companion))\n copyFileSync(companion, `${queryPath}${suffix}`);\n }\n return queryAccessToken(queryPath);\n } finally {\n rmSync(snapshotDir, { recursive: true, force: true });\n }\n }\n}\n\nfunction isLockError(err: unknown): boolean {\n return err instanceof Error && /database is locked/i.test(err.message);\n}\n\nfunction decodeJwtSub(token: string): string | null {\n const payload = token.split(\".\")[1];\n if (!payload) return null;\n try {\n const b64 = payload.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded = b64.padEnd(Math.ceil(b64.length / 4) * 4, \"=\");\n const json = JSON.parse(Buffer.from(padded, \"base64\").toString(\"utf-8\"));\n return typeof json.sub === \"string\" ? json.sub.trim() : null;\n } catch {\n return null;\n }\n}\n\nasync function fetchUsageCsv(token: string): Promise<string> {\n const baseUrl = (\n process.env.CURSOR_WEB_BASE_URL?.trim() || \"https://cursor.com\"\n ).replace(/\\/+$/, \"\");\n const url = `${baseUrl}/api/dashboard/export-usage-events-csv?strategy=tokens`;\n const sub = decodeJwtSub(token);\n const cookieValues = sub ? [token, `${sub}::${token}`] : [token];\n\n const attempts: Array<Record<string, string>> = [\n { Authorization: `Bearer ${token}` },\n ];\n for (const cv of cookieValues) {\n attempts.push({ Cookie: `${SESSION_COOKIE}=${cv}` });\n attempts.push({\n Authorization: `Bearer ${token}`,\n Cookie: `${SESSION_COOKIE}=${cv}`,\n });\n }\n\n const failures: string[] = [];\n for (const headers of attempts) {\n let resp: Response;\n try {\n resp = await fetch(url, {\n headers: { Accept: \"text/csv,*/*;q=0.8\", ...headers },\n signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n });\n } catch (e) {\n const reason =\n e instanceof Error && e.name === \"TimeoutError\"\n ? \"timeout\"\n : `network: ${(e as Error).message}`;\n const err = new Error(`Cursor usage export skipped (${reason})`);\n (err as { skip?: boolean }).skip = true;\n throw err;\n }\n if (resp.ok) return await resp.text();\n failures.push(`${resp.status} ${resp.statusText}`);\n }\n\n throw new Error(`Cursor usage export auth failed (${failures.join(\"; \")})`);\n}\n\nfunction parseCsv(text: string): string[][] {\n const rows: string[][] = [];\n let field = \"\";\n let row: string[] = [];\n let inQuotes = false;\n let i = 0;\n\n while (i < text.length) {\n const c = text[i];\n if (inQuotes) {\n if (c === '\"') {\n if (text[i + 1] === '\"') {\n field += '\"';\n i += 2;\n continue;\n }\n inQuotes = false;\n i++;\n continue;\n }\n field += c;\n i++;\n continue;\n }\n if (c === '\"') {\n inQuotes = true;\n i++;\n continue;\n }\n if (c === \",\") {\n row.push(field);\n field = \"\";\n i++;\n continue;\n }\n if (c === \"\\r\") {\n i++;\n continue;\n }\n if (c === \"\\n\") {\n row.push(field);\n rows.push(row);\n field = \"\";\n row = [];\n i++;\n continue;\n }\n field += c;\n i++;\n }\n\n if (field !== \"\" || row.length > 0) {\n row.push(field);\n rows.push(row);\n }\n\n return rows;\n}\n\nfunction parseDate(value: string | undefined): Date | null {\n if (!value) return null;\n const t = String(value).trim();\n if (!t) return null;\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(t)) return new Date(`${t}T00:00:00Z`);\n const d = new Date(t);\n return Number.isNaN(d.getTime()) ? null : d;\n}\n\nfunction parseInt0(value: string | undefined): number {\n if (value == null) return 0;\n const n = Number(String(value).replace(/,/g, \"\").trim());\n return Number.isFinite(n) && n > 0 ? Math.round(n) : 0;\n}\n\nexport interface CursorParserOptions {\n dbPath?: string;\n readToken?: (dbPath: string) => string | null;\n fetchCsv?: (token: string) => Promise<string>;\n}\n\nfunction createToolDefinition(dbPath: string): ToolDefinition {\n return {\n id: TOOL_ID,\n name: TOOL_NAME,\n dataDir: dirname(dbPath),\n };\n}\n\nexport class CursorParser implements IParser {\n readonly tool: ToolDefinition;\n private readonly dbPath: string;\n private readonly readToken: (dbPath: string) => string | null;\n private readonly fetchCsv: (token: string) => Promise<string>;\n\n constructor(options: CursorParserOptions = {}) {\n this.dbPath = options.dbPath || getCursorStateDbPath() || \"\";\n this.readToken = options.readToken || readAccessToken;\n this.fetchCsv = options.fetchCsv || fetchUsageCsv;\n this.tool = createToolDefinition(this.dbPath);\n }\n\n async parse(): Promise<ParseResult> {\n if (!this.dbPath || !existsSync(this.dbPath)) {\n return { buckets: [], sessions: [] };\n }\n\n let token: string | null;\n try {\n token = this.readToken(this.dbPath);\n } catch (err) {\n if (err instanceof Error && err.message.includes(\"ENOENT\")) {\n throw new Error(\n \"sqlite3 CLI not found. Install sqlite3 to sync Cursor data.\",\n );\n }\n throw err;\n }\n if (!token) return { buckets: [], sessions: [] };\n\n let csv: string;\n try {\n csv = await this.fetchCsv(token);\n } catch (err) {\n if ((err as { skip?: boolean }).skip)\n return { buckets: [], sessions: [] };\n throw err;\n }\n\n const rows = parseCsv(csv);\n if (rows.length < 2) return { buckets: [], sessions: [] };\n\n const header = rows[0].map((h) => h.trim());\n const idx = (name: string) => header.indexOf(name);\n const dateIdx = idx(\"Date\");\n const modelIdx = idx(\"Model\");\n const inputCacheWriteIdx = idx(\"Input (w/ Cache Write)\");\n const inputNoCacheIdx = idx(\"Input (w/o Cache Write)\");\n const cacheReadIdx = idx(\"Cache Read\");\n const outputIdx = idx(\"Output Tokens\");\n\n if (dateIdx < 0 || modelIdx < 0) return { buckets: [], sessions: [] };\n\n const entries: TokenUsageEntry[] = [];\n for (let r = 1; r < rows.length; r++) {\n const row = rows[r];\n if (row.length === 1 && row[0].trim() === \"\") continue;\n\n const timestamp = parseDate(row[dateIdx]);\n const model = row[modelIdx]?.trim();\n if (!timestamp || !model) continue;\n\n const inputCacheWrite =\n inputCacheWriteIdx >= 0 ? parseInt0(row[inputCacheWriteIdx]) : 0;\n const inputNoCache =\n inputNoCacheIdx >= 0 ? parseInt0(row[inputNoCacheIdx]) : 0;\n const cacheRead = cacheReadIdx >= 0 ? parseInt0(row[cacheReadIdx]) : 0;\n const output = outputIdx >= 0 ? parseInt0(row[outputIdx]) : 0;\n\n if (inputCacheWrite + inputNoCache + cacheRead + output === 0) continue;\n\n entries.push({\n source: TOOL_ID,\n model,\n project: \"unknown\",\n timestamp,\n inputTokens: inputCacheWrite + inputNoCache,\n outputTokens: output,\n cachedTokens: cacheRead,\n reasoningTokens: 0,\n });\n }\n\n return {\n buckets: aggregateToBuckets(entries),\n sessions: [],\n };\n }\n\n isInstalled(): boolean {\n return existsSync(this.dbPath);\n }\n}\n\nregisterParser(new CursorParser());\n","import { createHash } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { homedir, hostname } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { aggregateToBuckets } from \"../domain/aggregator\";\nimport { hasInvalidTokenCounts } from \"../domain/token-usage\";\nimport type {\n ParseResult,\n SessionMetadata,\n SessionModelUsage,\n TokenUsageEntry,\n} from \"../domain/types\";\nimport { readSqliteRows, type SqliteQueryRows } from \"../infrastructure/sqlite\";\nimport { registerParser } from \"./registry\";\nimport type { IParser, ToolDefinition } from \"./types\";\n\nconst TOOL_ID = \"zcode\";\nconst TOOL_NAME = \"ZCode\";\nconst DEFAULT_DB_PATH = join(homedir(), \".zcode\", \"cli\", \"db\", \"db.sqlite\");\n\nconst MODEL_USAGE_QUERY = `SELECT\n model_usage.session_id as sessionId,\n session.directory as directory,\n model_usage.model_id as model,\n model_usage.started_at as startedAt,\n model_usage.input_tokens as inputTokens,\n model_usage.output_tokens as outputTokens,\n model_usage.reasoning_tokens as reasoningTokens,\n model_usage.cache_read_input_tokens as cacheReadInputTokens\n FROM model_usage\n LEFT JOIN session ON session.id = model_usage.session_id\n WHERE model_usage.input_tokens > 0\n OR model_usage.output_tokens > 0\n OR model_usage.reasoning_tokens > 0\n OR model_usage.cache_read_input_tokens > 0`;\n\nconst SESSION_QUERY = `SELECT\n id,\n directory,\n time_created as timeCreated,\n time_updated as timeUpdated\n FROM session`;\n\nconst MESSAGE_QUERY = `SELECT\n session_id as sessionId,\n time_created as timeCreated,\n data\n FROM message\n ORDER BY time_created`;\n\nconst TURN_USAGE_QUERY = `SELECT\n session_id as sessionId,\n duration_ms as durationMs\n FROM turn_usage\n WHERE duration_ms IS NOT NULL`;\n\ninterface ZCodeModelUsageRow {\n sessionId?: unknown;\n directory?: unknown;\n model?: unknown;\n startedAt?: unknown;\n inputTokens?: unknown;\n outputTokens?: unknown;\n reasoningTokens?: unknown;\n cacheReadInputTokens?: unknown;\n}\n\ninterface ZCodeSessionRow {\n id?: unknown;\n directory?: unknown;\n timeCreated?: unknown;\n timeUpdated?: unknown;\n}\n\ninterface ZCodeMessageRow {\n sessionId?: unknown;\n timeCreated?: unknown;\n data?: unknown;\n}\n\ninterface ZCodeTurnUsageRow {\n sessionId?: unknown;\n durationMs?: unknown;\n}\n\ninterface ZCodeMessageData {\n role?: unknown;\n time?: {\n created?: unknown;\n };\n}\n\ntype ZCodeSessionDraft = {\n sessionId: string;\n source: string;\n project: string;\n firstMessageAt: Date | null;\n lastMessageAt: Date | null;\n fallbackFirstAt: Date | null;\n fallbackLastAt: Date | null;\n activeSeconds: number;\n messageCount: number;\n userMessageCount: number;\n userPromptHours: number[];\n};\n\nexport interface ZCodeParserOptions {\n dbPath?: string;\n queryRows?: SqliteQueryRows;\n}\n\nfunction createToolDefinition(dbPath: string): ToolDefinition {\n return {\n id: TOOL_ID,\n name: TOOL_NAME,\n dataDir: dirname(dbPath),\n };\n}\n\nfunction toSafeNumber(value: unknown): number {\n const numberValue = Number(value);\n return Number.isFinite(numberValue) && numberValue > 0 ? numberValue : 0;\n}\n\nfunction getString(value: unknown): string | null {\n return typeof value === \"string\" && value.length > 0 ? value : null;\n}\n\nfunction parseUnixMillis(value: unknown): Date | null {\n const numberValue = Number(value);\n if (!Number.isFinite(numberValue)) {\n return null;\n }\n\n const timestamp = new Date(numberValue);\n return Number.isNaN(timestamp.getTime()) ? null : timestamp;\n}\n\nfunction getPathLeaf(value: string | null): string {\n if (!value) {\n return \"unknown\";\n }\n\n const normalized = value.replace(/\\\\/g, \"/\").replace(/\\/+$/, \"\");\n const leaf = normalized.split(\"/\").filter(Boolean).pop();\n return leaf || \"unknown\";\n}\n\nfunction parseMessageData(value: unknown): ZCodeMessageData | null {\n if (typeof value !== \"string\" || value.length === 0) {\n return null;\n }\n\n try {\n const parsed = JSON.parse(value) as ZCodeMessageData;\n return parsed && typeof parsed === \"object\" ? parsed : null;\n } catch {\n return null;\n }\n}\n\nfunction getOrCreateDraft(\n drafts: Map<string, ZCodeSessionDraft>,\n sessionId: string,\n project: string,\n): ZCodeSessionDraft {\n const existing = drafts.get(sessionId);\n if (existing) {\n if (existing.project === \"unknown\" && project !== \"unknown\") {\n existing.project = project;\n }\n return existing;\n }\n\n const next: ZCodeSessionDraft = {\n sessionId,\n source: TOOL_ID,\n project,\n firstMessageAt: null,\n lastMessageAt: null,\n fallbackFirstAt: null,\n fallbackLastAt: null,\n activeSeconds: 0,\n messageCount: 0,\n userMessageCount: 0,\n userPromptHours: new Array(24).fill(0),\n };\n\n drafts.set(sessionId, next);\n return next;\n}\n\nfunction buildSessionUsage(entries: TokenUsageEntry[]) {\n const usageBySession = new Map<string, Map<string, SessionModelUsage>>();\n\n for (const entry of entries) {\n if (!entry.sessionId || hasInvalidTokenCounts(entry)) {\n continue;\n }\n\n let byModel = usageBySession.get(entry.sessionId);\n if (!byModel) {\n byModel = new Map<string, SessionModelUsage>();\n usageBySession.set(entry.sessionId, byModel);\n }\n\n const totalTokens =\n entry.inputTokens +\n entry.outputTokens +\n entry.reasoningTokens +\n entry.cachedTokens;\n const existing = byModel.get(entry.model);\n\n if (existing) {\n existing.inputTokens += entry.inputTokens;\n existing.outputTokens += entry.outputTokens;\n existing.reasoningTokens += entry.reasoningTokens;\n existing.cachedTokens += entry.cachedTokens;\n existing.totalTokens += totalTokens;\n continue;\n }\n\n byModel.set(entry.model, {\n model: entry.model,\n inputTokens: entry.inputTokens,\n outputTokens: entry.outputTokens,\n reasoningTokens: entry.reasoningTokens,\n cachedTokens: entry.cachedTokens,\n totalTokens,\n });\n }\n\n return usageBySession;\n}\n\nfunction buildSessions(input: {\n sessionRows: ZCodeSessionRow[];\n messageRows: ZCodeMessageRow[];\n turnRows: ZCodeTurnUsageRow[];\n entries: TokenUsageEntry[];\n}): SessionMetadata[] {\n const drafts = new Map<string, ZCodeSessionDraft>();\n\n for (const row of input.sessionRows) {\n const sessionId = getString(row.id);\n if (!sessionId) {\n continue;\n }\n\n const draft = getOrCreateDraft(\n drafts,\n sessionId,\n getPathLeaf(getString(row.directory)),\n );\n draft.fallbackFirstAt = parseUnixMillis(row.timeCreated);\n draft.fallbackLastAt = parseUnixMillis(row.timeUpdated);\n }\n\n for (const row of input.messageRows) {\n const sessionId = getString(row.sessionId);\n if (!sessionId) {\n continue;\n }\n\n const data = parseMessageData(row.data);\n const role =\n data?.role === \"user\" || data?.role === \"assistant\" ? data.role : null;\n if (!role) {\n continue;\n }\n\n const timestamp =\n parseUnixMillis(data?.time?.created) ?? parseUnixMillis(row.timeCreated);\n if (!timestamp) {\n continue;\n }\n\n const draft = getOrCreateDraft(drafts, sessionId, \"unknown\");\n draft.messageCount += 1;\n\n if (!draft.firstMessageAt || timestamp < draft.firstMessageAt) {\n draft.firstMessageAt = timestamp;\n }\n if (!draft.lastMessageAt || timestamp > draft.lastMessageAt) {\n draft.lastMessageAt = timestamp;\n }\n\n if (role === \"user\") {\n draft.userMessageCount += 1;\n draft.userPromptHours[timestamp.getUTCHours()] += 1;\n }\n }\n\n for (const row of input.turnRows) {\n const sessionId = getString(row.sessionId);\n if (!sessionId) {\n continue;\n }\n\n const draft = getOrCreateDraft(drafts, sessionId, \"unknown\");\n draft.activeSeconds += Math.round(toSafeNumber(row.durationMs) / 1000);\n }\n\n const usageBySession = buildSessionUsage(input.entries);\n const host = hostname().replace(/\\.local$/, \"\");\n\n return Array.from(drafts.values())\n .map((draft) => {\n const firstMessageAt = draft.firstMessageAt ?? draft.fallbackFirstAt;\n const lastMessageAt =\n draft.lastMessageAt ?? draft.fallbackLastAt ?? firstMessageAt;\n\n if (!firstMessageAt || !lastMessageAt) {\n return null;\n }\n\n const modelUsages = Array.from(\n usageBySession.get(draft.sessionId)?.values() ?? [],\n ).sort((left, right) => {\n if (right.totalTokens !== left.totalTokens) {\n return right.totalTokens - left.totalTokens;\n }\n\n return left.model.localeCompare(right.model);\n });\n const inputTokens = modelUsages.reduce(\n (sum, usage) => sum + usage.inputTokens,\n 0,\n );\n const outputTokens = modelUsages.reduce(\n (sum, usage) => sum + usage.outputTokens,\n 0,\n );\n const reasoningTokens = modelUsages.reduce(\n (sum, usage) => sum + usage.reasoningTokens,\n 0,\n );\n const cachedTokens = modelUsages.reduce(\n (sum, usage) => sum + usage.cachedTokens,\n 0,\n );\n const totalTokens = modelUsages.reduce(\n (sum, usage) => sum + usage.totalTokens,\n 0,\n );\n const durationSeconds = Math.max(\n 0,\n Math.round((lastMessageAt.getTime() - firstMessageAt.getTime()) / 1000),\n );\n\n return {\n source: draft.source,\n project: draft.project,\n sessionHash: createHash(\"sha256\")\n .update(draft.sessionId)\n .digest(\"hex\")\n .slice(0, 16),\n hostname: host,\n firstMessageAt: firstMessageAt.toISOString(),\n lastMessageAt: lastMessageAt.toISOString(),\n durationSeconds,\n activeSeconds: draft.activeSeconds,\n messageCount: draft.messageCount,\n userMessageCount: draft.userMessageCount,\n userPromptHours: draft.userPromptHours,\n inputTokens,\n outputTokens,\n reasoningTokens,\n cachedTokens,\n totalTokens,\n primaryModel: modelUsages[0]?.model ?? \"\",\n modelUsages,\n } satisfies SessionMetadata;\n })\n .filter((session): session is SessionMetadata => session !== null);\n}\n\nexport class ZCodeParser implements IParser {\n readonly tool: ToolDefinition;\n private readonly dbPath: string;\n private readonly queryRows: SqliteQueryRows;\n\n constructor(options: ZCodeParserOptions = {}) {\n this.dbPath = options.dbPath || DEFAULT_DB_PATH;\n this.queryRows = options.queryRows || readSqliteRows;\n this.tool = createToolDefinition(this.dbPath);\n }\n\n async parse(): Promise<ParseResult> {\n if (!existsSync(this.dbPath)) {\n return { buckets: [], sessions: [] };\n }\n\n const usageRows = await this.queryRows<ZCodeModelUsageRow>(\n this.dbPath,\n MODEL_USAGE_QUERY,\n );\n const entries: TokenUsageEntry[] = [];\n\n for (const row of usageRows) {\n const timestamp = parseUnixMillis(row.startedAt);\n if (!timestamp) {\n continue;\n }\n\n const inputTokens = toSafeNumber(row.inputTokens);\n const outputTokens = toSafeNumber(row.outputTokens);\n const reasoningTokens = toSafeNumber(row.reasoningTokens);\n const cachedTokens = toSafeNumber(row.cacheReadInputTokens);\n\n if (\n inputTokens === 0 &&\n outputTokens === 0 &&\n reasoningTokens === 0 &&\n cachedTokens === 0\n ) {\n continue;\n }\n\n entries.push({\n sessionId: getString(row.sessionId) ?? undefined,\n source: TOOL_ID,\n model: getString(row.model) ?? \"unknown\",\n project: getPathLeaf(getString(row.directory)),\n timestamp,\n inputTokens,\n outputTokens,\n reasoningTokens,\n cachedTokens,\n });\n }\n\n let sessionRows: ZCodeSessionRow[] = [];\n let messageRows: ZCodeMessageRow[] = [];\n let turnRows: ZCodeTurnUsageRow[] = [];\n\n try {\n [sessionRows, messageRows, turnRows] = await Promise.all([\n this.queryRows<ZCodeSessionRow>(this.dbPath, SESSION_QUERY),\n this.queryRows<ZCodeMessageRow>(this.dbPath, MESSAGE_QUERY),\n this.queryRows<ZCodeTurnUsageRow>(this.dbPath, TURN_USAGE_QUERY),\n ]);\n } catch {\n return {\n buckets: aggregateToBuckets(entries),\n sessions: [],\n };\n }\n\n return {\n buckets: aggregateToBuckets(entries),\n sessions: buildSessions({\n sessionRows,\n messageRows,\n turnRows,\n entries,\n }),\n };\n }\n\n isInstalled(): boolean {\n return existsSync(this.dbPath);\n }\n}\n\nregisterParser(new ZCodeParser());\n","import { Command, Option } from \"commander\";\nimport { handleConfig } from \"./commands/config\";\nimport { runDaemon } from \"./commands/daemon\";\nimport { runHome } from \"./commands/home\";\nimport { runInit } from \"./commands/init\";\nimport { runServiceCommand } from \"./commands/service\";\nimport { runStatus } from \"./commands/status\";\nimport { runSyncCommand } from \"./commands/sync\";\nimport { runUninstall } from \"./commands/uninstall\";\nimport { getCliVersion } from \"./infrastructure/runtime/cli-version\";\nimport { isInteractiveTerminal } from \"./infrastructure/ui/prompts\";\n\nconst CLI_VERSION = getCliVersion();\n\nexport function createCli(): Command {\n const program = new Command();\n\n program\n .name(\"tokenarena\")\n .description(\"Track token burn across AI coding tools\")\n .version(CLI_VERSION)\n .showHelpAfterError()\n .showSuggestionAfterError()\n .helpCommand(\"help [command]\", \"Display help for command\");\n\n // Default action: show help or error for unknown commands\n program.action(async () => {\n const userArgs = process.argv.slice(2).filter((a) => !a.startsWith(\"-\"));\n if (userArgs.length > 0) {\n program.error(`unknown command '${userArgs[0]}'`);\n }\n if (isInteractiveTerminal()) {\n await runHome(program);\n return;\n }\n program.help();\n });\n\n // init command\n program\n .command(\"init\")\n .description(\"Initialize configuration with API key\")\n .option(\"--api-url <url>\", \"Custom API server URL\")\n .action(async (opts) => {\n await runInit(opts);\n });\n\n // sync command\n program\n .command(\"sync\")\n .description(\"Manually sync usage data to server\")\n .addOption(new Option(\"--quiet\").hideHelp())\n .action(async (opts) => {\n await runSyncCommand(opts);\n });\n\n // daemon command\n program\n .command(\"daemon\")\n .description(\"Run continuous sync (every 30 minutes by default)\")\n .option(\"--interval <ms>\", \"Sync interval in milliseconds\", parseInt)\n .addOption(new Option(\"--service\").hideHelp())\n .action(async (opts) => {\n await runDaemon(opts);\n });\n\n // service command\n program\n .command(\"service [action]\")\n .description(\n \"Manage background service (setup|start|stop|restart|status|uninstall)\",\n )\n .action(async (action) => {\n await runServiceCommand({ action });\n });\n\n // status command\n program\n .command(\"status\")\n .description(\"Show configuration and detected tools\")\n .option(\"--show\", \"Show interactive local usage dashboard\")\n .action(async (opts) => {\n await runStatus(opts);\n });\n\n // config command (with subcommands)\n program\n .command(\"config\")\n .description(\"Manage configuration\")\n .argument(\"[subcommand]\", \"get|set|show\")\n .argument(\"[key]\", \"Config key\")\n .argument(\"[value]\", \"Config value\")\n .allowUnknownOption(true)\n .action(async (subcommand, key, value) => {\n await handleConfig(\n [subcommand, key, value].filter(\n (item): item is string => typeof item === \"string\",\n ),\n );\n });\n\n // uninstall command\n program\n .command(\"uninstall\")\n .description(\"Remove all local configuration and data\")\n .action(async () => {\n await runUninstall();\n });\n\n return program;\n}\n","import { randomUUID } from \"node:crypto\";\nimport {\n existsSync,\n mkdirSync,\n readFileSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\nimport { getConfigHome } from \"../xdg\";\n\nexport interface Config {\n apiKey: string;\n apiUrl: string;\n deviceId?: string;\n syncInterval?: number;\n logLevel?: \"debug\" | \"info\" | \"warn\" | \"error\";\n}\n\nconst CONFIG_DIR = join(getConfigHome(), \"tokenarena\");\nconst isDev = process.env.TOKEN_ARENA_DEV === \"1\";\nconst CONFIG_FILE = join(CONFIG_DIR, isDev ? \"config.dev.json\" : \"config.json\");\n\nconst DEFAULT_API_URL = \"https://token.guji.uno\";\nconst VALID_CONFIG_KEYS = [\n \"apiKey\",\n \"apiUrl\",\n \"deviceId\",\n \"syncInterval\",\n \"logLevel\",\n];\n\nexport function getConfigPath(): string {\n return CONFIG_FILE;\n}\n\nexport function getConfigDir(): string {\n return CONFIG_DIR;\n}\n\nexport function loadConfig(): Config | null {\n if (!existsSync(CONFIG_FILE)) return null;\n try {\n const raw = readFileSync(CONFIG_FILE, \"utf-8\");\n const config = JSON.parse(raw) as Config;\n // Ensure apiUrl has a default\n if (!config.apiUrl) {\n config.apiUrl = DEFAULT_API_URL;\n }\n return config;\n } catch {\n return null;\n }\n}\n\nexport function saveConfig(config: Config): void {\n mkdirSync(CONFIG_DIR, { recursive: true });\n writeFileSync(CONFIG_FILE, `${JSON.stringify(config, null, 2)}\\n`, \"utf-8\");\n}\n\nexport function deleteConfig(): void {\n if (existsSync(CONFIG_FILE)) {\n unlinkSync(CONFIG_FILE);\n }\n}\n\nexport function getOrCreateDeviceId(config: Config): string {\n if (config.deviceId) return config.deviceId;\n\n const next = randomUUID();\n saveConfig({ ...config, deviceId: next });\n\n return next;\n}\n\nexport function validateApiKey(key: string): boolean {\n return key.startsWith(\"ta_\");\n}\n\nexport function isValidConfigKey(key: string): boolean {\n return VALID_CONFIG_KEYS.includes(key);\n}\n\nexport function getDefaultApiUrl(): string {\n return process.env.TOKEN_ARENA_API_URL || DEFAULT_API_URL;\n}\n","import { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\n/**\n * XDG Base Directory specification helpers.\n * @see https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html\n */\n\n/** User-specific configuration directory (`XDG_CONFIG_HOME`, default `~/.config`) */\nexport function getConfigHome(): string {\n return process.env.XDG_CONFIG_HOME || join(homedir(), \".config\");\n}\n\n/** User-specific data directory (`XDG_DATA_HOME`, default `~/.local/share`) */\nexport function getDataHome(): string {\n return process.env.XDG_DATA_HOME || join(homedir(), \".local\", \"share\");\n}\n\n/** User-specific cache directory (`XDG_CACHE_HOME`, default `~/.cache`) */\nexport function getCacheHome(): string {\n return process.env.XDG_CACHE_HOME || join(homedir(), \".cache\");\n}\n\n/** User-specific state directory (`XDG_STATE_HOME`, default `~/.local/state`) */\nexport function getStateHome(): string {\n return process.env.XDG_STATE_HOME || join(homedir(), \".local\", \"state\");\n}\n\n/**\n * User-specific runtime directory (`XDG_RUNTIME_DIR`).\n * Falls back to state home when not set (e.g. on macOS).\n */\nexport function getRuntimeDir(): string {\n return process.env.XDG_RUNTIME_DIR || getStateHome();\n}\n","const hasColor = Boolean(process.stdout.isTTY && process.env.NO_COLOR !== \"1\");\n\nfunction withCode(code: string, value: string): string {\n if (!hasColor) return value;\n return `\\u001b[${code}m${value}\\u001b[0m`;\n}\n\nexport function bold(value: string): string {\n return withCode(\"1\", value);\n}\n\nexport function dim(value: string): string {\n return withCode(\"2\", value);\n}\n\nexport function cyan(value: string): string {\n return withCode(\"36\", value);\n}\n\nexport function green(value: string): string {\n return withCode(\"32\", value);\n}\n\nexport function yellow(value: string): string {\n return withCode(\"33\", value);\n}\n\nexport function red(value: string): string {\n return withCode(\"31\", value);\n}\n\nexport function magenta(value: string): string {\n return withCode(\"35\", value);\n}\n\nexport function formatHeader(title: string, subtitle?: string): string {\n const lines = [`${cyan(\"◈\")} ${bold(title)}`];\n if (subtitle) {\n lines.push(dim(subtitle));\n }\n return `\\n${lines.join(\"\\n\")}`;\n}\n\nexport function formatSection(title: string): string {\n return `\\n${bold(title)}`;\n}\n\nexport function formatKeyValue(label: string, value: string): string {\n return ` ${dim(label.padEnd(14, \" \"))} ${value}`;\n}\n\nexport function formatBullet(\n value: string,\n tone: \"neutral\" | \"success\" | \"warning\" | \"danger\" = \"neutral\",\n): string {\n const icon =\n tone === \"success\"\n ? green(\"✔\")\n : tone === \"warning\"\n ? yellow(\"!\")\n : tone === \"danger\"\n ? red(\"✖\")\n : cyan(\"•\");\n return ` ${icon} ${value}`;\n}\n\nexport function formatMutedPath(path: string): string {\n return dim(path);\n}\n\nexport function maskSecret(value: string, visible = 8): string {\n if (!value) return \"(empty)\";\n if (value.length <= visible) return value;\n return `${value.slice(0, visible)}…`;\n}\n\nexport function formatDurationMinutes(minutes: number): string {\n if (minutes < 60) return `${minutes} 分钟`;\n const hours = Math.floor(minutes / 60);\n const restMinutes = minutes % 60;\n return restMinutes > 0\n ? `${hours} 小时 ${restMinutes} 分钟`\n : `${hours} 小时`;\n}\n\nexport function formatStatusBadge(\n label: string,\n tone: \"success\" | \"warning\" | \"danger\" | \"neutral\" = \"neutral\",\n): string {\n if (tone === \"success\") return green(label);\n if (tone === \"warning\") return yellow(label);\n if (tone === \"danger\") return red(label);\n return magenta(label);\n}\n","import { confirm, input, password, select } from \"@inquirer/prompts\";\n\ntype Choice<T> = {\n value: T;\n name?: string;\n description?: string;\n disabled?: boolean;\n};\n\nexport function isInteractiveTerminal(): boolean {\n return Boolean(process.stdin.isTTY && process.stdout.isTTY);\n}\n\nexport async function promptConfirm(options: {\n message: string;\n defaultValue?: boolean;\n}): Promise<boolean> {\n return confirm({\n message: options.message,\n default: options.defaultValue,\n });\n}\n\nexport async function promptText(options: {\n message: string;\n defaultValue?: string;\n validate?: (value: string) => boolean | string;\n}): Promise<string> {\n return input({\n message: options.message,\n default: options.defaultValue,\n validate: options.validate,\n });\n}\n\nexport async function promptPassword(options: {\n message: string;\n mask?: string;\n validate?: (value: string) => boolean | string;\n}): Promise<string> {\n return password({\n message: options.message,\n mask: options.mask ?? \"*\",\n validate: options.validate,\n });\n}\n\nexport async function promptSelect<T>(options: {\n message: string;\n choices: ReadonlyArray<Choice<T>>;\n}): Promise<T> {\n return select({\n message: options.message,\n choices: [...options.choices],\n pageSize: Math.min(Math.max(options.choices.length, 6), 10),\n });\n}\n","type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nconst LOG_LEVELS: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n};\n\nexport class Logger {\n private level: LogLevel;\n\n constructor(level: LogLevel = \"info\") {\n this.level = level;\n }\n\n setLevel(level: LogLevel): void {\n this.level = level;\n }\n\n debug(msg: string): void {\n if (LOG_LEVELS[this.level] <= LOG_LEVELS.debug) {\n process.stderr.write(`[debug] ${msg}\\n`);\n }\n }\n\n info(msg: string): void {\n if (LOG_LEVELS[this.level] <= LOG_LEVELS.info) {\n process.stdout.write(`${msg}\\n`);\n }\n }\n\n warn(msg: string): void {\n if (LOG_LEVELS[this.level] <= LOG_LEVELS.warn) {\n process.stderr.write(`warn: ${msg}\\n`);\n }\n }\n\n error(msg: string): void {\n if (LOG_LEVELS[this.level] <= LOG_LEVELS.error) {\n process.stderr.write(`error: ${msg}\\n`);\n }\n }\n\n log(msg: string): void {\n this.info(msg);\n }\n}\n\nexport const logger = new Logger();\n","import {\n getDefaultApiUrl,\n isValidConfigKey,\n loadConfig,\n saveConfig,\n validateApiKey,\n} from \"../infrastructure/config/manager\";\nimport {\n formatBullet,\n formatHeader,\n formatKeyValue,\n formatSection,\n maskSecret,\n} from \"../infrastructure/ui/format\";\nimport {\n isInteractiveTerminal,\n promptPassword,\n promptSelect,\n promptText,\n} from \"../infrastructure/ui/prompts\";\nimport { logger } from \"../utils/logger\";\n\nconst VALID_KEYS = [\"apiKey\", \"apiUrl\", \"syncInterval\", \"logLevel\"] as const;\n\ntype ConfigKey = (typeof VALID_KEYS)[number];\ntype ConfigSubcommand = \"get\" | \"set\" | \"show\";\n\nexport function isConfigKey(value: string): value is ConfigKey {\n return isValidConfigKey(value) && VALID_KEYS.includes(value as ConfigKey);\n}\n\nexport function formatConfigValue(key: ConfigKey, value: unknown): string {\n if (value === undefined || value === null || value === \"\") {\n return \"(empty)\";\n }\n\n if (key === \"apiKey\") {\n return maskSecret(String(value));\n }\n\n if (key === \"syncInterval\") {\n const ms = Number(value);\n const minutes = Math.round(ms / 60000);\n return `${minutes} 分钟 (${ms} ms)`;\n }\n\n return String(value);\n}\n\nasync function promptConfigSubcommand(): Promise<ConfigSubcommand> {\n logger.info(\n formatHeader(\"配置中心\", \"通过交互式菜单查看或修改 TokenArena CLI 配置。\"),\n );\n\n return promptSelect<ConfigSubcommand>({\n message: \"请选择配置操作\",\n choices: [\n {\n name: \"查看完整配置\",\n value: \"show\",\n description: \"以更适合阅读的方式展示当前配置\",\n },\n {\n name: \"读取单个配置项\",\n value: \"get\",\n description: \"查看某个配置键当前保存的值\",\n },\n {\n name: \"修改配置项\",\n value: \"set\",\n description: \"更新 API Key、API 地址、同步间隔或日志级别\",\n },\n ],\n });\n}\n\nasync function promptConfigKey(message: string): Promise<ConfigKey> {\n return promptSelect<ConfigKey>({\n message,\n choices: [\n {\n name: \"apiKey\",\n value: \"apiKey\",\n description: \"上传数据时使用的 CLI API Key\",\n },\n {\n name: \"apiUrl\",\n value: \"apiUrl\",\n description: \"TokenArena 服务端地址\",\n },\n {\n name: \"syncInterval\",\n value: \"syncInterval\",\n description: \"daemon 默认同步间隔(毫秒)\",\n },\n {\n name: \"logLevel\",\n value: \"logLevel\",\n description: \"CLI 日志级别\",\n },\n ],\n });\n}\n\nasync function promptSyncIntervalValue(\n existingValue?: number,\n): Promise<string> {\n const preset = await promptSelect<string>({\n message: \"请选择默认同步间隔\",\n choices: [\n {\n name: \"30 分钟\",\n value: String(30 * 60_000),\n description: \"适合作为默认值\",\n },\n {\n name: \"10 分钟\",\n value: String(10 * 60_000),\n description: \"更省电,仍保持较及时同步\",\n },\n {\n name: \"30 分钟\",\n value: String(30 * 60_000),\n description: \"适合低频使用场景\",\n },\n {\n name: \"60 分钟\",\n value: String(60 * 60_000),\n description: \"长周期后台同步\",\n },\n {\n name: \"自定义(毫秒)\",\n value: \"custom\",\n description: \"输入任意正整数毫秒值\",\n },\n ],\n });\n\n if (preset !== \"custom\") {\n return preset;\n }\n\n return promptText({\n message: \"请输入 syncInterval(毫秒)\",\n defaultValue: existingValue ? String(existingValue) : undefined,\n validate: (value) => {\n const parsed = Number.parseInt(value, 10);\n if (Number.isNaN(parsed) || parsed <= 0) {\n return \"请输入大于 0 的毫秒数,例如 300000。\";\n }\n return true;\n },\n });\n}\n\nasync function promptConfigValue(\n key: ConfigKey,\n existingValue?: unknown,\n): Promise<string> {\n switch (key) {\n case \"apiKey\":\n return promptPassword({\n message: \"请输入新的 CLI API Key\",\n validate: (value) =>\n validateApiKey(value) || 'API Key 必须以 \"ta_\" 开头。',\n });\n case \"apiUrl\":\n return promptText({\n message: \"请输入 API 服务地址\",\n defaultValue:\n typeof existingValue === \"string\" && existingValue.length > 0\n ? existingValue\n : getDefaultApiUrl(),\n validate: (value) => {\n try {\n const url = new URL(value);\n return Boolean(url.protocol && url.host) || \"请输入合法 URL。\";\n } catch {\n return \"请输入合法 URL。\";\n }\n },\n });\n case \"syncInterval\":\n return promptSyncIntervalValue(\n typeof existingValue === \"number\" ? existingValue : undefined,\n );\n case \"logLevel\":\n return promptSelect<string>({\n message: \"请选择日志级别\",\n choices: [\n {\n name: \"info\",\n value: \"info\",\n description: \"默认,输出常规进度与提示\",\n },\n {\n name: \"warn\",\n value: \"warn\",\n description: \"仅输出警告与错误\",\n },\n {\n name: \"error\",\n value: \"error\",\n description: \"只输出错误\",\n },\n {\n name: \"debug\",\n value: \"debug\",\n description: \"输出更详细的调试日志\",\n },\n ],\n });\n }\n}\n\nfunction printConfigShow(): void {\n const config = loadConfig();\n\n if (!config) {\n logger.info(formatHeader(\"当前配置\", \"尚未创建本地配置文件。\"));\n logger.info(formatBullet(\"运行 tokenarena init 完成首次配置。\", \"warning\"));\n return;\n }\n\n logger.info(formatHeader(\"当前配置\"));\n logger.info(formatSection(\"基础配置\"));\n logger.info(formatKeyValue(\"API Key\", maskSecret(config.apiKey || \"\")));\n logger.info(\n formatKeyValue(\"API 地址\", config.apiUrl || \"https://token.guji.uno\"),\n );\n logger.info(\n formatKeyValue(\n \"同步间隔\",\n config.syncInterval\n ? `${Math.round(config.syncInterval / 60000)} 分钟 (${config.syncInterval} ms)`\n : \"未设置(daemon 默认 5 分钟)\",\n ),\n );\n logger.info(formatKeyValue(\"日志级别\", config.logLevel || \"info\"));\n if (config.deviceId) {\n logger.info(formatKeyValue(\"设备 ID\", maskSecret(config.deviceId, 12)));\n }\n}\n\nexport async function handleConfig(args: string[]): Promise<void> {\n const interactive = isInteractiveTerminal();\n let sub = args[0] as ConfigSubcommand | undefined;\n\n if (!sub) {\n if (!interactive) {\n logger.error(\"Usage: tokenarena config <get|set|show>\");\n process.exit(1);\n }\n sub = await promptConfigSubcommand();\n }\n\n switch (sub) {\n case \"get\": {\n let key = args[1];\n if (!key) {\n if (!interactive) {\n logger.error(\"Usage: tokenarena config get <key>\");\n process.exit(1);\n }\n key = await promptConfigKey(\"请选择要读取的配置项\");\n }\n\n if (!isConfigKey(key)) {\n logger.error(`Unknown config key: ${key}`);\n logger.error(`Valid keys: ${VALID_KEYS.join(\", \")}`);\n process.exit(1);\n }\n\n const config = loadConfig();\n if (!config || !(key in config)) {\n process.exit(0);\n }\n\n const record = config as unknown as Record<string, unknown>;\n console.log(record[key] ?? \"\");\n break;\n }\n case \"set\": {\n let key = args[1];\n if (!key) {\n if (!interactive) {\n logger.error(\"Usage: tokenarena config set <key> <value>\");\n process.exit(1);\n }\n key = await promptConfigKey(\"请选择要修改的配置项\");\n }\n\n if (!isConfigKey(key)) {\n logger.error(`Unknown config key: ${key}`);\n logger.error(`Valid keys: ${VALID_KEYS.join(\", \")}`);\n process.exit(1);\n }\n\n const config = loadConfig() || {\n apiKey: \"\",\n apiUrl: getDefaultApiUrl(),\n };\n const record = config as unknown as Record<string, unknown>;\n\n let value = args[2];\n if (value === undefined) {\n if (!interactive) {\n logger.error(\"Usage: tokenarena config set <key> <value>\");\n process.exit(1);\n }\n value = await promptConfigValue(key, record[key]);\n }\n\n let normalized: string | number = value;\n if (key === \"apiKey\" && !validateApiKey(value)) {\n logger.error('API Key must start with \"ta_\"');\n process.exit(1);\n }\n\n if (key === \"apiUrl\") {\n try {\n const url = new URL(value);\n normalized = url.toString().replace(/\\/$/, \"\");\n } catch {\n logger.error(\"apiUrl must be a valid URL\");\n process.exit(1);\n }\n }\n\n if (key === \"syncInterval\") {\n normalized = Number.parseInt(value, 10);\n if (Number.isNaN(normalized) || normalized <= 0) {\n logger.error(\"syncInterval must be a positive number (milliseconds)\");\n process.exit(1);\n }\n }\n\n record[key] = normalized;\n saveConfig(config);\n\n if (interactive) {\n logger.info(formatHeader(\"配置已更新\"));\n logger.info(formatKeyValue(key, formatConfigValue(key, normalized)));\n } else {\n logger.info(`Set ${key} = ${normalized}`);\n }\n break;\n }\n case \"show\": {\n if (interactive) {\n printConfigShow();\n } else {\n const config = loadConfig();\n console.log(config ? JSON.stringify(config, null, 2) : \"{}\");\n }\n break;\n }\n default:\n logger.error(`Unknown config subcommand: ${sub || \"(none)\"}`);\n logger.error(\"Usage: tokenarena config <get|set|show>\");\n process.exit(1);\n }\n}\n","import { hostname } from \"node:os\";\nimport { toProjectIdentity } from \"../domain/project-identity\";\nimport type {\n ApiSettings,\n DeviceMetadata,\n SessionMetadata,\n TokenBucket,\n UploadSessionMetadata,\n UploadTokenBucket,\n} from \"../domain/types\";\nimport {\n buildUploadManifestScope,\n diffUploadManifest,\n type UploadManifest,\n type UploadManifestScopeChange,\n} from \"../domain/upload-manifest\";\nimport { ApiClient, getIngestPayloadSize } from \"../infrastructure/api/client\";\nimport {\n type Config,\n getOrCreateDeviceId,\n} from \"../infrastructure/config/manager\";\nimport {\n describeExistingSyncLock,\n tryAcquireSyncLock,\n} from \"../infrastructure/runtime/lock\";\nimport {\n markSyncFailed,\n markSyncStarted,\n markSyncSucceeded,\n type SyncSource,\n} from \"../infrastructure/runtime/state\";\nimport {\n loadUploadManifest,\n saveUploadManifest,\n} from \"../infrastructure/runtime/upload-manifest\";\nimport { logger } from \"../utils/logger\";\nimport { runAllParsers } from \"./parser-service\";\n\nconst BATCH_SIZE = 100;\nconst SESSION_BATCH_SIZE = 500;\nconst PROGRESS_BAR_WIDTH = 28;\n\nexport function formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes}B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;\n}\n\nexport function renderProgressBar(progress: number): string {\n const safeProgress = Math.max(0, Math.min(progress, 1));\n const filled = Math.round(safeProgress * PROGRESS_BAR_WIDTH);\n return `${\"█\".repeat(filled)}${\"░\".repeat(PROGRESS_BAR_WIDTH - filled)}`;\n}\n\nfunction writeUploadProgress(\n sent: number,\n total: number,\n batchNum: number,\n totalBatches: number,\n): void {\n const pct = total > 0 ? Math.round((sent / total) * 100) : 100;\n const progressBar = renderProgressBar(total > 0 ? sent / total : 1);\n const batchLabel =\n totalBatches > 1 ? ` · batch ${batchNum}/${totalBatches}` : \"\";\n\n process.stdout.write(\n `\\r Uploading ${progressBar} ${String(pct).padStart(3, \" \")}% · ${formatBytes(sent)}/${formatBytes(total)}${batchLabel}\\x1b[K`,\n );\n}\n\nfunction formatScopeChangeReason(reason: UploadManifestScopeChange): string {\n switch (reason) {\n case \"server_or_api_key\":\n return \"server/API key\";\n case \"device_id\":\n return \"device ID\";\n case \"project_identity\":\n return \"project identity settings\";\n case \"snapshot_protocol\":\n return \"snapshot sync protocol\";\n }\n}\n\nexport function resolveSnapshotResetDeviceId(input: {\n previous: UploadManifest | null;\n scopeChangedReasons: UploadManifestScopeChange[];\n}): string | null {\n if (!input.previous) {\n return null;\n }\n\n if (input.scopeChangedReasons.includes(\"server_or_api_key\")) {\n return null;\n }\n\n if (\n input.scopeChangedReasons.includes(\"project_identity\") ||\n input.scopeChangedReasons.includes(\"snapshot_protocol\")\n ) {\n return input.previous.scope.deviceId;\n }\n\n return null;\n}\n\nfunction persistUploadManifest(manifest: UploadManifest, quiet: boolean): void {\n try {\n saveUploadManifest(manifest);\n } catch (error) {\n if (!quiet) {\n logger.warn(\n `Uploaded data, but failed to update the local sync manifest: ${(error as Error).message}`,\n );\n }\n }\n}\n\nexport interface SyncOptions {\n source?: SyncSource;\n throws?: boolean;\n quiet?: boolean;\n}\n\nexport interface SyncResult {\n buckets: number;\n sessions: number;\n skipped?: \"locked\";\n}\n\nfunction toDeviceMetadata(config: Config): DeviceMetadata {\n return {\n deviceId: getOrCreateDeviceId(config),\n hostname: hostname().replace(/\\.local$/, \"\"),\n };\n}\n\nexport function toUploadBuckets(\n buckets: TokenBucket[],\n settings: ApiSettings,\n device: DeviceMetadata,\n): UploadTokenBucket[] {\n const aggregated = new Map<string, UploadTokenBucket>();\n\n for (const bucket of buckets) {\n const project = toProjectIdentity({\n project: bucket.project || \"unknown\",\n mode: settings.projectMode,\n salt: settings.projectHashSalt,\n });\n const key = [\n bucket.source,\n bucket.model,\n project.projectKey,\n bucket.bucketStart,\n device.deviceId,\n ].join(\"|\");\n\n const existing = aggregated.get(key);\n if (existing) {\n existing.inputTokens += bucket.inputTokens;\n existing.outputTokens += bucket.outputTokens;\n existing.reasoningTokens += bucket.reasoningTokens || 0;\n existing.cachedTokens += bucket.cachedTokens || 0;\n existing.totalTokens += bucket.totalTokens;\n continue;\n }\n\n aggregated.set(key, {\n source: bucket.source,\n model: bucket.model,\n projectKey: project.projectKey,\n projectLabel: project.projectLabel,\n bucketStart: bucket.bucketStart,\n deviceId: device.deviceId,\n hostname: device.hostname,\n inputTokens: bucket.inputTokens,\n outputTokens: bucket.outputTokens,\n reasoningTokens: bucket.reasoningTokens || 0,\n cachedTokens: bucket.cachedTokens || 0,\n totalTokens: bucket.totalTokens,\n });\n }\n\n return Array.from(aggregated.values());\n}\n\nexport function toUploadSessions(\n sessions: SessionMetadata[],\n settings: ApiSettings,\n device: DeviceMetadata,\n): UploadSessionMetadata[] {\n return sessions.map((session) => {\n const project = toProjectIdentity({\n project: session.project || \"unknown\",\n mode: settings.projectMode,\n salt: settings.projectHashSalt,\n });\n\n return {\n source: session.source,\n projectKey: project.projectKey,\n projectLabel: project.projectLabel,\n sessionHash: session.sessionHash,\n deviceId: device.deviceId,\n hostname: device.hostname,\n firstMessageAt: session.firstMessageAt,\n lastMessageAt: session.lastMessageAt,\n durationSeconds: session.durationSeconds,\n activeSeconds: session.activeSeconds,\n messageCount: session.messageCount,\n userMessageCount: session.userMessageCount,\n inputTokens: session.inputTokens,\n outputTokens: session.outputTokens,\n reasoningTokens: session.reasoningTokens,\n cachedTokens: session.cachedTokens,\n totalTokens: session.totalTokens,\n primaryModel: session.primaryModel,\n modelUsages: session.modelUsages,\n };\n });\n}\n\nclass SyncFailure extends Error {\n constructor(\n message: string,\n readonly kind: \"auth_error\" | \"error\",\n readonly causeError?: Error,\n ) {\n super(message);\n }\n}\n\nexport async function runSync(\n config: Config,\n opts: SyncOptions = {},\n): Promise<SyncResult> {\n const { quiet = false, source = \"manual\", throws = false } = opts;\n\n const lock = tryAcquireSyncLock(source);\n if (!lock) {\n const detail = describeExistingSyncLock();\n const message = detail\n ? `Another sync is already running (${detail}). Skipping.`\n : \"Another sync is already running. Skipping.\";\n\n markSyncFailed(source, message, \"skipped_locked\");\n logger.info(message);\n return {\n buckets: 0,\n sessions: 0,\n skipped: \"locked\",\n };\n }\n\n markSyncStarted(source);\n\n let totalIngested = 0;\n let totalSessionsSynced = 0;\n let caughtError: SyncFailure | null = null;\n\n try {\n const {\n buckets: allBuckets,\n sessions: allSessions,\n parserResults,\n } = await runAllParsers();\n\n if (allBuckets.length === 0 && allSessions.length === 0) {\n if (!quiet) {\n logger.info(\"No new usage data found.\");\n }\n markSyncSucceeded(source, { buckets: 0, sessions: 0 });\n return { buckets: 0, sessions: 0 };\n }\n\n if (!quiet && parserResults.length > 0) {\n for (const p of parserResults) {\n const parts: string[] = [];\n if (p.buckets > 0) parts.push(`${p.buckets} buckets`);\n if (p.sessions > 0) parts.push(`${p.sessions} sessions`);\n logger.info(` ${p.source}: ${parts.join(\", \")}`);\n }\n }\n\n const apiUrl = config.apiUrl || \"https://token.guji.uno\";\n const apiClient = new ApiClient(apiUrl, config.apiKey);\n\n let settings: ApiSettings | null;\n try {\n settings = await apiClient.fetchSettings();\n } catch (error) {\n if ((error as Error).message === \"UNAUTHORIZED\") {\n throw new SyncFailure(\n \"Invalid API key. Run `tokenarena init` to reconfigure.\",\n \"auth_error\",\n error as Error,\n );\n }\n\n settings = null;\n }\n\n if (!settings) {\n throw new SyncFailure(\n \"Could not fetch usage settings. Check your server URL and API key.\",\n \"error\",\n );\n }\n\n const device = toDeviceMetadata(config);\n const manifestScope = buildUploadManifestScope({\n apiKey: config.apiKey,\n apiUrl,\n deviceId: device.deviceId,\n settings,\n });\n const uploadBuckets = toUploadBuckets(allBuckets, settings, device);\n const uploadSessions = toUploadSessions(allSessions, settings, device);\n const previousManifest = loadUploadManifest();\n const uploadDiff = diffUploadManifest({\n buckets: uploadBuckets,\n previous: previousManifest,\n scope: manifestScope,\n sessions: uploadSessions,\n });\n const changedBuckets = uploadDiff.bucketsToUpload;\n const changedSessions = uploadDiff.sessionsToUpload;\n const snapshotResetDeviceId = resolveSnapshotResetDeviceId({\n previous: previousManifest,\n scopeChangedReasons: uploadDiff.scopeChangedReasons,\n });\n\n if (!quiet && uploadDiff.scopeChangedReasons.length > 0) {\n const scopeReasons = uploadDiff.scopeChangedReasons\n .map(formatScopeChangeReason)\n .join(\", \");\n if (snapshotResetDeviceId) {\n logger.warn(\n `Upload scope changed (${scopeReasons}). TokenArena will replace the previous remote snapshot for this device before uploading the current snapshot again.`,\n );\n } else {\n logger.warn(\n `Upload scope changed (${scopeReasons}). TokenArena will upload the current snapshot again, but existing remote records from the previous scope will not be deleted automatically.`,\n );\n }\n }\n\n if (\n !quiet &&\n (uploadDiff.removedBuckets > 0 || uploadDiff.removedSessions > 0)\n ) {\n const parts: string[] = [];\n if (uploadDiff.removedBuckets > 0) {\n parts.push(`${uploadDiff.removedBuckets} buckets`);\n }\n if (uploadDiff.removedSessions > 0) {\n parts.push(`${uploadDiff.removedSessions} sessions`);\n }\n logger.warn(\n `Detected ${parts.join(\" + \")} that were present in the previous local snapshot but are missing now. Remote deletions are not supported yet, so renamed projects or removed local logs may leave stale data online.`,\n );\n }\n\n if (snapshotResetDeviceId) {\n const deleted = await apiClient.deleteDeviceData(snapshotResetDeviceId);\n if (!quiet) {\n const deletedParts: string[] = [];\n if (deleted.deletedBuckets > 0) {\n deletedParts.push(`${deleted.deletedBuckets} buckets`);\n }\n if (deleted.deletedSessions > 0) {\n deletedParts.push(`${deleted.deletedSessions} sessions`);\n }\n\n logger.info(\n deletedParts.length > 0\n ? `Cleared ${deletedParts.join(\" + \")} from the previous remote snapshot before re-uploading.`\n : \"Previous remote snapshot was already empty before re-uploading.\",\n );\n }\n }\n\n if (changedBuckets.length === 0 && changedSessions.length === 0) {\n if (!quiet) {\n const skippedParts: string[] = [];\n if (uploadDiff.unchangedBuckets > 0) {\n skippedParts.push(`${uploadDiff.unchangedBuckets} unchanged buckets`);\n }\n if (uploadDiff.unchangedSessions > 0) {\n skippedParts.push(\n `${uploadDiff.unchangedSessions} unchanged sessions`,\n );\n }\n logger.info(\n skippedParts.length > 0\n ? `No new or updated usage data to upload. Skipped ${skippedParts.join(\" + \")}.`\n : \"No new or updated usage data to upload.\",\n );\n }\n persistUploadManifest(uploadDiff.nextManifest, quiet);\n markSyncSucceeded(source, { buckets: 0, sessions: 0 });\n return { buckets: 0, sessions: 0 };\n }\n\n const bucketBatches = Math.ceil(changedBuckets.length / BATCH_SIZE);\n const sessionBatches = Math.ceil(\n changedSessions.length / SESSION_BATCH_SIZE,\n );\n const totalBatches = Math.max(bucketBatches, sessionBatches, 1);\n const batchPayloadSizes = Array.from(\n { length: totalBatches },\n (_, batchIdx) =>\n getIngestPayloadSize(\n device,\n changedBuckets.slice(\n batchIdx * BATCH_SIZE,\n (batchIdx + 1) * BATCH_SIZE,\n ),\n changedSessions.slice(\n batchIdx * SESSION_BATCH_SIZE,\n (batchIdx + 1) * SESSION_BATCH_SIZE,\n ),\n ),\n );\n const totalPayloadBytes = batchPayloadSizes.reduce(\n (sum, size) => sum + size,\n 0,\n );\n let uploadedBytesBeforeBatch = 0;\n\n if (!quiet) {\n const parts: string[] = [];\n if (changedBuckets.length > 0) {\n parts.push(`${changedBuckets.length} buckets`);\n }\n if (changedSessions.length > 0) {\n parts.push(`${changedSessions.length} sessions`);\n }\n const skippedParts: string[] = [];\n if (uploadDiff.unchangedBuckets > 0) {\n skippedParts.push(`${uploadDiff.unchangedBuckets} unchanged buckets`);\n }\n if (uploadDiff.unchangedSessions > 0) {\n skippedParts.push(`${uploadDiff.unchangedSessions} unchanged sessions`);\n }\n logger.info(\n `Uploading ${parts.join(\" + \")} (${totalBatches} batch${totalBatches > 1 ? \"es\" : \"\"}${skippedParts.length > 0 ? `, skipped ${skippedParts.join(\" + \")}` : \"\"})...`,\n );\n }\n\n for (let batchIdx = 0; batchIdx < totalBatches; batchIdx++) {\n const batch = changedBuckets.slice(\n batchIdx * BATCH_SIZE,\n (batchIdx + 1) * BATCH_SIZE,\n );\n const batchSessions = changedSessions.slice(\n batchIdx * SESSION_BATCH_SIZE,\n (batchIdx + 1) * SESSION_BATCH_SIZE,\n );\n const batchNum = batchIdx + 1;\n\n const result = await apiClient.ingest(\n device,\n batch,\n batchSessions.length > 0 ? batchSessions : undefined,\n quiet\n ? undefined\n : (sent, total) => {\n writeUploadProgress(\n uploadedBytesBeforeBatch + sent,\n totalPayloadBytes || total,\n batchNum,\n totalBatches,\n );\n },\n );\n\n totalIngested += result.ingested ?? batch.length;\n totalSessionsSynced += result.sessions ?? batchSessions.length;\n uploadedBytesBeforeBatch += batchPayloadSizes[batchIdx] ?? 0;\n }\n\n if (!quiet && (totalBatches > 1 || changedBuckets.length > 0)) {\n writeUploadProgress(\n totalPayloadBytes,\n totalPayloadBytes,\n totalBatches,\n totalBatches,\n );\n process.stdout.write(\"\\n\");\n }\n\n const syncParts = [`${totalIngested} buckets`];\n if (totalSessionsSynced > 0) {\n syncParts.push(`${totalSessionsSynced} sessions`);\n }\n logger.info(`Synced ${syncParts.join(\" + \")}.`);\n\n if (!quiet) {\n logger.info(`\\nView your dashboard at: ${apiUrl}/usage`);\n }\n\n persistUploadManifest(uploadDiff.nextManifest, quiet);\n markSyncSucceeded(source, {\n buckets: totalIngested,\n sessions: totalSessionsSynced,\n });\n\n return {\n buckets: totalIngested,\n sessions: totalSessionsSynced,\n };\n } catch (error) {\n const httpErr = error as Error & { statusCode?: number };\n\n if (httpErr.message === \"UNAUTHORIZED\") {\n caughtError = new SyncFailure(\n \"Invalid API key. Run `tokenarena init` to reconfigure.\",\n \"auth_error\",\n error as Error,\n );\n } else if (error instanceof SyncFailure) {\n caughtError = error;\n } else if (totalIngested > 0) {\n caughtError = new SyncFailure(\n `Sync partially completed (${totalIngested} buckets uploaded). ${httpErr.message}`,\n \"error\",\n error as Error,\n );\n } else {\n caughtError = new SyncFailure(\n `Sync failed: ${httpErr.message}`,\n \"error\",\n error as Error,\n );\n }\n\n markSyncFailed(source, caughtError.message, caughtError.kind);\n } finally {\n lock.release();\n }\n\n if (!caughtError) {\n return {\n buckets: totalIngested,\n sessions: totalSessionsSynced,\n };\n }\n\n logger.error(caughtError.message);\n if (throws) {\n throw caughtError.causeError ?? caughtError;\n }\n process.exit(1);\n}\n","import { createHmac } from \"node:crypto\";\n\nexport function toProjectIdentity(input: {\n project: string;\n mode: \"hashed\" | \"raw\" | \"disabled\";\n salt: string;\n}) {\n if (input.mode === \"disabled\") {\n return { projectKey: \"unknown\", projectLabel: \"Unknown Project\" };\n }\n\n if (input.mode === \"raw\") {\n return { projectKey: input.project, projectLabel: input.project };\n }\n\n const projectKey = createHmac(\"sha256\", input.salt)\n .update(input.project)\n .digest(\"hex\")\n .slice(0, 16);\n\n return {\n projectKey,\n projectLabel: `Project ${projectKey.slice(0, 6)}`,\n };\n}\n","import { createHash } from \"node:crypto\";\nimport type {\n ApiSettings,\n UploadSessionMetadata,\n UploadTokenBucket,\n} from \"./types\";\n\nconst MANIFEST_VERSION = 1 as const;\nconst SNAPSHOT_PROTOCOL_VERSION = 1 as const;\n\n// codeql[cs/insufficient-password-hash] - Used for API key fingerprinting and content change detection, not password storage.\n// API keys are high-entropy tokens; SHA-256 is appropriate for identifier comparison.\nfunction fingerprint(value: string): string {\n return createHash(\"sha256\").update(value).digest(\"hex\").slice(0, 16);\n}\n\nfunction normalizeApiUrl(apiUrl: string): string {\n let end = apiUrl.length;\n while (end > 0 && apiUrl[end - 1] === \"/\") end--;\n return apiUrl.slice(0, end) || \"/\";\n}\n\nexport interface UploadManifestScope {\n apiKeyHash: string;\n apiUrl: string;\n deviceId: string;\n projectHashSaltHash: string;\n projectMode: ApiSettings[\"projectMode\"];\n snapshotProtocolVersion: number;\n}\n\nexport interface UploadManifest {\n buckets: Record<string, string>;\n scope: UploadManifestScope;\n sessions: Record<string, string>;\n updatedAt: string;\n version: typeof MANIFEST_VERSION;\n}\n\nexport interface UploadManifestDiff {\n bucketsToUpload: UploadTokenBucket[];\n nextManifest: UploadManifest;\n removedBuckets: number;\n removedSessions: number;\n scopeChangedReasons: UploadManifestScopeChange[];\n sessionsToUpload: UploadSessionMetadata[];\n unchangedBuckets: number;\n unchangedSessions: number;\n}\n\nexport type UploadManifestScopeChange =\n | \"device_id\"\n | \"project_identity\"\n | \"snapshot_protocol\"\n | \"server_or_api_key\";\n\nexport function buildUploadManifestScope(input: {\n apiKey: string;\n apiUrl: string;\n deviceId: string;\n settings: ApiSettings;\n}): UploadManifestScope {\n return {\n apiKeyHash: fingerprint(input.apiKey),\n apiUrl: normalizeApiUrl(input.apiUrl),\n deviceId: input.deviceId,\n projectHashSaltHash: fingerprint(input.settings.projectHashSalt),\n projectMode: input.settings.projectMode,\n snapshotProtocolVersion: SNAPSHOT_PROTOCOL_VERSION,\n };\n}\n\nexport function describeUploadManifestScopeChanges(\n previous: UploadManifestScope,\n current: UploadManifestScope,\n): UploadManifestScopeChange[] {\n const changes: UploadManifestScopeChange[] = [];\n\n if (\n previous.apiUrl !== current.apiUrl ||\n previous.apiKeyHash !== current.apiKeyHash\n ) {\n changes.push(\"server_or_api_key\");\n }\n\n if (previous.deviceId !== current.deviceId) {\n changes.push(\"device_id\");\n }\n\n if (\n previous.projectMode !== current.projectMode ||\n previous.projectHashSaltHash !== current.projectHashSaltHash\n ) {\n changes.push(\"project_identity\");\n }\n\n if (previous.snapshotProtocolVersion !== current.snapshotProtocolVersion) {\n changes.push(\"snapshot_protocol\");\n }\n\n return changes;\n}\n\nexport function getUploadBucketManifestKey(bucket: UploadTokenBucket): string {\n return [\n bucket.deviceId,\n bucket.source,\n bucket.model,\n bucket.projectKey,\n bucket.bucketStart,\n ].join(\"|\");\n}\n\nexport function getUploadSessionManifestKey(\n session: UploadSessionMetadata,\n): string {\n return [session.deviceId, session.source, session.sessionHash].join(\"|\");\n}\n\nfunction getUploadBucketContentHash(bucket: UploadTokenBucket): string {\n return fingerprint(\n JSON.stringify({\n cachedTokens: bucket.cachedTokens,\n hostname: bucket.hostname,\n inputTokens: bucket.inputTokens,\n outputTokens: bucket.outputTokens,\n projectLabel: bucket.projectLabel,\n reasoningTokens: bucket.reasoningTokens,\n totalTokens: bucket.totalTokens,\n }),\n );\n}\n\nfunction getUploadSessionContentHash(session: UploadSessionMetadata): string {\n return fingerprint(\n JSON.stringify({\n activeSeconds: session.activeSeconds,\n cachedTokens: session.cachedTokens,\n durationSeconds: session.durationSeconds,\n firstMessageAt: session.firstMessageAt,\n hostname: session.hostname,\n inputTokens: session.inputTokens,\n lastMessageAt: session.lastMessageAt,\n messageCount: session.messageCount,\n modelUsages: session.modelUsages,\n outputTokens: session.outputTokens,\n primaryModel: session.primaryModel,\n projectKey: session.projectKey,\n projectLabel: session.projectLabel,\n reasoningTokens: session.reasoningTokens,\n totalTokens: session.totalTokens,\n userMessageCount: session.userMessageCount,\n }),\n );\n}\n\nfunction buildRecordHashes<T>(\n items: T[],\n getKey: (item: T) => string,\n getHash: (item: T) => string,\n): Record<string, string> {\n const hashes: Record<string, string> = {};\n\n for (const item of items) {\n hashes[getKey(item)] = getHash(item);\n }\n\n return hashes;\n}\n\nexport function createUploadManifest(input: {\n buckets: UploadTokenBucket[];\n scope: UploadManifestScope;\n sessions: UploadSessionMetadata[];\n updatedAt?: string;\n}): UploadManifest {\n return {\n buckets: buildRecordHashes(\n input.buckets,\n getUploadBucketManifestKey,\n getUploadBucketContentHash,\n ),\n scope: input.scope,\n sessions: buildRecordHashes(\n input.sessions,\n getUploadSessionManifestKey,\n getUploadSessionContentHash,\n ),\n updatedAt: input.updatedAt ?? new Date().toISOString(),\n version: MANIFEST_VERSION,\n };\n}\n\nfunction countRemovedRecords(\n previous: Record<string, string>,\n current: Record<string, string>,\n): number {\n let removed = 0;\n\n for (const key of Object.keys(previous)) {\n if (!(key in current)) {\n removed++;\n }\n }\n\n return removed;\n}\n\nexport function diffUploadManifest(input: {\n buckets: UploadTokenBucket[];\n previous: UploadManifest | null;\n scope: UploadManifestScope;\n sessions: UploadSessionMetadata[];\n updatedAt?: string;\n}): UploadManifestDiff {\n const nextManifest = createUploadManifest({\n buckets: input.buckets,\n scope: input.scope,\n sessions: input.sessions,\n updatedAt: input.updatedAt,\n });\n\n const scopeChangedReasons = input.previous\n ? describeUploadManifestScopeChanges(input.previous.scope, input.scope)\n : [];\n\n const previousBuckets =\n input.previous && scopeChangedReasons.length === 0\n ? input.previous.buckets\n : {};\n const previousSessions =\n input.previous && scopeChangedReasons.length === 0\n ? input.previous.sessions\n : {};\n\n const bucketsToUpload = input.buckets.filter((bucket) => {\n const key = getUploadBucketManifestKey(bucket);\n return previousBuckets[key] !== nextManifest.buckets[key];\n });\n const sessionsToUpload = input.sessions.filter((session) => {\n const key = getUploadSessionManifestKey(session);\n return previousSessions[key] !== nextManifest.sessions[key];\n });\n\n return {\n bucketsToUpload,\n nextManifest,\n removedBuckets: countRemovedRecords(previousBuckets, nextManifest.buckets),\n removedSessions: countRemovedRecords(\n previousSessions,\n nextManifest.sessions,\n ),\n scopeChangedReasons,\n sessionsToUpload,\n unchangedBuckets: input.buckets.length - bucketsToUpload.length,\n unchangedSessions: input.sessions.length - sessionsToUpload.length,\n };\n}\n","import http from \"node:http\";\nimport https from \"node:https\";\nimport { URL } from \"node:url\";\nimport type {\n ApiSettings,\n DeviceMetadata,\n IngestResponse,\n UploadSessionMetadata,\n UploadTokenBucket,\n} from \"../../domain/types\";\n\nconst MAX_RETRIES = 3;\nconst INITIAL_DELAY = 1000;\nconst TIMEOUT_MS = 60_000;\n\nexport function getIngestPayloadSize(\n device: DeviceMetadata,\n buckets: UploadTokenBucket[],\n sessions?: UploadSessionMetadata[],\n): number {\n const payload = {\n schemaVersion: 2 as const,\n device,\n buckets,\n sessions: sessions ?? [],\n };\n\n return Buffer.byteLength(JSON.stringify(payload));\n}\n\nexport class ApiClient {\n constructor(\n private apiUrl: string,\n private apiKey: string,\n ) {}\n\n /**\n * Ingest buckets and sessions to server\n */\n async ingest(\n device: DeviceMetadata,\n buckets: UploadTokenBucket[],\n sessions?: UploadSessionMetadata[],\n onProgress?: (sent: number, total: number) => void,\n ): Promise<{ ingested?: number; sessions?: number }> {\n let lastError: Error | undefined;\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n try {\n return await this.sendIngest(device, buckets, sessions, onProgress);\n } catch (err) {\n lastError = err as Error;\n const httpErr = err as { statusCode?: number; message: string };\n // Don't retry auth errors or client errors\n if (\n httpErr.message === \"UNAUTHORIZED\" ||\n (httpErr.statusCode &&\n httpErr.statusCode >= 400 &&\n httpErr.statusCode < 500)\n ) {\n throw err;\n }\n if (attempt < MAX_RETRIES - 1) {\n const delay = INITIAL_DELAY * 2 ** attempt;\n await new Promise((r) => setTimeout(r, delay));\n }\n }\n }\n throw lastError;\n }\n\n private sendIngest(\n device: DeviceMetadata,\n buckets: UploadTokenBucket[],\n sessions?: UploadSessionMetadata[],\n onProgress?: (sent: number, total: number) => void,\n ): Promise<{ ingested?: number; sessions?: number }> {\n return new Promise((resolve, reject) => {\n const url = new URL(\"/api/usage/ingest\", this.apiUrl);\n const body = Buffer.from(\n JSON.stringify({\n schemaVersion: 2 as const,\n device,\n buckets,\n sessions: sessions ?? [],\n }),\n );\n const totalBytes = body.length;\n const mod = url.protocol === \"https:\" ? https : http;\n\n const req = mod.request(\n url,\n {\n method: \"POST\",\n timeout: TIMEOUT_MS,\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n \"Content-Length\": totalBytes,\n },\n },\n (res) => {\n let data = \"\";\n res.on(\"data\", (chunk) => {\n data += chunk;\n });\n res.on(\"end\", () => {\n if (res.statusCode === 401) {\n reject(new Error(\"UNAUTHORIZED\"));\n return;\n }\n if (\n !res.statusCode ||\n res.statusCode < 200 ||\n res.statusCode >= 300\n ) {\n const err = new Error(\n `HTTP ${res.statusCode}: ${data}`,\n ) as Error & {\n statusCode?: number;\n };\n err.statusCode = res.statusCode;\n reject(err);\n return;\n }\n try {\n const response = JSON.parse(data) as IngestResponse;\n resolve({\n ingested: response.bucketCount ?? response.ingested,\n sessions: response.sessionCount ?? response.sessions,\n });\n } catch {\n reject(new Error(`Invalid JSON response: ${data}`));\n }\n });\n },\n );\n\n req.on(\"error\", (err) => reject(err));\n req.on(\"timeout\", () => {\n req.destroy();\n reject(new Error(\"Request timed out (60s)\"));\n });\n\n // Write body in chunks to report upload progress\n const CHUNK = 16 * 1024;\n let sent = 0;\n\n const writeNext = () => {\n let ok = true;\n while (ok && sent < totalBytes) {\n const slice = body.subarray(sent, sent + CHUNK);\n sent += slice.length;\n if (onProgress) onProgress(sent, totalBytes);\n ok = req.write(slice);\n }\n if (sent < totalBytes) {\n req.once(\"drain\", writeNext);\n } else {\n req.end();\n }\n };\n\n writeNext();\n });\n }\n\n /**\n * Fetch user settings from server\n */\n async fetchSettings(): Promise<ApiSettings | null> {\n return new Promise((resolve, reject) => {\n const url = new URL(\"/api/usage/settings\", this.apiUrl);\n const mod = url.protocol === \"https:\" ? https : http;\n\n const req = mod.request(\n url,\n {\n method: \"GET\",\n timeout: 10_000,\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n },\n },\n (res) => {\n let data = \"\";\n res.on(\"data\", (chunk) => {\n data += chunk;\n });\n res.on(\"end\", () => {\n if (res.statusCode === 401) {\n reject(new Error(\"UNAUTHORIZED\"));\n return;\n }\n if (\n !res.statusCode ||\n res.statusCode < 200 ||\n res.statusCode >= 300\n ) {\n resolve(null);\n return;\n }\n try {\n const settings = JSON.parse(data) as ApiSettings;\n if (\n settings.schemaVersion !== 2 ||\n !settings.projectMode ||\n !settings.projectHashSalt ||\n !settings.timezone\n ) {\n resolve(null);\n return;\n }\n\n resolve(settings);\n } catch {\n resolve(null);\n }\n });\n },\n );\n\n req.on(\"error\", () => resolve(null));\n req.on(\"timeout\", () => {\n req.destroy();\n resolve(null);\n });\n req.end();\n });\n }\n\n async deleteDeviceData(deviceId: string): Promise<{\n deletedBuckets: number;\n deletedSessions: number;\n }> {\n return new Promise((resolve, reject) => {\n const url = new URL(\"/api/usage/ingest\", this.apiUrl);\n url.searchParams.set(\"deviceId\", deviceId);\n const mod = url.protocol === \"https:\" ? https : http;\n\n const req = mod.request(\n url,\n {\n method: \"DELETE\",\n timeout: TIMEOUT_MS,\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n },\n },\n (res) => {\n let data = \"\";\n res.on(\"data\", (chunk) => {\n data += chunk;\n });\n res.on(\"end\", () => {\n if (res.statusCode === 401) {\n reject(new Error(\"UNAUTHORIZED\"));\n return;\n }\n if (\n !res.statusCode ||\n res.statusCode < 200 ||\n res.statusCode >= 300\n ) {\n const err = new Error(\n `HTTP ${res.statusCode}: ${data}`,\n ) as Error & {\n statusCode?: number;\n };\n err.statusCode = res.statusCode;\n reject(err);\n return;\n }\n try {\n resolve(JSON.parse(data));\n } catch {\n reject(new Error(`Invalid JSON response: ${data}`));\n }\n });\n },\n );\n\n req.on(\"error\", (err) => reject(err));\n req.on(\"timeout\", () => {\n req.destroy();\n reject(new Error(\"Request timed out (60s)\"));\n });\n req.end();\n });\n }\n}\n","import {\n closeSync,\n existsSync,\n openSync,\n readFileSync,\n rmSync,\n writeFileSync,\n} from \"node:fs\";\nimport { ensureAppDirs, getSyncLockPath } from \"./paths\";\nimport type { SyncSource } from \"./state\";\n\ninterface LockMetadata {\n createdAt: string;\n pid: number;\n source: SyncSource;\n}\n\nexport interface SyncLock {\n release(): void;\n}\n\nfunction isProcessAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n return code !== \"ESRCH\";\n }\n}\n\nfunction readLockMetadata(lockPath: string): LockMetadata | null {\n if (!existsSync(lockPath)) {\n return null;\n }\n\n try {\n return JSON.parse(readFileSync(lockPath, \"utf-8\")) as LockMetadata;\n } catch {\n return null;\n }\n}\n\nfunction removeStaleLock(lockPath: string): void {\n const metadata = readLockMetadata(lockPath);\n if (!metadata) {\n rmSync(lockPath, { force: true });\n return;\n }\n\n if (!isProcessAlive(metadata.pid)) {\n rmSync(lockPath, { force: true });\n }\n}\n\nexport function tryAcquireSyncLock(source: SyncSource): SyncLock | null {\n ensureAppDirs();\n const lockPath = getSyncLockPath();\n\n try {\n const fd = openSync(lockPath, \"wx\");\n const metadata: LockMetadata = {\n createdAt: new Date().toISOString(),\n pid: process.pid,\n source,\n };\n writeFileSync(fd, JSON.stringify(metadata, null, 2));\n closeSync(fd);\n\n return {\n release() {\n rmSync(lockPath, { force: true });\n },\n };\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== \"EEXIST\") {\n throw error;\n }\n }\n\n removeStaleLock(lockPath);\n\n try {\n const fd = openSync(lockPath, \"wx\");\n const metadata: LockMetadata = {\n createdAt: new Date().toISOString(),\n pid: process.pid,\n source,\n };\n writeFileSync(fd, JSON.stringify(metadata, null, 2));\n closeSync(fd);\n\n return {\n release() {\n rmSync(lockPath, { force: true });\n },\n };\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code === \"EEXIST\") {\n return null;\n }\n throw error;\n }\n}\n\nexport function describeExistingSyncLock(): string | null {\n const metadata = readLockMetadata(getSyncLockPath());\n if (!metadata) {\n return null;\n }\n\n return `pid=${metadata.pid}, source=${metadata.source}, createdAt=${metadata.createdAt}`;\n}\n","import { mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { getRuntimeDir, getStateHome } from \"../xdg\";\n\nconst APP_NAME = \"tokenarena\";\n\nexport function getConfigDir(): string {\n // Re-exported from manager for backward compat — callers should import from manager directly\n throw new Error(\"Use getConfigDir() from config/manager instead\");\n}\n\nexport function getRuntimeDirPath(): string {\n return join(getRuntimeDir(), APP_NAME);\n}\n\nexport function getStateDir(): string {\n return join(getStateHome(), APP_NAME);\n}\n\nexport function getSyncLockPath(): string {\n return join(getRuntimeDirPath(), \"sync.lock\");\n}\n\nexport function getSyncStatePath(): string {\n return join(getStateDir(), \"status.json\");\n}\n\nexport function getUploadManifestPath(): string {\n return join(getStateDir(), \"upload-manifest.json\");\n}\n\nexport function ensureAppDirs(): void {\n mkdirSync(getRuntimeDirPath(), { recursive: true });\n mkdirSync(getStateDir(), { recursive: true });\n}\n","import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { ensureAppDirs, getSyncStatePath } from \"./paths\";\n\nexport type SyncSource = \"daemon\" | \"default\" | \"init\" | \"manual\";\n\nexport type SyncStateStatus =\n | \"auth_error\"\n | \"error\"\n | \"idle\"\n | \"skipped_locked\"\n | \"syncing\";\n\nexport interface SyncState {\n pid?: number;\n lastAttemptAt?: string;\n lastCompletedAt?: string;\n lastError?: string;\n lastFailureAt?: string;\n lastResult?: {\n buckets: number;\n sessions: number;\n };\n lastSource?: SyncSource;\n lastSuccessAt?: string;\n status: SyncStateStatus;\n}\n\nfunction getDefaultState(): SyncState {\n return { status: \"idle\" };\n}\n\nexport function loadSyncState(): SyncState {\n const path = getSyncStatePath();\n if (!existsSync(path)) {\n return getDefaultState();\n }\n\n try {\n return {\n ...getDefaultState(),\n ...(JSON.parse(readFileSync(path, \"utf-8\")) as Partial<SyncState>),\n };\n } catch {\n return getDefaultState();\n }\n}\n\nexport function saveSyncState(next: SyncState): void {\n ensureAppDirs();\n writeFileSync(\n getSyncStatePath(),\n `${JSON.stringify(next, null, 2)}\\n`,\n \"utf-8\",\n );\n}\n\nexport function markSyncStarted(source: SyncSource): void {\n const current = loadSyncState();\n saveSyncState({\n ...current,\n pid: process.pid,\n lastAttemptAt: new Date().toISOString(),\n lastSource: source,\n status: \"syncing\",\n });\n}\n\nexport function markSyncSucceeded(\n source: SyncSource,\n result: { buckets: number; sessions: number },\n): void {\n const now = new Date().toISOString();\n const current = loadSyncState();\n saveSyncState({\n ...current,\n lastCompletedAt: now,\n lastError: undefined,\n lastFailureAt: undefined,\n lastResult: result,\n lastSource: source,\n lastSuccessAt: now,\n pid: undefined,\n status: \"idle\",\n });\n}\n\nexport function markSyncFailed(\n source: SyncSource,\n error: string,\n status: Extract<SyncStateStatus, \"auth_error\" | \"error\" | \"skipped_locked\">,\n): void {\n const now = new Date().toISOString();\n const current = loadSyncState();\n saveSyncState({\n ...current,\n lastCompletedAt: now,\n lastError: error,\n lastFailureAt: now,\n lastSource: source,\n pid: undefined,\n status,\n });\n}\n","import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport type {\n UploadManifest,\n UploadManifestScope,\n} from \"../../domain/upload-manifest\";\nimport { ensureAppDirs, getUploadManifestPath } from \"./paths\";\n\nfunction isRecordOfStrings(value: unknown): value is Record<string, string> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return false;\n }\n\n return Object.values(value).every((entry) => typeof entry === \"string\");\n}\n\ntype ParsedUploadManifest = Omit<UploadManifest, \"scope\"> & {\n scope: Omit<UploadManifestScope, \"snapshotProtocolVersion\"> & {\n snapshotProtocolVersion?: number;\n };\n};\n\nfunction isUploadManifest(value: unknown): value is ParsedUploadManifest {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return false;\n }\n\n const manifest = value as Partial<ParsedUploadManifest>;\n\n return (\n manifest.version === 1 &&\n !!manifest.scope &&\n typeof manifest.scope === \"object\" &&\n typeof manifest.scope.apiUrl === \"string\" &&\n typeof manifest.scope.apiKeyHash === \"string\" &&\n typeof manifest.scope.deviceId === \"string\" &&\n typeof manifest.scope.projectMode === \"string\" &&\n typeof manifest.scope.projectHashSaltHash === \"string\" &&\n (manifest.scope.snapshotProtocolVersion === undefined ||\n typeof manifest.scope.snapshotProtocolVersion === \"number\") &&\n typeof manifest.updatedAt === \"string\" &&\n isRecordOfStrings(manifest.buckets) &&\n isRecordOfStrings(manifest.sessions)\n );\n}\n\nexport function loadUploadManifest(): UploadManifest | null {\n const path = getUploadManifestPath();\n if (!existsSync(path)) {\n return null;\n }\n\n try {\n const parsed = JSON.parse(readFileSync(path, \"utf-8\")) as unknown;\n if (!isUploadManifest(parsed)) {\n return null;\n }\n\n return {\n ...parsed,\n scope: {\n ...parsed.scope,\n snapshotProtocolVersion: parsed.scope.snapshotProtocolVersion ?? 0,\n },\n };\n } catch {\n return null;\n }\n}\n\nexport function saveUploadManifest(manifest: UploadManifest): void {\n ensureAppDirs();\n writeFileSync(\n getUploadManifestPath(),\n `${JSON.stringify(manifest, null, 2)}\\n`,\n \"utf-8\",\n );\n}\n","import type {\n ParseResult,\n SessionMetadata,\n TokenBucket,\n} from \"../domain/types\";\nimport { detectInstalledTools, getAllParsers } from \"../parsers/registry\";\nimport { logger } from \"../utils/logger\";\n\nexport interface ParserResult {\n source: string;\n buckets: number;\n sessions: number;\n}\n\nexport interface AllParsersResult {\n buckets: TokenBucket[];\n sessions: SessionMetadata[];\n parserResults: ParserResult[];\n}\n\n/**\n * Run all registered parsers and collect results\n */\nexport async function runAllParsers(): Promise<AllParsersResult> {\n const allBuckets: TokenBucket[] = [];\n const allSessions: SessionMetadata[] = [];\n const parserResults: ParserResult[] = [];\n\n for (const parser of getAllParsers()) {\n try {\n const result: ParseResult = await parser.parse();\n const buckets = result.buckets;\n const sessions = result.sessions;\n\n if (buckets.length > 0) allBuckets.push(...buckets);\n if (sessions.length > 0) allSessions.push(...sessions);\n\n if (buckets.length > 0 || sessions.length > 0) {\n parserResults.push({\n source: parser.tool.id,\n buckets: buckets.length,\n sessions: sessions.length,\n });\n }\n } catch (err) {\n logger.warn(`${parser.tool.id} parser failed: ${(err as Error).message}`);\n }\n }\n\n return { buckets: allBuckets, sessions: allSessions, parserResults };\n}\n\n/**\n * Get list of detected tools for status display\n */\nexport function getDetectedTools() {\n return detectInstalledTools();\n}\n","import { execFileSync, spawn } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { appendFile, mkdir, readFile } from \"node:fs/promises\";\nimport { homedir, platform } from \"node:os\";\nimport { dirname, join, posix, win32 } from \"node:path\";\nimport { ApiClient } from \"../infrastructure/api/client\";\nimport {\n type Config,\n getDefaultApiUrl,\n getOrCreateDeviceId,\n loadConfig,\n saveConfig,\n validateApiKey,\n} from \"../infrastructure/config/manager\";\nimport { getServiceBackend } from \"../infrastructure/service\";\nimport {\n formatBullet,\n formatHeader,\n formatKeyValue,\n formatMutedPath,\n formatSection,\n maskSecret,\n} from \"../infrastructure/ui/format\";\nimport { promptConfirm, promptPassword } from \"../infrastructure/ui/prompts\";\nimport { getDetectedTools } from \"../services/parser-service\";\nimport { runSync } from \"../services/sync-service\";\nimport { logger } from \"../utils/logger\";\n\ninterface BrowserLaunchCommand {\n command: string;\n args: string[];\n}\n\nexport interface ShellAliasSetup {\n aliasLine: string;\n aliasPatterns: string[];\n configFile: string;\n shellLabel: string;\n sourceHint: string;\n}\n\ninterface ResolveShellAliasSetupOptions {\n currentPlatform?: NodeJS.Platform;\n env?: NodeJS.ProcessEnv;\n exists?: (path: string) => boolean;\n homeDir?: string;\n resolvePowerShellProfilePath?: () => string | null;\n}\n\nfunction joinForPlatform(\n currentPlatform: NodeJS.Platform,\n ...parts: string[]\n): string {\n return currentPlatform === \"win32\"\n ? win32.join(...parts)\n : posix.join(...parts);\n}\n\nfunction basenameLikeShell(input: string): string {\n return (\n input\n .split(/[\\\\/]+/)\n .pop()\n ?.replace(/\\.exe$/i, \"\") ?? input\n );\n}\n\nexport function getBrowserLaunchCommand(\n url: string,\n currentPlatform: NodeJS.Platform = platform(),\n): BrowserLaunchCommand {\n switch (currentPlatform) {\n case \"darwin\":\n return {\n command: \"open\",\n args: [url],\n };\n case \"win32\":\n return {\n command: \"cmd.exe\",\n args: [\"/d\", \"/s\", \"/c\", \"start\", \"\", url],\n };\n default:\n return {\n command: \"xdg-open\",\n args: [url],\n };\n }\n}\n\nfunction openBrowser(url: string): void {\n const { command, args } = getBrowserLaunchCommand(url);\n\n try {\n const child = spawn(command, args, {\n detached: true,\n stdio: \"ignore\",\n windowsHide: true,\n });\n\n child.on(\"error\", () => {});\n child.unref();\n } catch {\n // Best-effort only. We still print the URL for manual use.\n }\n}\n\nfunction resolvePowerShellProfilePath(): string | null {\n const systemRoot = process.env.SYSTEMROOT || \"C:\\\\Windows\";\n const candidates = [\n \"pwsh.exe\",\n join(systemRoot, \"System32\", \"WindowsPowerShell\", \"v1.0\", \"powershell.exe\"),\n ];\n\n for (const command of candidates) {\n try {\n const output = execFileSync(\n command,\n [\n \"-NoLogo\",\n \"-NoProfile\",\n \"-Command\",\n \"$PROFILE.CurrentUserCurrentHost\",\n ],\n {\n encoding: \"utf-8\",\n timeout: 3000,\n windowsHide: true,\n },\n ).trim();\n\n if (output) {\n return output;\n }\n } catch {\n // Try the next PowerShell executable.\n }\n }\n\n return null;\n}\n\nexport function resolveShellAliasSetup(\n options: ResolveShellAliasSetupOptions = {},\n): ShellAliasSetup | null {\n const currentPlatform = options.currentPlatform ?? platform();\n const env = options.env ?? process.env;\n const homeDir = options.homeDir ?? homedir();\n const pathExists = options.exists ?? existsSync;\n\n const shellFromEnv = env.SHELL\n ? basenameLikeShell(env.SHELL).toLowerCase()\n : \"\";\n const shellName =\n shellFromEnv || (currentPlatform === \"win32\" ? \"powershell\" : \"\");\n const aliasName = \"ta\";\n\n switch (shellName) {\n case \"zsh\":\n return {\n aliasLine: `alias ${aliasName}=\"tokenarena\"`,\n aliasPatterns: [`alias ${aliasName}=`, `function ${aliasName}`],\n configFile: joinForPlatform(currentPlatform, homeDir, \".zshrc\"),\n shellLabel: \"zsh\",\n sourceHint: \"source ~/.zshrc\",\n };\n case \"bash\": {\n const bashProfile = joinForPlatform(\n currentPlatform,\n homeDir,\n \".bash_profile\",\n );\n const useBashProfile =\n currentPlatform === \"darwin\" && pathExists(bashProfile);\n\n return {\n aliasLine: `alias ${aliasName}=\"tokenarena\"`,\n aliasPatterns: [`alias ${aliasName}=`, `function ${aliasName}`],\n configFile: useBashProfile\n ? bashProfile\n : joinForPlatform(currentPlatform, homeDir, \".bashrc\"),\n shellLabel: \"bash\",\n sourceHint: useBashProfile\n ? \"source ~/.bash_profile\"\n : \"source ~/.bashrc\",\n };\n }\n case \"fish\":\n return {\n aliasLine: `alias ${aliasName} \"tokenarena\"`,\n aliasPatterns: [`alias ${aliasName}`, `function ${aliasName}`],\n configFile: joinForPlatform(\n currentPlatform,\n homeDir,\n \".config\",\n \"fish\",\n \"config.fish\",\n ),\n shellLabel: \"fish\",\n sourceHint: \"source ~/.config/fish/config.fish\",\n };\n case \"powershell\": {\n const configFile =\n options.resolvePowerShellProfilePath?.() ||\n resolvePowerShellProfilePath() ||\n joinForPlatform(\n currentPlatform,\n homeDir,\n \"Documents\",\n \"PowerShell\",\n \"Microsoft.PowerShell_profile.ps1\",\n );\n\n return {\n aliasLine: `Set-Alias -Name ${aliasName} -Value tokenarena`,\n aliasPatterns: [\n `set-alias -name ${aliasName}`,\n `set-alias ${aliasName}`,\n `new-alias ${aliasName}`,\n `function ${aliasName}`,\n ],\n configFile,\n shellLabel: \"PowerShell\",\n sourceHint: \". $PROFILE\",\n };\n }\n default:\n return null;\n }\n}\n\nexport interface InitOptions {\n apiUrl?: string;\n}\n\nexport async function runInit(opts: InitOptions = {}): Promise<void> {\n logger.info(formatHeader(\"TokenArena 初始化\"));\n\n const existing = loadConfig();\n if (existing?.apiKey) {\n logger.info(formatSection(\"检测到已有配置\"));\n logger.info(formatKeyValue(\"当前 API Key\", maskSecret(existing.apiKey)));\n logger.info(\n formatKeyValue(\n \"当前 API 地址\",\n existing.apiUrl || \"https://token.guji.uno\",\n ),\n );\n\n const shouldOverwrite = await promptConfirm({\n message: \"已经存在本地配置,是否覆盖并重新初始化?\",\n defaultValue: false,\n });\n\n if (!shouldOverwrite) {\n logger.info(formatBullet(\"已取消初始化。\", \"warning\"));\n return;\n }\n }\n\n const apiUrl = opts.apiUrl || getDefaultApiUrl();\n const cliKeysUrl = `${apiUrl}/zh/settings/cli-keys`;\n logger.info(formatSection(\"第 1 步:准备 API Key\"));\n logger.info(formatBullet(\"浏览器将尝试自动打开 CLI Key 页面。\"));\n logger.info(formatKeyValue(\"Key 页面\", formatMutedPath(cliKeysUrl)));\n openBrowser(cliKeysUrl);\n\n const apiKey = await promptPassword({\n message: \"请粘贴你的 CLI API Key\",\n validate: (value) => validateApiKey(value) || 'API Key 必须以 \"ta_\" 开头。',\n });\n\n logger.info(formatSection(\"第 2 步:验证 API Key\"));\n logger.info(formatKeyValue(\"待验证 Key\", maskSecret(apiKey)));\n try {\n const client = new ApiClient(apiUrl, apiKey);\n const settings = await client.fetchSettings();\n\n if (!settings) {\n logger.info(\n formatBullet(\n \"无法在线验证 Key(可能是网络原因),将继续保存。\",\n \"warning\",\n ),\n );\n } else {\n logger.info(formatBullet(\"API Key 验证成功。\", \"success\"));\n }\n } catch (err) {\n if ((err as Error).message === \"UNAUTHORIZED\") {\n logger.error(\"Invalid API key. Please check and try again.\");\n process.exit(1);\n }\n logger.info(\n formatBullet(\n \"无法完成在线验证(可能是网络原因),将继续保存。\",\n \"warning\",\n ),\n );\n }\n\n const config: Config = {\n apiKey,\n apiUrl,\n ...(existing?.deviceId ? { deviceId: existing.deviceId } : {}),\n };\n saveConfig(config);\n const deviceId = getOrCreateDeviceId(config);\n config.deviceId = deviceId;\n logger.info(formatSection(\"第 3 步:完成本地注册\"));\n\n const tools = getDetectedTools();\n if (tools.length > 0) {\n logger.info(formatSection(\"检测到的 AI CLI\"));\n for (const tool of tools) {\n logger.info(formatBullet(tool.name, \"success\"));\n }\n } else {\n logger.info(formatSection(\"检测到的 AI CLI\"));\n logger.info(\n formatBullet(\n \"当前未检测到已安装工具,稍后安装后也可以直接执行 sync。\",\n \"warning\",\n ),\n );\n }\n\n logger.info(formatSection(\"首次同步\"));\n logger.info(formatBullet(\"正在上传本地已有的使用数据。\"));\n await runSync(config, { source: \"init\" });\n\n logger.info(formatSection(\"初始化完成\"));\n logger.info(formatBullet(\"TokenArena 已准备就绪。\", \"success\"));\n logger.info(formatKeyValue(\"控制台\", `${apiUrl}/usage`));\n\n await setupShellAlias();\n await setupBackgroundService();\n}\n\nasync function setupBackgroundService(): Promise<void> {\n const backend = getServiceBackend();\n if (!backend) {\n return;\n }\n\n const support = backend.canSetup();\n if (!support.ok) {\n return;\n }\n\n const shouldSetup = await promptConfirm({\n message: `是否设置 ${backend.displayName} 以自动运行 daemon?`,\n defaultValue: true,\n });\n\n if (!shouldSetup) {\n logger.info(formatBullet(\"已跳过后台服务设置。\"));\n return;\n }\n\n try {\n await backend.setup(true);\n } catch (err) {\n logger.warn(`${backend.displayName} 设置失败: ${(err as Error).message}`);\n }\n}\n\nasync function setupShellAlias(): Promise<void> {\n const setup = resolveShellAliasSetup();\n if (!setup) {\n return;\n }\n\n const shouldCreateAlias = await promptConfirm({\n message: `是否为 ${setup.shellLabel} 自动添加 ta 别名?`,\n defaultValue: true,\n });\n if (!shouldCreateAlias) {\n logger.info(formatBullet(\"已跳过 shell alias 设置。\"));\n return;\n }\n\n try {\n await mkdir(dirname(setup.configFile), { recursive: true });\n\n let existingContent = \"\";\n if (existsSync(setup.configFile)) {\n existingContent = await readFile(setup.configFile, \"utf-8\");\n }\n\n const normalizedContent = existingContent.toLowerCase();\n const aliasExists = setup.aliasPatterns.some((pattern) =>\n normalizedContent.includes(pattern.toLowerCase()),\n );\n\n if (aliasExists) {\n logger.info(formatBullet(`别名 ta 已存在:${setup.configFile}`));\n return;\n }\n\n const aliasWithComment = `\\n# TokenArena alias\\n${setup.aliasLine}\\n`;\n await appendFile(setup.configFile, aliasWithComment, \"utf-8\");\n\n logger.info(formatSection(\"Shell alias\"));\n logger.info(formatBullet(`已写入 ${setup.configFile}`, \"success\"));\n logger.info(\n formatKeyValue(\"生效方式\", `执行 '${setup.sourceHint}' 或重启终端`),\n );\n logger.info(formatKeyValue(\"之后可用\", \"ta sync\"));\n } catch (err) {\n logger.info(formatSection(\"Shell alias\"));\n logger.info(\n formatBullet(\n `无法写入 ${setup.configFile}: ${(err as Error).message}`,\n \"warning\",\n ),\n );\n logger.info(formatKeyValue(\"请手动添加\", setup.aliasLine));\n }\n}\n","import { platform } from \"node:os\";\nimport { createLinuxSystemdServiceBackend } from \"./linux-systemd\";\nimport { createMacosLaunchdServiceBackend } from \"./macos-launchd\";\nimport type { ServiceBackend } from \"./types\";\n\nexport function getServiceBackend(\n currentPlatform: NodeJS.Platform = platform(),\n): ServiceBackend | null {\n switch (currentPlatform) {\n case \"linux\":\n return createLinuxSystemdServiceBackend();\n case \"darwin\":\n return createMacosLaunchdServiceBackend();\n default:\n return null;\n }\n}\n","import { execFileSync } from \"node:child_process\";\nimport { existsSync, mkdirSync, rmSync, writeFileSync } from \"node:fs\";\nimport { homedir, platform } from \"node:os\";\nimport { posix } from \"node:path\";\nimport { isCommandAvailable } from \"../../utils/command\";\nimport { logger } from \"../../utils/logger\";\nimport {\n formatBullet,\n formatHeader,\n formatKeyValue,\n formatSection,\n} from \"../ui/format\";\nimport { promptConfirm } from \"../ui/prompts\";\nimport type { ServiceBackend, ServiceSupport } from \"./types\";\nimport {\n escapeDoubleQuotedValue,\n getManagedServiceEnvironment,\n resolveManagedDaemonCommand,\n} from \"./utils\";\n\nconst SYSTEMD_SERVICE_NAME = \"tokenarena\";\n\nexport interface SystemdServiceDefinitionOptions {\n environment: Record<string, string>;\n execPath: string;\n args: string[];\n}\n\nexport function getLinuxSystemdServiceDir(homePath = homedir()): string {\n return posix.join(homePath, \".config\", \"systemd\", \"user\");\n}\n\nexport function getLinuxSystemdServiceFile(homePath = homedir()): string {\n return posix.join(\n getLinuxSystemdServiceDir(homePath),\n `${SYSTEMD_SERVICE_NAME}.service`,\n );\n}\n\nexport function buildSystemdServiceContent(\n options: SystemdServiceDefinitionOptions,\n): string {\n const envLines = Object.entries(options.environment)\n .map(\n ([key, value]) =>\n `Environment=\"${escapeDoubleQuotedValue(key)}=${escapeDoubleQuotedValue(value)}\"`,\n )\n .join(\"\\n\");\n const execArgs = [options.execPath, ...options.args]\n .map((value) => `\"${escapeDoubleQuotedValue(value)}\"`)\n .join(\" \");\n\n return `[Unit]\nDescription=TokenArena Daemon - AI Usage Tracker\nAfter=network-online.target\nWants=network-online.target\n\n[Service]\nType=simple\nExecStart=${execArgs}\nRestart=on-failure\nRestartSec=10\n${envLines}\n\n[Install]\nWantedBy=default.target\n`;\n}\n\nfunction getSystemdSupport(): ServiceSupport {\n if (platform() !== \"linux\") {\n return {\n ok: false,\n reason: \"systemd 仅在 Linux 上可用。\",\n };\n }\n\n if (!isCommandAvailable(\"systemctl\")) {\n return {\n ok: false,\n reason: \"未检测到 systemctl。\",\n };\n }\n\n return { ok: true };\n}\n\nfunction execSystemctl(args: string[]): void {\n execFileSync(\"systemctl\", [\"--user\", ...args], {\n stdio: \"inherit\",\n });\n}\n\nfunction ensureSystemdAvailable(): boolean {\n const support = getSystemdSupport();\n if (support.ok) {\n return true;\n }\n\n logger.info(formatBullet(`systemd 不可用。${support.reason}`, \"warning\"));\n return false;\n}\n\nexport function createLinuxSystemdServiceBackend(): ServiceBackend {\n function isInstalled(): boolean {\n return existsSync(getLinuxSystemdServiceFile());\n }\n\n async function setup(skipPrompt = false): Promise<void> {\n if (!ensureSystemdAvailable()) {\n return;\n }\n\n const serviceDir = getLinuxSystemdServiceDir();\n const serviceFile = getLinuxSystemdServiceFile();\n\n logger.info(formatHeader(\"设置 systemd 服务\", \"TokenArena daemon\"));\n\n if (!skipPrompt) {\n const shouldSetup = await promptConfirm({\n message: \"是否创建并启用 systemd 用户服务?\",\n defaultValue: true,\n });\n\n if (!shouldSetup) {\n logger.info(formatBullet(\"已取消服务设置。\"));\n return;\n }\n }\n\n try {\n const command = resolveManagedDaemonCommand();\n const content = buildSystemdServiceContent({\n environment: getManagedServiceEnvironment(),\n execPath: command.execPath,\n args: command.args,\n });\n\n mkdirSync(serviceDir, { recursive: true });\n writeFileSync(serviceFile, content, \"utf-8\");\n\n execSystemctl([\"daemon-reload\"]);\n execSystemctl([\"enable\", SYSTEMD_SERVICE_NAME]);\n execSystemctl([\"start\", SYSTEMD_SERVICE_NAME]);\n\n logger.info(formatSection(\"服务已设置\"));\n logger.info(formatBullet(`服务文件: ${serviceFile}`, \"success\"));\n logger.info(formatBullet(\"服务已启用并启动\", \"success\"));\n logger.info(\n formatKeyValue(\"查看状态\", \"systemctl --user status tokenarena\"),\n );\n } catch (err) {\n logger.error(`设置服务失败: ${(err as Error).message}`);\n throw err;\n }\n }\n\n async function start(): Promise<void> {\n if (!ensureSystemdAvailable()) {\n return;\n }\n\n if (!isInstalled()) {\n logger.info(\n formatBullet(\n \"服务文件不存在。请先运行 'tokenarena service setup'。\",\n \"warning\",\n ),\n );\n return;\n }\n\n try {\n execSystemctl([\"start\", SYSTEMD_SERVICE_NAME]);\n logger.info(formatBullet(\"服务已启动\", \"success\"));\n } catch (err) {\n logger.error(`启动服务失败: ${(err as Error).message}`);\n throw err;\n }\n }\n\n async function stop(): Promise<void> {\n if (!ensureSystemdAvailable()) {\n return;\n }\n\n if (!isInstalled()) {\n logger.info(\n formatBullet(\n \"服务文件不存在。请先运行 'tokenarena service setup'。\",\n \"warning\",\n ),\n );\n return;\n }\n\n try {\n execSystemctl([\"stop\", SYSTEMD_SERVICE_NAME]);\n logger.info(formatBullet(\"服务已停止\", \"success\"));\n } catch (err) {\n logger.error(`停止服务失败: ${(err as Error).message}`);\n throw err;\n }\n }\n\n async function restart(): Promise<void> {\n if (!ensureSystemdAvailable()) {\n return;\n }\n\n if (!isInstalled()) {\n logger.info(\n formatBullet(\n \"服务文件不存在。请先运行 'tokenarena service setup'。\",\n \"warning\",\n ),\n );\n return;\n }\n\n try {\n execSystemctl([\"restart\", SYSTEMD_SERVICE_NAME]);\n logger.info(formatBullet(\"服务已重启\", \"success\"));\n } catch (err) {\n logger.error(`重启服务失败: ${(err as Error).message}`);\n throw err;\n }\n }\n\n async function status(): Promise<void> {\n if (!ensureSystemdAvailable()) {\n return;\n }\n\n if (!isInstalled()) {\n logger.info(\n formatBullet(\n \"服务文件不存在。请先运行 'tokenarena service setup'。\",\n \"warning\",\n ),\n );\n return;\n }\n\n try {\n execSystemctl([\"status\", SYSTEMD_SERVICE_NAME]);\n } catch {\n // systemctl status returns non-zero when the service is inactive or failed.\n }\n }\n\n async function uninstall(skipPrompt = false): Promise<void> {\n const serviceFile = getLinuxSystemdServiceFile();\n if (!existsSync(serviceFile)) {\n logger.info(formatBullet(\"服务文件不存在。\", \"warning\"));\n return;\n }\n\n if (!skipPrompt) {\n const shouldUninstall = await promptConfirm({\n message: \"是否卸载 systemd 服务?\",\n defaultValue: false,\n });\n\n if (!shouldUninstall) {\n logger.info(formatBullet(\"已取消卸载。\"));\n return;\n }\n }\n\n const support = getSystemdSupport();\n if (support.ok) {\n try {\n execSystemctl([\"stop\", SYSTEMD_SERVICE_NAME]);\n } catch {\n // Best effort: proceed with file cleanup.\n }\n\n try {\n execSystemctl([\"disable\", SYSTEMD_SERVICE_NAME]);\n } catch {\n // Best effort: proceed with file cleanup.\n }\n } else {\n logger.info(\n formatBullet(\n `当前无法访问 systemd,将只删除服务文件。${support.reason}`,\n \"warning\",\n ),\n );\n }\n\n try {\n rmSync(serviceFile);\n if (support.ok) {\n execSystemctl([\"daemon-reload\"]);\n }\n\n logger.info(formatSection(\"服务已卸载\"));\n logger.info(formatBullet(\"服务已停用并删除\", \"success\"));\n } catch (err) {\n logger.error(`卸载服务失败: ${(err as Error).message}`);\n throw err;\n }\n }\n\n return {\n displayName: \"systemd 用户服务\",\n canSetup: getSystemdSupport,\n isInstalled,\n getDefinitionPath: getLinuxSystemdServiceFile,\n getStatusHint: () => \"systemctl --user status tokenarena\",\n setup,\n start,\n stop,\n restart,\n status,\n uninstall,\n };\n}\n","import { execSync } from \"node:child_process\";\nimport { platform } from \"node:os\";\n\n/**\n * Check if a command is available in PATH.\n * Uses `command -v` on Unix and `where` on Windows.\n *\n * @param command - The command name to check (e.g., 'systemctl', 'git')\n * @returns true if the command exists, false otherwise\n */\nexport function isCommandAvailable(command: string): boolean {\n try {\n const check =\n platform() === \"win32\" ? `where ${command}` : `command -v ${command}`;\n execSync(check, { stdio: \"ignore\" });\n return true;\n } catch {\n return false;\n }\n}\n","const SERVICE_PATH_FALLBACKS = [\n \"/opt/homebrew/bin\",\n \"/usr/local/bin\",\n \"/usr/bin\",\n \"/bin\",\n \"/usr/sbin\",\n \"/sbin\",\n];\n\nconst SERVICE_ENV_KEYS = [\n \"TOKEN_ARENA_DEV\",\n \"XDG_CONFIG_HOME\",\n \"XDG_STATE_HOME\",\n \"XDG_RUNTIME_DIR\",\n] as const;\n\nexport interface ManagedDaemonCommand {\n execPath: string;\n args: string[];\n}\n\nfunction dedupePaths(paths: string[]): string[] {\n return [...new Set(paths.filter(Boolean))];\n}\n\nexport function getManagedServiceEnvironment(\n env: NodeJS.ProcessEnv = process.env,\n): Record<string, string> {\n const pathEntries = dedupePaths([\n ...(env.PATH?.split(\":\") ?? []),\n ...SERVICE_PATH_FALLBACKS,\n ]);\n const next: Record<string, string> = {\n PATH: pathEntries.join(\":\"),\n };\n\n for (const key of SERVICE_ENV_KEYS) {\n const value = env[key];\n if (value) {\n next[key] = value;\n }\n }\n\n return next;\n}\n\nexport function resolveManagedDaemonCommand(\n execPath = process.execPath,\n argv = process.argv,\n): ManagedDaemonCommand {\n const scriptPath = argv[1];\n if (!scriptPath) {\n throw new Error(\"无法解析 CLI 入口路径,请通过 tokenarena 命令重新执行。\");\n }\n\n return {\n execPath,\n args: [scriptPath, \"daemon\", \"--service\"],\n };\n}\n\nexport function escapeDoubleQuotedValue(value: string): string {\n return value.replaceAll(\"\\\\\", \"\\\\\\\\\").replaceAll('\"', '\\\\\"');\n}\n\nexport function escapeXml(value: string): string {\n return value\n .replaceAll(\"&\", \"&amp;\")\n .replaceAll(\"<\", \"&lt;\")\n .replaceAll(\">\", \"&gt;\")\n .replaceAll('\"', \"&quot;\")\n .replaceAll(\"'\", \"&apos;\");\n}\n","import { execFileSync } from \"node:child_process\";\nimport { existsSync, mkdirSync, rmSync, writeFileSync } from \"node:fs\";\nimport { homedir, platform } from \"node:os\";\nimport { posix } from \"node:path\";\nimport { isCommandAvailable } from \"../../utils/command\";\nimport { logger } from \"../../utils/logger\";\nimport { ensureAppDirs, getStateDir } from \"../runtime/paths\";\nimport {\n formatBullet,\n formatHeader,\n formatKeyValue,\n formatSection,\n} from \"../ui/format\";\nimport { promptConfirm } from \"../ui/prompts\";\nimport type { ServiceBackend, ServiceSupport } from \"./types\";\nimport {\n escapeXml,\n getManagedServiceEnvironment,\n resolveManagedDaemonCommand,\n} from \"./utils\";\n\nexport const MACOS_LAUNCHD_LABEL = \"com.guji.tokenarena\";\n\nexport interface LaunchdPlistOptions {\n label: string;\n programArguments: string[];\n environment: Record<string, string>;\n workingDirectory: string;\n standardOutPath: string;\n standardErrorPath: string;\n}\n\nfunction getCurrentUid(): number | null {\n return typeof process.getuid === \"function\" ? process.getuid() : null;\n}\n\nexport function getMacosLaunchAgentDir(homePath = homedir()): string {\n return posix.join(homePath, \"Library\", \"LaunchAgents\");\n}\n\nexport function getMacosLaunchAgentFile(homePath = homedir()): string {\n return posix.join(\n getMacosLaunchAgentDir(homePath),\n `${MACOS_LAUNCHD_LABEL}.plist`,\n );\n}\n\nexport function getMacosLaunchdDomain(uid = getCurrentUid()): string {\n if (uid == null) {\n throw new Error(\"无法获取当前用户 UID。\");\n }\n\n return `gui/${uid}`;\n}\n\nexport function getMacosLaunchdServiceTarget(uid = getCurrentUid()): string {\n return `${getMacosLaunchdDomain(uid)}/${MACOS_LAUNCHD_LABEL}`;\n}\n\nexport function getMacosLaunchdLogPaths(stateDir = getStateDir()): {\n stdoutPath: string;\n stderrPath: string;\n} {\n return {\n stdoutPath: posix.join(stateDir, \"launchd.stdout.log\"),\n stderrPath: posix.join(stateDir, \"launchd.stderr.log\"),\n };\n}\n\nfunction renderPlistArray(values: string[]): string {\n return values\n .map((value) => ` <string>${escapeXml(value)}</string>`)\n .join(\"\\n\");\n}\n\nfunction renderPlistDict(entries: Record<string, string>): string {\n return Object.entries(entries)\n .map(\n ([key, value]) =>\n ` <key>${escapeXml(key)}</key>\\n <string>${escapeXml(value)}</string>`,\n )\n .join(\"\\n\");\n}\n\nexport function buildLaunchdPlist(options: LaunchdPlistOptions): string {\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n <dict>\n <key>Label</key>\n <string>${escapeXml(options.label)}</string>\n <key>ProgramArguments</key>\n <array>\n${renderPlistArray(options.programArguments)}\n </array>\n <key>WorkingDirectory</key>\n <string>${escapeXml(options.workingDirectory)}</string>\n <key>EnvironmentVariables</key>\n <dict>\n${renderPlistDict(options.environment)}\n </dict>\n <key>KeepAlive</key>\n <dict>\n <key>SuccessfulExit</key>\n <false/>\n </dict>\n <key>ProcessType</key>\n <string>Background</string>\n <key>ThrottleInterval</key>\n <integer>30</integer>\n <key>ExitTimeOut</key>\n <integer>15</integer>\n <key>StandardOutPath</key>\n <string>${escapeXml(options.standardOutPath)}</string>\n <key>StandardErrorPath</key>\n <string>${escapeXml(options.standardErrorPath)}</string>\n </dict>\n</plist>\n`;\n}\n\nfunction getLaunchctlSupport(): ServiceSupport {\n if (platform() !== \"darwin\") {\n return {\n ok: false,\n reason: \"launchd 仅在 macOS 上可用。\",\n };\n }\n\n if (!isCommandAvailable(\"launchctl\")) {\n return {\n ok: false,\n reason: \"未检测到 launchctl。\",\n };\n }\n\n const uid = getCurrentUid();\n if (uid == null) {\n return {\n ok: false,\n reason: \"无法获取当前用户 UID。\",\n };\n }\n\n try {\n execFileSync(\"launchctl\", [\"print\", getMacosLaunchdDomain(uid)], {\n stdio: \"ignore\",\n });\n return { ok: true };\n } catch {\n return {\n ok: false,\n reason: \"当前未检测到图形化登录会话,请在桌面终端中执行。\",\n };\n }\n}\n\nfunction execLaunchctl(args: string[], inherit = true): void {\n execFileSync(\"launchctl\", args, {\n stdio: inherit ? \"inherit\" : \"ignore\",\n });\n}\n\nfunction isLoaded(): boolean {\n try {\n execLaunchctl([\"print\", getMacosLaunchdServiceTarget()], false);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction ensureLaunchctlAvailable(): boolean {\n const support = getLaunchctlSupport();\n if (support.ok) {\n return true;\n }\n\n logger.info(formatBullet(`launchd 不可用。${support.reason}`, \"warning\"));\n return false;\n}\n\nfunction writeLaunchAgentPlist(): string {\n const plistFile = getMacosLaunchAgentFile();\n const { stdoutPath, stderrPath } = getMacosLaunchdLogPaths();\n const command = resolveManagedDaemonCommand();\n const plist = buildLaunchdPlist({\n label: MACOS_LAUNCHD_LABEL,\n programArguments: [command.execPath, ...command.args],\n environment: getManagedServiceEnvironment(),\n workingDirectory: homedir(),\n standardOutPath: stdoutPath,\n standardErrorPath: stderrPath,\n });\n\n ensureAppDirs();\n mkdirSync(getMacosLaunchAgentDir(), { recursive: true });\n writeFileSync(plistFile, plist, \"utf-8\");\n\n return plistFile;\n}\n\nfunction bootstrapLaunchAgent(): void {\n const domain = getMacosLaunchdDomain();\n const serviceTarget = getMacosLaunchdServiceTarget();\n const plistFile = getMacosLaunchAgentFile();\n\n if (isLoaded()) {\n try {\n execLaunchctl([\"bootout\", serviceTarget]);\n } catch {\n // Best effort: try a fresh bootstrap anyway.\n }\n }\n\n execLaunchctl([\"bootstrap\", domain, plistFile]);\n execLaunchctl([\"enable\", serviceTarget]);\n execLaunchctl([\"kickstart\", \"-k\", serviceTarget]);\n}\n\nexport function createMacosLaunchdServiceBackend(): ServiceBackend {\n function isInstalled(): boolean {\n return existsSync(getMacosLaunchAgentFile());\n }\n\n async function setup(skipPrompt = false): Promise<void> {\n if (!ensureLaunchctlAvailable()) {\n return;\n }\n\n logger.info(formatHeader(\"设置 launchd 服务\", \"TokenArena daemon\"));\n\n if (!skipPrompt) {\n const shouldSetup = await promptConfirm({\n message: \"是否创建并启用 launchd 用户服务?\",\n defaultValue: true,\n });\n\n if (!shouldSetup) {\n logger.info(formatBullet(\"已取消服务设置。\"));\n return;\n }\n }\n\n try {\n const plistFile = writeLaunchAgentPlist();\n bootstrapLaunchAgent();\n\n logger.info(formatSection(\"服务已设置\"));\n logger.info(formatBullet(`服务文件: ${plistFile}`, \"success\"));\n logger.info(formatBullet(\"服务已启用并启动\", \"success\"));\n logger.info(\n formatKeyValue(\n \"查看状态\",\n `launchctl print ${getMacosLaunchdServiceTarget()}`,\n ),\n );\n } catch (err) {\n logger.error(`设置服务失败: ${(err as Error).message}`);\n throw err;\n }\n }\n\n async function start(): Promise<void> {\n if (!ensureLaunchctlAvailable()) {\n return;\n }\n\n if (!isInstalled()) {\n logger.info(\n formatBullet(\n \"服务文件不存在。请先运行 'tokenarena service setup'。\",\n \"warning\",\n ),\n );\n return;\n }\n\n try {\n if (!isLoaded()) {\n execLaunchctl([\n \"bootstrap\",\n getMacosLaunchdDomain(),\n getMacosLaunchAgentFile(),\n ]);\n }\n execLaunchctl([\"enable\", getMacosLaunchdServiceTarget()]);\n execLaunchctl([\"kickstart\", \"-k\", getMacosLaunchdServiceTarget()]);\n logger.info(formatBullet(\"服务已启动\", \"success\"));\n } catch (err) {\n logger.error(`启动服务失败: ${(err as Error).message}`);\n throw err;\n }\n }\n\n async function stop(): Promise<void> {\n if (!isInstalled()) {\n logger.info(\n formatBullet(\n \"服务文件不存在。请先运行 'tokenarena service setup'。\",\n \"warning\",\n ),\n );\n return;\n }\n\n if (!ensureLaunchctlAvailable()) {\n return;\n }\n\n if (!isLoaded()) {\n logger.info(formatBullet(\"服务当前未运行。\", \"warning\"));\n return;\n }\n\n try {\n execLaunchctl([\"bootout\", getMacosLaunchdServiceTarget()]);\n logger.info(formatBullet(\"服务已停止\", \"success\"));\n } catch (err) {\n logger.error(`停止服务失败: ${(err as Error).message}`);\n throw err;\n }\n }\n\n async function restart(): Promise<void> {\n if (!ensureLaunchctlAvailable()) {\n return;\n }\n\n if (!isInstalled()) {\n logger.info(\n formatBullet(\n \"服务文件不存在。请先运行 'tokenarena service setup'。\",\n \"warning\",\n ),\n );\n return;\n }\n\n try {\n if (isLoaded()) {\n execLaunchctl([\"kickstart\", \"-k\", getMacosLaunchdServiceTarget()]);\n } else {\n execLaunchctl([\n \"bootstrap\",\n getMacosLaunchdDomain(),\n getMacosLaunchAgentFile(),\n ]);\n execLaunchctl([\"enable\", getMacosLaunchdServiceTarget()]);\n execLaunchctl([\"kickstart\", \"-k\", getMacosLaunchdServiceTarget()]);\n }\n logger.info(formatBullet(\"服务已重启\", \"success\"));\n } catch (err) {\n logger.error(`重启服务失败: ${(err as Error).message}`);\n throw err;\n }\n }\n\n async function status(): Promise<void> {\n if (!isInstalled()) {\n logger.info(\n formatBullet(\n \"服务文件不存在。请先运行 'tokenarena service setup'。\",\n \"warning\",\n ),\n );\n return;\n }\n\n if (!ensureLaunchctlAvailable()) {\n return;\n }\n\n try {\n execLaunchctl([\"print\", getMacosLaunchdServiceTarget()]);\n } catch {\n logger.info(formatBullet(\"服务当前未加载。\", \"warning\"));\n logger.info(formatKeyValue(\"服务文件\", getMacosLaunchAgentFile()));\n }\n }\n\n async function uninstall(skipPrompt = false): Promise<void> {\n const plistFile = getMacosLaunchAgentFile();\n if (!existsSync(plistFile)) {\n logger.info(formatBullet(\"服务文件不存在。\", \"warning\"));\n return;\n }\n\n if (!skipPrompt) {\n const shouldUninstall = await promptConfirm({\n message: \"是否卸载 launchd 服务?\",\n defaultValue: false,\n });\n\n if (!shouldUninstall) {\n logger.info(formatBullet(\"已取消卸载。\"));\n return;\n }\n }\n\n const support = getLaunchctlSupport();\n if (support.ok && isLoaded()) {\n try {\n execLaunchctl([\"bootout\", getMacosLaunchdServiceTarget()]);\n } catch {\n // Best effort: continue with file cleanup.\n }\n } else if (!support.ok) {\n logger.info(\n formatBullet(\n `当前无法访问 launchd,会直接删除本地 plist 文件。${support.reason}`,\n \"warning\",\n ),\n );\n }\n\n try {\n const { stdoutPath, stderrPath } = getMacosLaunchdLogPaths();\n rmSync(plistFile);\n rmSync(stdoutPath, { force: true });\n rmSync(stderrPath, { force: true });\n\n logger.info(formatSection(\"服务已卸载\"));\n logger.info(formatBullet(\"服务已停用并删除\", \"success\"));\n } catch (err) {\n logger.error(`卸载服务失败: ${(err as Error).message}`);\n throw err;\n }\n }\n\n return {\n displayName: \"launchd 用户服务\",\n canSetup: getLaunchctlSupport,\n isInstalled,\n getDefinitionPath: getMacosLaunchAgentFile,\n getStatusHint: () => `launchctl print ${getMacosLaunchdServiceTarget()}`,\n setup,\n start,\n stop,\n restart,\n status,\n uninstall,\n };\n}\n","import { loadConfig } from \"../infrastructure/config/manager\";\nimport { formatBullet, formatHeader } from \"../infrastructure/ui/format\";\nimport {\n isInteractiveTerminal,\n promptConfirm,\n} from \"../infrastructure/ui/prompts\";\nimport { runSync } from \"../services/sync-service\";\nimport { logger } from \"../utils/logger\";\nimport { runInit } from \"./init\";\n\nconst DEFAULT_INTERVAL = 30 * 60_000; // 30 minutes\n\nfunction log(msg: string): void {\n const ts = new Date().toLocaleTimeString(\"en-US\", { hour12: false });\n process.stdout.write(`[${ts}] ${msg}\\n`);\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport interface DaemonOptions {\n interval?: number;\n service?: boolean;\n}\n\nexport function getDaemonExitCode(opts: DaemonOptions = {}): number {\n return opts.service ? 0 : 1;\n}\n\nexport async function runDaemon(opts: DaemonOptions = {}): Promise<void> {\n const config = loadConfig();\n if (!config?.apiKey) {\n if (isInteractiveTerminal()) {\n logger.info(\n formatHeader(\n \"尚未完成初始化\",\n \"启动 daemon 前需要先配置有效的 API Key。\",\n ),\n );\n const shouldInit = await promptConfirm({\n message: \"是否先进入初始化流程?\",\n defaultValue: true,\n });\n if (shouldInit) {\n await runInit();\n return;\n }\n logger.info(formatBullet(\"已取消启动 daemon。\", \"warning\"));\n return;\n }\n\n const message = opts.service\n ? \"Not configured. Exiting service mode.\"\n : \"Not configured. Run `tokenarena init` first.\";\n logger.error(message);\n process.exit(getDaemonExitCode(opts));\n }\n\n const interval = opts.interval || config.syncInterval || DEFAULT_INTERVAL;\n const intervalMin = Math.round(interval / 60000);\n const stopHint = opts.service ? \"service mode\" : \"Ctrl+C to stop\";\n\n log(`Daemon started (sync every ${intervalMin}m, ${stopHint})`);\n\n // eslint-disable-next-line no-constant-condition\n while (true) {\n try {\n const fresh = loadConfig();\n await runSync(fresh ?? config, {\n quiet: true,\n source: \"daemon\",\n throws: true,\n });\n } catch (err) {\n if ((err as Error).message === \"UNAUTHORIZED\") {\n const message = opts.service\n ? \"API key invalid. Exiting service mode.\"\n : \"API key invalid. Exiting.\";\n log(message);\n process.exit(getDaemonExitCode(opts));\n }\n log(`Sync error: ${(err as Error).message}`);\n }\n await sleep(interval);\n }\n}\n","import type { SessionMetadata, TokenBucket } from \"./types\";\n\nexport interface LocalUsageToolDefinition {\n id: string;\n name: string;\n}\n\nexport interface LocalUsageTotals {\n inputTokens: number;\n outputTokens: number;\n cachedTokens: number;\n reasoningTokens: number;\n totalTokens: number;\n buckets: number;\n sessions: number;\n projects: number;\n models: number;\n}\n\nexport interface LocalUsageRankItem {\n name: string;\n totalTokens: number;\n inputTokens: number;\n outputTokens: number;\n cachedTokens: number;\n reasoningTokens: number;\n sessions: number;\n}\n\nexport interface LocalUsageSessionItem {\n project: string;\n primaryModel: string;\n lastMessageAt: string;\n totalTokens: number;\n messageCount: number;\n activeSeconds: number;\n}\n\nexport interface LocalUsageToolSummary {\n source: string;\n name: string;\n totals: LocalUsageTotals;\n topModels: LocalUsageRankItem[];\n topProjects: LocalUsageRankItem[];\n sessions: LocalUsageSessionItem[];\n}\n\nexport interface LocalUsageDashboardData {\n generatedAt: string;\n totals: LocalUsageTotals;\n tools: LocalUsageToolSummary[];\n}\n\nexport interface BuildLocalUsageDashboardInput {\n buckets: TokenBucket[];\n sessions: SessionMetadata[];\n tools: LocalUsageToolDefinition[];\n}\n\nfunction createTotals(): LocalUsageTotals {\n return {\n inputTokens: 0,\n outputTokens: 0,\n cachedTokens: 0,\n reasoningTokens: 0,\n totalTokens: 0,\n buckets: 0,\n sessions: 0,\n projects: 0,\n models: 0,\n };\n}\n\nfunction addBucketToTotals(\n totals: LocalUsageTotals,\n bucket: TokenBucket,\n): void {\n totals.inputTokens += bucket.inputTokens || 0;\n totals.outputTokens += bucket.outputTokens || 0;\n totals.cachedTokens += bucket.cachedTokens || 0;\n totals.reasoningTokens += bucket.reasoningTokens || 0;\n totals.totalTokens += bucket.totalTokens || 0;\n totals.buckets += 1;\n}\n\nfunction addBucketToRank(\n map: Map<string, LocalUsageRankItem>,\n key: string,\n bucket: TokenBucket,\n): void {\n const name = key || \"unknown\";\n const current = map.get(name) ?? {\n name,\n inputTokens: 0,\n outputTokens: 0,\n cachedTokens: 0,\n reasoningTokens: 0,\n totalTokens: 0,\n sessions: 0,\n };\n\n current.inputTokens += bucket.inputTokens || 0;\n current.outputTokens += bucket.outputTokens || 0;\n current.cachedTokens += bucket.cachedTokens || 0;\n current.reasoningTokens += bucket.reasoningTokens || 0;\n current.totalTokens += bucket.totalTokens || 0;\n map.set(name, current);\n}\n\nfunction sortRankItems(\n items: Iterable<LocalUsageRankItem>,\n): LocalUsageRankItem[] {\n return Array.from(items).sort((left, right) => {\n if (right.totalTokens !== left.totalTokens) {\n return right.totalTokens - left.totalTokens;\n }\n return left.name.localeCompare(right.name);\n });\n}\n\nfunction buildToolSummary(input: {\n source: string;\n name: string;\n buckets: TokenBucket[];\n sessions: SessionMetadata[];\n}): LocalUsageToolSummary {\n const totals = createTotals();\n const modelTotals = new Map<string, LocalUsageRankItem>();\n const projectTotals = new Map<string, LocalUsageRankItem>();\n const projects = new Set<string>();\n const models = new Set<string>();\n\n for (const bucket of input.buckets) {\n addBucketToTotals(totals, bucket);\n addBucketToRank(modelTotals, bucket.model, bucket);\n addBucketToRank(projectTotals, bucket.project, bucket);\n projects.add(bucket.project || \"unknown\");\n models.add(bucket.model || \"unknown\");\n }\n\n for (const session of input.sessions) {\n const projectName = session.project || \"unknown\";\n const modelName = session.primaryModel || \"unknown\";\n projects.add(projectName);\n models.add(modelName);\n\n const project = projectTotals.get(projectName);\n if (project) {\n project.sessions += 1;\n } else {\n projectTotals.set(projectName, {\n name: projectName,\n inputTokens: 0,\n outputTokens: 0,\n cachedTokens: 0,\n reasoningTokens: 0,\n totalTokens: 0,\n sessions: 1,\n });\n }\n\n const model = modelTotals.get(modelName);\n if (model) {\n model.sessions += 1;\n } else {\n modelTotals.set(modelName, {\n name: modelName,\n inputTokens: 0,\n outputTokens: 0,\n cachedTokens: 0,\n reasoningTokens: 0,\n totalTokens: 0,\n sessions: 1,\n });\n }\n }\n\n totals.sessions = input.sessions.length;\n totals.projects = projects.size;\n totals.models = models.size;\n\n return {\n source: input.source,\n name: input.name,\n totals,\n topModels: sortRankItems(modelTotals.values()).slice(0, 8),\n topProjects: sortRankItems(projectTotals.values()).slice(0, 8),\n sessions: input.sessions\n .slice()\n .sort(\n (left, right) =>\n new Date(right.lastMessageAt).getTime() -\n new Date(left.lastMessageAt).getTime(),\n )\n .slice(0, 8)\n .map((session) => ({\n project: session.project || \"unknown\",\n primaryModel: session.primaryModel || \"unknown\",\n lastMessageAt: session.lastMessageAt,\n totalTokens: session.totalTokens || 0,\n messageCount: session.messageCount || 0,\n activeSeconds: session.activeSeconds || 0,\n })),\n };\n}\n\nexport function buildLocalUsageDashboardData(\n input: BuildLocalUsageDashboardInput,\n): LocalUsageDashboardData {\n const toolNames = new Map(input.tools.map((tool) => [tool.id, tool.name]));\n const parsedSources = new Set<string>();\n for (const bucket of input.buckets) parsedSources.add(bucket.source);\n for (const session of input.sessions) parsedSources.add(session.source);\n\n const sources = Array.from(parsedSources);\n\n const tools = sources\n .sort((left, right) => {\n const leftToolIndex = input.tools.findIndex((tool) => tool.id === left);\n const rightToolIndex = input.tools.findIndex((tool) => tool.id === right);\n if (leftToolIndex !== -1 || rightToolIndex !== -1) {\n if (leftToolIndex === -1) return 1;\n if (rightToolIndex === -1) return -1;\n return leftToolIndex - rightToolIndex;\n }\n return left.localeCompare(right);\n })\n .map((source) =>\n buildToolSummary({\n source,\n name: toolNames.get(source) ?? source,\n buckets: input.buckets.filter((bucket) => bucket.source === source),\n sessions: input.sessions.filter((session) => session.source === source),\n }),\n );\n\n const totals = createTotals();\n const projects = new Set<string>();\n const models = new Set<string>();\n\n for (const bucket of input.buckets) {\n addBucketToTotals(totals, bucket);\n projects.add(bucket.project || \"unknown\");\n models.add(bucket.model || \"unknown\");\n }\n for (const session of input.sessions) {\n projects.add(session.project || \"unknown\");\n models.add(session.primaryModel || \"unknown\");\n }\n\n totals.sessions = input.sessions.length;\n totals.projects = projects.size;\n totals.models = models.size;\n\n return {\n generatedAt: new Date().toISOString(),\n totals,\n tools,\n };\n}\n","import { readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst FALLBACK_VERSION = \"0.0.0\";\n\nlet cachedVersion: string | undefined;\n\nexport function getCliVersion(metaUrl = import.meta.url): string {\n if (cachedVersion) {\n return cachedVersion;\n }\n\n const packageJsonPath = join(\n dirname(fileURLToPath(metaUrl)),\n \"..\",\n \"package.json\",\n );\n\n try {\n const packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\")) as {\n version?: string;\n };\n\n cachedVersion =\n typeof packageJson.version === \"string\"\n ? packageJson.version\n : FALLBACK_VERSION;\n } catch {\n cachedVersion = FALLBACK_VERSION;\n }\n\n return cachedVersion;\n}\n","import type {\n LocalUsageDashboardData,\n LocalUsageRankItem,\n LocalUsageSessionItem,\n LocalUsageToolSummary,\n} from \"../../domain/local-usage-summary\";\nimport { bold, cyan, dim, green, magenta, yellow } from \"./format\";\n\nconst MAX_RANK_ROWS = 6;\nconst MAX_SESSION_ROWS = 6;\n\nfunction stripAnsi(value: string): string {\n let output = \"\";\n for (let index = 0; index < value.length; index += 1) {\n if (value.charCodeAt(index) === 27 && value[index + 1] === \"[\") {\n index += 2;\n while (index < value.length && value[index] !== \"m\") {\n index += 1;\n }\n continue;\n }\n output += value[index];\n }\n return output;\n}\n\nfunction visibleLength(value: string): number {\n return stripAnsi(value).length;\n}\n\nfunction truncate(value: string, maxWidth: number): string {\n if (maxWidth <= 0) return \"\";\n if (visibleLength(value) <= maxWidth) return value;\n\n const plain = stripAnsi(value);\n if (maxWidth <= 1) return \"…\";\n return `${plain.slice(0, maxWidth - 1)}…`;\n}\n\nfunction pad(value: string, width: number): string {\n return `${value}${\" \".repeat(Math.max(0, width - visibleLength(value)))}`;\n}\n\nfunction colorByIndex(value: string, index: number): string {\n switch (index % 4) {\n case 0:\n return cyan(value);\n case 1:\n return green(value);\n case 2:\n return yellow(value);\n default:\n return magenta(value);\n }\n}\n\nfunction renderTabToken(\n tool: LocalUsageToolSummary,\n index: number,\n selectedIndex: number,\n): string {\n const rawLabel = ` ${tool.name} `;\n const leftBlock = colorByIndex(\"▌\", index);\n return index === selectedIndex\n ? `${leftBlock} ${bold(rawLabel)}`\n : `${leftBlock} ${dim(rawLabel)}`;\n}\n\nfunction formatCompactNumber(value: number): string {\n const safeValue = Math.round(value || 0);\n if (Math.abs(safeValue) >= 1_000_000_000) {\n return `${(safeValue / 1_000_000_000).toFixed(1)}B`;\n }\n if (Math.abs(safeValue) >= 1_000_000) {\n return `${(safeValue / 1_000_000).toFixed(1)}M`;\n }\n if (Math.abs(safeValue) >= 1_000) {\n return `${(safeValue / 1_000).toFixed(1)}K`;\n }\n return String(safeValue);\n}\n\nfunction formatDateTime(value: string): string {\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return value || \"-\";\n return date.toLocaleString(undefined, {\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n });\n}\n\nfunction formatDuration(seconds: number): string {\n const safeSeconds = Math.max(0, Math.round(seconds || 0));\n if (safeSeconds < 60) return `${safeSeconds}s`;\n const minutes = Math.round(safeSeconds / 60);\n if (minutes < 60) return `${minutes}m`;\n const hours = Math.floor(minutes / 60);\n const restMinutes = minutes % 60;\n return restMinutes > 0 ? `${hours}h${restMinutes}m` : `${hours}h`;\n}\n\nfunction renderTabs(\n tools: LocalUsageToolSummary[],\n selectedIndex: number,\n width: number,\n): string {\n const allTokens = tools.map((tool, index) =>\n renderTabToken(tool, index, selectedIndex),\n );\n const fullLine = allTokens.join(\" \");\n if (visibleLength(fullLine) <= width) {\n return fullLine;\n }\n\n const leftIndicator = selectedIndex > 0 ? dim(\"‹ \") : \"\";\n const tokens: string[] = [];\n let usedWidth = visibleLength(leftIndicator);\n\n for (let index = selectedIndex; index < tools.length; index += 1) {\n const token = renderTabToken(tools[index], index, selectedIndex);\n const separatorWidth = tokens.length > 0 ? 1 : 0;\n const hasMore = index < tools.length - 1;\n const rightIndicatorWidth = hasMore ? 4 : 0;\n\n if (\n usedWidth + separatorWidth + visibleLength(token) + rightIndicatorWidth >\n width\n ) {\n if (tokens.length === 0) {\n tokens.push(\n truncate(token, Math.max(1, width - usedWidth - rightIndicatorWidth)),\n );\n }\n break;\n }\n\n if (tokens.length > 0) {\n usedWidth += 1;\n }\n tokens.push(token);\n usedWidth += visibleLength(token);\n }\n\n const nextHidden = selectedIndex + tokens.length < tools.length;\n const rightIndicator = nextHidden ? dim(\" … ›\") : \"\";\n return truncate(\n `${leftIndicator}${tokens.join(\" \")}${rightIndicator}`,\n width,\n );\n}\n\nfunction renderOverview(tool: LocalUsageToolSummary): string[] {\n return [\n `${bold(\"Overview\")} ${dim(tool.source)}`,\n ` Tokens ${formatCompactNumber(tool.totals.totalTokens)} total · ${formatCompactNumber(tool.totals.inputTokens)} input · ${formatCompactNumber(tool.totals.outputTokens)} output`,\n ` Details ${formatCompactNumber(tool.totals.cachedTokens)} cached · ${formatCompactNumber(tool.totals.reasoningTokens)} reasoning`,\n ` Scope ${tool.totals.sessions} sessions · ${tool.totals.buckets} buckets · ${tool.totals.projects} projects · ${tool.totals.models} models`,\n ];\n}\n\nfunction renderRankTable(title: string, items: LocalUsageRankItem[]): string[] {\n const lines = [bold(title)];\n if (items.length === 0) {\n lines.push(dim(\" No usage found.\"));\n return lines;\n }\n\n lines.push(dim(` ${pad(\"Name\", 28)} ${pad(\"Tokens\", 10)} Sessions`));\n for (const item of items.slice(0, MAX_RANK_ROWS)) {\n lines.push(\n ` ${pad(truncate(item.name, 28), 28)} ${pad(formatCompactNumber(item.totalTokens), 10)} ${item.sessions}`,\n );\n }\n return lines;\n}\n\nfunction renderSessionTable(items: LocalUsageSessionItem[]): string[] {\n const lines = [bold(\"Recent Sessions\")];\n if (items.length === 0) {\n lines.push(dim(\" No sessions found.\"));\n return lines;\n }\n\n lines.push(\n dim(\n ` ${pad(\"When\", 12)} ${pad(\"Project\", 20)} ${pad(\"Model\", 18)} ${pad(\"Tokens\", 8)} Msgs Active`,\n ),\n );\n for (const session of items.slice(0, MAX_SESSION_ROWS)) {\n lines.push(\n ` ${pad(formatDateTime(session.lastMessageAt), 12)} ${pad(truncate(session.project, 20), 20)} ${pad(truncate(session.primaryModel, 18), 18)} ${pad(formatCompactNumber(session.totalTokens), 8)} ${pad(String(session.messageCount), 4)} ${formatDuration(session.activeSeconds)}`,\n );\n }\n return lines;\n}\n\nfunction renderTool(\n tool: LocalUsageToolSummary,\n allTools: LocalUsageToolSummary[],\n selectedIndex: number,\n width: number,\n interactive: boolean,\n): string {\n const lines = [\n `${cyan(\"◈\")} ${bold(\"TokenArena Local Usage\")}`,\n dim(\n interactive\n ? \"Tab/→ next · Shift+Tab/← previous · q/Esc/Ctrl+C quit\"\n : \"Static local usage snapshot\",\n ),\n \"\",\n renderTabs(allTools, selectedIndex, width),\n \"\",\n ...renderOverview(tool),\n \"\",\n ...renderRankTable(\"Top Models\", tool.topModels),\n \"\",\n ...renderRankTable(\"Top Projects\", tool.topProjects),\n \"\",\n ...renderSessionTable(tool.sessions),\n ];\n\n return lines.map((line) => truncate(line, width)).join(\"\\n\");\n}\n\nexport function renderLocalUsageDashboard(\n data: LocalUsageDashboardData,\n selectedIndex = 0,\n options: { interactive?: boolean; width?: number } = {},\n): string {\n const width = Math.max(40, options.width ?? process.stdout.columns ?? 100);\n\n if (data.tools.length === 0 || data.totals.totalTokens === 0) {\n return [\n `${cyan(\"◈\")} ${bold(\"TokenArena Local Usage\")}`,\n dim(\"No local usage records were found.\"),\n \"\",\n yellow(\n \"! Use supported AI CLI tools first, or run `ta status` to check detected tools.\",\n ),\n ]\n .map((line) => truncate(line, width))\n .join(\"\\n\");\n }\n\n const safeIndex = Math.max(0, Math.min(selectedIndex, data.tools.length - 1));\n return renderTool(\n data.tools[safeIndex],\n data.tools,\n safeIndex,\n width,\n Boolean(options.interactive),\n );\n}\n\nfunction isShiftTab(value: string): boolean {\n return value === \"\\u001b[Z\";\n}\n\nfunction isNextTabKey(value: string): boolean {\n return value === \"\\t\" || value === \"\\u001b[C\";\n}\n\nfunction isPreviousTabKey(value: string): boolean {\n return isShiftTab(value) || value === \"\\u001b[D\";\n}\n\nfunction isQuit(value: string): boolean {\n return (\n value === \"q\" || value === \"Q\" || value === \"\\u001b\" || value === \"\\u0003\"\n );\n}\n\nexport async function showLocalUsageDashboard(\n data: LocalUsageDashboardData,\n): Promise<void> {\n if (!process.stdin.isTTY || !process.stdout.isTTY) {\n process.stdout.write(`${renderLocalUsageDashboard(data)}\\n`);\n return;\n }\n\n if (data.tools.length === 0 || data.totals.totalTokens === 0) {\n process.stdout.write(`${renderLocalUsageDashboard(data)}\\n`);\n return;\n }\n\n let selectedIndex = 0;\n const stdin = process.stdin;\n const stdout = process.stdout;\n const wasRaw = stdin.isRaw;\n\n await new Promise<void>((resolve) => {\n const render = () => {\n stdout.write(\"\\u001b[?25l\\u001b[2J\\u001b[H\");\n stdout.write(\n renderLocalUsageDashboard(data, selectedIndex, {\n interactive: true,\n width: stdout.columns ?? 100,\n }),\n );\n stdout.write(\"\\n\");\n };\n\n const cleanup = () => {\n stdout.write(\"\\u001b[?25h\\u001b[2J\\u001b[H\");\n stdin.off(\"data\", onData);\n stdout.off(\"resize\", render);\n if (stdin.isTTY) stdin.setRawMode(wasRaw);\n stdin.pause();\n resolve();\n };\n\n const onData = (chunk: Buffer | string) => {\n const value = chunk.toString(\"utf8\");\n if (isQuit(value)) {\n cleanup();\n return;\n }\n if (isNextTabKey(value)) {\n selectedIndex = (selectedIndex + 1) % data.tools.length;\n render();\n return;\n }\n if (isPreviousTabKey(value)) {\n selectedIndex =\n (selectedIndex - 1 + data.tools.length) % data.tools.length;\n render();\n }\n };\n\n stdin.setRawMode(true);\n stdin.resume();\n stdin.setEncoding(\"utf8\");\n stdin.on(\"data\", onData);\n stdout.on(\"resize\", render);\n render();\n });\n}\n","import { buildLocalUsageDashboardData } from \"../domain/local-usage-summary\";\nimport { getConfigPath, loadConfig } from \"../infrastructure/config/manager\";\nimport { getCliVersion } from \"../infrastructure/runtime/cli-version\";\nimport { loadSyncState } from \"../infrastructure/runtime/state\";\nimport {\n formatBullet,\n formatHeader,\n formatKeyValue,\n formatSection,\n formatStatusBadge,\n maskSecret,\n} from \"../infrastructure/ui/format\";\nimport { showLocalUsageDashboard } from \"../infrastructure/ui/local-usage-dashboard\";\nimport {\n detectInstalledTools,\n getAllTools,\n isToolInstalled,\n} from \"../parsers/registry\";\nimport { runAllParsers } from \"../services/parser-service\";\nimport { logger } from \"../utils/logger\";\n\nexport interface StatusCommandOptions {\n show?: boolean;\n}\n\nfunction formatMaybe(value?: string): string {\n return value || \"(never)\";\n}\n\nasync function runStatusDashboard(): Promise<void> {\n if (!process.stdin.isTTY || !process.stdout.isTTY) {\n const result = await runAllParsers();\n await showLocalUsageDashboard(\n buildLocalUsageDashboardData({\n buckets: result.buckets,\n sessions: result.sessions,\n tools: getAllTools(),\n }),\n );\n return;\n }\n\n process.stdout.write(\"Loading local usage…\\n\");\n const result = await runAllParsers();\n await showLocalUsageDashboard(\n buildLocalUsageDashboardData({\n buckets: result.buckets,\n sessions: result.sessions,\n tools: getAllTools(),\n }),\n );\n}\n\nexport async function runStatus(\n opts: StatusCommandOptions = {},\n): Promise<void> {\n if (opts.show) {\n await runStatusDashboard();\n return;\n }\n\n const config = loadConfig();\n logger.info(\n formatHeader(\n \"TokenArena 状态\",\n `版本 ${getCliVersion()} · 查看当前配置、已检测工具以及最近一次同步情况。`,\n ),\n );\n\n logger.info(formatSection(\"配置\"));\n if (!config?.apiKey) {\n logger.info(formatKeyValue(\"状态\", formatStatusBadge(\"未配置\", \"warning\")));\n logger.info(formatBullet(\"运行 tokenarena init 完成首次设置。\", \"warning\"));\n } else {\n logger.info(formatKeyValue(\"状态\", formatStatusBadge(\"已配置\", \"success\")));\n logger.info(formatKeyValue(\"配置文件\", getConfigPath()));\n logger.info(formatKeyValue(\"API Key\", maskSecret(config.apiKey)));\n logger.info(\n formatKeyValue(\"API URL\", config.apiUrl || \"https://token.guji.uno\"),\n );\n if (config.syncInterval) {\n logger.info(\n formatKeyValue(\n \"同步间隔\",\n `${Math.round(config.syncInterval / 60000)} 分钟`,\n ),\n );\n }\n }\n\n logger.info(formatSection(\"已检测工具\"));\n const detected = detectInstalledTools();\n if (detected.length === 0) {\n logger.info(formatBullet(\"未检测到已安装的 AI CLI。\", \"warning\"));\n } else {\n for (const tool of detected) {\n logger.info(formatBullet(tool.name, \"success\"));\n }\n }\n\n logger.info(formatSection(\"支持的工具\"));\n for (const tool of getAllTools()) {\n const installed = isToolInstalled(tool.id);\n logger.info(\n formatBullet(\n `${tool.name} · ${installed ? \"已安装\" : \"未发现\"}`,\n installed ? \"success\" : \"neutral\",\n ),\n );\n }\n\n const syncState = loadSyncState();\n logger.info(formatSection(\"同步状态\"));\n const statusTone =\n syncState.status === \"idle\"\n ? \"success\"\n : syncState.status === \"syncing\"\n ? \"warning\"\n : \"danger\";\n logger.info(\n formatKeyValue(\"状态\", formatStatusBadge(syncState.status, statusTone)),\n );\n logger.info(formatKeyValue(\"上次尝试\", formatMaybe(syncState.lastAttemptAt)));\n logger.info(formatKeyValue(\"上次成功\", formatMaybe(syncState.lastSuccessAt)));\n if (syncState.lastSource) {\n logger.info(formatKeyValue(\"触发来源\", syncState.lastSource));\n }\n if (syncState.lastError) {\n logger.info(formatKeyValue(\"错误信息\", syncState.lastError));\n }\n if (syncState.lastResult) {\n logger.info(\n formatKeyValue(\n \"最近结果\",\n `${syncState.lastResult.buckets} buckets, ${syncState.lastResult.sessions} sessions`,\n ),\n );\n }\n}\n","import { loadConfig } from \"../infrastructure/config/manager\";\nimport { formatBullet, formatHeader } from \"../infrastructure/ui/format\";\nimport {\n isInteractiveTerminal,\n promptConfirm,\n} from \"../infrastructure/ui/prompts\";\nimport { runSync } from \"../services/sync-service\";\nimport { logger } from \"../utils/logger\";\nimport { runInit } from \"./init\";\n\nexport interface SyncCommandOptions {\n quiet?: boolean;\n}\n\nexport async function runSyncCommand(\n opts: SyncCommandOptions = {},\n): Promise<void> {\n const config = loadConfig();\n if (!config?.apiKey) {\n if (isInteractiveTerminal()) {\n logger.info(\n formatHeader(\"尚未完成初始化\", \"同步前需要先配置有效的 API Key。\"),\n );\n const shouldInit = await promptConfirm({\n message: \"是否现在进入初始化流程?\",\n defaultValue: true,\n });\n if (shouldInit) {\n await runInit();\n return;\n }\n logger.info(formatBullet(\"已取消同步。\", \"warning\"));\n return;\n }\n\n logger.error(\"Not configured. Run `tokenarena init` first.\");\n process.exit(1);\n }\n\n await runSync(config, {\n quiet: opts.quiet,\n source: \"manual\",\n });\n}\n","import { existsSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { homedir, platform } from \"node:os\";\nimport {\n deleteConfig,\n getConfigDir,\n getConfigPath,\n loadConfig,\n} from \"../infrastructure/config/manager\";\nimport {\n getRuntimeDirPath,\n getStateDir,\n} from \"../infrastructure/runtime/paths\";\nimport { getServiceBackend } from \"../infrastructure/service\";\nimport {\n formatBullet,\n formatHeader,\n formatKeyValue,\n formatSection,\n maskSecret,\n} from \"../infrastructure/ui/format\";\nimport { promptConfirm } from \"../infrastructure/ui/prompts\";\nimport { logger } from \"../utils/logger\";\n\nfunction removeShellAlias(): void {\n const shell = process.env.SHELL;\n if (!shell) return;\n\n const shellName = shell.split(\"/\").pop() ?? \"\";\n const aliasName = \"ta\";\n\n let configFile: string;\n\n switch (shellName) {\n case \"zsh\":\n configFile = `${homedir()}/.zshrc`;\n break;\n case \"bash\":\n if (platform() === \"darwin\" && existsSync(`${homedir()}/.bash_profile`)) {\n configFile = `${homedir()}/.bash_profile`;\n } else {\n configFile = `${homedir()}/.bashrc`;\n }\n break;\n case \"fish\":\n configFile = `${homedir()}/.config/fish/config.fish`;\n break;\n default:\n return;\n }\n\n if (!existsSync(configFile)) return;\n\n try {\n let content = readFileSync(configFile, \"utf-8\");\n\n // Match the alias block: \"# TokenArena alias\" comment line + alias line\n const aliasPatterns = [\n // zsh / bash format: alias ta=\"tokenarena\"\n new RegExp(\n `\\\\n?#\\\\s*TokenArena alias\\\\s*\\\\n\\\\s*alias\\\\s+${aliasName}\\\\s*=\\\\s*\"tokenarena\"\\\\s*\\\\n?`,\n \"g\",\n ),\n // fish format: alias ta \"tokenarena\"\n new RegExp(\n `\\\\n?#\\\\s*TokenArena alias\\\\s*\\\\n\\\\s*alias\\\\s+${aliasName}\\\\s+\"tokenarena\"\\\\s*\\\\n?`,\n \"g\",\n ),\n // Loose match for any ta alias line\n new RegExp(`\\\\n?alias\\\\s+${aliasName}\\\\s*=\\\\s*\"tokenarena\"\\\\s*\\\\n?`, \"g\"),\n new RegExp(`\\\\n?alias\\\\s+${aliasName}\\\\s+\"tokenarena\"\\\\s*\\\\n?`, \"g\"),\n ];\n\n for (const pattern of aliasPatterns) {\n const next = content.replace(pattern, \"\\n\");\n if (next !== content) {\n content = next;\n }\n }\n\n writeFileSync(configFile, content, \"utf-8\");\n logger.info(`Removed shell alias from ${configFile}`);\n } catch (err) {\n logger.warn(\n `Could not update ${configFile}: ${(err as Error).message}. Please remove the alias manually.`,\n );\n }\n}\n\nexport async function runUninstall(): Promise<void> {\n const configPath = getConfigPath();\n const configDir = getConfigDir();\n const stateDir = getStateDir();\n const runtimeDir = getRuntimeDirPath();\n const serviceBackend = getServiceBackend();\n const hasInstalledService = serviceBackend?.isInstalled() ?? false;\n const hasLocalArtifacts =\n existsSync(configPath) ||\n existsSync(configDir) ||\n existsSync(stateDir) ||\n existsSync(runtimeDir) ||\n hasInstalledService;\n\n if (!hasLocalArtifacts) {\n logger.info(formatHeader(\"卸载 TokenArena\"));\n logger.info(formatBullet(\"未发现本地配置,无需卸载。\"));\n return;\n }\n\n const config = loadConfig();\n logger.info(\n formatHeader(\n \"卸载 TokenArena\",\n \"该操作会删除本地配置、同步状态与运行时文件。\",\n ),\n );\n if (config?.apiKey) {\n logger.info(formatKeyValue(\"API Key\", maskSecret(config.apiKey)));\n }\n logger.info(formatKeyValue(\"配置目录\", configDir));\n logger.info(formatKeyValue(\"状态目录\", stateDir));\n logger.info(formatKeyValue(\"运行目录\", runtimeDir));\n if (hasInstalledService && serviceBackend) {\n logger.info(formatKeyValue(\"后台服务\", serviceBackend.getDefinitionPath()));\n }\n\n const shouldUninstall = await promptConfirm({\n message: \"确认继续卸载本地 TokenArena 数据?\",\n defaultValue: false,\n });\n if (!shouldUninstall) {\n logger.info(formatBullet(\"已取消卸载。\", \"warning\"));\n return;\n }\n\n if (hasInstalledService && serviceBackend) {\n const shouldRemoveService = await promptConfirm({\n message: `检测到已安装 ${serviceBackend.displayName},是否一并卸载?`,\n defaultValue: true,\n });\n\n if (shouldRemoveService) {\n try {\n await serviceBackend.uninstall(true);\n } catch (err) {\n logger.warn(`后台服务卸载失败: ${(err as Error).message}`);\n }\n }\n }\n\n // 1. Delete config file\n logger.info(formatSection(\"执行结果\"));\n if (existsSync(configPath)) {\n deleteConfig();\n logger.info(formatBullet(\"已删除配置文件。\", \"success\"));\n }\n\n // 2. Remove config directory if empty\n if (existsSync(configDir)) {\n try {\n rmSync(configDir, { recursive: false, force: true });\n logger.info(formatBullet(\"已删除配置目录。\", \"success\"));\n } catch {\n // Directory not empty (other files), skip silently\n }\n }\n\n // 3. Delete state directory (status.json, etc.)\n if (existsSync(stateDir)) {\n rmSync(stateDir, { recursive: true, force: true });\n logger.info(formatBullet(\"已删除状态数据。\", \"success\"));\n }\n\n // 4. Delete runtime directory (sync.lock, etc.)\n if (existsSync(runtimeDir)) {\n rmSync(runtimeDir, { recursive: true, force: true });\n logger.info(formatBullet(\"已删除运行时数据。\", \"success\"));\n }\n\n // 5. Clean up shell alias\n removeShellAlias();\n\n logger.info(formatSection(\"完成\"));\n logger.info(formatBullet(\"TokenArena 已从本地卸载完成。\", \"success\"));\n}\n","import type { Command } from \"commander\";\nimport { loadConfig } from \"../infrastructure/config/manager\";\nimport {\n formatBullet,\n formatHeader,\n formatKeyValue,\n formatStatusBadge,\n maskSecret,\n} from \"../infrastructure/ui/format\";\nimport { promptConfirm, promptSelect } from \"../infrastructure/ui/prompts\";\nimport { logger } from \"../utils/logger\";\nimport { handleConfig } from \"./config\";\nimport { runDaemon } from \"./daemon\";\nimport { runInit } from \"./init\";\nimport { runStatus } from \"./status\";\nimport { runSyncCommand } from \"./sync\";\nimport { runUninstall } from \"./uninstall\";\n\ntype HomeAction =\n | \"init\"\n | \"status\"\n | \"sync\"\n | \"config\"\n | \"daemon\"\n | \"uninstall\"\n | \"help\"\n | \"exit\";\n\nfunction logHomeSummary(): void {\n const config = loadConfig();\n const configured = Boolean(config?.apiKey);\n\n logger.info(\n formatHeader(\n \"TokenArena CLI\",\n \"通过更友好的交互完成初始化、同步、配置与清理。\",\n ),\n );\n logger.info(\n formatKeyValue(\n \"配置状态\",\n configured\n ? formatStatusBadge(\"已配置\", \"success\")\n : formatStatusBadge(\"未配置\", \"warning\"),\n ),\n );\n\n if (configured && config) {\n logger.info(formatKeyValue(\"API Key\", maskSecret(config.apiKey)));\n logger.info(\n formatKeyValue(\"API 地址\", config.apiUrl || \"https://token.guji.uno\"),\n );\n } else {\n logger.info(formatBullet(\"建议先运行初始化流程绑定 API Key。\", \"warning\"));\n }\n}\n\nasync function pickHomeAction(): Promise<HomeAction> {\n return promptSelect<HomeAction>({\n message: \"请选择要执行的操作\",\n choices: [\n {\n name: \"初始化 TokenArena\",\n value: \"init\",\n description: \"配置 API Key、检测工具并执行首次同步\",\n },\n {\n name: \"查看当前状态\",\n value: \"status\",\n description: \"查看配置、工具检测结果与最近同步状态\",\n },\n {\n name: \"立即同步\",\n value: \"sync\",\n description: \"手动上传本地最新 token 使用数据\",\n },\n {\n name: \"管理配置\",\n value: \"config\",\n description: \"查看或修改 API Key、API 地址、同步间隔等配置\",\n },\n {\n name: \"启动守护同步\",\n value: \"daemon\",\n description: \"持续后台同步,适合长期运行\",\n },\n {\n name: \"卸载本地配置\",\n value: \"uninstall\",\n description: \"删除本地配置、状态与运行时文件\",\n },\n {\n name: \"查看帮助\",\n value: \"help\",\n description: \"展示完整命令帮助\",\n },\n {\n name: \"退出\",\n value: \"exit\",\n description: \"结束当前交互\",\n },\n ],\n });\n}\n\nexport async function runHome(program: Command): Promise<void> {\n while (true) {\n logHomeSummary();\n\n const action = await pickHomeAction();\n logger.info(\"\");\n\n switch (action) {\n case \"init\":\n await runInit();\n break;\n case \"status\":\n await runStatus();\n break;\n case \"sync\":\n await runSyncCommand();\n break;\n case \"config\":\n await handleConfig([]);\n break;\n case \"daemon\":\n await runDaemon();\n return;\n case \"uninstall\":\n await runUninstall();\n break;\n case \"help\":\n program.outputHelp();\n break;\n case \"exit\":\n logger.info(formatBullet(\"已退出交互式主页。\", \"neutral\"));\n return;\n }\n\n const continueAnswer = await promptConfirm({\n message: \"是否继续执行其他操作?\",\n defaultValue: true,\n });\n\n if (!continueAnswer) {\n logger.info(formatBullet(\"下次可直接运行 tokenarena 继续。\", \"neutral\"));\n return;\n }\n }\n}\n","import { getServiceBackend } from \"../infrastructure/service\";\nimport {\n formatBullet,\n formatHeader,\n formatKeyValue,\n formatSection,\n} from \"../infrastructure/ui/format\";\nimport { logger } from \"../utils/logger\";\n\nexport interface ServiceCommandOptions {\n action?: string;\n skipPrompt?: boolean;\n}\n\nfunction printUsage(backendName?: string): void {\n logger.info(formatHeader(\"TokenArena 后台服务管理\"));\n if (backendName) {\n logger.info(formatKeyValue(\"当前实现\", backendName));\n }\n logger.info(formatSection(\"可用操作\"));\n logger.info(formatBullet(\"setup - 创建并启用服务\"));\n logger.info(formatBullet(\"start - 启动服务\"));\n logger.info(formatBullet(\"stop - 停止服务\"));\n logger.info(formatBullet(\"restart - 重启服务\"));\n logger.info(formatBullet(\"status - 查看服务状态\"));\n logger.info(formatBullet(\"uninstall - 卸载服务\"));\n}\n\nexport async function runServiceCommand(\n opts: ServiceCommandOptions,\n): Promise<void> {\n const backend = getServiceBackend();\n if (!backend) {\n logger.info(\n formatBullet(\n \"后台服务仅在 Linux(systemd) 和 macOS(launchd) 上支持。\",\n \"warning\",\n ),\n );\n return;\n }\n\n const action = opts.action?.toLowerCase();\n if (!action) {\n printUsage(backend.displayName);\n const support = backend.canSetup();\n if (!support.ok && support.reason) {\n logger.info(\n formatBullet(`当前环境暂不可管理服务。${support.reason}`, \"warning\"),\n );\n }\n return;\n }\n\n switch (action) {\n case \"setup\":\n await backend.setup(opts.skipPrompt);\n break;\n case \"start\":\n await backend.start();\n break;\n case \"stop\":\n await backend.stop();\n break;\n case \"restart\":\n await backend.restart();\n break;\n case \"status\":\n await backend.status();\n break;\n case \"uninstall\":\n await backend.uninstall(opts.skipPrompt);\n break;\n default:\n logger.error(`未知操作: ${action}`);\n process.exit(1);\n }\n}\n","import { existsSync, realpathSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nexport function isMainModule(\n argvEntry = process.argv[1],\n metaUrl = import.meta.url,\n): boolean {\n if (!argvEntry) {\n return false;\n }\n\n const currentModulePath = fileURLToPath(metaUrl);\n\n try {\n return realpathSync(argvEntry) === realpathSync(currentModulePath);\n } catch {\n if (!existsSync(argvEntry)) {\n return false;\n }\n\n return resolve(argvEntry) === resolve(currentModulePath);\n }\n}\n","// Import parsers to register them before CLI setup\nimport \"./parsers/claude-code.js\";\nimport \"./parsers/codex.js\";\nimport \"./parsers/gsd.js\";\nimport \"./parsers/gemini-cli.js\";\nimport \"./parsers/hermes.js\";\nimport \"./parsers/copilot-cli.js\";\nimport \"./parsers/oh-my-pi.js\";\nimport \"./parsers/opencode.js\";\nimport \"./parsers/openclaw.js\";\nimport \"./parsers/qwen-code.js\";\nimport \"./parsers/kimi-code.js\";\nimport \"./parsers/droid.js\";\nimport \"./parsers/pi-coding-agent.js\";\nimport \"./parsers/qwenpaw.js\";\nimport \"./parsers/cline.js\";\nimport \"./parsers/kiro.js\";\nimport \"./parsers/roo-code.js\";\nimport \"./parsers/cursor.js\";\nimport \"./parsers/zcode.js\";\n\nimport { createCli } from \"./cli.js\";\nimport { isMainModule } from \"./infrastructure/runtime/main-module.js\";\n\nexport function normalizeArgv(argv: string[]) {\n return argv.filter((arg, index) => index < 2 || arg !== \"--\");\n}\n\nexport async function run(argv = process.argv) {\n const program = createCli();\n await program.parseAsync(normalizeArgv(argv));\n}\n\nif (isMainModule()) {\n void run();\n}\n"],"mappings":";;;AAAA,SAAS,cAAAA,aAAY,oBAAoB;AACzC,SAAS,eAAe;AACxB,SAAS,QAAAC,OAAM,OAAAC,YAAW;;;ACF1B,SAAS,gBAAgB;;;ACEzB,IAAM,mBAAmB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,sBACd,OACS;AACT,SAAO,iBAAiB,KAAK,CAAC,QAAQ;AACpC,UAAM,QAAQ,MAAM,GAAG;AACvB,WAAO,CAAC,OAAO,cAAc,KAAK,KAAK,QAAQ;AAAA,EACjD,CAAC;AACH;;;ADTO,SAAS,gBAAgB,MAAkB;AAChD,QAAM,IAAI,IAAI,KAAK,IAAI;AACvB,IAAE,WAAW,EAAE,WAAW,IAAI,KAAK,IAAI,IAAI,GAAG,CAAC;AAC/C,SAAO;AACT;AAKO,SAAS,mBAAmB,SAA2C;AAC5E,QAAM,MAAM,oBAAI,IAAyB;AACzC,QAAM,OAAO,SAAS,EAAE,QAAQ,YAAY,EAAE;AAE9C,aAAW,KAAK,SAAS;AACvB,QAAI,sBAAsB,CAAC,GAAG;AAC5B;AAAA,IACF;AAEA,UAAM,cAAc,gBAAgB,EAAE,SAAS,EAAE,YAAY;AAC7D,UAAM,MAAM,GAAG,EAAE,MAAM,IAAI,EAAE,KAAK,IAAI,EAAE,OAAO,IAAI,WAAW;AAE9D,QAAI,CAAC,IAAI,IAAI,GAAG,GAAG;AACjB,UAAI,IAAI,KAAK;AAAA,QACX,QAAQ,EAAE;AAAA,QACV,OAAO,EAAE;AAAA,QACT,SAAS,EAAE;AAAA,QACX;AAAA,QACA,UAAU;AAAA,QACV,aAAa;AAAA,QACb,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,cAAc;AAAA,QACd,aAAa;AAAA,MACf,CAAC;AAAA,IACH;AAEA,UAAM,IAAI,IAAI,IAAI,GAAG;AACrB,QAAI,CAAC,EAAG;AACR,MAAE,eAAe,EAAE,eAAe;AAClC,MAAE,gBAAgB,EAAE,gBAAgB;AACpC,MAAE,mBAAmB,EAAE,mBAAmB;AAC1C,MAAE,gBAAgB,EAAE,gBAAgB;AACpC,MAAE,gBACC,EAAE,eAAe,MACjB,EAAE,gBAAgB,MAClB,EAAE,mBAAmB,MACrB,EAAE,gBAAgB;AAAA,EACvB;AAEA,SAAO,MAAM,KAAK,IAAI,OAAO,CAAC;AAChC;;;AEzDA,SAAS,kBAAkB;AAC3B,SAAS,YAAAC,iBAAgB;AASzB,SAAS,mBAAmB,OAAwB;AAClD,SACE,MAAM,cACN,MAAM,eACN,MAAM,kBACN,MAAM;AAEV;AAEA,SAAS,kBAAkB,SAA4B;AACrD,QAAM,iBAAiB,oBAAI,IAA4C;AAEvE,aAAW,SAAS,SAAS;AAC3B,QAAI,CAAC,MAAM,WAAW;AACpB;AAAA,IACF;AAEA,QAAI,sBAAsB,KAAK,GAAG;AAChC;AAAA,IACF;AAEA,QAAI,UAAU,eAAe,IAAI,MAAM,SAAS;AAChD,QAAI,CAAC,SAAS;AACZ,gBAAU,oBAAI,IAA+B;AAC7C,qBAAe,IAAI,MAAM,WAAW,OAAO;AAAA,IAC7C;AAEA,UAAM,WAAW,QAAQ,IAAI,MAAM,KAAK;AACxC,QAAI,UAAU;AACZ,eAAS,eAAe,MAAM;AAC9B,eAAS,gBAAgB,MAAM;AAC/B,eAAS,mBAAmB,MAAM;AAClC,eAAS,gBAAgB,MAAM;AAC/B,eAAS,eAAe,mBAAmB,KAAK;AAChD;AAAA,IACF;AAEA,YAAQ,IAAI,MAAM,OAAO;AAAA,MACvB,OAAO,MAAM;AAAA,MACb,aAAa,MAAM;AAAA,MACnB,cAAc,MAAM;AAAA,MACpB,iBAAiB,MAAM;AAAA,MACvB,cAAc,MAAM;AAAA,MACpB,aAAa,mBAAmB,KAAK;AAAA,IACvC,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AASO,SAAS,gBACd,QACA,UAA6B,CAAC,GACX;AACnB,QAAM,SAAS,oBAAI,IAA4B;AAC/C,aAAW,KAAK,QAAQ;AACtB,QAAI,CAAC,OAAO,IAAI,EAAE,SAAS,EAAG,QAAO,IAAI,EAAE,WAAW,CAAC,CAAC;AACxD,WAAO,IAAI,EAAE,SAAS,GAAG,KAAK,CAAC;AAAA,EACjC;AAEA,QAAM,WAA8B,CAAC;AACrC,QAAM,OAAOC,UAAS,EAAE,QAAQ,YAAY,EAAE;AAC9C,QAAM,iBAAiB,kBAAkB,OAAO;AAEhD,aAAW,CAAC,WAAW,aAAa,KAAK,QAAQ;AAC/C,kBAAc,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,QAAQ,IAAI,EAAE,UAAU,QAAQ,CAAC;AAE1E,UAAM,QAAQ,cAAc,CAAC;AAC7B,UAAM,OAAO,cAAc,cAAc,SAAS,CAAC;AACnD,UAAM,kBAAkB,KAAK;AAAA,OAC1B,KAAK,UAAU,QAAQ,IAAI,MAAM,UAAU,QAAQ,KAAK;AAAA,IAC3D;AAEA,QAAI,gBAAgB;AACpB,QAAI,YAAyB;AAC7B,QAAI,UAAuB;AAC3B,QAAI,0BAA0B;AAE9B,eAAW,SAAS,eAAe;AACjC,UAAI,MAAM,SAAS,QAAQ;AACzB,YAAI,cAAc,QAAQ,YAAY,QAAQ,UAAU,WAAW;AACjE,2BAAiB,KAAK;AAAA,aACnB,QAAQ,QAAQ,IAAI,UAAU,QAAQ,KAAK;AAAA,UAC9C;AAAA,QACF;AACA,oBAAY;AACZ,kBAAU;AACV,kCAA0B;AAAA,MAC5B,WAAW,yBAAyB;AAClC,oBAAY,MAAM;AAClB,kBAAU,MAAM;AAChB,kCAA0B;AAAA,MAC5B,WAAW,cAAc,MAAM;AAC7B,kBAAU,MAAM;AAAA,MAClB;AAAA,IACF;AACA,QAAI,cAAc,QAAQ,YAAY,QAAQ,UAAU,WAAW;AACjE,uBAAiB,KAAK;AAAA,SACnB,QAAQ,QAAQ,IAAI,UAAU,QAAQ,KAAK;AAAA,MAC9C;AAAA,IACF;AAEA,UAAM,kBAAkB,IAAI,MAAM,EAAE,EAAE,KAAK,CAAC;AAC5C,QAAI,mBAAmB;AACvB,eAAW,SAAS,eAAe;AACjC,UAAI,MAAM,SAAS,QAAQ;AACzB;AACA,wBAAgB,MAAM,UAAU,YAAY,CAAC;AAAA,MAC/C;AAAA,IACF;AAEA,UAAM,cAAc,MAAM;AAAA,MACxB,eAAe,IAAI,SAAS,GAAG,OAAO,KAAK,CAAC;AAAA,IAC9C,EAAE,KAAK,CAAC,MAAM,UAAU;AACtB,UAAI,MAAM,gBAAgB,KAAK,aAAa;AAC1C,eAAO,MAAM,cAAc,KAAK;AAAA,MAClC;AAEA,aAAO,KAAK,MAAM,cAAc,MAAM,KAAK;AAAA,IAC7C,CAAC;AACD,UAAM,cAAc,YAAY;AAAA,MAC9B,CAAC,KAAK,UAAU,MAAM,MAAM;AAAA,MAC5B;AAAA,IACF;AACA,UAAM,eAAe,YAAY;AAAA,MAC/B,CAAC,KAAK,UAAU,MAAM,MAAM;AAAA,MAC5B;AAAA,IACF;AACA,UAAM,kBAAkB,YAAY;AAAA,MAClC,CAAC,KAAK,UAAU,MAAM,MAAM;AAAA,MAC5B;AAAA,IACF;AACA,UAAM,eAAe,YAAY;AAAA,MAC/B,CAAC,KAAK,UAAU,MAAM,MAAM;AAAA,MAC5B;AAAA,IACF;AACA,UAAM,cAAc,YAAY;AAAA,MAC9B,CAAC,KAAK,UAAU,MAAM,MAAM;AAAA,MAC5B;AAAA,IACF;AACA,UAAM,eAAe,YAAY,CAAC,GAAG,SAAS;AAE9C,UAAM,cAAc,WAAW,QAAQ,EACpC,OAAO,SAAS,EAChB,OAAO,KAAK,EACZ,MAAM,GAAG,EAAE;AAEd,aAAS,KAAK;AAAA,MACZ,QAAQ,MAAM;AAAA,MACd,SAAS,MAAM,WAAW;AAAA,MAC1B;AAAA,MACA,UAAU;AAAA,MACV,gBAAgB,MAAM,UAAU,YAAY;AAAA,MAC5C,eAAe,KAAK,UAAU,YAAY;AAAA,MAC1C;AAAA,MACA;AAAA,MACA,cAAc,cAAc;AAAA,MAC5B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AACT;;;AC3LA,SAAS,YAAY,aAAa,oBAAoB;AACtD,SAAS,UAAU,MAAM,WAAW;AAK7B,SAAS,eAAe,KAAuB;AACpD,QAAM,UAAoB,CAAC;AAC3B,MAAI,CAAC,WAAW,GAAG,EAAG,QAAO;AAE7B,MAAI;AACF,eAAW,SAAS,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC,GAAG;AAC7D,YAAM,WAAW,KAAK,KAAK,MAAM,IAAI;AACrC,UAAI,MAAM,YAAY,GAAG;AACvB,gBAAQ,KAAK,GAAG,eAAe,QAAQ,CAAC;AAAA,MAC1C,WAAW,MAAM,KAAK,SAAS,QAAQ,GAAG;AACxC,gBAAQ,KAAK,QAAQ;AAAA,MACvB;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;AAwBO,SAAS,aAAa,UAAiC;AAC5D,MAAI;AACF,WAAO,aAAa,UAAU,OAAO;AAAA,EACvC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKO,SAAS,WAAc,SAAsB;AAClD,QAAM,UAAe,CAAC;AACtB,aAAW,QAAQ,QAAQ,MAAM,IAAI,GAAG;AACtC,QAAI,CAAC,KAAK,KAAK,EAAG;AAClB,QAAI;AACF,cAAQ,KAAK,KAAK,MAAM,IAAI,CAAM;AAAA,IACpC,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO;AACT;AAsBO,SAAS,iBAAiB,UAA0B;AACzD,SAAO,SAAS,UAAU,QAAQ;AACpC;;;AC7FA,SAAS,cAAAC,mBAAkB;AAGpB,IAAM,QAA0B,CAAC;AAExC,IAAM,UAAU,oBAAI,IAAqB;AAElC,SAAS,eAAe,QAAuB;AACpD,UAAQ,IAAI,OAAO,KAAK,IAAI,MAAM;AAClC,MAAI,CAAC,MAAM,KAAK,CAAC,SAAS,KAAK,OAAO,OAAO,KAAK,EAAE,GAAG;AACrD,UAAM,KAAK,OAAO,IAAI;AAAA,EACxB;AACF;AAMO,SAAS,gBAA2B;AACzC,SAAO,MAAM,KAAK,QAAQ,OAAO,CAAC;AACpC;AAEO,SAAS,gBAAgB,QAAyB;AACvD,QAAM,SAAS,QAAQ,IAAI,MAAM;AACjC,MAAI,QAAQ,aAAa;AACvB,WAAO,OAAO,YAAY;AAAA,EAC5B;AAEA,QAAM,OAAO,MAAM,KAAK,CAAC,cAAc,UAAU,OAAO,MAAM;AAC9D,SAAO,OAAOC,YAAW,KAAK,OAAO,IAAI;AAC3C;AAEO,SAAS,uBAAyC;AACvD,SAAO,MAAM,OAAO,CAAC,SAAS,gBAAgB,KAAK,EAAE,CAAC;AACxD;AAEO,SAAS,cAAgC;AAC9C,SAAO;AACT;;;ALpBA,IAAM,OAAuB;AAAA,EAC3B,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,SAASC,MAAK,QAAQ,GAAG,WAAW,UAAU;AAChD;AAEA,SAAS,iBAA2B;AAClC,QAAM,QAAQ,CAACA,MAAK,QAAQ,GAAG,SAAS,CAAC;AAEzC,QAAM,MAAM,QAAQ,IAAI,mBAAmB,KAAK;AAChD,MAAI,KAAK;AACP,QAAI,SAAS;AACb,QAAI,OAAO,WAAW,GAAG,EAAG,UAASA,MAAK,QAAQ,GAAG,OAAO,MAAM,CAAC,CAAC;AACpE,aAAS,OAAO,QAAQ,WAAW,EAAE,KAAK;AAC1C,UAAM,KAAK,MAAM;AAAA,EACnB;AAEA,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,SAAmB,CAAC;AAC1B,aAAW,KAAK,OAAO;AACrB,QAAI,MAAM;AACV,QAAI;AACF,YAAM,aAAa,CAAC;AAAA,IACtB,QAAQ;AAAA,IAER;AACA,QAAI,KAAK,IAAI,GAAG,EAAG;AACnB,SAAK,IAAI,GAAG;AACZ,WAAO,KAAK,CAAC;AAAA,EACf;AACA,SAAO;AACT;AAEA,SAAS,oBACP,UACA,aACe;AACf,QAAM,SAAS,cAAcC;AAC7B,SAAO,SAAS,WAAW,MAAM,IAAI,SAAS,MAAM,OAAO,MAAM,IAAI;AACvE;AAEA,SAAS,eAAe,UAAkB,aAA6B;AACrE,QAAM,WAAW,oBAAoB,UAAU,WAAW;AAC1D,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,eAAe,SAAS,MAAMA,IAAG,EAAE,CAAC;AAC1C,MAAI,CAAC,aAAc,QAAO;AAC1B,QAAM,QAAQ,aAAa,MAAM,GAAG,EAAE,OAAO,OAAO;AACpD,SAAO,MAAM,SAAS,IAAI,MAAM,MAAM,SAAS,CAAC,IAAI;AACtD;AAEA,IAAM,mBAAN,MAA0C;AAAA,EAC/B,OAAO;AAAA,EAEhB,MAAM,QAA8B;AAClC,UAAM,UAA6B,CAAC;AACpC,UAAM,gBAAgC,CAAC;AACvC,UAAM,YAAY,oBAAI,IAAY;AAClC,UAAM,iBAAiB,oBAAI,IAAY;AACvC,UAAM,mBAAmB,oBAAI,IAAY;AAEzC,UAAM,QAAQ,eAAe;AAE7B,eAAW,QAAQ,OAAO;AACxB,YAAM,cAAcD,MAAK,MAAM,UAAU;AACzC,YAAM,eAAe,eAAe,WAAW;AAE/C,iBAAW,YAAY,cAAc;AACnC,cAAM,WAAW,oBAAoB,UAAU,WAAW;AAC1D,YAAI,aAAa,MAAM;AACrB,cAAI,iBAAiB,IAAI,QAAQ,EAAG;AACpC,2BAAiB,IAAI,QAAQ;AAAA,QAC/B;AAEA,cAAM,UAAU,aAAa,QAAQ;AACrC,YAAI,CAAC,QAAS;AAEd,cAAM,UAAU,eAAe,UAAU,WAAW;AACpD,cAAM,YAAY,iBAAiB,QAAQ;AAC3C,uBAAe,IAAI,SAAS;AAE5B,mBAAW,QAAQ,QAAQ,MAAM,IAAI,GAAG;AACtC,cAAI,CAAC,KAAK,KAAK,EAAG;AAClB,cAAI;AACF,kBAAM,MAAM,KAAK,MAAM,IAAI;AAC3B,kBAAM,YAAY,IAAI;AACtB,gBAAI,CAAC,UAAW;AAEhB,kBAAM,kBAAkB,IAAI,KAAK,SAAS;AAC1C,gBAAI,OAAO,MAAM,gBAAgB,QAAQ,CAAC,EAAG;AAE7C,gBACE,IAAI,SAAS,UACb,IAAI,SAAS,eACb,IAAI,SAAS,cACb,IAAI,SAAS,eACb;AACA,4BAAc,KAAK;AAAA,gBACjB;AAAA,gBACA,QAAQ;AAAA,gBACR;AAAA,gBACA,WAAW;AAAA,gBACX,MAAM,IAAI,SAAS,SAAS,SAAS;AAAA,cACvC,CAAC;AAAA,YACH;AAEA,gBAAI,IAAI,SAAS,YAAa;AAC9B,kBAAM,UAAU,IAAI;AACpB,gBAAI,CAAC,SAAS,MAAO;AAErB,kBAAM,QAAQ,QAAQ;AACtB,gBAAI,MAAM,gBAAgB,QAAQ,MAAM,iBAAiB,MAAM;AAC7D;AAAA,YACF;AAEA,kBAAM,OAAO,IAAI;AACjB,gBAAI,MAAM;AACR,kBAAI,UAAU,IAAI,IAAI,EAAG;AACzB,wBAAU,IAAI,IAAI;AAAA,YACpB;AAEA,oBAAQ,KAAK;AAAA,cACX;AAAA,cACA,QAAQ;AAAA,cACR,OAAO,QAAQ,SAAS;AAAA,cACxB;AAAA,cACA,WAAW;AAAA,cACX,aAAa,MAAM,gBAAgB;AAAA,cACnC,cAAc,MAAM,iBAAiB;AAAA,cACrC,iBAAiB;AAAA,cACjB,cAAc,MAAM,2BAA2B;AAAA,YACjD,CAAC;AAAA,UACH,QAAQ;AAAA,UAER;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,eAAW,QAAQ,OAAO;AACxB,iBAAW,kBAAkB,CAAC,eAAe,UAAU,GAAG;AACxD,cAAM,kBAAkB,eAAeA,MAAK,MAAM,cAAc,CAAC;AAEjE,mBAAW,YAAY,iBAAiB;AACtC,gBAAM,YAAY,iBAAiB,QAAQ;AAC3C,cAAI,eAAe,IAAI,SAAS,EAAG;AACnC,yBAAe,IAAI,SAAS;AAE5B,gBAAM,UAAU,aAAa,QAAQ;AACrC,cAAI,CAAC,QAAS;AAEd,qBAAW,QAAQ,QAAQ,MAAM,IAAI,GAAG;AACtC,gBAAI,CAAC,KAAK,KAAK,EAAG;AAClB,gBAAI;AACF,oBAAM,MAAM,KAAK,MAAM,IAAI;AAC3B,oBAAM,YAAY,IAAI;AACtB,kBAAI,CAAC,UAAW;AAEhB,oBAAM,kBAAkB,IAAI,KAAK,SAAS;AAC1C,kBAAI,OAAO,MAAM,gBAAgB,QAAQ,CAAC,EAAG;AAE7C,kBACE,IAAI,SAAS,UACb,IAAI,SAAS,eACb,IAAI,SAAS,cACb,IAAI,SAAS,eACb;AACA,8BAAc,KAAK;AAAA,kBACjB;AAAA,kBACA,QAAQ;AAAA,kBACR,SAAS;AAAA,kBACT,WAAW;AAAA,kBACX,MAAM,IAAI,SAAS,SAAS,SAAS;AAAA,gBACvC,CAAC;AAAA,cACH;AAAA,YACF,QAAQ;AAAA,YAER;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS,mBAAmB,OAAO;AAAA,MACnC,UAAU,gBAAgB,eAAe,OAAO;AAAA,IAClD;AAAA,EACF;AAAA,EAEA,cAAuB;AACrB,UAAM,QAAQ,eAAe;AAC7B,WAAO,MAAM;AAAA,MACX,CAAC,SACCE,YAAWF,MAAK,MAAM,UAAU,CAAC,KACjCE,YAAWF,MAAK,MAAM,aAAa,CAAC,KACpCE,YAAWF,MAAK,MAAM,UAAU,CAAC;AAAA,IACrC;AAAA,EACF;AACF;AAEA,eAAe,IAAI,iBAAiB,CAAC;;;AMzNrC,SAAS,WAAAG,gBAAe;AACxB,SAAS,QAAAC,aAAY;AAYrB,IAAM,UAAU;AAChB,IAAM,YAAY;AAClB,IAAM,mBAAmBC,MAAKC,SAAQ,GAAG,UAAU,UAAU;AAE7D,SAAS,qBAAqB,SAAiC;AAC7D,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,MAAM;AAAA,IACN;AAAA,EACF;AACF;AAEA,SAAS,aAAa,OAAwB;AAC5C,QAAM,cAAc,OAAO,KAAK;AAChC,SAAO,OAAO,SAAS,WAAW,IAAI,cAAc;AACtD;AAEA,SAAS,mBAAmB,SAAkB,UAA2B;AACvE,SAAO,KAAK,IAAI,GAAG,aAAa,OAAO,IAAI,aAAa,QAAQ,CAAC;AACnE;AA8BA,SAAS,YAAY,OAAuB;AAC1C,QAAM,aAAa,MAAM,QAAQ,OAAO,GAAG,EAAE,QAAQ,QAAQ,EAAE;AAC/D,QAAM,OAAO,WAAW,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,IAAI;AACvD,SAAO,QAAQ;AACjB;AAEO,SAAS,oBAAoB,SAAyC;AAC3E,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AAEA,QAAM,gBAAgB,QAAQ,KAAK;AACnC,MAAI,eAAe;AACjB,UAAM,QAAQ,cAAc,MAAM,4BAA4B;AAC9D,QAAI,OAAO;AACT,aAAO,MAAM,CAAC;AAAA,IAChB;AAAA,EACF;AAEA,MAAI,QAAQ,KAAK;AACf,WAAO,YAAY,QAAQ,GAAG;AAAA,EAChC;AAEA,SAAO;AACT;AAEO,IAAM,cAAN,MAAqC;AAAA,EAG1C,YAA6B,UAAU,kBAAkB;AAA5B;AAC3B,SAAK,OAAO,qBAAqB,OAAO;AAAA,EAC1C;AAAA,EAF6B;AAAA,EAFpB;AAAA,EAMT,MAAM,QAA8B;AAClC,UAAM,UAA6B,CAAC;AACpC,UAAM,gBAAgC,CAAC;AACvC,UAAM,QAAQ,eAAe,KAAK,OAAO;AAEzC,QAAI,MAAM,WAAW,GAAG;AACtB,aAAO,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,EAAE;AAAA,IACrC;AAEA,eAAW,YAAY,OAAO;AAC5B,YAAM,UAAU,aAAa,QAAQ;AACrC,UAAI,CAAC,QAAS;AAEd,UAAI,iBAAiB;AACrB,YAAM,eAAe;AACrB,iBAAW,QAAQ,QAAQ,MAAM,IAAI,GAAG;AACtC,YAAI,CAAC,KAAK,KAAK,EAAG;AAClB,YAAI;AACF,gBAAM,MAAM,KAAK,MAAM,IAAI;AAC3B,cAAI,IAAI,SAAS,gBAAgB;AAC/B,6BAAiB,oBAAoB,IAAI,OAAO;AAChD;AAAA,UACF;AAAA,QACF,QAAQ;AACN;AAAA,QACF;AAAA,MACF;AAEA,UAAI,mBAAmB;AAOvB,YAAM,YAAY,oBAAI,IAAwB;AAE9C,iBAAW,QAAQ,QAAQ,MAAM,IAAI,GAAG;AACtC,YAAI,CAAC,KAAK,KAAK,EAAG;AAClB,YAAI;AACF,gBAAM,MAAM,KAAK,MAAM,IAAI;AAE3B,cAAI,IAAI,SAAS,kBAAkB,IAAI,WAAW;AAChD,kBAAM,iBAAiB,IAAI,KAAK,IAAI,SAAS;AAC7C,gBAAI,CAAC,OAAO,MAAM,eAAe,QAAQ,CAAC,GAAG;AAC3C,4BAAc,KAAK;AAAA,gBACjB,WAAW;AAAA,gBACX,QAAQ;AAAA,gBACR,SAAS;AAAA,gBACT,WAAW;AAAA,gBACX,MAAM;AAAA,cACR,CAAC;AAAA,YACH;AAAA,UACF;AAEA,cAAI,IAAI,SAAS,kBAAkB,IAAI,SAAS,OAAO;AACrD,+BAAmB,IAAI,QAAQ;AAC/B;AAAA,UACF;AAEA,cAAI,IAAI,SAAS,YAAa;AAE9B,gBAAM,UAAU,IAAI;AACpB,cAAI,CAAC,WAAW,QAAQ,SAAS,cAAe;AAEhD,gBAAM,OAAO,QAAQ;AACrB,cAAI,CAAC,KAAM;AAEX,gBAAM,YAAY,IAAI,YAAY,IAAI,KAAK,IAAI,SAAS,IAAI;AAC5D,cAAI,CAAC,aAAa,OAAO,MAAM,UAAU,QAAQ,CAAC,EAAG;AAErD,wBAAc,KAAK;AAAA,YACjB,WAAW;AAAA,YACX,QAAQ;AAAA,YACR,SAAS;AAAA,YACT;AAAA,YACA,MAAM;AAAA,UACR,CAAC;AAED,cAAI,QAAQ,KAAK;AACjB,cAAI,CAAC,SAAS,KAAK,mBAAmB;AACpC,kBAAM,WAAW,GAAG,KAAK,SAAS,QAAQ,SAAS,oBAAoB,EAAE;AACzE,kBAAM,OAAO,UAAU,IAAI,QAAQ;AACnC,kBAAM,OAAO,KAAK;AAClB,gBAAI,MAAM;AACR,sBAAQ;AAAA,gBACN,cAAc;AAAA,kBACZ,KAAK;AAAA,kBACL,KAAK;AAAA,gBACP;AAAA,gBACA,eAAe;AAAA,kBACb,KAAK;AAAA,kBACL,KAAK;AAAA,gBACP;AAAA,gBACA,qBAAqB;AAAA,kBACnB,KAAK;AAAA,kBACL,KAAK;AAAA,gBACP;AAAA,gBACA,yBAAyB;AAAA,kBACvB,KAAK;AAAA,kBACL,KAAK;AAAA,gBACP;AAAA,cACF;AAAA,YACF,OAAO;AACL,sBAAQ;AAAA,YACV;AACA,sBAAU,IAAI,UAAU,EAAE,GAAG,KAAK,CAAC;AAAA,UACrC;AACA,cAAI,CAAC,MAAO;AAEZ,gBAAM,QACJ,KAAK,SAAS,QAAQ,SAAS,oBAAoB;AACrD,gBAAM,cAAc,aAAa,MAAM,mBAAmB;AAC1D,gBAAM,kBAAkB,aAAa,MAAM,uBAAuB;AAClE,gBAAM,cAAc,KAAK;AAAA,YACvB;AAAA,YACA,aAAa,MAAM,YAAY,IAAI;AAAA,UACrC;AACA,gBAAM,eAAe,KAAK;AAAA,YACxB;AAAA,YACA,aAAa,MAAM,aAAa,IAAI;AAAA,UACtC;AAEA,cACE,gBAAgB,KAChB,iBAAiB,KACjB,oBAAoB,KACpB,gBAAgB,GAChB;AACA;AAAA,UACF;AAEA,kBAAQ,KAAK;AAAA,YACX,WAAW;AAAA,YACX,QAAQ;AAAA,YACR;AAAA,YACA,SAAS;AAAA,YACT;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,cAAc;AAAA,UAChB,CAAC;AAAA,QACH,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS,mBAAmB,OAAO;AAAA,MACnC,UAAU,gBAAgB,eAAe,OAAO;AAAA,IAClD;AAAA,EACF;AACF;AAEA,eAAe,IAAI,YAAY,CAAC;;;AC3PhC,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,WAAAC,gBAAe;AACxB,SAAS,QAAAC,aAAY;AAgBrB,IAAMC,WAAU;AAChB,IAAMC,aAAY;AAClB,IAAM,uBAAuBC,MAAKC,SAAQ,GAAG,QAAQ,UAAU;AA4B/D,SAASC,sBAAqB,SAAiC;AAC7D,SAAO;AAAA,IACL,IAAIJ;AAAA,IACJ,MAAMC;AAAA,IACN;AAAA,EACF;AACF;AAEA,SAASI,cAAa,OAAwB;AAC5C,QAAM,cAAc,OAAO,KAAK;AAChC,SAAO,OAAO,SAAS,WAAW,IAAI,cAAc;AACtD;AAEA,SAASC,aAAY,OAAuB;AAC1C,QAAM,aAAa,MAAM,QAAQ,OAAO,GAAG,EAAE,QAAQ,QAAQ,EAAE;AAC/D,QAAM,OAAO,WAAW,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,IAAI;AACvD,SAAO,QAAQ;AACjB;AAEA,SAAS,mBAAmB,OAAuB;AACjD,SAAO,MAAM,QAAQ,OAAO,GAAG,EAAE,QAAQ,QAAQ,EAAE;AACrD;AAEA,SAAS,eACP,UACG,MACK;AACR,aAAW,OAAO,MAAM;AACtB,UAAM,QAAQ,MAAM,GAAG;AACvB,UAAM,cAAcD,cAAa,KAAK;AACtC,QAAI,cAAc,GAAG;AACnB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,yBAAyB,KAAqB;AAC5D,SAAOC,aAAY,GAAG;AACxB;AAEO,SAAS,yBACd,UACA,cAAc,sBACN;AACR,QAAM,qBAAqB,mBAAmB,QAAQ;AACtD,QAAM,wBAAwB,mBAAmB,WAAW;AAC5D,QAAM,SAAS,GAAG,qBAAqB;AAEvC,MAAI,CAAC,mBAAmB,WAAW,MAAM,GAAG;AAC1C,WAAO;AAAA,EACT;AAEA,QAAM,eAAe,mBAAmB,MAAM,OAAO,MAAM;AAC3D,QAAM,eAAe,aAAa,MAAM,GAAG,EAAE,CAAC;AAC9C,MAAI,CAAC,cAAc;AACjB,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,UAAU,mBAAmB,YAAY;AAC/C,QAAI,QAAQ,SAAS,GAAG,KAAK,QAAQ,SAAS,IAAI,GAAG;AACnD,aAAOA,aAAY,OAAO;AAAA,IAC5B;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,QAAM,YAAY,aAAa,MAAM,GAAG,EAAE,OAAO,OAAO;AACxD,SAAO,UAAU,SAAS,IAAI,UAAU,UAAU,SAAS,CAAC,IAAI;AAClE;AAEO,IAAM,YAAN,MAAmC;AAAA,EAGxC,YAA6B,cAAc,sBAAsB;AAApC;AAC3B,SAAK,OAAOF,sBAAqB,WAAW;AAAA,EAC9C;AAAA,EAF6B;AAAA,EAFpB;AAAA,EAMT,MAAM,QAA8B;AAClC,UAAM,eAAe,eAAe,KAAK,WAAW;AACpD,QAAI,aAAa,WAAW,GAAG;AAC7B,aAAO,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,EAAE;AAAA,IACrC;AAEA,UAAM,UAA6B,CAAC;AACpC,UAAM,gBAAgC,CAAC;AACvC,UAAM,eAAe,oBAAI,IAAY;AAErC,eAAW,YAAY,cAAc;AACnC,YAAM,UAAU,aAAa,QAAQ;AACrC,UAAI,CAAC,QAAS;AAEd,YAAM,OAAO,WAAqB,OAAO;AACzC,UAAI,KAAK,WAAW,EAAG;AAEvB,UAAI,YAAY;AAChB,UAAI,UAAU,yBAAyB,UAAU,KAAK,WAAW;AAEjE,iBAAW,OAAO,MAAM;AACtB,YAAI,IAAI,SAAS,UAAW;AAC5B,YAAI,IAAI,IAAI;AACV,sBAAY,IAAI;AAAA,QAClB;AACA,YAAI,IAAI,KAAK;AACX,oBAAU,yBAAyB,IAAI,GAAG;AAAA,QAC5C;AACA;AAAA,MACF;AAEA,iBAAW,OAAO,MAAM;AACtB,YAAI,IAAI,SAAS,UAAW;AAE5B,cAAM,UAAU,IAAI;AACpB,YAAI,CAAC,QAAS;AAEd,cAAM,eAAe,IAAI,aAAa,QAAQ;AAC9C,YAAI,CAAC,aAAc;AAEnB,cAAM,YAAY,IAAI,KAAK,YAAY;AACvC,YAAI,OAAO,MAAM,UAAU,QAAQ,CAAC,EAAG;AAEvC,YAAI,QAAQ,SAAS,UAAU,QAAQ,SAAS,aAAa;AAC3D,wBAAc,KAAK;AAAA,YACjB;AAAA,YACA,QAAQJ;AAAA,YACR;AAAA,YACA;AAAA,YACA,MAAM,QAAQ;AAAA,UAChB,CAAC;AAAA,QACH;AAEA,YAAI,QAAQ,SAAS,YAAa;AAElC,cAAM,QAAQ,QAAQ;AACtB,YAAI,CAAC,MAAO;AAEZ,cAAM,cAAc,eAAe,OAAO,SAAS,aAAa;AAChE,cAAM,eAAe,eAAe,OAAO,UAAU,cAAc;AACnE,cAAM,eAAe;AAAA,UACnB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AACA,cAAM,kBAAkB;AAAA,UACtB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAEA,YACE,gBAAgB,KAChB,iBAAiB,KACjB,iBAAiB,KACjB,oBAAoB,GACpB;AACA;AAAA,QACF;AAEA,YAAI,IAAI,IAAI;AACV,cAAI,aAAa,IAAI,IAAI,EAAE,EAAG;AAC9B,uBAAa,IAAI,IAAI,EAAE;AAAA,QACzB;AAEA,gBAAQ,KAAK;AAAA,UACX;AAAA,UACA,QAAQA;AAAA,UACR,OAAO,QAAQ,SAAS;AAAA,UACxB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS,mBAAmB,OAAO;AAAA,MACnC,UAAU,gBAAgB,eAAe,OAAO;AAAA,IAClD;AAAA,EACF;AAAA,EAEA,cAAuB;AACrB,WAAOO,YAAW,KAAK,WAAW;AAAA,EACpC;AACF;AAEA,eAAe,IAAI,UAAU,CAAC;;;AChP9B,SAAS,cAAAC,aAAY,eAAAC,cAAa,gBAAAC,qBAAoB;AACtD,SAAS,WAAAC,gBAAe;AACxB,SAAS,YAAAC,WAAU,QAAAC,aAAY;AAW/B,IAAMC,QAAuB;AAAA,EAC3B,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,SAASC,MAAKC,SAAQ,GAAG,WAAW,KAAK;AAC3C;AAQA,SAAS,iBAAiB,SAA2B;AACnD,QAAM,UAAoB,CAAC;AAC3B,MAAI,CAACC,YAAW,OAAO,EAAG,QAAO;AAEjC,MAAI;AACJ,MAAI;AACF,kBAAcC,aAAY,SAAS,EAAE,eAAe,KAAK,CAAC;AAAA,EAC5D,QAAQ;AACN,WAAO;AAAA,EACT;AACA,aAAW,SAAS,aAAa;AAC/B,QAAI,CAAC,MAAM,YAAY,EAAG;AAC1B,qBAAiBH,MAAK,SAAS,MAAM,MAAM,OAAO,GAAG,SAAS,CAAC;AAAA,EACjE;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,KAAa,KAAe,OAAqB;AACzE,MAAI,QAAQ,EAAG;AACf,MAAI;AACJ,MAAI;AACF,cAAUG,aAAY,KAAK,EAAE,eAAe,KAAK,CAAC;AAAA,EACpD,QAAQ;AACN;AAAA,EACF;AACA,aAAW,KAAK,SAAS;AACvB,UAAM,OAAOH,MAAK,KAAK,EAAE,IAAI;AAC7B,QAAI,EAAE,YAAY,GAAG;AACnB,uBAAiB,MAAM,KAAK,QAAQ,CAAC;AAAA,IACvC,WAAW,EAAE,KAAK,SAAS,QAAQ,KAAK,EAAE,KAAK,SAAS,OAAO,GAAG;AAChE,UAAI,KAAK,IAAI;AAAA,IACf;AAAA,EACF;AACF;AAmCA,SAAS,WAAW,UAAuC;AACzD,MAAI;AACJ,MAAI;AACF,UAAMI,cAAa,UAAU,OAAO;AAAA,EACtC,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,MAAI,SAAS,SAAS,QAAQ,GAAG;AAC/B,UAAM,WAA4B,CAAC;AACnC,QAAI,cAA+B;AACnC,QAAI,QAAuB;AAC3B,QAAI,aAA4B;AAChC,eAAW,QAAQ,IAAI,MAAM,IAAI,GAAG;AAClC,YAAM,UAAU,KAAK,KAAK;AAC1B,UAAI,CAAC,QAAS;AACd,UAAI;AACJ,UAAI;AACF,cAAM,KAAK,MAAM,OAAO;AAAA,MAC1B,QAAQ;AACN;AAAA,MACF;AACA,UAAI,CAAC,eAAe,MAAM,QAAQ,IAAI,WAAW,GAAG;AAClD,sBAAc,IAAI;AAClB,YAAI,OAAO,IAAI,UAAU,SAAU,SAAQ,IAAI;AAC/C,YAAI,OAAO,IAAI,eAAe,SAAU,cAAa,IAAI;AACzD;AAAA,MACF;AACA,UAAI,OAAO,IAAI,SAAS,YAAY,OAAO,IAAI,SAAS,UAAU;AAChE,iBAAS,KAAK,GAAoB;AAAA,MACpC;AAAA,IACF;AACA,WAAO,EAAE,UAAU,aAAa,OAAO,WAAW;AAAA,EACpD;AAEA,MAAI;AAOJ,MAAI;AACF,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB,QAAQ;AACN,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,UAAU,MAAM,QAAQ,MAAM,QAAQ,IAClC,KAAK,WACL,MAAM,QAAQ,MAAM,OAAO,IACzB,KAAK,UACL,CAAC;AAAA,IACP,aAAa,MAAM,QAAQ,MAAM,WAAW,IAAI,KAAK,cAAc;AAAA,IACnE,OAAO,OAAO,MAAM,UAAU,WAAW,KAAK,QAAQ;AAAA,IACtD,YAAY,OAAO,MAAM,eAAe,WAAW,KAAK,aAAa;AAAA,EACvE;AACF;AAIA,SAAS,aAAa,KAAiD;AACrE,QAAM,IAAI,IAAI,QAAQ,IAAI;AAC1B,MAAI,MAAM,OAAQ,QAAO;AACzB,MAAI,MAAM,YAAY,MAAM,WAAW,MAAM,YAAa,QAAO;AACjE,SAAO;AACT;AAEA,SAAS,uBAAuB,aAAsC;AACpE,MAAI,CAAC,eAAe,YAAY,WAAW,EAAG,QAAO;AACrD,QAAM,QAAQ,YAAY,CAAC;AAC3B,MAAI,CAAC,MAAO,QAAO;AACnB,SAAOC,UAAS,OAAO,KAAK,EAAE,QAAQ,WAAW,EAAE,CAAC,KAAK;AAC3D;AAEA,IAAM,kBAAN,MAAyC;AAAA,EAC9B,OAAON;AAAA,EAEhB,MAAM,QAA8B;AAClC,UAAM,eAAe,iBAAiBA,MAAK,OAAO;AAClD,QAAI,aAAa,WAAW,GAAG;AAC7B,aAAO,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,EAAE;AAAA,IACrC;AAEA,UAAM,UAA6B,CAAC;AACpC,UAAM,gBAAgC,CAAC;AAEvC,eAAW,YAAY,cAAc;AACnC,YAAM,SAAS,WAAW,QAAQ;AAClC,UAAI,CAAC,OAAQ;AAEb,YAAM,UAAU,uBAAuB,OAAO,WAAW;AAEzD,iBAAW,OAAO,OAAO,UAAU;AACjC,cAAM,OAAO,aAAa,GAAG;AAC7B,YAAI,CAAC,KAAM;AAEX,cAAM,YAAY,IAAI,aAAa,IAAI,cAAc,OAAO;AAC5D,YAAI,CAAC,UAAW;AAChB,cAAM,KAAK,IAAI,KAAK,SAAS;AAC7B,YAAI,OAAO,MAAM,GAAG,QAAQ,CAAC,EAAG;AAEhC,sBAAc,KAAK;AAAA,UACjB,WAAW;AAAA,UACX,QAAQ;AAAA,UACR;AAAA,UACA,WAAW;AAAA,UACX;AAAA,QACF,CAAC;AAED,cAAM,SAAS,IAAI;AACnB,cAAM,QAAQ,IAAI,SAAS,IAAI,iBAAiB,IAAI;AACpD,YAAI,CAAC,UAAU,CAAC,MAAO;AAIvB,YAAI,QAAQ;AACV,gBAAM,SAAS,OAAO,UAAU;AAChC,gBAAM,WAAW,OAAO,YAAY;AACpC,kBAAQ,KAAK;AAAA,YACX,WAAW;AAAA,YACX,QAAQ;AAAA,YACR,OAAO,IAAI,SAAS,OAAO,SAAS;AAAA,YACpC;AAAA,YACA,WAAW;AAAA,YACX,cAAc,OAAO,SAAS,KAAK;AAAA,YACnC,eAAe,OAAO,UAAU,KAAK;AAAA,YACrC,iBAAiB;AAAA,YACjB,cAAc;AAAA,UAChB,CAAC;AAAA,QACH,WAAW,OAAO;AAChB,gBAAM,SAAS,MAAM,2BAA2B;AAChD,gBAAM,WAAW,MAAM,sBAAsB;AAC7C,kBAAQ,KAAK;AAAA,YACX,WAAW;AAAA,YACX,QAAQ;AAAA,YACR,OAAO,IAAI,SAAS,OAAO,SAAS;AAAA,YACpC;AAAA,YACA,WAAW;AAAA,YACX,cACG,MAAM,oBAAoB,MAAM,gBAAgB,KAAK;AAAA,YACxD,eACG,MAAM,wBAAwB,MAAM,iBAAiB,KACtD;AAAA,YACF,iBAAiB;AAAA,YACjB,cAAc;AAAA,UAChB,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS,mBAAmB,OAAO;AAAA,MACnC,UAAU,gBAAgB,eAAe,OAAO;AAAA,IAClD;AAAA,EACF;AACF;AAEA,eAAe,IAAI,gBAAgB,CAAC;;;AC3PpC,SAAS,cAAAO,mBAAkB;AAC3B,SAAS,WAAAC,gBAAe;AACxB,SAAS,SAAS,QAAAC,aAAY;;;ACF9B,SAAS,oBAAoB;AAC7B,SAAS,qBAAqB;AAc9B,SAAS,4BAA+B,IAAkC;AACxE,QAAM,sBAAsB,QAAQ;AAEpC,UAAQ,eAAe,CACrB,YACG,SACM;AACT,UAAM,cACJ,OAAO,YAAY,WACf,OAAO,KAAK,CAAC,MAAM,WACjB,KAAK,CAAC,IACN,KACF,QAAQ;AACd,UAAM,iBACJ,OAAO,YAAY,WAAW,UAAU,QAAQ;AAElD,QACE,gBAAgB,yBAChB,eAAe,SAAS,QAAQ,GAChC;AACA;AAAA,IACF;AAEA,IACE,oBAIA,KAAK,SAAS,SAAS,GAAG,IAAI;AAAA,EAClC;AAEA,SAAO,GAAG,EAAE,QAAQ,MAAM;AACxB,YAAQ,cAAc;AAAA,EACxB,CAAC;AACH;AAEA,eAAe,0BACb,QACA,OACwB;AACxB,MAAI;AACF,WAAO,MAAM,4BAA4B,YAAY;AACnD,YAAM,iBAAiB;AACvB,YAAM,SAAU,MAAM,OAAO;AAI7B,YAAM,YAAY;AAAA,QAChB;AAAA,QACA,GAAG,cAAc,MAAM,EAAE,IAAI;AAAA,MAC/B;AACA,UAAI,YAAqB;AAEzB,iBAAW,YAAY,WAAW;AAChC,YAAI,KAAsC;AAC1C,YAAI;AACF,eAAK,IAAI,OAAO,aAAa,QAAQ;AACrC,iBAAO,GAAG,QAAQ,KAAK,EAAE,IAAI;AAAA,QAC/B,SAAS,KAAK;AACZ,sBAAY;AACZ,gBAAM,QAAQ;AACd,gBAAM,UAAW,IAAc;AAC/B,cACE,MAAM,SAAS,sBACf,QAAQ,SAAS,8BAA8B,GAC/C;AACA;AAAA,UACF;AAEA,gBAAM;AAAA,QACR,UAAE;AACA,cAAI,MAAM;AAAA,QACZ;AAAA,MACF;AAEA,YAAM;AAAA,IACR,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,UAAM,QAAQ;AACd,UAAM,UAAW,IAAc;AAC/B,QACE,MAAM,SAAS,gCACf,QAAQ,SAAS,aAAa,GAC9B;AACA,aAAO;AAAA,IACT;AAEA,UAAM;AAAA,EACR;AACF;AAEA,SAAS,sBAA4B,QAAgB,OAAuB;AAC1E,QAAM,aAAa;AAAA,IACjB,QAAQ,IAAI;AAAA,IACZ;AAAA,IACA;AAAA,EACF,EAAE,OAAO,CAAC,UAA2B,QAAQ,KAAK,CAAC;AAEnD,MAAI,YAA0B;AAE9B,aAAW,WAAW,YAAY;AAChC,QAAI;AACF,YAAM,SAAS,aAAa,SAAS,CAAC,SAAS,QAAQ,KAAK,GAAG;AAAA,QAC7D,UAAU;AAAA,QACV,WAAW,MAAM,OAAO;AAAA,QACxB,SAAS;AAAA,QACT,aAAa;AAAA,MACf,CAAC,EAAE,KAAK;AAER,UAAI,CAAC,UAAU,WAAW,MAAM;AAC9B,eAAO,CAAC;AAAA,MACV;AAEA,aAAO,KAAK,MAAM,MAAM;AAAA,IAC1B,SAAS,KAAK;AACZ,kBAAY;AACZ,YAAM,YAAY;AAClB,UAAI,UAAU,WAAW,OAAO,UAAU,SAAS,SAAS,QAAQ,GAAG;AACrE;AAAA,MACF;AAEA,YAAM;AAAA,IACR;AAAA,EACF;AAEA,QAAM,IAAI;AAAA,IACR,mGAAmG,WAAW,WAAW,WAAW;AAAA,EACtI;AACF;AAEA,eAAsB,eACpB,QACA,OACiB;AACjB,QAAM,cAAc,MAAM,0BAAgC,QAAQ,KAAK;AACvE,SAAO,eAAe,sBAA4B,QAAQ,KAAK;AACjE;;;ADzIA,IAAMC,WAAU;AAChB,IAAMC,aAAY;AAClB,IAAM,kBAAkBC,MAAKC,SAAQ,GAAG,WAAW,UAAU;AAE7D,IAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAcvB,IAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA6BvB,SAASC,sBAAqB,QAAgC;AAC5D,SAAO;AAAA,IACL,IAAIJ;AAAA,IACJ,MAAMC;AAAA,IACN,SAAS,QAAQ,MAAM;AAAA,EACzB;AACF;AAEA,SAASI,cAAa,OAAwB;AAC5C,QAAM,cAAc,OAAO,KAAK;AAChC,SAAO,OAAO,SAAS,WAAW,IAAI,cAAc;AACtD;AAEA,SAAS,mBAAmB,OAA6B;AACvD,QAAM,cAAc,OAAO,KAAK;AAChC,MAAI,CAAC,OAAO,SAAS,WAAW,GAAG;AACjC,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,IAAI,KAAK,cAAc,GAAI;AAC7C,SAAO,OAAO,MAAM,UAAU,QAAQ,CAAC,IAAI,OAAO;AACpD;AAEO,IAAM,eAAN,MAAsC;AAAA,EAClC;AAAA,EACQ;AAAA,EACA;AAAA,EAEjB,YAAY,UAA+B,CAAC,GAAG;AAC7C,SAAK,SAAS,QAAQ,UAAU;AAChC,SAAK,YAAY,QAAQ,aAAa;AACtC,SAAK,OAAOD,sBAAqB,KAAK,MAAM;AAAA,EAC9C;AAAA,EAEA,MAAM,QAA8B;AAClC,QAAI,CAACE,YAAW,KAAK,MAAM,GAAG;AAC5B,aAAO,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,EAAE;AAAA,IACrC;AAEA,UAAM,cAAc,MAAM,KAAK;AAAA,MAC7B,KAAK;AAAA,MACL;AAAA,IACF;AAEA,UAAM,UAA6B,CAAC;AACpC,eAAW,OAAO,aAAa;AAC7B,YAAM,YACJ,OAAO,IAAI,OAAO,YAAY,IAAI,GAAG,SAAS,IAAI,IAAI,KAAK;AAC7D,UAAI,CAAC,UAAW;AAEhB,YAAM,YAAY,mBAAmB,IAAI,SAAS;AAClD,UAAI,CAAC,UAAW;AAEhB,YAAM,cAAcD,cAAa,IAAI,WAAW;AAChD,YAAM,eAAeA,cAAa,IAAI,YAAY;AAClD,YAAM,eAAeA,cAAa,IAAI,eAAe;AACrD,YAAM,kBAAkBA,cAAa,IAAI,eAAe;AAExD,UACE,gBAAgB,KAChB,iBAAiB,KACjB,iBAAiB,KACjB,oBAAoB,GACpB;AACA;AAAA,MACF;AAEA,cAAQ,KAAK;AAAA,QACX;AAAA,QACA,QAAQL;AAAA,QACR,OACE,OAAO,IAAI,UAAU,YAAY,IAAI,MAAM,SAAS,IAChD,IAAI,QACJ;AAAA,QACN,SAAS;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAEA,QAAI;AACJ,QAAI;AACF,oBAAc,MAAM,KAAK;AAAA,QACvB,KAAK;AAAA,QACL;AAAA,MACF;AAAA,IACF,QAAQ;AACN,aAAO;AAAA,QACL,SAAS,mBAAmB,OAAO;AAAA,QACnC,UAAU,CAAC;AAAA,MACb;AAAA,IACF;AAEA,UAAM,gBAAgC,CAAC;AACvC,eAAW,OAAO,aAAa;AAC7B,YAAM,YACJ,OAAO,IAAI,cAAc,YAAY,IAAI,UAAU,SAAS,IACxD,IAAI,YACJ;AACN,UAAI,CAAC,UAAW;AAEhB,YAAM,OACJ,IAAI,SAAS,UAAU,IAAI,SAAS,cAAc,IAAI,OAAO;AAC/D,UAAI,CAAC,KAAM;AAEX,YAAM,YAAY,mBAAmB,IAAI,SAAS;AAClD,UAAI,CAAC,UAAW;AAEhB,oBAAc,KAAK;AAAA,QACjB;AAAA,QACA,QAAQA;AAAA,QACR,SAAS;AAAA,QACT;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL,SAAS,mBAAmB,OAAO;AAAA,MACnC,UAAU,gBAAgB,eAAe,OAAO;AAAA,IAClD;AAAA,EACF;AAAA,EAEA,cAAuB;AACrB,WAAOM,YAAW,KAAK,MAAM;AAAA,EAC/B;AACF;AAEA,eAAe,IAAI,aAAa,CAAC;;;AEhMjC,SAAS,cAAAC,aAAY,eAAAC,cAAa,gBAAAC,qBAAoB;AACtD,SAAS,WAAAC,gBAAe;AACxB,SAAS,YAAAC,WAAU,WAAAC,UAAS,QAAAC,aAAY;AAWxC,IAAM,WAAWC,MAAKC,SAAQ,GAAG,UAAU;AAE3C,IAAMC,QAAuB;AAAA,EAC3B,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,SAAS;AACX;AAwBA,SAAS,kBACP,KACA,SACA,SACM;AACN,MAAI,CAACC,YAAW,GAAG,KAAK,QAAQ,IAAI,GAAG,GAAG;AACxC;AAAA,EACF;AAEA,UAAQ,IAAI,GAAG;AAEf,MAAI;AACF,eAAW,SAASC,aAAY,KAAK,EAAE,eAAe,KAAK,CAAC,GAAG;AAC7D,YAAM,WAAWJ,MAAK,KAAK,MAAM,IAAI;AAErC,UAAI,MAAM,YAAY,GAAG;AACvB,0BAAkB,UAAU,SAAS,OAAO;AAC5C;AAAA,MACF;AAEA,UAAI,MAAM,OAAO,KAAK,MAAM,SAAS,gBAAgB;AACnD,gBAAQ,KAAK;AAAA,UACX,UAAU;AAAA,UACV,WAAWK,UAASC,SAAQ,QAAQ,CAAC;AAAA,QACvC,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AACF;AAEA,SAAS,eACP,SAC2C;AAC3C,QAAM,UAAqD,CAAC;AAC5D,oBAAkB,SAAS,SAAS,oBAAI,IAAY,CAAC;AACrD,SAAO;AACT;AAEA,SAAS,sBACP,SACQ;AACR,QAAM,cAAc,SAAS,WAAW,SAAS;AACjD,MAAI,CAAC,YAAa,QAAO;AACzB,SAAOD,UAAS,YAAY,QAAQ,WAAW,EAAE,CAAC,KAAK;AACzD;AAEA,IAAM,mBAAN,MAA0C;AAAA,EAC/B,OAAOH;AAAA,EAEhB,MAAM,QAA8B;AAClC,UAAM,aAAa,eAAe,QAAQ;AAC1C,QAAI,WAAW,WAAW,GAAG;AAC3B,aAAO,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,EAAE;AAAA,IACrC;AAEA,UAAM,UAA6B,CAAC;AACpC,UAAM,gBAAgC,CAAC;AAEvC,eAAW,EAAE,UAAU,UAAU,KAAK,YAAY;AAChD,UAAI;AACJ,UAAI;AACF,kBAAUK,cAAa,UAAU,OAAO;AAAA,MAC1C,QAAQ;AACN;AAAA,MACF;AAEA,UAAI,iBAAiB;AAErB,iBAAW,QAAQ,QAAQ,MAAM,IAAI,GAAG;AACtC,YAAI,CAAC,KAAK,KAAK,EAAG;AAElB,YAAI;AACF,gBAAM,MAAM,KAAK,MAAM,IAAI;AAC3B,gBAAM,YAAY,IAAI,YAAY,IAAI,KAAK,IAAI,SAAS,IAAI;AAC5D,gBAAM,eAAe,aAAa,CAAC,OAAO,MAAM,UAAU,QAAQ,CAAC;AAEnE,cAAI,IAAI,SAAS,mBAAmB,IAAI,SAAS,kBAAkB;AACjE,6BAAiB,sBAAsB,IAAI,MAAM,OAAO;AAAA,UAC1D;AAEA,cAAI,gBAAgB,aAAa,IAAI,SAAS,gBAAgB;AAC5D,0BAAc,KAAK;AAAA,cACjB;AAAA,cACA,QAAQ;AAAA,cACR,SAAS;AAAA,cACT;AAAA,cACA,MAAM;AAAA,YACR,CAAC;AAAA,UACH;AAEA,cAAI,gBAAgB,aAAa,IAAI,SAAS,qBAAqB;AACjE,0BAAc,KAAK;AAAA,cACjB;AAAA,cACA,QAAQ;AAAA,cACR,SAAS;AAAA,cACT;AAAA,cACA,MAAM;AAAA,YACR,CAAC;AAAA,UACH;AAEA,cAAI,IAAI,SAAS,sBAAsB,CAAC,gBAAgB,CAAC,WAAW;AAClE;AAAA,UACF;AAEA,gBAAM,eAAe,IAAI,MAAM,gBAAgB,CAAC;AAChD,qBAAW,CAAC,OAAO,OAAO,KAAK,OAAO,QAAQ,YAAY,GAAG;AAC3D,kBAAM,QAAQ,SAAS;AACvB,gBAAI,CAAC,MAAO;AAEZ,kBAAM,aAAa,MAAM,eAAe;AACxC,kBAAM,aAAa,MAAM,mBAAmB;AAC5C,kBAAM,SAAS,MAAM,gBAAgB;AAErC,gBAAI,eAAe,KAAK,eAAe,KAAK,WAAW,GAAG;AACxD;AAAA,YACF;AAEA,oBAAQ,KAAK;AAAA,cACX;AAAA,cACA,QAAQ;AAAA,cACR;AAAA,cACA,SAAS;AAAA,cACT;AAAA,cACA,aAAa,KAAK,IAAI,GAAG,aAAa,UAAU;AAAA,cAChD,cAAc;AAAA,cACd,iBAAiB;AAAA,cACjB,cAAc;AAAA,YAChB,CAAC;AAAA,UACH;AAAA,QACF,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS,mBAAmB,OAAO;AAAA,MACnC,UAAU,gBAAgB,eAAe,OAAO;AAAA,IAClD;AAAA,EACF;AAAA,EAEA,cAAuB;AACrB,WAAOJ,YAAW,QAAQ;AAAA,EAC5B;AACF;AAEA,eAAe,IAAI,iBAAiB,CAAC;;;AC/LrC,SAAS,cAAAK,mBAAkB;AAC3B,SAAS,WAAAC,gBAAe;AACxB,SAAS,QAAAC,aAAY;AAgBrB,IAAMC,WAAU;AAChB,IAAMC,aAAY;AAClB,IAAMC,wBAAuBC,MAAKC,SAAQ,GAAG,QAAQ,SAAS,UAAU;AA4BxE,SAASC,sBAAqB,SAAiC;AAC7D,SAAO;AAAA,IACL,IAAIL;AAAA,IACJ,MAAMC;AAAA,IACN;AAAA,EACF;AACF;AAEA,SAASK,cAAa,OAAwB;AAC5C,QAAM,cAAc,OAAO,KAAK;AAChC,SAAO,OAAO,SAAS,WAAW,IAAI,cAAc;AACtD;AAEA,SAASC,aAAY,OAAuB;AAC1C,QAAM,aAAa,MAAM,QAAQ,OAAO,GAAG,EAAE,QAAQ,QAAQ,EAAE;AAC/D,QAAM,OAAO,WAAW,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,IAAI;AACvD,SAAO,QAAQ;AACjB;AAEA,SAASC,oBAAmB,OAAuB;AACjD,SAAO,MAAM,QAAQ,OAAO,GAAG,EAAE,QAAQ,QAAQ,EAAE;AACrD;AAEA,SAASC,gBACP,UACG,MACK;AACR,aAAW,OAAO,MAAM;AACtB,UAAM,QAAQ,MAAM,GAAG;AACvB,UAAM,cAAcH,cAAa,KAAK;AACtC,QAAI,cAAc,GAAG;AACnB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,4BAA4B,KAAqB;AAC/D,SAAOC,aAAY,GAAG;AACxB;AAEO,SAAS,4BACd,UACA,cAAcL,uBACN;AACR,QAAM,qBAAqBM,oBAAmB,QAAQ;AACtD,QAAM,wBAAwBA,oBAAmB,WAAW;AAC5D,QAAM,SAAS,GAAG,qBAAqB;AAEvC,MAAI,CAAC,mBAAmB,WAAW,MAAM,GAAG;AAC1C,WAAO;AAAA,EACT;AAEA,QAAM,eAAe,mBAAmB,MAAM,OAAO,MAAM;AAC3D,QAAM,eAAe,aAAa,MAAM,GAAG,EAAE,CAAC;AAC9C,MAAI,CAAC,cAAc;AACjB,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,UAAU,mBAAmB,YAAY;AAC/C,QAAI,QAAQ,SAAS,GAAG,KAAK,QAAQ,SAAS,IAAI,GAAG;AACnD,aAAOD,aAAY,OAAO;AAAA,IAC5B;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,QAAM,YAAY,aAAa,MAAM,GAAG,EAAE,OAAO,OAAO;AACxD,SAAO,UAAU,SAAS,IAAI,UAAU,UAAU,SAAS,CAAC,IAAI;AAClE;AAEO,IAAM,eAAN,MAAsC;AAAA,EAG3C,YAA6B,cAAcL,uBAAsB;AAApC;AAC3B,SAAK,OAAOG,sBAAqB,WAAW;AAAA,EAC9C;AAAA,EAF6B;AAAA,EAFpB;AAAA,EAMT,MAAM,QAA8B;AAClC,UAAM,eAAe,eAAe,KAAK,WAAW;AACpD,QAAI,aAAa,WAAW,GAAG;AAC7B,aAAO,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,EAAE;AAAA,IACrC;AAEA,UAAM,UAA6B,CAAC;AACpC,UAAM,gBAAgC,CAAC;AACvC,UAAM,eAAe,oBAAI,IAAY;AAErC,eAAW,YAAY,cAAc;AACnC,YAAM,UAAU,aAAa,QAAQ;AACrC,UAAI,CAAC,QAAS;AAEd,YAAM,OAAO,WAAwB,OAAO;AAC5C,UAAI,KAAK,WAAW,EAAG;AAEvB,UAAI,YAAY;AAChB,UAAI,UAAU,4BAA4B,UAAU,KAAK,WAAW;AAEpE,iBAAW,OAAO,MAAM;AACtB,YAAI,IAAI,SAAS,UAAW;AAC5B,YAAI,IAAI,IAAI;AACV,sBAAY,IAAI;AAAA,QAClB;AACA,YAAI,IAAI,KAAK;AACX,oBAAU,4BAA4B,IAAI,GAAG;AAAA,QAC/C;AACA;AAAA,MACF;AAEA,iBAAW,OAAO,MAAM;AACtB,YAAI,IAAI,SAAS,UAAW;AAE5B,cAAM,UAAU,IAAI;AACpB,YAAI,CAAC,QAAS;AAEd,cAAM,eAAe,IAAI,aAAa,QAAQ;AAC9C,YAAI,CAAC,aAAc;AAEnB,cAAM,YAAY,IAAI,KAAK,YAAY;AACvC,YAAI,OAAO,MAAM,UAAU,QAAQ,CAAC,EAAG;AAEvC,YAAI,QAAQ,SAAS,UAAU,QAAQ,SAAS,aAAa;AAC3D,wBAAc,KAAK;AAAA,YACjB;AAAA,YACA,QAAQL;AAAA,YACR;AAAA,YACA;AAAA,YACA,MAAM,QAAQ;AAAA,UAChB,CAAC;AAAA,QACH;AAEA,YAAI,QAAQ,SAAS,YAAa;AAElC,cAAM,QAAQ,QAAQ;AACtB,YAAI,CAAC,MAAO;AAEZ,cAAM,cAAcS,gBAAe,OAAO,SAAS,aAAa;AAChE,cAAM,eAAeA,gBAAe,OAAO,UAAU,cAAc;AACnE,cAAM,eAAeA;AAAA,UACnB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AACA,cAAM,kBAAkBA;AAAA,UACtB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAEA,YACE,gBAAgB,KAChB,iBAAiB,KACjB,iBAAiB,KACjB,oBAAoB,GACpB;AACA;AAAA,QACF;AAEA,YAAI,IAAI,IAAI;AACV,cAAI,aAAa,IAAI,IAAI,EAAE,EAAG;AAC9B,uBAAa,IAAI,IAAI,EAAE;AAAA,QACzB;AAEA,gBAAQ,KAAK;AAAA,UACX;AAAA,UACA,QAAQT;AAAA,UACR,OAAO,QAAQ,SAAS;AAAA,UACxB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS,mBAAmB,OAAO;AAAA,MACnC,UAAU,gBAAgB,eAAe,OAAO;AAAA,IAClD;AAAA,EACF;AAAA,EAEA,cAAuB;AACrB,WAAOU,YAAW,KAAK,WAAW;AAAA,EACpC;AACF;AAEA,eAAe,IAAI,aAAa,CAAC;;;AChPjC,SAAS,gBAAAC,qBAAoB;AAC7B,SAAsB,cAAAC,aAAY,eAAAC,cAAa,gBAAAC,qBAAoB;AACnE,SAAS,WAAAC,gBAAe;AACxB,SAAS,YAAAC,WAAU,QAAAC,aAAY;AAW/B,IAAMC,oBAAmBC,MAAKC,SAAQ,GAAG,UAAU,SAAS,UAAU;AAEtE,IAAMC,QAAuB;AAAA,EAC3B,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,SAASH;AACX;AAgCA,SAAS,oBAAoB,MAAyB,QAAQ,KAAe;AAC3E,QAAM,OAAO;AAAA,IACX,IAAI;AAAA,IACJ,IAAI,gBAAgBC,MAAK,IAAI,eAAe,UAAU,IAAI;AAAA,IAC1DD;AAAA,IACA,IAAI,eAAeC,MAAK,IAAI,cAAc,UAAU,IAAI;AAAA,IACxD,IAAI,UAAUA,MAAK,IAAI,SAAS,UAAU,IAAI;AAAA,EAChD,EAAE,OAAO,CAAC,UAA2B,QAAQ,KAAK,CAAC;AAEnD,SAAO,MAAM,KAAK,IAAI,IAAI,IAAI,CAAC;AACjC;AAEA,eAAeG,6BACb,IACY;AACZ,QAAM,sBAAsB,QAAQ;AAEpC,UAAQ,eAAe,CACrB,YACG,SACM;AACT,UAAM,cACJ,OAAO,YAAY,WACf,OAAO,KAAK,CAAC,MAAM,WACjB,KAAK,CAAC,IACN,KACF,QAAQ;AACd,UAAM,iBACJ,OAAO,YAAY,WAAW,UAAU,QAAQ;AAElD,QACE,gBAAgB,yBAChB,eAAe,SAAS,QAAQ,GAChC;AACA;AAAA,IACF;AAEA,IACE,oBAIA,KAAK,SAAS,SAAS,GAAG,IAAI;AAAA,EAClC;AAEA,MAAI;AACF,WAAO,MAAM,GAAG;AAAA,EAClB,UAAE;AACA,YAAQ,cAAc;AAAA,EACxB;AACF;AAEA,eAAeC,2BACb,QACA,OAC6B;AAC7B,MAAI;AACF,WAAO,MAAMD,6BAA4B,YAAY;AACnD,YAAM,iBAAiB;AACvB,YAAM,SAAU,MAAM,OAAO;AAU7B,YAAM,KAAK,IAAI,OAAO,aAAa,MAAM;AAEzC,UAAI;AACF,eAAO,GAAG,QAAQ,KAAK,EAAE,IAAI;AAAA,MAC/B,UAAE;AACA,WAAG,MAAM;AAAA,MACX;AAAA,IACF,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,UAAM,QAAQ;AACd,UAAM,UAAW,IAAc;AAC/B,QACE,MAAM,SAAS,gCACf,QAAQ,SAAS,aAAa,GAC9B;AACA,aAAO;AAAA,IACT;AAEA,UAAM;AAAA,EACR;AACF;AAEA,SAASE,uBAAsB,QAAgB,OAA4B;AACzE,QAAM,aAAa;AAAA,IACjB,QAAQ,IAAI;AAAA,IACZ;AAAA,IACA;AAAA,EACF,EAAE,OAAO,CAAC,UAA2B,QAAQ,KAAK,CAAC;AAEnD,MAAI,YAA0B;AAE9B,aAAW,WAAW,YAAY;AAChC,QAAI;AACF,YAAM,SAASC,cAAa,SAAS,CAAC,SAAS,QAAQ,KAAK,GAAG;AAAA,QAC7D,UAAU;AAAA,QACV,WAAW,MAAM,OAAO;AAAA,QACxB,SAAS;AAAA,QACT,aAAa;AAAA,MACf,CAAC,EAAE,KAAK;AAER,UAAI,CAAC,UAAU,WAAW,MAAM;AAC9B,eAAO,CAAC;AAAA,MACV;AAEA,aAAO,KAAK,MAAM,MAAM;AAAA,IAC1B,SAAS,KAAK;AACZ,kBAAY;AACZ,YAAM,YAAY;AAClB,UAAI,UAAU,WAAW,OAAO,UAAU,SAAS,SAAS,QAAQ,GAAG;AACrE;AAAA,MACF;AAEA,YAAM;AAAA,IACR;AAAA,EACF;AAEA,QAAM,IAAI;AAAA,IACR,mGAAmG,WAAW,WAAW,WAAW;AAAA,EACtI;AACF;AAEO,IAAM,iBAAN,MAAwC;AAAA,EAG7C,YACmB,eAA+B,qBAChD;AADiB;AAAA,EAChB;AAAA,EADgB;AAAA,EAHV,OAAOJ;AAAA,EAMhB,MAAM,QAA8B;AAClC,UAAM,UAAkC,CAAC;AACzC,UAAM,WAAoC,CAAC;AAE3C,eAAW,WAAW,KAAK,aAAa,GAAG;AACzC,YAAM,SAAS,MAAM,KAAK,UAAU,OAAO;AAC3C,UAAI,OAAO,QAAQ,SAAS,GAAG;AAC7B,gBAAQ,KAAK,GAAG,OAAO,OAAO;AAAA,MAChC;AACA,UAAI,OAAO,SAAS,SAAS,GAAG;AAC9B,iBAAS,KAAK,GAAG,OAAO,QAAQ;AAAA,MAClC;AAAA,IACF;AAEA,WAAO,EAAE,SAAS,SAAS;AAAA,EAC7B;AAAA,EAEA,cAAuB;AACrB,WAAO,KAAK,aAAa,EAAE,KAAK,CAAC,QAAQK,YAAW,GAAG,CAAC;AAAA,EAC1D;AAAA,EAEA,MAAc,UAAU,SAAuC;AAC7D,UAAM,SAASP,MAAK,SAAS,aAAa;AAC1C,UAAM,cAAcA,MAAK,SAAS,WAAW,SAAS;AAEtD,QAAIO,YAAW,MAAM,GAAG;AACtB,UAAI;AACF,eAAO,MAAM,KAAK,gBAAgB,MAAM;AAAA,MAC1C,SAAS,KAAK;AACZ,gBAAQ,OAAO;AAAA,UACb,uCAAwC,IAAc,OAAO;AAAA;AAAA,QAC/D;AAAA,MACF;AAAA,IACF;AAEA,WAAO,KAAK,cAAc,WAAW;AAAA,EACvC;AAAA,EAEA,MAAc,gBAAgB,QAAsC;AAClE,UAAM,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASd,UAAM,cAAc,MAAMH,2BAA0B,QAAQ,KAAK;AACjE,UAAM,OAAO,eAAeC,uBAAsB,QAAQ,KAAK;AAE/D,QAAI,KAAK,WAAW,GAAG;AACrB,aAAO,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,EAAE;AAAA,IACrC;AAEA,UAAM,UAA6B,CAAC;AACpC,UAAM,gBAAgC,CAAC;AAEvC,eAAW,OAAO,MAAM;AACtB,YAAM,YAAY,IAAI,KAAK,IAAI,OAAO;AACtC,UAAI,OAAO,MAAM,UAAU,QAAQ,CAAC,EAAG;AAEvC,YAAM,UAAU,IAAI,WAAWG,UAAS,IAAI,QAAQ,IAAI;AACxD,YAAM,YAAY,IAAI,aAAa;AACnC,UAAI,IAAI,SAAS,UAAU,IAAI,SAAS,YAAa;AAErD,oBAAc,KAAK;AAAA,QACjB;AAAA,QACA,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA,MAAM,IAAI,SAAS,SAAS,SAAS;AAAA,MACvC,CAAC;AAED,UAAI,CAAC,IAAI,QAAS;AAElB,UAAI;AACJ,UAAI;AACF,iBACE,OAAO,IAAI,WAAW,WAAW,KAAK,MAAM,IAAI,MAAM,IAAI,IAAI;AAAA,MAClE,QAAQ;AACN;AAAA,MACF;AACA,UAAI,CAAC,UAAW,CAAC,OAAO,SAAS,CAAC,OAAO,OAAS;AAElD,cAAQ,KAAK;AAAA,QACX;AAAA,QACA,QAAQ;AAAA,QACR,OAAO,IAAI,WAAW;AAAA,QACtB;AAAA,QACA;AAAA,QACA,aAAa,OAAO,SAAS;AAAA,QAC7B,cAAc,OAAO,UAAU;AAAA,QAC/B,iBAAiB,OAAO,aAAa;AAAA,QACrC,cAAc,OAAO,OAAO,QAAQ;AAAA,MACtC,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL,SAAS,mBAAmB,OAAO;AAAA,MACnC,UAAU,gBAAgB,eAAe,OAAO;AAAA,IAClD;AAAA,EACF;AAAA,EAEQ,cAAc,aAAkC;AACtD,QAAI,CAACD,YAAW,WAAW,EAAG,QAAO,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,EAAE;AAEjE,UAAM,UAA6B,CAAC;AACpC,UAAM,gBAAgC,CAAC;AAEvC,QAAI;AACJ,QAAI;AACF,oBAAcE,aAAY,aAAa,EAAE,eAAe,KAAK,CAAC,EAAE;AAAA,QAC9D,CAAC,WAAW,OAAO,YAAY,KAAK,OAAO,KAAK,WAAW,MAAM;AAAA,MACnE;AAAA,IACF,QAAQ;AACN,aAAO,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,EAAE;AAAA,IACrC;AAEA,eAAW,cAAc,aAAa;AACpC,YAAM,cAAcT,MAAK,aAAa,WAAW,IAAI;AACrD,UAAI;AACJ,UAAI;AACF,uBAAeS,aAAY,WAAW,EAAE;AAAA,UAAO,CAAC,SAC9C,KAAK,SAAS,OAAO;AAAA,QACvB;AAAA,MACF,QAAQ;AACN;AAAA,MACF;AAEA,iBAAW,QAAQ,cAAc;AAC/B,cAAM,WAAWT,MAAK,aAAa,IAAI;AAEvC,YAAI;AACJ,YAAI;AACF,iBAAO,KAAK,MAAMU,cAAa,UAAU,OAAO,CAAC;AAAA,QACnD,QAAQ;AACN;AAAA,QACF;AAEA,cAAM,UAAU,KAAK,MAAM,WAAW,KAAK;AAC3C,YAAI,CAAC,QAAS;AACd,cAAM,YAAY,IAAI,KAAK,OAAO;AAClC,YAAI,OAAO,MAAM,UAAU,QAAQ,CAAC,EAAG;AAEvC,cAAM,WAAW,KAAK,MAAM;AAC5B,cAAM,UAAU,WAAWF,UAAS,QAAQ,IAAI;AAChD,YAAI,KAAK,SAAS,UAAU,KAAK,SAAS,YAAa;AAEvD,sBAAc,KAAK;AAAA,UACjB,WAAW,WAAW;AAAA,UACtB,QAAQ;AAAA,UACR;AAAA,UACA;AAAA,UACA,MAAM,KAAK,SAAS,SAAS,SAAS;AAAA,QACxC,CAAC;AAED,YAAI,CAAC,KAAK,QAAS;AACnB,cAAM,SAAS,KAAK;AACpB,YAAI,CAAC,UAAW,CAAC,OAAO,SAAS,CAAC,OAAO,OAAS;AAElD,gBAAQ,KAAK;AAAA,UACX,WAAW,WAAW;AAAA,UACtB,QAAQ;AAAA,UACR,OAAO,KAAK,WAAW;AAAA,UACvB;AAAA,UACA;AAAA,UACA,aAAa,OAAO,SAAS;AAAA,UAC7B,cAAc,OAAO,UAAU;AAAA,UAC/B,iBAAiB,OAAO,aAAa;AAAA,UACrC,cAAc,OAAO,OAAO,QAAQ;AAAA,QACtC,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS,mBAAmB,OAAO;AAAA,MACnC,UAAU,gBAAgB,eAAe,OAAO;AAAA,IAClD;AAAA,EACF;AACF;AAEA,eAAe,IAAI,eAAe,CAAC;;;ACnXnC,SAAsB,cAAAG,cAAY,eAAAC,cAAa,gBAAAC,qBAAoB;AACnE,SAAS,WAAAC,gBAAe;AACxB,SAAS,QAAAC,cAAY;AAWrB,IAAMC,WAAU;AAChB,IAAMC,aAAY;AAClB,IAAMC,oBAAmBC,OAAKC,SAAQ,GAAG,WAAW;AACpD,IAAM,oBAAoB,CAAC,aAAa,YAAY,UAAU;AAE9D,IAAMC,QAAuB;AAAA,EAC3B,IAAIL;AAAA,EACJ,MAAMC;AAAA,EACN,SAASC;AACX;AA6BA,SAAS,UACP,UACG,MACK;AACR,aAAW,OAAO,MAAM;AACtB,UAAM,QAAS,MAAkC,GAAG;AACpD,QAAI,OAAO,UAAU,YAAY,QAAQ,EAAG,QAAO;AAAA,EACrD;AACA,SAAO;AACT;AAEO,SAAS,iBAAiB,UAAUE,SAAQ,GAAa;AAC9D,QAAM,QAAQ,CAACD,OAAK,SAAS,WAAW,CAAC;AAEzC,MAAI;AACF,UAAM,eAAeG,aAAY,SAAS,EAAE,eAAe,KAAK,CAAC,EAC9D;AAAA,MACC,CAAC,UAAU,MAAM,YAAY,KAAK,iBAAiB,KAAK,MAAM,IAAI;AAAA,IACpE,EACC,IAAI,CAAC,UAAUH,OAAK,SAAS,MAAM,IAAI,CAAC,EACxC,KAAK,CAAC,MAAM,UAAU,KAAK,cAAc,KAAK,CAAC;AAElD,UAAM,KAAK,GAAG,YAAY;AAAA,EAC5B,QAAQ;AAAA,EAER;AAEA,QAAM,KAAK,GAAG,kBAAkB,IAAI,CAAC,SAASA,OAAK,SAAS,IAAI,CAAC,CAAC;AAElE,SAAO,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC;AAClC;AAEO,IAAM,iBAAN,MAAwC;AAAA,EAG7C,YACmB,eAA+B,kBAChD;AADiB;AAAA,EAChB;AAAA,EADgB;AAAA,EAHV,OAAOE;AAAA,EAMhB,MAAM,QAA8B;AAClC,UAAM,UAA6B,CAAC;AACpC,UAAM,gBAAgC,CAAC;AAEvC,eAAW,QAAQ,KAAK,aAAa,GAAG;AACtC,YAAM,YAAYF,OAAK,MAAM,QAAQ;AACrC,UAAI,CAACI,aAAW,SAAS,EAAG;AAE5B,UAAI;AACJ,UAAI;AACF,oBAAYD,aAAY,WAAW,EAAE,eAAe,KAAK,CAAC,EAAE;AAAA,UAC1D,CAAC,MAAM,EAAE,YAAY;AAAA,QACvB;AAAA,MACF,QAAQ;AACN;AAAA,MACF;AAEA,iBAAW,YAAY,WAAW;AAChC,cAAM,UAAU,SAAS;AACzB,cAAM,cAAcH,OAAK,WAAW,SAAS,MAAM,UAAU;AAC7D,YAAI,CAACI,aAAW,WAAW,EAAG;AAE9B,YAAI;AACJ,YAAI;AACF,kBAAQD,aAAY,WAAW,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,QAAQ,CAAC;AAAA,QACrE,QAAQ;AACN;AAAA,QACF;AAEA,mBAAW,QAAQ,OAAO;AACxB,gBAAM,WAAWH,OAAK,aAAa,IAAI;AAEvC,cAAI;AACJ,cAAI;AACF,sBAAUK,cAAa,UAAU,OAAO;AAAA,UAC1C,QAAQ;AACN;AAAA,UACF;AAEA,qBAAW,QAAQ,QAAQ,MAAM,IAAI,GAAG;AACtC,gBAAI,CAAC,KAAK,KAAK,EAAG;AAClB,gBAAI;AACF,oBAAM,MAAM,KAAK,MAAM,IAAI;AAE3B,kBAAI,IAAI,SAAS,UAAW;AAC5B,oBAAM,MAAM,IAAI;AAChB,kBAAI,CAAC,IAAK;AAEV,oBAAM,YAAY,IAAI,aAAa,IAAI;AACvC,kBAAI,CAAC,UAAW;AAChB,oBAAM,KAAK,IAAI;AAAA,gBACb,OAAO,cAAc,WAAW,YAAY;AAAA,cAC9C;AACA,kBAAI,OAAO,MAAM,GAAG,QAAQ,CAAC,EAAG;AAChC,kBAAI,IAAI,SAAS,UAAU,IAAI,SAAS,YAAa;AAErD,4BAAc,KAAK;AAAA,gBACjB,WAAW;AAAA,gBACX,QAAQR;AAAA,gBACR;AAAA,gBACA,WAAW;AAAA,gBACX,MAAM,IAAI,SAAS,SAAS,SAAS;AAAA,cACvC,CAAC;AAED,kBAAI,IAAI,SAAS,YAAa;AAC9B,oBAAM,QAAQ,IAAI;AAClB,kBAAI,CAAC,MAAO;AAEZ,sBAAQ,KAAK;AAAA,gBACX,WAAW;AAAA,gBACX,QAAQA;AAAA,gBACR,OAAO,IAAI,SAAS,IAAI,SAAS;AAAA,gBACjC;AAAA,gBACA,WAAW;AAAA,gBACX,aAAa;AAAA,kBACX;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,gBACF;AAAA,gBACA,cAAc;AAAA,kBACZ;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,gBACF;AAAA,gBACA,iBAAiB;AAAA,gBACjB,cAAc;AAAA,kBACZ;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,gBACF;AAAA,cACF,CAAC;AAAA,YACH,QAAQ;AAAA,YAAC;AAAA,UACX;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS,mBAAmB,OAAO;AAAA,MACnC,UAAU,gBAAgB,eAAe,OAAO;AAAA,IAClD;AAAA,EACF;AAAA,EAEA,cAAuB;AACrB,WAAO,KAAK,aAAa,EAAE,KAAK,CAAC,SAASO,aAAWJ,OAAK,MAAM,QAAQ,CAAC,CAAC;AAAA,EAC5E;AACF;AAEA,eAAe,IAAI,eAAe,CAAC;;;AC7MnC,SAAS,cAAAM,cAAY,eAAAC,oBAAmB;AACxC,SAAS,WAAAC,iBAAe;AACxB,SAAS,QAAAC,cAAY;AAYrB,IAAMC,WAAU;AAChB,IAAMC,aAAY;AAClB,IAAMC,oBAAmBC,OAAKC,UAAQ,GAAG,SAAS,KAAK;AAyBvD,SAASC,sBAAqB,SAAiC;AAC7D,SAAO;AAAA,IACL,IAAIL;AAAA,IACJ,MAAMC;AAAA,IACN;AAAA,EACF;AACF;AAEA,SAASK,cAAa,OAAwB;AAC5C,QAAM,cAAc,OAAO,KAAK;AAChC,SAAO,OAAO,SAAS,WAAW,IAAI,cAAc;AACtD;AAEA,SAASC,aAAY,OAAuB;AAC1C,QAAM,aAAa,MAAM,QAAQ,OAAO,GAAG,EAAE,QAAQ,QAAQ,EAAE;AAC/D,QAAM,OAAO,WAAW,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,IAAI;AACvD,SAAO,QAAQ;AACjB;AAEA,SAASC,oBAAmB,OAAuB;AACjD,SAAO,MAAM,QAAQ,OAAO,GAAG,EAAE,QAAQ,QAAQ,EAAE;AACrD;AAEA,SAASC,kBAAiB,SAA2B;AACnD,QAAM,UAAoB,CAAC;AAC3B,MAAI,CAACC,aAAW,OAAO,EAAG,QAAO;AAEjC,MAAI;AACF,eAAW,SAASC,aAAY,SAAS,EAAE,eAAe,KAAK,CAAC,GAAG;AACjE,UAAI,CAAC,MAAM,YAAY,EAAG;AAE1B,YAAM,WAAWR,OAAK,SAAS,MAAM,MAAM,OAAO;AAClD,UAAI,CAACO,aAAW,QAAQ,EAAG;AAE3B,UAAI;AACF,mBAAW,QAAQC,aAAY,QAAQ,GAAG;AACxC,cAAI,KAAK,SAAS,QAAQ,GAAG;AAC3B,oBAAQ,KAAKR,OAAK,UAAU,IAAI,CAAC;AAAA,UACnC;AAAA,QACF;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEO,SAAS,mBACd,KACA,UACA,UAAUD,mBACF;AACR,MAAI,KAAK;AACP,WAAOK,aAAY,GAAG;AAAA,EACxB;AAEA,QAAM,qBAAqBC,oBAAmB,QAAQ;AACtD,QAAM,oBAAoBA,oBAAmB,OAAO;AACpD,QAAM,SAAS,GAAG,iBAAiB;AAEnC,MAAI,CAAC,mBAAmB,WAAW,MAAM,GAAG;AAC1C,WAAO;AAAA,EACT;AAEA,QAAM,eAAe,mBAAmB,MAAM,OAAO,MAAM;AAC3D,QAAM,YAAY,aAAa,MAAM,GAAG,EAAE,CAAC;AAC3C,SAAO,aAAa;AACtB;AAEO,IAAM,iBAAN,MAAwC;AAAA,EAG7C,YAA6B,UAAUN,mBAAkB;AAA5B;AAC3B,SAAK,OAAOG,sBAAqB,OAAO;AAAA,EAC1C;AAAA,EAF6B;AAAA,EAFpB;AAAA,EAMT,MAAM,QAA8B;AAClC,UAAM,eAAeI,kBAAiB,KAAK,OAAO;AAClD,QAAI,aAAa,WAAW,GAAG;AAC7B,aAAO,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,EAAE;AAAA,IACrC;AAEA,UAAM,UAA6B,CAAC;AACpC,UAAM,gBAAgC,CAAC;AACvC,UAAM,YAAY,oBAAI,IAAY;AAElC,eAAW,YAAY,cAAc;AACnC,YAAM,UAAU,aAAa,QAAQ;AACrC,UAAI,CAAC,QAAS;AAEd,YAAM,YAAY;AAElB,iBAAW,QAAQ,QAAQ,MAAM,IAAI,GAAG;AACtC,YAAI,CAAC,KAAK,KAAK,EAAG;AAElB,YAAI;AACF,gBAAM,MAAM,KAAK,MAAM,IAAI;AAC3B,cAAI,CAAC,IAAI,UAAW;AAEpB,gBAAM,YAAY,IAAI,KAAK,IAAI,SAAS;AACxC,cAAI,OAAO,MAAM,UAAU,QAAQ,CAAC,EAAG;AAEvC,gBAAM,UAAU,mBAAmB,IAAI,KAAK,UAAU,KAAK,OAAO;AAElE,cAAI,IAAI,SAAS,UAAU,IAAI,SAAS,aAAa;AACnD,0BAAc,KAAK;AAAA,cACjB;AAAA,cACA,QAAQT;AAAA,cACR;AAAA,cACA;AAAA,cACA,MAAM,IAAI;AAAA,YACZ,CAAC;AAAA,UACH;AAEA,cAAI,IAAI,SAAS,YAAa;AAE9B,gBAAM,QAAQ,IAAI,iBAAiB,IAAI;AACvC,cAAI,CAAC,MAAO;AAEZ,gBAAM,aACJM,cAAa,MAAM,gBAAgB,KACnCA,cAAa,MAAM,YAAY;AACjC,gBAAM,cACJA,cAAa,MAAM,oBAAoB,KACvCA,cAAa,MAAM,aAAa;AAClC,gBAAM,eAAeA,cAAa,MAAM,uBAAuB;AAC/D,gBAAM,kBAAkBA,cAAa,MAAM,kBAAkB;AAE7D,cACE,eAAe,KACf,gBAAgB,KAChB,iBAAiB,KACjB,oBAAoB,GACpB;AACA;AAAA,UACF;AAEA,cAAI,IAAI,MAAM;AACZ,gBAAI,UAAU,IAAI,IAAI,IAAI,EAAG;AAC7B,sBAAU,IAAI,IAAI,IAAI;AAAA,UACxB;AAEA,kBAAQ,KAAK;AAAA,YACX;AAAA,YACA,QAAQN;AAAA,YACR,OAAO,IAAI,SAAS;AAAA,YACpB;AAAA,YACA;AAAA,YACA,aAAa,KAAK,IAAI,GAAG,aAAa,YAAY;AAAA,YAClD,cAAc,KAAK,IAAI,GAAG,cAAc,eAAe;AAAA,YACvD;AAAA,YACA;AAAA,UACF,CAAC;AAAA,QACH,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS,mBAAmB,OAAO;AAAA,MACnC,UAAU,gBAAgB,eAAe,OAAO;AAAA,IAClD;AAAA,EACF;AAAA,EAEA,cAAuB;AACrB,WAAOU,aAAW,KAAK,OAAO;AAAA,EAChC;AACF;AAEA,eAAe,IAAI,eAAe,CAAC;;;ACvNnC,SAAS,cAAAE,cAAY,eAAAC,oBAAmB;AACxC,SAAS,WAAAC,iBAAe;AACxB,SAAS,QAAAC,cAAY;AAYrB,IAAMC,WAAU;AAChB,IAAMC,aAAY;AAClB,IAAMC,wBAAuBC,OAAKC,UAAQ,GAAG,SAAS,UAAU;AAChE,IAAM,sBAAsBD,OAAKC,UAAQ,GAAG,SAAS,WAAW;AAEhE,IAAM,mBAAmB,oBAAI,IAAI,CAAC,eAAe,gBAAgB,OAAO,CAAC;AACzE,IAAM,wBAAwB,oBAAI,IAAI;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AA4BD,SAASC,sBAAqB,SAAiC;AAC7D,SAAO;AAAA,IACL,IAAIL;AAAA,IACJ,MAAMC;AAAA,IACN;AAAA,EACF;AACF;AAEA,SAASK,cAAa,OAAwB;AAC5C,QAAM,cAAc,OAAO,KAAK;AAChC,SAAO,OAAO,SAAS,WAAW,IAAI,cAAc;AACtD;AAEA,SAASC,aAAY,OAAuB;AAC1C,QAAM,aAAa,MAAM,QAAQ,OAAO,GAAG,EAAE,QAAQ,QAAQ,EAAE;AAC/D,QAAM,OAAO,WAAW,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,IAAI;AACvD,SAAO,QAAQ;AACjB;AAEA,SAAS,cACP,SACkD;AAClD,QAAM,UAA4D,CAAC;AACnE,MAAI,CAACC,aAAW,OAAO,EAAG,QAAO;AAEjC,MAAI;AACF,eAAW,WAAWC,aAAY,SAAS,EAAE,eAAe,KAAK,CAAC,GAAG;AACnE,UAAI,CAAC,QAAQ,YAAY,EAAG;AAE5B,YAAM,cAAcN,OAAK,SAAS,QAAQ,IAAI;AAC9C,UAAI;AACF,mBAAW,WAAWM,aAAY,aAAa;AAAA,UAC7C,eAAe;AAAA,QACjB,CAAC,GAAG;AACF,cAAI,CAAC,QAAQ,YAAY,EAAG;AAE5B,gBAAM,WAAWN,OAAK,aAAa,QAAQ,MAAM,YAAY;AAC7D,cAAIK,aAAW,QAAQ,GAAG;AACxB,oBAAQ,KAAK,EAAE,UAAU,UAAU,aAAa,QAAQ,KAAK,CAAC;AAAA,UAChE;AAAA,QACF;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,SAAS,eAAe,OAAiD;AACvE,MAAI,SAAS,KAAM,QAAO;AAC1B,QAAM,YAAY,IAAI,KAAK,KAAK;AAChC,SAAO,OAAO,MAAM,UAAU,QAAQ,CAAC,IAAI,OAAO;AACpD;AAEA,SAAS,iBACP,MACA,SAC6B;AAC7B,MAAI,SAAS,SAAS,UAAU,SAAS,SAAS,aAAa;AAC7D,WAAO,QAAQ;AAAA,EACjB;AAEA,MAAI,QAAQ,iBAAiB,IAAI,IAAI,GAAG;AACtC,WAAO;AAAA,EACT;AAEA,MAAI,QAAQ,sBAAsB,IAAI,IAAI,GAAG;AAC3C,WAAO;AAAA,EACT;AAEA,MAAI,MAAM,YAAY,EAAE,SAAS,WAAW,GAAG;AAC7C,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,SAAS,eAAe,YAAyC;AAC/D,QAAM,aAAa,oBAAI,IAAoB;AAC3C,QAAM,UAAU,aAAa,UAAU;AACvC,MAAI,CAAC,QAAS,QAAO;AAErB,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,OAAO;AAKjC,UAAM,aAAa,OAAO,cAAc,OAAO,YAAY,CAAC;AAC5D,eAAW,CAAC,MAAM,IAAI,KAAK,OAAO,QAAQ,UAAU,GAAG;AACrD,YAAM,YACJ,OAAO,SAAS,WAAW,OAAO,KAAK,QAAQ,KAAK,OAAO;AAC7D,UAAI,CAAC,UAAW;AAEhB,iBAAW,IAAI,MAAMD,aAAY,SAAS,CAAC;AAAA,IAC7C;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;AAEO,IAAM,iBAAN,MAAwC;AAAA,EACpC;AAAA,EACQ;AAAA,EACA;AAAA,EAEjB,YAAY,UAAiC,CAAC,GAAG;AAC/C,SAAK,cAAc,QAAQ,eAAeL;AAC1C,SAAK,aAAa,QAAQ,cAAc;AACxC,SAAK,OAAOG,sBAAqB,KAAK,WAAW;AAAA,EACnD;AAAA,EAEA,MAAM,QAA8B;AAClC,UAAM,YAAY,cAAc,KAAK,WAAW;AAChD,QAAI,UAAU,WAAW,GAAG;AAC1B,aAAO,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,EAAE;AAAA,IACrC;AAEA,UAAM,aAAa,eAAe,KAAK,UAAU;AACjD,UAAM,UAA6B,CAAC;AACpC,UAAM,gBAAgC,CAAC;AACvC,UAAM,iBAAiB,oBAAI,IAAY;AAEvC,eAAW,EAAE,UAAU,YAAY,KAAK,WAAW;AACjD,YAAM,UAAU,aAAa,QAAQ;AACrC,UAAI,CAAC,QAAS;AAEd,YAAM,YAAY;AAClB,YAAM,UAAU,WAAW,IAAI,WAAW,KAAK;AAC/C,UAAI,eAAe;AACnB,UAAI;AAEJ,iBAAW,QAAQ,QAAQ,MAAM,IAAI,GAAG;AACtC,YAAI,CAAC,KAAK,KAAK,EAAG;AAElB,YAAI;AACJ,YAAI;AACF,gBAAM,KAAK,MAAM,IAAI;AAAA,QACvB,QAAQ;AACN;AAAA,QACF;AAEA,cAAM,UAAU,IAAI;AACpB,YAAI,CAAC,QAAS;AAEd,YAAI,QAAQ,OAAO;AACjB,yBAAe,QAAQ;AAAA,QACzB;AAEA,cAAM,iBACJ,QAAQ,aAAa,IAAI,aAAa;AACxC,cAAM,YAAY,eAAe,cAAc;AAC/C,YAAI,QAAQ,aAAa,MAAM;AAC7B,6BAAmB,QAAQ;AAAA,QAC7B,WAAW,IAAI,aAAa,MAAM;AAChC,6BAAmB,IAAI;AAAA,QACzB;AAEA,cAAM,OAAO,iBAAiB,IAAI,MAAM,OAAO;AAC/C,YAAI,QAAQ,WAAW;AACrB,wBAAc,KAAK;AAAA,YACjB;AAAA,YACA,QAAQL;AAAA,YACR;AAAA,YACA;AAAA,YACA;AAAA,UACF,CAAC;AAAA,QACH;AAEA,YAAI,IAAI,SAAS,eAAgB;AAEjC,cAAM,aAAa,QAAQ;AAC3B,YAAI,CAAC,cAAc,CAAC,UAAW;AAE/B,cAAM,cAAcM,cAAa,WAAW,WAAW;AACvD,cAAM,eAAeA,cAAa,WAAW,MAAM;AACnD,cAAM,eAAeA,cAAa,WAAW,gBAAgB;AAC7D,cAAM,oBAAoBA,cAAa,WAAW,oBAAoB;AAEtE,YACE,gBAAgB,KAChB,iBAAiB,KACjB,iBAAiB,KACjB,sBAAsB,GACtB;AACA;AAAA,QACF;AAEA,YAAI,QAAQ,YAAY;AACtB,cAAI,eAAe,IAAI,QAAQ,UAAU,EAAG;AAC5C,yBAAe,IAAI,QAAQ,UAAU;AAAA,QACvC;AAEA,YAAI,CAAC,MAAM;AACT,wBAAc,KAAK;AAAA,YACjB;AAAA,YACA,QAAQN;AAAA,YACR;AAAA,YACA;AAAA,YACA,MAAM;AAAA,UACR,CAAC;AAAA,QACH;AAEA,gBAAQ,KAAK;AAAA,UACX;AAAA,UACA,QAAQA;AAAA,UACR,OAAO;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,iBAAiB;AAAA,UACjB;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS,mBAAmB,OAAO;AAAA,MACnC,UAAU,gBAAgB,eAAe,OAAO;AAAA,IAClD;AAAA,EACF;AAAA,EAEA,cAAuB;AACrB,WAAOQ,aAAW,KAAK,WAAW;AAAA,EACpC;AACF;AAEA,eAAe,IAAI,eAAe,CAAC;;;AChSnC,SAAS,cAAAE,cAAY,eAAAC,oBAAmB;AACxC,SAAS,WAAAC,iBAAe;AACxB,SAAS,YAAAC,WAAU,WAAAC,UAAS,QAAAC,cAAY;AAYxC,IAAMC,WAAU;AAChB,IAAMC,aAAY;AAClB,IAAMC,oBAAmBC,OAAKC,UAAQ,GAAG,YAAY,UAAU;AAoB/D,SAASC,sBAAqB,SAAiC;AAC7D,SAAO;AAAA,IACL,IAAIL;AAAA,IACJ,MAAMC;AAAA,IACN;AAAA,EACF;AACF;AAEA,SAASK,kBAAiB,KAAuB;AAC/C,QAAM,UAAoB,CAAC;AAC3B,MAAI,CAACC,aAAW,GAAG,EAAG,QAAO;AAE7B,MAAI;AACF,eAAW,SAASC,aAAY,KAAK,EAAE,eAAe,KAAK,CAAC,GAAG;AAC7D,YAAM,WAAWL,OAAK,KAAK,MAAM,IAAI;AACrC,UAAI,MAAM,YAAY,GAAG;AACvB,gBAAQ,KAAK,GAAGG,kBAAiB,QAAQ,CAAC;AAAA,MAC5C,WACE,MAAM,OAAO,KACb,MAAM,KAAK,SAAS,QAAQ,KAC5B,CAAC,MAAM,KAAK,SAAS,gBAAgB,GACrC;AACA,gBAAQ,KAAK,QAAQ;AAAA,MACvB;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;AAEO,SAAS,oBAAoB,MAAsB;AACxD,QAAM,QAAQ,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AAC5C,SAAO,MAAM,SAAS,IAAI,MAAM,MAAM,SAAS,CAAC,IAAI;AACtD;AAEA,SAASG,cAAa,OAAwB;AAC5C,QAAM,cAAc,OAAO,KAAK;AAChC,SAAO,OAAO,SAAS,WAAW,IAAI,cAAc;AACtD;AAEO,IAAM,cAAN,MAAqC;AAAA,EAG1C,YAA6B,UAAUP,mBAAkB;AAA5B;AAC3B,SAAK,OAAOG,sBAAqB,OAAO;AAAA,EAC1C;AAAA,EAF6B;AAAA,EAFpB;AAAA,EAMT,MAAM,QAA8B;AAClC,UAAM,eAAeC,kBAAiB,KAAK,OAAO;AAClD,QAAI,aAAa,WAAW,GAAG;AAC7B,aAAO,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,EAAE;AAAA,IACrC;AAEA,UAAM,UAA6B,CAAC;AACpC,UAAM,gBAAgC,CAAC;AAEvC,eAAW,YAAY,cAAc;AACnC,YAAM,YAAY;AAClB,YAAM,UAAU,oBAAoBI,UAASC,SAAQ,QAAQ,CAAC,CAAC;AAC/D,UAAI,wBAAqC;AAEzC,YAAM,UAAU,aAAa,QAAQ;AACrC,UAAI,CAAC,QAAS;AAEd,iBAAW,QAAQ,QAAQ,MAAM,IAAI,GAAG;AACtC,YAAI,CAAC,KAAK,KAAK,EAAG;AAElB,YAAI;AACJ,YAAI;AACF,gBAAM,KAAK,MAAM,IAAI;AAAA,QACvB,QAAQ;AACN;AAAA,QACF;AAEA,YAAI,IAAI,SAAS,aAAa,CAAC,IAAI,UAAW;AAE9C,cAAM,YAAY,IAAI,KAAK,IAAI,SAAS;AACxC,YAAI,OAAO,MAAM,UAAU,QAAQ,CAAC,EAAG;AAEvC,cAAM,OAAO,IAAI,SAAS;AAC1B,YAAI,SAAS,UAAU,SAAS,YAAa;AAE7C,YAAI,0BAA0B,MAAM;AAClC,kCAAwB;AAAA,QAC1B;AAEA,sBAAc,KAAK;AAAA,UACjB;AAAA,UACA,QAAQX;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AAEA,YAAM,eAAeG;AAAA,QACnBQ,SAAQ,QAAQ;AAAA,QAChB,GAAGD,UAAS,UAAU,QAAQ,CAAC;AAAA,MACjC;AACA,YAAM,kBAAkB,aAAa,YAAY;AACjD,UAAI,CAAC,mBAAmB,0BAA0B,KAAM;AAExD,UAAI;AACJ,UAAI;AACF,mBAAW,KAAK,MAAM,eAAe;AAAA,MACvC,QAAQ;AACN;AAAA,MACF;AAEA,YAAM,aAAa,SAAS;AAC5B,UAAI,CAAC,WAAY;AAEjB,YAAM,eAAeD,cAAa,WAAW,eAAe;AAC5D,YAAM,kBAAkBA,cAAa,WAAW,cAAc;AAC9D,YAAM,cAAc,KAAK;AAAA,QACvB;AAAA,QACAA,cAAa,WAAW,WAAW,IAAI;AAAA,MACzC;AACA,YAAM,eAAe,KAAK;AAAA,QACxB;AAAA,QACAA,cAAa,WAAW,YAAY,IAAI;AAAA,MAC1C;AAEA,UACE,gBAAgB,KAChB,iBAAiB,KACjB,iBAAiB,KACjB,oBAAoB,GACpB;AACA;AAAA,MACF;AAEA,cAAQ,KAAK;AAAA,QACX;AAAA,QACA,QAAQT;AAAA,QACR,OAAO,SAAS,SAAS;AAAA,QACzB;AAAA,QACA,WAAW;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL,SAAS,mBAAmB,OAAO;AAAA,MACnC,UAAU,gBAAgB,eAAe,OAAO;AAAA,IAClD;AAAA,EACF;AAAA,EAEA,cAAuB;AACrB,WAAOO,aAAW,KAAK,OAAO;AAAA,EAChC;AACF;AAEA,eAAe,IAAI,YAAY,CAAC;;;AClMhC,SAAS,cAAAK,oBAAkB;AAC3B,SAAS,WAAAC,iBAAe;AACxB,SAAS,QAAAC,cAAY;AAgBrB,IAAMC,WAAU;AAChB,IAAMC,aAAY;AAClB,IAAMC,wBAAuBC,OAAKC,UAAQ,GAAG,OAAO,SAAS,UAAU;AA4BvE,SAASC,sBAAqB,SAAiC;AAC7D,SAAO;AAAA,IACL,IAAIL;AAAA,IACJ,MAAMC;AAAA,IACN;AAAA,EACF;AACF;AAEA,SAASK,cAAa,OAAwB;AAC5C,QAAM,cAAc,OAAO,KAAK;AAChC,SAAO,OAAO,SAAS,WAAW,IAAI,cAAc;AACtD;AAEA,SAASC,aAAY,OAAuB;AAC1C,QAAM,aAAa,MAAM,QAAQ,OAAO,GAAG,EAAE,QAAQ,QAAQ,EAAE;AAC/D,QAAM,OAAO,WAAW,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,IAAI;AACvD,SAAO,QAAQ;AACjB;AAEA,SAASC,oBAAmB,OAAuB;AACjD,SAAO,MAAM,QAAQ,OAAO,GAAG,EAAE,QAAQ,QAAQ,EAAE;AACrD;AAEA,SAASC,gBAAe,UAAmB,MAAoC;AAC7E,aAAW,OAAO,MAAM;AACtB,UAAM,QAAQ,MAAM,GAAG;AACvB,UAAM,cAAcH,cAAa,KAAK;AACtC,QAAI,cAAc,GAAG;AACnB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,wBAAwB,KAAqB;AAC3D,SAAOC,aAAY,GAAG;AACxB;AAEO,SAAS,wBACd,UACA,cAAcL,uBACN;AACR,QAAM,qBAAqBM,oBAAmB,QAAQ;AACtD,QAAM,wBAAwBA,oBAAmB,WAAW;AAC5D,QAAM,SAAS,GAAG,qBAAqB;AAEvC,MAAI,CAAC,mBAAmB,WAAW,MAAM,GAAG;AAC1C,WAAO;AAAA,EACT;AAEA,QAAM,eAAe,mBAAmB,MAAM,OAAO,MAAM;AAC3D,QAAM,eAAe,aAAa,MAAM,GAAG,EAAE,CAAC;AAC9C,MAAI,CAAC,cAAc;AACjB,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,UAAU,mBAAmB,YAAY;AAC/C,QAAI,QAAQ,SAAS,GAAG,KAAK,QAAQ,SAAS,IAAI,GAAG;AACnD,aAAOD,aAAY,OAAO;AAAA,IAC5B;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,QAAM,YAAY,aAAa,MAAM,GAAG,EAAE,OAAO,OAAO;AACxD,SAAO,UAAU,SAAS,IAAI,UAAU,UAAU,SAAS,CAAC,IAAI;AAClE;AAEO,IAAM,sBAAN,MAA6C;AAAA,EAGlD,YAA6B,cAAcL,uBAAsB;AAApC;AAC3B,SAAK,OAAOG,sBAAqB,WAAW;AAAA,EAC9C;AAAA,EAF6B;AAAA,EAFpB;AAAA,EAMT,MAAM,QAA8B;AAClC,UAAM,eAAe,eAAe,KAAK,WAAW;AACpD,QAAI,aAAa,WAAW,GAAG;AAC7B,aAAO,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,EAAE;AAAA,IACrC;AAEA,UAAM,UAA6B,CAAC;AACpC,UAAM,gBAAgC,CAAC;AACvC,UAAM,eAAe,oBAAI,IAAY;AAErC,eAAW,YAAY,cAAc;AACnC,YAAM,UAAU,aAAa,QAAQ;AACrC,UAAI,CAAC,QAAS;AAEd,YAAM,OAAO,WAAoB,OAAO;AACxC,UAAI,KAAK,WAAW,EAAG;AAEvB,UAAI,YAAY;AAChB,UAAI,UAAU,wBAAwB,UAAU,KAAK,WAAW;AAEhE,iBAAW,OAAO,MAAM;AACtB,YAAI,IAAI,SAAS,UAAW;AAC5B,YAAI,IAAI,IAAI;AACV,sBAAY,IAAI;AAAA,QAClB;AACA,YAAI,IAAI,KAAK;AACX,oBAAU,wBAAwB,IAAI,GAAG;AAAA,QAC3C;AACA;AAAA,MACF;AAEA,iBAAW,OAAO,MAAM;AACtB,YAAI,IAAI,SAAS,UAAW;AAE5B,cAAM,UAAU,IAAI;AACpB,YAAI,CAAC,QAAS;AAEd,cAAM,eAAe,IAAI,aAAa,QAAQ;AAC9C,YAAI,CAAC,aAAc;AAEnB,cAAM,YAAY,IAAI,KAAK,YAAY;AACvC,YAAI,OAAO,MAAM,UAAU,QAAQ,CAAC,EAAG;AAEvC,YAAI,QAAQ,SAAS,UAAU,QAAQ,SAAS,aAAa;AAC3D,wBAAc,KAAK;AAAA,YACjB;AAAA,YACA,QAAQL;AAAA,YACR;AAAA,YACA;AAAA,YACA,MAAM,QAAQ;AAAA,UAChB,CAAC;AAAA,QACH;AAEA,YAAI,QAAQ,SAAS,YAAa;AAElC,cAAM,QAAQ,QAAQ;AACtB,YAAI,CAAC,MAAO;AAEZ,cAAM,cAAcS,gBAAe,OAAO,SAAS,aAAa;AAChE,cAAM,eAAeA,gBAAe,OAAO,UAAU,cAAc;AACnE,cAAM,eAAeA;AAAA,UACnB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AACA,cAAM,kBAAkBA;AAAA,UACtB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAEA,YACE,gBAAgB,KAChB,iBAAiB,KACjB,iBAAiB,KACjB,oBAAoB,GACpB;AACA;AAAA,QACF;AAEA,YAAI,IAAI,IAAI;AACV,cAAI,aAAa,IAAI,IAAI,EAAE,EAAG;AAC9B,uBAAa,IAAI,IAAI,EAAE;AAAA,QACzB;AAEA,gBAAQ,KAAK;AAAA,UACX;AAAA,UACA,QAAQT;AAAA,UACR,OAAO,QAAQ,SAAS;AAAA,UACxB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS,mBAAmB,OAAO;AAAA,MACnC,UAAU,gBAAgB,eAAe,OAAO;AAAA,IAClD;AAAA,EACF;AAAA,EAEA,cAAuB;AACrB,WAAOU,aAAW,KAAK,WAAW;AAAA,EACpC;AACF;AAEA,eAAe,IAAI,oBAAoB,CAAC;;;AC7OxC,SAAS,cAAAC,cAAY,eAAAC,oBAAmB;AACxC,SAAS,WAAAC,WAAS,YAAAC,iBAAgB;AAClC,SAAS,QAAAC,cAAY;AAarB,IAAMC,YAAU;AAChB,IAAMC,cAAY;AAClB,IAAM,qBAAqBC,OAAKC,UAAQ,GAAG,YAAY,kBAAkB;AACzE,IAAM,yBAAyBD,OAAKC,UAAQ,GAAG,YAAY,WAAW;AA4DtE,SAASC,sBAAqB,WAAmC;AAC/D,SAAO;AAAA,IACL,IAAIJ;AAAA,IACJ,MAAMC;AAAA,IACN,SAAS;AAAA,EACX;AACF;AAEA,SAASI,cAAa,OAAwB;AAC5C,QAAM,cAAc,OAAO,KAAK;AAChC,SAAO,OAAO,SAAS,WAAW,KAAK,cAAc,IAAI,cAAc;AACzE;AAEA,SAAS,eAAe,OAA4B;AAClD,MAAI,CAAC,sBAAsB,KAAK,KAAK,GAAG;AACtC,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,oBAAI,KAAK,GAAG,KAAK,gBAAgB;AACnD,SAAO,OAAO,MAAM,UAAU,QAAQ,CAAC,IAAI,OAAO;AACpD;AAEA,SAAS,UAAU,OAA+B;AAChD,SAAO,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ;AACjE;AAEA,SAAS,aAAa,WAAmB,QAAoC;AAC3E,QAAM,aAAa,UAAU,OAAO,WAAW;AAC/C,QAAM,YAAY,UAAU,OAAO,UAAU;AAE7C,MAAI,cAAc,WAAW;AAC3B,WAAO,GAAG,UAAU,IAAI,SAAS;AAAA,EACnC;AAEA,SAAO,aAAa,aAAa;AACnC;AAEO,IAAM,gBAAN,MAAuC;AAAA,EACnC;AAAA,EACQ;AAAA,EACA;AAAA,EAEjB,YAAY,UAAgC,CAAC,GAAG;AAC9C,SAAK,YAAY,QAAQ,aAAa;AACtC,SAAK,gBAAgB,QAAQ,iBAAiB;AAC9C,SAAK,OAAOD,sBAAqB,KAAK,SAAS;AAAA,EACjD;AAAA,EAEA,MAAM,QAA8B;AAClC,UAAM,UAA6B,CAAC;AACpC,UAAM,gBAAgC,CAAC;AAEvC,UAAM,UAAU,aAAa,KAAK,SAAS;AAC3C,QAAI,SAAS;AACX,UAAI;AACF,cAAM,YAAY,KAAK,MAAM,OAAO;AAEpC,mBAAW,CAAC,SAAS,cAAc,KAAK,OAAO,QAAQ,SAAS,GAAG;AACjE,gBAAM,YAAY,eAAe,OAAO;AACxC,cAAI,CAAC,aAAa,OAAO,mBAAmB,UAAU;AACpD;AAAA,UACF;AAEA,qBAAW,CAAC,WAAW,MAAM,KAAK,OAAO,QAAQ,cAAc,GAAG;AAChE,gBAAI,CAAC,UAAU,OAAO,WAAW,UAAU;AACzC;AAAA,YACF;AAEA,kBAAM,cAAcC,cAAa,OAAO,aAAa;AACrD,kBAAM,eAAeA,cAAa,OAAO,iBAAiB;AAC1D,gBAAI,gBAAgB,KAAK,iBAAiB,GAAG;AAC3C;AAAA,YACF;AAEA,oBAAQ,KAAK;AAAA,cACX,QAAQL;AAAA,cACR,OAAO,aAAa,WAAW,MAAM;AAAA,cACrC,SAAS;AAAA,cACT;AAAA,cACA;AAAA,cACA;AAAA,cACA,iBAAiB;AAAA,cACjB,cAAc;AAAA,YAChB,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF,QAAQ;AAAA,MAAC;AAAA,IACX;AAEA,UAAM,oBAAoB,MAAM,KAAK,uBAAuB;AAC5D,kBAAc,KAAK,GAAG,iBAAiB;AAEvC,WAAO;AAAA,MACL,SAAS,mBAAmB,OAAO;AAAA,MACnC,UAAU,KAAK,kBAAkB,aAAa;AAAA,IAChD;AAAA,EACF;AAAA,EAEA,MAAc,yBAAkD;AAC9D,UAAM,SAAyB,CAAC;AAEhC,QAAI,CAACM,aAAW,KAAK,aAAa,GAAG;AACnC,aAAO;AAAA,IACT;AAEA,QAAI;AACF,YAAM,gBAAgBC,aAAY,KAAK,aAAa;AAEpD,iBAAW,gBAAgB,eAAe;AACxC,cAAM,gBAAgBL,OAAK,KAAK,eAAe,YAAY;AAC3D,cAAM,YAAYA,OAAK,eAAe,YAAY;AAClD,cAAM,eAAeA,OAAK,eAAe,UAAU;AAGnD,cAAM,eAAe,aAAa,SAAS;AAC3C,YAAI,CAAC,cAAc;AACjB;AAAA,QACF;AAEA,YAAI;AACJ,YAAI;AACF,sBAAY,KAAK,MAAM,YAAY;AAAA,QACrC,QAAQ;AACN;AAAA,QACF;AAEA,YAAI,CAAC,UAAU,SAAS,CAAC,MAAM,QAAQ,UAAU,KAAK,GAAG;AACvD;AAAA,QACF;AAGA,cAAM,eAAe,KAAK,gBAAgB,YAAY;AAEtD,mBAAW,QAAQ,UAAU,OAAO;AAClC,gBAAM,qBAAqB,aAAa,IAAI,KAAK,UAAU;AAC3D,cAAI,CAAC,oBAAoB;AACvB;AAAA,UACF;AAEA,cAAI;AACF,kBAAM,cAAc,KAAK;AAAA,cACvB;AAAA,YACF;AACA,kBAAM,kBAAkB,KAAK,gBAAgB,WAAW;AAExD,uBAAW,OAAO,iBAAiB;AACjC,qBAAO,KAAK;AAAA,gBACV,WAAW,KAAK;AAAA,gBAChB,QAAQF;AAAA,gBACR,SAAS;AAAA,gBACT,WAAW,IAAI,KAAK,IAAI,SAAS;AAAA,gBACjC,MAAM,IAAI;AAAA,cACZ,CAAC;AAAA,YACH;AAAA,UACF,QAAQ;AAAA,UAAC;AAAA,QACX;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,gBAAgB,cAA2C;AACjE,UAAM,QAAQ,oBAAI,IAAoB;AAEtC,QAAI,CAACM,aAAW,YAAY,GAAG;AAC7B,aAAO;AAAA,IACT;AAEA,QAAI;AACF,YAAM,mBAAmBC,aAAY,YAAY;AAEjD,iBAAW,YAAY,kBAAkB;AACvC,YAAI,CAAC,SAAS,SAAS,OAAO,GAAG;AAC/B;AAAA,QACF;AAEA,cAAM,WAAWL,OAAK,cAAc,QAAQ;AAC5C,cAAM,UAAU,aAAa,QAAQ;AACrC,YAAI,SAAS;AAEX,gBAAM,YAAY,SACf,QAAQ,WAAW,EAAE,EACrB,QAAQ,SAAS,EAAE;AACtB,gBAAM,IAAI,WAAW,OAAO;AAAA,QAC9B;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,gBAAgB,aAAmD;AACzE,UAAM,WAA6B,CAAC;AAEpC,QAAI,CAAC,YAAY,OAAO,QAAQ,SAAS;AACvC,aAAO;AAAA,IACT;AAEA,eAAW,CAAC,WAAW,KAAK,YAAY,MAAM,OAAO,SAAS;AAC5D,UAAI,CAAC,eAAe,OAAO,gBAAgB,UAAU;AACnD;AAAA,MACF;AAEA,YAAM,MAAM;AAGZ,WAAK,IAAI,SAAS,UAAU,IAAI,SAAS,gBAAgB,IAAI,WAAW;AACtE,iBAAS,KAAK,GAAG;AAAA,MACnB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,kBAAkB,QAA2C;AACnE,UAAM,aAAa,oBAAI,IAWrB;AAEF,eAAW,SAAS,QAAQ;AAC1B,YAAM,MAAM,GAAG,MAAM,SAAS,IAAI,MAAM,MAAM,IAAI,MAAM,OAAO;AAE/D,UAAI,CAAC,WAAW,IAAI,GAAG,GAAG;AACxB,mBAAW,IAAI,KAAK;AAAA,UAClB,QAAQ,MAAM;AAAA,UACd,SAAS,MAAM;AAAA,UACf,gBAAgB,MAAM;AAAA,UACtB,eAAe,MAAM;AAAA,UACrB,cAAc;AAAA,UACd,kBAAkB;AAAA,UAClB,aAAa,oBAAI,IAAI;AAAA,QACvB,CAAC;AAAA,MACH;AAEA,YAAM,UAAU,WAAW,IAAI,GAAG;AAClC,UAAI,CAAC,QAAS;AAEd,cAAQ,gBACN,MAAM,YAAY,QAAQ,gBACtB,MAAM,YACN,QAAQ;AACd,cAAQ;AAER,UAAI,MAAM,SAAS,QAAQ;AACzB,gBAAQ;AAAA,MACV;AAAA,IACF;AAEA,WAAO,MAAM,KAAK,WAAW,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,YAAY,WAAW,MAAM;AACzE,YAAM,CAAC,WAAW,IAAI,WAAW,MAAM,GAAG;AAC1C,YAAM,iBAAiB,YAAY,eAAe,YAAY;AAC9D,YAAM,gBAAgB,YAAY,cAAc,YAAY;AAC5D,YAAM,kBAAkB,KAAK;AAAA,SAC1B,YAAY,cAAc,QAAQ,IACjC,YAAY,eAAe,QAAQ,KACnC;AAAA,MACJ;AAGA,YAAM,cAAc;AACpB,YAAM,eAAe;AACrB,YAAM,kBAAkB;AACxB,YAAM,eAAe;AACrB,YAAM,cAAc;AAGpB,YAAM,cAAmC,MAAM;AAAA,QAC7C,YAAY,YAAY,QAAQ;AAAA,MAClC,EAAE,IAAI,CAAC,CAAC,OAAO,KAAK,OAAO;AAAA,QACzB;AAAA,QACA,aAAa,MAAM;AAAA,QACnB,cAAc,MAAM;AAAA,QACpB,iBAAiB;AAAA,QACjB,cAAc;AAAA,QACd,aAAa,MAAM,cAAc,MAAM;AAAA,MACzC,EAAE;AAEF,aAAO;AAAA,QACL,QAAQ,YAAY;AAAA,QACpB,SAAS,YAAY;AAAA,QACrB;AAAA,QACA,UAAUM,UAAS,EAAE,QAAQ,YAAY,EAAE;AAAA,QAC3C;AAAA,QACA;AAAA,QACA;AAAA,QACA,eAAe;AAAA;AAAA,QACf,cAAc,YAAY;AAAA,QAC1B,kBAAkB,YAAY;AAAA,QAC9B,iBAAiB,CAAC;AAAA;AAAA,QAClB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,cAAc;AAAA;AAAA,QACd;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,cAAuB;AACrB,WAAOF,aAAW,KAAK,SAAS,KAAKA,aAAW,KAAK,aAAa;AAAA,EACpE;AACF;AAEA,eAAe,IAAI,cAAc,CAAC;;;AC7YlC,SAAS,gBAAAG,eAAc,gBAAgB;AACvC,SAAS,WAAAC,iBAAe;AACxB,SAAS,YAAAC,WAAU,QAAAC,cAAY;AAW/B,IAAM,eAAe;AAErB,IAAM,QAAQ;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAMC,QAAuB;AAAA,EAC3B,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,SAASC,OAAKC,UAAQ,GAAG,QAAQ;AACnC;AAEA,SAAS,eAAyB;AAChC,QAAM,MAAgB,CAAC;AACvB,MAAI,QAAQ,aAAa,UAAU;AACjC,UAAM,OAAOD,OAAKC,UAAQ,GAAG,WAAW,qBAAqB;AAC7D,eAAW,KAAK,MAAO,KAAI,KAAKD,OAAK,MAAM,CAAC,CAAC;AAAA,EAC/C,WAAW,QAAQ,aAAa,SAAS;AACvC,UAAM,UACJ,QAAQ,IAAI,SAAS,KAAK,KAAKA,OAAKC,UAAQ,GAAG,WAAW,SAAS;AACrE,eAAW,KAAK,MAAO,KAAI,KAAKD,OAAK,SAAS,CAAC,CAAC;AAAA,EAClD,OAAO;AACL,UAAM,MACJ,QAAQ,IAAI,iBAAiB,KAAK,KAAKA,OAAKC,UAAQ,GAAG,SAAS;AAClE,eAAW,KAAK,MAAO,KAAI,KAAKD,OAAK,KAAK,CAAC,CAAC;AAAA,EAC9C;AACA,SAAO;AACT;AAEA,SAAS,yBAAmC;AAC1C,QAAM,OAAiB,CAAC;AACxB,aAAW,QAAQ,aAAa,GAAG;AACjC,UAAM,MAAMA,OAAK,MAAM,QAAQ,iBAAiB,YAAY;AAC5D,QAAI;AACF,UAAI,SAAS,GAAG,EAAE,YAAY,EAAG,MAAK,KAAK,GAAG;AAAA,IAChD,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,aAAa,MAAuB;AAC3C,MAAI;AACF,WAAO,KAAK,MAAME,cAAa,MAAM,OAAO,CAAC;AAAA,EAC/C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,gBAAgB,SAA0B;AACjD,MAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,QAAM,UAAU,QAAQ,QAAQ,WAAW,EAAE;AAC7C,QAAM,OAAOC,UAAS,OAAO;AAC7B,SAAO,QAAQ;AACjB;AAEA,IAAM,cAAN,MAAqC;AAAA,EAC1B,OAAOJ;AAAA,EAEhB,cAAuB;AACrB,WAAO,uBAAuB,EAAE,SAAS;AAAA,EAC3C;AAAA,EAEA,MAAM,QAA8B;AAClC,UAAM,UAAU,uBAAuB;AACvC,QAAI,QAAQ,WAAW,EAAG,QAAO,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,EAAE;AAE7D,UAAM,UAA6B,CAAC;AACpC,UAAM,gBAAgC,CAAC;AAEvC,eAAW,UAAU,SAAS;AAC5B,YAAM,UAAU,aAAaC,OAAK,QAAQ,SAAS,kBAAkB,CAAC;AACtE,UAAI,CAAC,MAAM,QAAQ,OAAO,EAAG;AAE7B,iBAAW,QAAQ,SAAS;AAC1B,YAAI;AACF,cAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,CAAC,KAAK,GAAI;AACnD,gBAAM,SAAS,OAAO,KAAK,EAAE;AAC7B,gBAAM,UAAU;AAAA,YACb,KAAiC,2BAC/B,KAAiC;AAAA,UACtC;AACA,gBAAM,gBACF,KAAiC,WACjC,OAAQ,KAAiC,OAAO,EAAE,KAAK,KACzD;AAEF,gBAAM,WAAW;AAAA,YACfA,OAAK,QAAQ,SAAS,QAAQ,kBAAkB;AAAA,UAClD;AACA,cAAI,CAAC,MAAM,QAAQ,QAAQ,EAAG;AAE9B,qBAAW,OAAO,UAAU;AAC1B,gBAAI,CAAC,OAAO,OAAO,QAAQ,SAAU;AACrC,kBAAM,KAAK,OAAQ,IAAgC,EAAE;AACrD,gBAAI,CAAC,OAAO,SAAS,EAAE,EAAG;AAC1B,kBAAM,YAAY,IAAI,KAAK,EAAE;AAE7B,kBAAM,UAAW,IAAgC;AACjD,kBAAM,SAAU,IAAgC;AAEhD,gBAAI,YAAY,SAAS,WAAW,mBAAmB;AACrD,kBAAI,OAAuC;AAC3C,kBAAI;AACF,sBAAM,OAAQ,IAAgC;AAC9C,oBAAI,OAAO,SAAS,SAAU,QAAO,KAAK,MAAM,IAAI;AAAA,cACtD,QAAQ;AAAA,cAER;AACA,kBAAI,CAAC,KAAM;AAEX,oBAAM,cAAc,KAAK,IAAI,GAAG,OAAO,KAAK,QAAQ,KAAK,CAAC;AAC1D,oBAAM,eAAe,KAAK,IAAI,GAAG,OAAO,KAAK,SAAS,KAAK,CAAC;AAC5D,oBAAM,cAAc,KAAK,IAAI,GAAG,OAAO,KAAK,WAAW,KAAK,CAAC;AAC7D,oBAAM,aAAa,KAAK,IAAI,GAAG,OAAO,KAAK,UAAU,KAAK,CAAC;AAC3D,kBAAI,cAAc,eAAe,cAAc,eAAe;AAC5D;AAEF,oBAAM,QACH,KAAK,SAAS,OAAO,KAAK,KAAK,EAAE,KAAK,KAAM;AAC/C,kBAAI,OAAO,UAAU,SAAU;AAE/B,sBAAQ,KAAK;AAAA,gBACX,QAAQ;AAAA,gBACR;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA,aAAa,cAAc;AAAA,gBAC3B;AAAA,gBACA,iBAAiB;AAAA,gBACjB,cAAc;AAAA,cAChB,CAAC;AAAA,YACH;AAEA,gBACE,YAAY,SACX,YAAY,SAAS,WAAW,iBACjC;AACA,4BAAc,KAAK;AAAA,gBACjB,WAAW;AAAA,gBACX,QAAQ;AAAA,gBACR;AAAA,gBACA;AAAA,gBACA,MAAM;AAAA,cACR,CAAC;AAAA,YACH,WAAW,YAAY,SAAS,WAAW,mBAAmB;AAC5D,4BAAc,KAAK;AAAA,gBACjB,WAAW;AAAA,gBACX,QAAQ;AAAA,gBACR;AAAA,gBACA;AAAA,gBACA,MAAM;AAAA,cACR,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS,mBAAmB,OAAO;AAAA,MACnC,UAAU,gBAAgB,eAAe,OAAO;AAAA,IAClD;AAAA,EACF;AACF;AAEA,eAAe,IAAI,YAAY,CAAC;;;AC5LhC,SAAS,gBAAAI,qBAAoB;AAC7B;AAAA,EACE;AAAA,EACA,cAAAC;AAAA,EACA;AAAA,EACA,eAAAC;AAAA,EACA,gBAAAC;AAAA,EACA;AAAA,EACA,YAAAC;AAAA,OACK;AACP,SAAS,WAAAC,WAAS,cAAc;AAChC,SAAS,QAAAC,QAAM,eAAe;AAM9B,IAAM,qBAAqBC,OAAK,QAAQ,iBAAiB,gBAAgB;AAEzE,SAAS,qBAA6B;AACpC,MAAI,QAAQ,aAAa,UAAU;AACjC,WAAOA;AAAA,MACLC,UAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,QAAQ,aAAa,SAAS;AAChC,UAAM,UACJ,QAAQ,IAAI,SAAS,KAAK,KAAKD,OAAKC,UAAQ,GAAG,WAAW,SAAS;AACrE,WAAOD,OAAK,SAAS,QAAQ,kBAAkB;AAAA,EACjD;AACA,QAAM,gBACJ,QAAQ,IAAI,iBAAiB,KAAK,KAAKA,OAAKC,UAAQ,GAAG,SAAS;AAClE,SAAOD,OAAK,eAAe,QAAQ,kBAAkB;AACvD;AAEA,IAAME,QAAuB;AAAA,EAC3B,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,SAAS,mBAAmB;AAC9B;AAEA,SAAS,kBAAiC;AACxC,QAAM,WAAW,QAAQ,IAAI,gBAAgB,KAAK;AAClD,MAAI,UAAU;AACZ,UAAM,IAAI,QAAQ,QAAQ;AAC1B,WAAOC,aAAW,CAAC,IAAI,IAAI;AAAA,EAC7B;AACA,QAAM,MAAM,mBAAmB;AAC/B,SAAOA,aAAW,GAAG,IAAI,MAAM;AACjC;AAEA,SAAS,YAAY,KAAuB;AAC1C,SACE,eAAe,SACf,OAAO,IAAI,YAAY,YACvB,sBAAsB,KAAK,IAAI,OAAO;AAE1C;AAEA,IAAM,aACJ;AAKF,SAAS,QAAQ,QAAgB,KAAwB;AACvD,QAAM,MAAMC,cAAa,WAAW,CAAC,SAAS,QAAQ,GAAG,GAAG;AAAA,IAC1D,UAAU;AAAA,IACV,WAAW,MAAM,OAAO;AAAA,IACxB,SAAS;AAAA,EACX,CAAC;AACD,QAAM,UAAU,IAAI,KAAK;AACzB,MAAI,CAAC,WAAW,YAAY,KAAM,QAAO,CAAC;AAC1C,SAAO,KAAK,MAAM,OAAO;AAC3B;AAUA,SAAS,OAAO,QAAyB;AACvC,MAAI;AACF,WAAO,QAAQ,QAAQ,UAAU;AAAA,EACnC,SAAS,KAAK;AACZ,QAAI,CAAC,YAAY,GAAG,EAAG,OAAM;AAC7B,UAAM,cAAc,YAAYJ,OAAK,OAAO,GAAG,kBAAkB,CAAC;AAClE,UAAM,YAAYA,OAAK,aAAa,gBAAgB;AACpD,iBAAa,QAAQ,SAAS;AAC9B,eAAW,UAAU,CAAC,QAAQ,MAAM,GAAG;AACrC,YAAM,YAAY,GAAG,MAAM,GAAG,MAAM;AACpC,UAAIG,aAAW,SAAS;AACtB,qBAAa,WAAW,GAAG,SAAS,GAAG,MAAM,EAAE;AAAA,IACnD;AACA,QAAI;AACF,aAAO,QAAQ,WAAW,UAAU;AAAA,IACtC,UAAE;AACA,aAAO,aAAa,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,IACtD;AAAA,EACF;AACF;AAQA,SAAS,UAAU,WAA4B;AAC7C,MAAI;AACJ,MAAI;AACF,UAAME,cAAa,WAAW,OAAO;AAAA,EACvC,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACA,QAAM,QAAQ,IACX,MAAM,IAAI,EACV,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,OAAO;AACjB,MAAI,MAAM,WAAW,EAAG,QAAO,CAAC;AAEhC,MAAI;AACJ,MAAI;AACF,YAAQC,UAAS,SAAS,EAAE;AAAA,EAC9B,QAAQ;AACN,YAAQ,oBAAI,KAAK;AAAA,EACnB;AACA,QAAM,KAAK,MACR,YAAY,EACZ,QAAQ,KAAK,GAAG,EAChB,QAAQ,KAAK,EAAE,EACf,MAAM,GAAG,EAAE;AAEd,QAAM,OAAgB,CAAC;AACvB,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,QAAI;AACF,YAAM,MAAM,KAAK,MAAM,MAAM,CAAC,CAAC;AAC/B,WAAK,KAAK;AAAA,QACR,IAAI,IAAI;AAAA,QACR,OAAO,IAAI,SAAS;AAAA,QACpB,eAAe,IAAI,gBAAgB;AAAA,QACnC,kBAAkB,IAAI,mBAAmB;AAAA,QACzC,WAAW;AAAA,MACb,CAAC;AAAA,IACH,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO;AACT;AAQA,SAAS,mBAAmB,MAA6B;AACvD,QAAM,WAA0B,CAAC;AACjC,MAAI;AACJ,MAAI;AACF,cAAUC,cAAY,MAAM,EAAE,eAAe,KAAK,CAAC;AAAA,EACrD,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,aAAW,SAAS,SAAS;AAC3B,QAAI,CAAC,MAAM,YAAY,KAAK,MAAM,SAAS,WAAY;AACvD,UAAM,UAAUP,OAAK,MAAM,MAAM,IAAI;AACrC,QAAI;AACJ,QAAI;AACF,cAAQO,cAAY,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,OAAO,CAAC;AAAA,IAChE,QAAQ;AACN;AAAA,IACF;AACA,eAAW,QAAQ,OAAO;AACxB,UAAI;AACF,cAAM,OAAO,KAAK,MAAMF,cAAaL,OAAK,SAAS,IAAI,GAAG,OAAO,CAAC;AAClE,cAAM,OAAO,MAAM;AACnB,YAAI,CAAC,MAAM,WAAW,CAAC,MAAM,UAAW;AACxC,cAAM,UAAU,OAAO,KAAK,SAAS;AACrC,cAAM,QAAQ,OAAO,KAAK,WAAW,KAAK,SAAS;AACnD,YAAI,CAAC,OAAO,SAAS,OAAO,KAAK,CAAC,OAAO,SAAS,KAAK,EAAG;AAC1D,iBAAS,KAAK,EAAE,SAAS,OAAO,OAAO,OAAO,KAAK,OAAO,EAAE,CAAC;AAAA,MAC/D,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACA,WAAS,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,OAAO;AAC7C,SAAO;AACT;AAEA,SAASQ,cAAa,UAAyB,IAAyB;AACtE,MAAI,CAAC,SAAS,OAAQ,QAAO;AAC7B,QAAM,IAAI,GAAG,QAAQ;AACrB,MAAI,CAAC,OAAO,SAAS,CAAC,EAAG,QAAO;AAEhC,MAAI,OAAsB;AAC1B,MAAI,WAAW;AACf,aAAW,KAAK,UAAU;AACxB,QAAI,KAAK,EAAE,WAAW,KAAK,EAAE,MAAO,QAAO,EAAE;AAC7C,UAAM,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,EAAE,OAAO,GAAG,KAAK,IAAI,IAAI,EAAE,KAAK,CAAC;AACjE,QAAI,IAAI,UAAU;AAChB,iBAAW;AACX,aAAO,EAAE;AAAA,IACX;AAAA,EACF;AACA,SAAO,WAAW,KAAK,KAAK,MAAO,OAAO;AAC5C;AAEA,SAAS,mBAAmB,KAA+C;AACzE,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,UAAU,IAAI,KAAK;AACzB,MAAI,CAAC,QAAS,QAAO;AACrB,MAAI,YAAY,QAAQ,YAAY,KAAK,QAAQ,SAAS,GAAG;AAC3D,WAAO;AACT,QAAM,UAAU,QACb,QAAQ,qBAAqB,EAAE,EAC/B,QAAQ,WAAW,EAAE,EACrB,YAAY,EACZ,QAAQ,MAAM,GAAG;AACpB,SAAO,WAAW;AACpB;AAEA,SAAS,iBAAiB,OAA+C;AACvE,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,IAAI,oBAAI,KAAK,GAAG,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,KAAK,GAAG,CAAC,GAAG;AAC/D,SAAO,OAAO,MAAM,EAAE,QAAQ,CAAC,IAAI,OAAO;AAC5C;AAEA,IAAM,aAAN,MAAoC;AAAA,EACzB,OAAON;AAAA,EAEhB,MAAM,QAA8B;AAClC,UAAM,OAAO,gBAAgB;AAC7B,QAAI,CAAC,KAAM,QAAO,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,EAAE;AAE9C,UAAM,SAASF,OAAK,MAAM,YAAY,gBAAgB;AACtD,UAAM,YAAYA,OAAK,MAAM,YAAY,wBAAwB;AAEjE,QAAI;AACJ,QAAI;AACF,UAAIG,aAAW,MAAM,GAAG;AACtB,eAAO,OAAO,MAAM;AAAA,MACtB,WAAWA,aAAW,SAAS,GAAG;AAChC,eAAO,UAAU,SAAS;AAAA,MAC5B,OAAO;AACL,eAAO,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,EAAE;AAAA,MACrC;AAAA,IACF,SAAS,KAAK;AACZ,UACE,eAAe,SACf,OAAO,IAAI,YAAY,YACvB,IAAI,QAAQ,SAAS,QAAQ,GAC7B;AACA,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAEA,QAAI,CAAC,KAAK,OAAQ,QAAO,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,EAAE;AAErD,UAAM,WAAW,mBAAmB,IAAI;AACxC,UAAM,UAA6B,CAAC;AAEpC,eAAW,OAAO,MAAM;AACtB,YAAM,cAAc,KAAK,IAAI,GAAG,OAAO,IAAI,aAAa,KAAK,CAAC;AAC9D,YAAM,eAAe,KAAK,IAAI,GAAG,OAAO,IAAI,gBAAgB,KAAK,CAAC;AAClE,UAAI,gBAAgB,KAAK,iBAAiB,EAAG;AAC7C,YAAM,YAAY,iBAAiB,IAAI,SAAS;AAChD,UAAI,CAAC,UAAW;AAEhB,UAAI,QAAQ,mBAAmBK,cAAa,UAAU,SAAS,CAAC;AAChE,UAAI,CAAC,OAAO;AACV,cAAM,WAAW,IAAI,SAAS,IAAI,KAAK;AACvC,YAAI,WAAW,QAAQ,YAAY,MAAM,SAAS;AAChD,kBAAQ,mBAAmB,OAAO;AAAA,QACpC;AAAA,MACF;AACA,UAAI,CAAC,MAAO,SAAQ;AAEpB,cAAQ,KAAK;AAAA,QACX,QAAQ;AAAA,QACR;AAAA,QACA,SAAS;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA,iBAAiB;AAAA,QACjB,cAAc;AAAA,MAChB,CAAC;AAAA,IACH;AAEA,WAAO,EAAE,SAAS,mBAAmB,OAAO,GAAG,UAAU,CAAC,EAAE;AAAA,EAC9D;AAAA,EAEA,cAAuB;AACrB,WAAO,gBAAgB,MAAM;AAAA,EAC/B;AACF;AAEA,eAAe,IAAI,WAAW,CAAC;;;ACvT/B,SAAS,eAAAC,eAAa,gBAAAC,eAAc,YAAAC,iBAAgB;AACpD,SAAS,WAAAC,iBAAe;AACxB,SAAS,YAAAC,WAAU,QAAAC,cAAY;AAW/B,IAAMC,gBAAe;AAErB,IAAMC,SAAQ;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAASC,gBAAyB;AAChC,QAAM,MAAgB,CAAC;AACvB,MAAI;AACJ,MAAI,QAAQ,aAAa,UAAU;AACjC,YAAQ,CAACC,OAAKC,UAAQ,GAAG,WAAW,qBAAqB,CAAC;AAAA,EAC5D,WAAW,QAAQ,aAAa,SAAS;AACvC,YAAQ;AAAA,MACN,QAAQ,IAAI,SAAS,KAAK,KAAKD,OAAKC,UAAQ,GAAG,WAAW,SAAS;AAAA,IACrE;AAAA,EACF,OAAO;AACL,YAAQ,CAAC,QAAQ,IAAI,iBAAiB,KAAK,KAAKD,OAAKC,UAAQ,GAAG,SAAS,CAAC;AAAA,EAC5E;AACA,aAAW,QAAQ,OAAO;AACxB,eAAW,KAAKH,QAAO;AACrB,UAAI,KAAKE,OAAK,MAAM,CAAC,CAAC;AAAA,IACxB;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,oBAA8B;AACrC,QAAM,OAAiB,CAAC;AACxB,aAAW,QAAQD,cAAa,GAAG;AACjC,UAAM,MAAMC,OAAK,MAAM,QAAQ,iBAAiBH,aAAY;AAC5D,QAAI;AACF,UAAIK,UAAS,GAAG,EAAE,YAAY,EAAG,MAAK,KAAK,GAAG;AAAA,IAChD,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAASC,cAAgB,MAAwB;AAC/C,MAAI;AACF,WAAO,KAAK,MAAMC,cAAa,MAAM,OAAO,CAAC;AAAA,EAC/C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAASC,iBAAgB,SAAqC;AAC5D,MAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,QAAM,UAAU,QAAQ,QAAQ,WAAW,EAAE;AAC7C,QAAM,OAAOC,UAAS,OAAO;AAC7B,SAAO,QAAQ;AACjB;AAeA,SAAS,iBAAiB,QAA+B;AACvD,QAAM,WAAWN,OAAK,QAAQ,OAAO;AACrC,QAAM,QAAQG;AAAA,IACZH,OAAK,UAAU,aAAa;AAAA,EAC9B;AACA,MAAI,OAAO,WAAW,MAAM,QAAQ,MAAM,OAAO,EAAG,QAAO,MAAM;AAEjE,QAAM,QAAuB,CAAC;AAC9B,MAAI;AACJ,MAAI;AACF,YAAQO,cAAY,UAAU,EAAE,eAAe,KAAK,CAAC;AAAA,EACvD,QAAQ;AACN,WAAO;AAAA,EACT;AACA,aAAW,SAAS,OAAO;AACzB,QACE,CAAC,MAAM,YAAY,KACnB,MAAM,KAAK,WAAW,GAAG,KACzB,MAAM,KAAK,WAAW,GAAG;AAEzB;AACF,UAAM,OAAOJ;AAAA,MACXH,OAAK,UAAU,MAAM,MAAM,mBAAmB;AAAA,IAChD;AACA,QAAI,QAAQ,OAAO,SAAS,SAAU,OAAM,KAAK,IAAI;AAAA,EACvD;AACA,SAAO;AACT;AAEA,IAAMQ,QAAuB;AAAA,EAC3B,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,SAAST,cAAa,EAAE,CAAC,KAAK;AAChC;AAEA,IAAM,gBAAN,MAAuC;AAAA,EAC5B,OAAOS;AAAA,EAEhB,MAAM,QAA8B;AAClC,UAAM,UAAU,kBAAkB;AAClC,QAAI,QAAQ,WAAW,EAAG,QAAO,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,EAAE;AAE7D,UAAM,UAA6B,CAAC;AACpC,UAAM,SAAyB,CAAC;AAEhC,eAAW,UAAU,SAAS;AAC5B,YAAM,QAAQ,iBAAiB,MAAM;AACrC,UAAI,CAAC,MAAM,OAAQ;AAEnB,iBAAW,QAAQ,OAAO;AACxB,YAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,CAAC,KAAK,GAAI;AACnD,cAAM,SAAS,OAAO,KAAK,EAAE;AAC7B,cAAM,UAAUH,iBAAgB,KAAK,SAAS;AAC9C,cAAM,gBACH,KAAK,iBAAiB,OAAO,KAAK,aAAa,EAAE,KAAK,KACvD;AAEF,cAAM,WAAWF;AAAA,UACfH,OAAK,QAAQ,SAAS,QAAQ,kBAAkB;AAAA,QAClD;AACA,YAAI,CAAC,MAAM,QAAQ,QAAQ,EAAG;AAE9B,mBAAW,OAAO,UAAU;AAC1B,cAAI,CAAC,OAAO,OAAO,QAAQ,SAAU;AACrC,gBAAM,KAAK,OAAO,IAAI,EAAE;AACxB,cAAI,CAAC,OAAO,SAAS,EAAE,EAAG;AAC1B,gBAAM,YAAY,IAAI,KAAK,EAAE;AAE7B,cAAI,IAAI,SAAS,SAAS,IAAI,QAAQ,mBAAmB;AACvD,gBAAI,OAMO;AACX,gBAAI;AACF,qBAAO,KAAK,MAAM,IAAI,QAAQ,EAAE;AAAA,YAClC,QAAQ;AAAA,YAER;AACA,gBAAI,CAAC,KAAM;AAEX,kBAAM,cAAc,KAAK,IAAI,GAAG,OAAO,KAAK,QAAQ,KAAK,CAAC;AAC1D,kBAAM,eAAe,KAAK,IAAI,GAAG,OAAO,KAAK,SAAS,KAAK,CAAC;AAC5D,kBAAM,cAAc,KAAK,IAAI,GAAG,OAAO,KAAK,WAAW,KAAK,CAAC;AAC7D,kBAAM,aAAa,KAAK,IAAI,GAAG,OAAO,KAAK,UAAU,KAAK,CAAC;AAC3D,gBAAI,cAAc,eAAe,cAAc,eAAe;AAC5D;AAEF,kBAAM,QACH,KAAK,SAAS,OAAO,KAAK,KAAK,EAAE,KAAK,KAAM;AAE/C,oBAAQ,KAAK;AAAA,cACX,WAAW;AAAA,cACX,QAAQ;AAAA,cACR;AAAA,cACA;AAAA,cACA;AAAA,cACA,aAAa,cAAc;AAAA,cAC3B;AAAA,cACA,iBAAiB;AAAA,cACjB,cAAc;AAAA,YAChB,CAAC;AACD,mBAAO,KAAK;AAAA,cACV,WAAW;AAAA,cACX,QAAQ;AAAA,cACR;AAAA,cACA;AAAA,cACA,MAAM;AAAA,YACR,CAAC;AAAA,UACH,WACE,IAAI,SAAS,SACZ,IAAI,SAAS,SAAS,IAAI,QAAQ,iBACnC;AACA,mBAAO,KAAK;AAAA,cACV,WAAW;AAAA,cACX,QAAQ;AAAA,cACR;AAAA,cACA;AAAA,cACA,MAAM;AAAA,YACR,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS,mBAAmB,OAAO;AAAA,MACnC,UAAU,gBAAgB,QAAQ,OAAO;AAAA,IAC3C;AAAA,EACF;AAAA,EAEA,cAAuB;AACrB,WAAO,kBAAkB,EAAE,SAAS;AAAA,EACtC;AACF;AAEA,eAAe,IAAI,cAAc,CAAC;;;AChOlC,SAAS,gBAAAS,qBAAoB;AAC7B,SAAS,gBAAAC,eAAc,cAAAC,cAAY,eAAAC,cAAa,UAAAC,eAAc;AAC9D,SAAS,WAAAC,WAAS,UAAAC,eAAc;AAChC,SAAS,WAAAC,UAAS,QAAAC,QAAM,WAAAC,gBAAe;AAMvC,IAAMC,YAAU;AAChB,IAAMC,cAAY;AAClB,IAAM,oBAAoBC,OAAK,QAAQ,iBAAiB,aAAa;AACrE,IAAM,mBAAmB;AACzB,IAAM,iBAAiB;AACvB,IAAM,mBAAmB;AAEzB,SAAS,wBAAgC;AACvC,MAAI,QAAQ,aAAa,UAAU;AACjC,WAAOA;AAAA,MACLC,UAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,QAAQ,aAAa,SAAS;AAChC,UAAM,UACJ,QAAQ,IAAI,SAAS,KAAK,KAAKD,OAAKC,UAAQ,GAAG,WAAW,SAAS;AACrE,WAAOD,OAAK,SAAS,UAAU,iBAAiB;AAAA,EAClD;AACA,QAAM,gBACJ,QAAQ,IAAI,iBAAiB,KAAK,KAAKA,OAAKC,UAAQ,GAAG,SAAS;AAClE,SAAOD,OAAK,eAAe,UAAU,iBAAiB;AACxD;AAEA,SAAS,uBAAsC;AAC7C,QAAM,WAAW,QAAQ,IAAI,sBAAsB,KAAK;AACxD,MAAI,UAAU;AACZ,UAAM,WAAWE,SAAQ,QAAQ;AACjC,WAAOC,aAAW,QAAQ,IAAI,WAAW;AAAA,EAC3C;AAEA,QAAM,aAAa,QAAQ,IAAI,mBAAmB,KAAK;AACvD,QAAM,aAAa,aACf,WACG,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,OAAO,EACd,IAAI,CAAC,MAAM;AACV,UAAM,IAAID,SAAQ,CAAC;AACnB,WAAO,EAAE,SAAS,QAAQ,IAAI,IAAIF,OAAK,GAAG,iBAAiB;AAAA,EAC7D,CAAC,IACH,CAAC,sBAAsB,CAAC;AAE5B,aAAW,KAAK,YAAY;AAC1B,QAAIG,aAAW,CAAC,EAAG,QAAO;AAAA,EAC5B;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,QAA+B;AACvD,QAAM,MAAM,4CAA4C,gBAAgB;AACxE,QAAM,aAAa;AAAA,IACjB,QAAQ,IAAI;AAAA,IACZ;AAAA,IACA;AAAA,EACF,EAAE,OAAO,CAAC,UAA2B,QAAQ,KAAK,CAAC;AAEnD,aAAW,WAAW,YAAY;AAChC,QAAI;AACF,YAAM,MAAMC,cAAa,SAAS,CAAC,SAAS,QAAQ,GAAG,GAAG;AAAA,QACxD,UAAU;AAAA,QACV,WAAW,IAAI,OAAO;AAAA,QACtB,SAAS;AAAA,QACT,aAAa;AAAA,MACf,CAAC,EAAE,KAAK;AAER,UAAI,CAAC,OAAO,QAAQ,KAAM;AAC1B,YAAM,OAAO,KAAK,MAAM,GAAG;AAC3B,YAAM,QAAQ,KAAK,CAAC,GAAG;AACvB,UAAI,OAAO,UAAU,SAAU;AAC/B,YAAM,QAAQ,MAAM,KAAK;AACzB,UAAI,MAAO,QAAO;AAAA,IACpB,SAAS,KAAK;AACZ,YAAM,YAAY;AAClB,UAAI,UAAU,WAAW,OAAO,UAAU,SAAS,SAAS,QAAQ,GAAG;AACrE;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,gBAAgB,QAA+B;AACtD,MAAI;AACF,WAAO,iBAAiB,MAAM;AAAA,EAChC,SAAS,KAAK;AACZ,QAAI,CAACC,aAAY,GAAG,EAAG,OAAM;AAE7B,UAAM,cAAcC,aAAYN,OAAKO,QAAO,GAAG,oBAAoB,CAAC;AACpE,UAAM,YAAYP,OAAK,aAAa,aAAa;AACjD,QAAI;AACF,MAAAQ,cAAa,QAAQ,SAAS;AAC9B,iBAAW,UAAU,CAAC,QAAQ,MAAM,GAAG;AACrC,cAAM,YAAY,GAAG,MAAM,GAAG,MAAM;AACpC,YAAIL,aAAW,SAAS;AACtB,UAAAK,cAAa,WAAW,GAAG,SAAS,GAAG,MAAM,EAAE;AAAA,MACnD;AACA,aAAO,iBAAiB,SAAS;AAAA,IACnC,UAAE;AACA,MAAAC,QAAO,aAAa,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,IACtD;AAAA,EACF;AACF;AAEA,SAASJ,aAAY,KAAuB;AAC1C,SAAO,eAAe,SAAS,sBAAsB,KAAK,IAAI,OAAO;AACvE;AAEA,SAAS,aAAa,OAA8B;AAClD,QAAM,UAAU,MAAM,MAAM,GAAG,EAAE,CAAC;AAClC,MAAI,CAAC,QAAS,QAAO;AACrB,MAAI;AACF,UAAM,MAAM,QAAQ,QAAQ,MAAM,GAAG,EAAE,QAAQ,MAAM,GAAG;AACxD,UAAM,SAAS,IAAI,OAAO,KAAK,KAAK,IAAI,SAAS,CAAC,IAAI,GAAG,GAAG;AAC5D,UAAM,OAAO,KAAK,MAAM,OAAO,KAAK,QAAQ,QAAQ,EAAE,SAAS,OAAO,CAAC;AACvE,WAAO,OAAO,KAAK,QAAQ,WAAW,KAAK,IAAI,KAAK,IAAI;AAAA,EAC1D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,cAAc,OAAgC;AAC3D,QAAM,WACJ,QAAQ,IAAI,qBAAqB,KAAK,KAAK,sBAC3C,QAAQ,QAAQ,EAAE;AACpB,QAAM,MAAM,GAAG,OAAO;AACtB,QAAM,MAAM,aAAa,KAAK;AAC9B,QAAM,eAAe,MAAM,CAAC,OAAO,GAAG,GAAG,KAAK,KAAK,EAAE,IAAI,CAAC,KAAK;AAE/D,QAAM,WAA0C;AAAA,IAC9C,EAAE,eAAe,UAAU,KAAK,GAAG;AAAA,EACrC;AACA,aAAW,MAAM,cAAc;AAC7B,aAAS,KAAK,EAAE,QAAQ,GAAG,cAAc,IAAI,EAAE,GAAG,CAAC;AACnD,aAAS,KAAK;AAAA,MACZ,eAAe,UAAU,KAAK;AAAA,MAC9B,QAAQ,GAAG,cAAc,IAAI,EAAE;AAAA,IACjC,CAAC;AAAA,EACH;AAEA,QAAM,WAAqB,CAAC;AAC5B,aAAW,WAAW,UAAU;AAC9B,QAAI;AACJ,QAAI;AACF,aAAO,MAAM,MAAM,KAAK;AAAA,QACtB,SAAS,EAAE,QAAQ,sBAAsB,GAAG,QAAQ;AAAA,QACpD,QAAQ,YAAY,QAAQ,gBAAgB;AAAA,MAC9C,CAAC;AAAA,IACH,SAAS,GAAG;AACV,YAAM,SACJ,aAAa,SAAS,EAAE,SAAS,iBAC7B,YACA,YAAa,EAAY,OAAO;AACtC,YAAM,MAAM,IAAI,MAAM,gCAAgC,MAAM,GAAG;AAC/D,MAAC,IAA2B,OAAO;AACnC,YAAM;AAAA,IACR;AACA,QAAI,KAAK,GAAI,QAAO,MAAM,KAAK,KAAK;AACpC,aAAS,KAAK,GAAG,KAAK,MAAM,IAAI,KAAK,UAAU,EAAE;AAAA,EACnD;AAEA,QAAM,IAAI,MAAM,oCAAoC,SAAS,KAAK,IAAI,CAAC,GAAG;AAC5E;AAEA,SAAS,SAAS,MAA0B;AAC1C,QAAM,OAAmB,CAAC;AAC1B,MAAI,QAAQ;AACZ,MAAI,MAAgB,CAAC;AACrB,MAAI,WAAW;AACf,MAAI,IAAI;AAER,SAAO,IAAI,KAAK,QAAQ;AACtB,UAAM,IAAI,KAAK,CAAC;AAChB,QAAI,UAAU;AACZ,UAAI,MAAM,KAAK;AACb,YAAI,KAAK,IAAI,CAAC,MAAM,KAAK;AACvB,mBAAS;AACT,eAAK;AACL;AAAA,QACF;AACA,mBAAW;AACX;AACA;AAAA,MACF;AACA,eAAS;AACT;AACA;AAAA,IACF;AACA,QAAI,MAAM,KAAK;AACb,iBAAW;AACX;AACA;AAAA,IACF;AACA,QAAI,MAAM,KAAK;AACb,UAAI,KAAK,KAAK;AACd,cAAQ;AACR;AACA;AAAA,IACF;AACA,QAAI,MAAM,MAAM;AACd;AACA;AAAA,IACF;AACA,QAAI,MAAM,MAAM;AACd,UAAI,KAAK,KAAK;AACd,WAAK,KAAK,GAAG;AACb,cAAQ;AACR,YAAM,CAAC;AACP;AACA;AAAA,IACF;AACA,aAAS;AACT;AAAA,EACF;AAEA,MAAI,UAAU,MAAM,IAAI,SAAS,GAAG;AAClC,QAAI,KAAK,KAAK;AACd,SAAK,KAAK,GAAG;AAAA,EACf;AAEA,SAAO;AACT;AAEA,SAAS,UAAU,OAAwC;AACzD,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,IAAI,OAAO,KAAK,EAAE,KAAK;AAC7B,MAAI,CAAC,EAAG,QAAO;AACf,MAAI,sBAAsB,KAAK,CAAC,EAAG,QAAO,oBAAI,KAAK,GAAG,CAAC,YAAY;AACnE,QAAM,IAAI,IAAI,KAAK,CAAC;AACpB,SAAO,OAAO,MAAM,EAAE,QAAQ,CAAC,IAAI,OAAO;AAC5C;AAEA,SAAS,UAAU,OAAmC;AACpD,MAAI,SAAS,KAAM,QAAO;AAC1B,QAAM,IAAI,OAAO,OAAO,KAAK,EAAE,QAAQ,MAAM,EAAE,EAAE,KAAK,CAAC;AACvD,SAAO,OAAO,SAAS,CAAC,KAAK,IAAI,IAAI,KAAK,MAAM,CAAC,IAAI;AACvD;AAQA,SAASK,uBAAqB,QAAgC;AAC5D,SAAO;AAAA,IACL,IAAIZ;AAAA,IACJ,MAAMC;AAAA,IACN,SAASY,SAAQ,MAAM;AAAA,EACzB;AACF;AAEO,IAAM,eAAN,MAAsC;AAAA,EAClC;AAAA,EACQ;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,UAA+B,CAAC,GAAG;AAC7C,SAAK,SAAS,QAAQ,UAAU,qBAAqB,KAAK;AAC1D,SAAK,YAAY,QAAQ,aAAa;AACtC,SAAK,WAAW,QAAQ,YAAY;AACpC,SAAK,OAAOD,uBAAqB,KAAK,MAAM;AAAA,EAC9C;AAAA,EAEA,MAAM,QAA8B;AAClC,QAAI,CAAC,KAAK,UAAU,CAACP,aAAW,KAAK,MAAM,GAAG;AAC5C,aAAO,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,EAAE;AAAA,IACrC;AAEA,QAAI;AACJ,QAAI;AACF,cAAQ,KAAK,UAAU,KAAK,MAAM;AAAA,IACpC,SAAS,KAAK;AACZ,UAAI,eAAe,SAAS,IAAI,QAAQ,SAAS,QAAQ,GAAG;AAC1D,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AACA,YAAM;AAAA,IACR;AACA,QAAI,CAAC,MAAO,QAAO,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,EAAE;AAE/C,QAAI;AACJ,QAAI;AACF,YAAM,MAAM,KAAK,SAAS,KAAK;AAAA,IACjC,SAAS,KAAK;AACZ,UAAK,IAA2B;AAC9B,eAAO,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,EAAE;AACrC,YAAM;AAAA,IACR;AAEA,UAAM,OAAO,SAAS,GAAG;AACzB,QAAI,KAAK,SAAS,EAAG,QAAO,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,EAAE;AAExD,UAAM,SAAS,KAAK,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AAC1C,UAAM,MAAM,CAAC,SAAiB,OAAO,QAAQ,IAAI;AACjD,UAAM,UAAU,IAAI,MAAM;AAC1B,UAAM,WAAW,IAAI,OAAO;AAC5B,UAAM,qBAAqB,IAAI,wBAAwB;AACvD,UAAM,kBAAkB,IAAI,yBAAyB;AACrD,UAAM,eAAe,IAAI,YAAY;AACrC,UAAM,YAAY,IAAI,eAAe;AAErC,QAAI,UAAU,KAAK,WAAW,EAAG,QAAO,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,EAAE;AAEpE,UAAM,UAA6B,CAAC;AACpC,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,YAAM,MAAM,KAAK,CAAC;AAClB,UAAI,IAAI,WAAW,KAAK,IAAI,CAAC,EAAE,KAAK,MAAM,GAAI;AAE9C,YAAM,YAAY,UAAU,IAAI,OAAO,CAAC;AACxC,YAAM,QAAQ,IAAI,QAAQ,GAAG,KAAK;AAClC,UAAI,CAAC,aAAa,CAAC,MAAO;AAE1B,YAAM,kBACJ,sBAAsB,IAAI,UAAU,IAAI,kBAAkB,CAAC,IAAI;AACjE,YAAM,eACJ,mBAAmB,IAAI,UAAU,IAAI,eAAe,CAAC,IAAI;AAC3D,YAAM,YAAY,gBAAgB,IAAI,UAAU,IAAI,YAAY,CAAC,IAAI;AACrE,YAAM,SAAS,aAAa,IAAI,UAAU,IAAI,SAAS,CAAC,IAAI;AAE5D,UAAI,kBAAkB,eAAe,YAAY,WAAW,EAAG;AAE/D,cAAQ,KAAK;AAAA,QACX,QAAQL;AAAA,QACR;AAAA,QACA,SAAS;AAAA,QACT;AAAA,QACA,aAAa,kBAAkB;AAAA,QAC/B,cAAc;AAAA,QACd,cAAc;AAAA,QACd,iBAAiB;AAAA,MACnB,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL,SAAS,mBAAmB,OAAO;AAAA,MACnC,UAAU,CAAC;AAAA,IACb;AAAA,EACF;AAAA,EAEA,cAAuB;AACrB,WAAOK,aAAW,KAAK,MAAM;AAAA,EAC/B;AACF;AAEA,eAAe,IAAI,aAAa,CAAC;;;ACxWjC,SAAS,cAAAS,mBAAkB;AAC3B,SAAS,cAAAC,oBAAkB;AAC3B,SAAS,WAAAC,WAAS,YAAAC,iBAAgB;AAClC,SAAS,WAAAC,UAAS,QAAAC,cAAY;AAa9B,IAAMC,YAAU;AAChB,IAAMC,cAAY;AAClB,IAAMC,mBAAkBC,OAAKC,UAAQ,GAAG,UAAU,OAAO,MAAM,WAAW;AAE1E,IAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgB1B,IAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAOtB,IAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAOtB,IAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AA6DzB,SAASC,uBAAqB,QAAgC;AAC5D,SAAO;AAAA,IACL,IAAIL;AAAA,IACJ,MAAMC;AAAA,IACN,SAASK,SAAQ,MAAM;AAAA,EACzB;AACF;AAEA,SAASC,eAAa,OAAwB;AAC5C,QAAM,cAAc,OAAO,KAAK;AAChC,SAAO,OAAO,SAAS,WAAW,KAAK,cAAc,IAAI,cAAc;AACzE;AAEA,SAASC,WAAU,OAA+B;AAChD,SAAO,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ;AACjE;AAEA,SAAS,gBAAgB,OAA6B;AACpD,QAAM,cAAc,OAAO,KAAK;AAChC,MAAI,CAAC,OAAO,SAAS,WAAW,GAAG;AACjC,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,IAAI,KAAK,WAAW;AACtC,SAAO,OAAO,MAAM,UAAU,QAAQ,CAAC,IAAI,OAAO;AACpD;AAEA,SAASC,aAAY,OAA8B;AACjD,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,MAAM,QAAQ,OAAO,GAAG,EAAE,QAAQ,QAAQ,EAAE;AAC/D,QAAM,OAAO,WAAW,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,IAAI;AACvD,SAAO,QAAQ;AACjB;AAEA,SAAS,iBAAiB,OAAyC;AACjE,MAAI,OAAO,UAAU,YAAY,MAAM,WAAW,GAAG;AACnD,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,WAAO,UAAU,OAAO,WAAW,WAAW,SAAS;AAAA,EACzD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,iBACP,QACA,WACA,SACmB;AACnB,QAAM,WAAW,OAAO,IAAI,SAAS;AACrC,MAAI,UAAU;AACZ,QAAI,SAAS,YAAY,aAAa,YAAY,WAAW;AAC3D,eAAS,UAAU;AAAA,IACrB;AACA,WAAO;AAAA,EACT;AAEA,QAAM,OAA0B;AAAA,IAC9B;AAAA,IACA,QAAQT;AAAA,IACR;AAAA,IACA,gBAAgB;AAAA,IAChB,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB,eAAe;AAAA,IACf,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,iBAAiB,IAAI,MAAM,EAAE,EAAE,KAAK,CAAC;AAAA,EACvC;AAEA,SAAO,IAAI,WAAW,IAAI;AAC1B,SAAO;AACT;AAEA,SAASU,mBAAkB,SAA4B;AACrD,QAAM,iBAAiB,oBAAI,IAA4C;AAEvE,aAAW,SAAS,SAAS;AAC3B,QAAI,CAAC,MAAM,aAAa,sBAAsB,KAAK,GAAG;AACpD;AAAA,IACF;AAEA,QAAI,UAAU,eAAe,IAAI,MAAM,SAAS;AAChD,QAAI,CAAC,SAAS;AACZ,gBAAU,oBAAI,IAA+B;AAC7C,qBAAe,IAAI,MAAM,WAAW,OAAO;AAAA,IAC7C;AAEA,UAAM,cACJ,MAAM,cACN,MAAM,eACN,MAAM,kBACN,MAAM;AACR,UAAM,WAAW,QAAQ,IAAI,MAAM,KAAK;AAExC,QAAI,UAAU;AACZ,eAAS,eAAe,MAAM;AAC9B,eAAS,gBAAgB,MAAM;AAC/B,eAAS,mBAAmB,MAAM;AAClC,eAAS,gBAAgB,MAAM;AAC/B,eAAS,eAAe;AACxB;AAAA,IACF;AAEA,YAAQ,IAAI,MAAM,OAAO;AAAA,MACvB,OAAO,MAAM;AAAA,MACb,aAAa,MAAM;AAAA,MACnB,cAAc,MAAM;AAAA,MACpB,iBAAiB,MAAM;AAAA,MACvB,cAAc,MAAM;AAAA,MACpB;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAEA,SAAS,cAAcC,QAKD;AACpB,QAAM,SAAS,oBAAI,IAA+B;AAElD,aAAW,OAAOA,OAAM,aAAa;AACnC,UAAM,YAAYH,WAAU,IAAI,EAAE;AAClC,QAAI,CAAC,WAAW;AACd;AAAA,IACF;AAEA,UAAM,QAAQ;AAAA,MACZ;AAAA,MACA;AAAA,MACAC,aAAYD,WAAU,IAAI,SAAS,CAAC;AAAA,IACtC;AACA,UAAM,kBAAkB,gBAAgB,IAAI,WAAW;AACvD,UAAM,iBAAiB,gBAAgB,IAAI,WAAW;AAAA,EACxD;AAEA,aAAW,OAAOG,OAAM,aAAa;AACnC,UAAM,YAAYH,WAAU,IAAI,SAAS;AACzC,QAAI,CAAC,WAAW;AACd;AAAA,IACF;AAEA,UAAM,OAAO,iBAAiB,IAAI,IAAI;AACtC,UAAM,OACJ,MAAM,SAAS,UAAU,MAAM,SAAS,cAAc,KAAK,OAAO;AACpE,QAAI,CAAC,MAAM;AACT;AAAA,IACF;AAEA,UAAM,YACJ,gBAAgB,MAAM,MAAM,OAAO,KAAK,gBAAgB,IAAI,WAAW;AACzE,QAAI,CAAC,WAAW;AACd;AAAA,IACF;AAEA,UAAM,QAAQ,iBAAiB,QAAQ,WAAW,SAAS;AAC3D,UAAM,gBAAgB;AAEtB,QAAI,CAAC,MAAM,kBAAkB,YAAY,MAAM,gBAAgB;AAC7D,YAAM,iBAAiB;AAAA,IACzB;AACA,QAAI,CAAC,MAAM,iBAAiB,YAAY,MAAM,eAAe;AAC3D,YAAM,gBAAgB;AAAA,IACxB;AAEA,QAAI,SAAS,QAAQ;AACnB,YAAM,oBAAoB;AAC1B,YAAM,gBAAgB,UAAU,YAAY,CAAC,KAAK;AAAA,IACpD;AAAA,EACF;AAEA,aAAW,OAAOG,OAAM,UAAU;AAChC,UAAM,YAAYH,WAAU,IAAI,SAAS;AACzC,QAAI,CAAC,WAAW;AACd;AAAA,IACF;AAEA,UAAM,QAAQ,iBAAiB,QAAQ,WAAW,SAAS;AAC3D,UAAM,iBAAiB,KAAK,MAAMD,eAAa,IAAI,UAAU,IAAI,GAAI;AAAA,EACvE;AAEA,QAAM,iBAAiBG,mBAAkBC,OAAM,OAAO;AACtD,QAAM,OAAOC,UAAS,EAAE,QAAQ,YAAY,EAAE;AAE9C,SAAO,MAAM,KAAK,OAAO,OAAO,CAAC,EAC9B,IAAI,CAAC,UAAU;AACd,UAAM,iBAAiB,MAAM,kBAAkB,MAAM;AACrD,UAAM,gBACJ,MAAM,iBAAiB,MAAM,kBAAkB;AAEjD,QAAI,CAAC,kBAAkB,CAAC,eAAe;AACrC,aAAO;AAAA,IACT;AAEA,UAAM,cAAc,MAAM;AAAA,MACxB,eAAe,IAAI,MAAM,SAAS,GAAG,OAAO,KAAK,CAAC;AAAA,IACpD,EAAE,KAAK,CAAC,MAAM,UAAU;AACtB,UAAI,MAAM,gBAAgB,KAAK,aAAa;AAC1C,eAAO,MAAM,cAAc,KAAK;AAAA,MAClC;AAEA,aAAO,KAAK,MAAM,cAAc,MAAM,KAAK;AAAA,IAC7C,CAAC;AACD,UAAM,cAAc,YAAY;AAAA,MAC9B,CAAC,KAAK,UAAU,MAAM,MAAM;AAAA,MAC5B;AAAA,IACF;AACA,UAAM,eAAe,YAAY;AAAA,MAC/B,CAAC,KAAK,UAAU,MAAM,MAAM;AAAA,MAC5B;AAAA,IACF;AACA,UAAM,kBAAkB,YAAY;AAAA,MAClC,CAAC,KAAK,UAAU,MAAM,MAAM;AAAA,MAC5B;AAAA,IACF;AACA,UAAM,eAAe,YAAY;AAAA,MAC/B,CAAC,KAAK,UAAU,MAAM,MAAM;AAAA,MAC5B;AAAA,IACF;AACA,UAAM,cAAc,YAAY;AAAA,MAC9B,CAAC,KAAK,UAAU,MAAM,MAAM;AAAA,MAC5B;AAAA,IACF;AACA,UAAM,kBAAkB,KAAK;AAAA,MAC3B;AAAA,MACA,KAAK,OAAO,cAAc,QAAQ,IAAI,eAAe,QAAQ,KAAK,GAAI;AAAA,IACxE;AAEA,WAAO;AAAA,MACL,QAAQ,MAAM;AAAA,MACd,SAAS,MAAM;AAAA,MACf,aAAaC,YAAW,QAAQ,EAC7B,OAAO,MAAM,SAAS,EACtB,OAAO,KAAK,EACZ,MAAM,GAAG,EAAE;AAAA,MACd,UAAU;AAAA,MACV,gBAAgB,eAAe,YAAY;AAAA,MAC3C,eAAe,cAAc,YAAY;AAAA,MACzC;AAAA,MACA,eAAe,MAAM;AAAA,MACrB,cAAc,MAAM;AAAA,MACpB,kBAAkB,MAAM;AAAA,MACxB,iBAAiB,MAAM;AAAA,MACvB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAc,YAAY,CAAC,GAAG,SAAS;AAAA,MACvC;AAAA,IACF;AAAA,EACF,CAAC,EACA,OAAO,CAAC,YAAwC,YAAY,IAAI;AACrE;AAEO,IAAM,cAAN,MAAqC;AAAA,EACjC;AAAA,EACQ;AAAA,EACA;AAAA,EAEjB,YAAY,UAA8B,CAAC,GAAG;AAC5C,SAAK,SAAS,QAAQ,UAAUX;AAChC,SAAK,YAAY,QAAQ,aAAa;AACtC,SAAK,OAAOG,uBAAqB,KAAK,MAAM;AAAA,EAC9C;AAAA,EAEA,MAAM,QAA8B;AAClC,QAAI,CAACS,aAAW,KAAK,MAAM,GAAG;AAC5B,aAAO,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,EAAE;AAAA,IACrC;AAEA,UAAM,YAAY,MAAM,KAAK;AAAA,MAC3B,KAAK;AAAA,MACL;AAAA,IACF;AACA,UAAM,UAA6B,CAAC;AAEpC,eAAW,OAAO,WAAW;AAC3B,YAAM,YAAY,gBAAgB,IAAI,SAAS;AAC/C,UAAI,CAAC,WAAW;AACd;AAAA,MACF;AAEA,YAAM,cAAcP,eAAa,IAAI,WAAW;AAChD,YAAM,eAAeA,eAAa,IAAI,YAAY;AAClD,YAAM,kBAAkBA,eAAa,IAAI,eAAe;AACxD,YAAM,eAAeA,eAAa,IAAI,oBAAoB;AAE1D,UACE,gBAAgB,KAChB,iBAAiB,KACjB,oBAAoB,KACpB,iBAAiB,GACjB;AACA;AAAA,MACF;AAEA,cAAQ,KAAK;AAAA,QACX,WAAWC,WAAU,IAAI,SAAS,KAAK;AAAA,QACvC,QAAQR;AAAA,QACR,OAAOQ,WAAU,IAAI,KAAK,KAAK;AAAA,QAC/B,SAASC,aAAYD,WAAU,IAAI,SAAS,CAAC;AAAA,QAC7C;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAEA,QAAI,cAAiC,CAAC;AACtC,QAAI,cAAiC,CAAC;AACtC,QAAI,WAAgC,CAAC;AAErC,QAAI;AACF,OAAC,aAAa,aAAa,QAAQ,IAAI,MAAM,QAAQ,IAAI;AAAA,QACvD,KAAK,UAA2B,KAAK,QAAQ,aAAa;AAAA,QAC1D,KAAK,UAA2B,KAAK,QAAQ,aAAa;AAAA,QAC1D,KAAK,UAA6B,KAAK,QAAQ,gBAAgB;AAAA,MACjE,CAAC;AAAA,IACH,QAAQ;AACN,aAAO;AAAA,QACL,SAAS,mBAAmB,OAAO;AAAA,QACnC,UAAU,CAAC;AAAA,MACb;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS,mBAAmB,OAAO;AAAA,MACnC,UAAU,cAAc;AAAA,QACtB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,cAAuB;AACrB,WAAOM,aAAW,KAAK,MAAM;AAAA,EAC/B;AACF;AAEA,eAAe,IAAI,YAAY,CAAC;;;ACjdhC,SAAS,SAAS,cAAc;;;ACAhC,SAAS,kBAAkB;AAC3B;AAAA,EACE,cAAAC;AAAA,EACA;AAAA,EACA,gBAAAC;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,QAAAC,cAAY;;;ACRrB,SAAS,WAAAC,iBAAe;AACxB,SAAS,QAAAC,cAAY;AAQd,SAAS,gBAAwB;AACtC,SAAO,QAAQ,IAAI,mBAAmBA,OAAKD,UAAQ,GAAG,SAAS;AACjE;AAaO,SAAS,eAAuB;AACrC,SAAO,QAAQ,IAAI,kBAAkBE,OAAKC,UAAQ,GAAG,UAAU,OAAO;AACxE;AAMO,SAAS,gBAAwB;AACtC,SAAO,QAAQ,IAAI,mBAAmB,aAAa;AACrD;;;ADfA,IAAM,aAAaC,OAAK,cAAc,GAAG,YAAY;AACrD,IAAM,QAAQ,QAAQ,IAAI,oBAAoB;AAC9C,IAAM,cAAcA,OAAK,YAAY,QAAQ,oBAAoB,aAAa;AAE9E,IAAM,kBAAkB;AACxB,IAAM,oBAAoB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,gBAAwB;AACtC,SAAO;AACT;AAEO,SAAS,eAAuB;AACrC,SAAO;AACT;AAEO,SAAS,aAA4B;AAC1C,MAAI,CAACC,aAAW,WAAW,EAAG,QAAO;AACrC,MAAI;AACF,UAAM,MAAMC,cAAa,aAAa,OAAO;AAC7C,UAAM,SAAS,KAAK,MAAM,GAAG;AAE7B,QAAI,CAAC,OAAO,QAAQ;AAClB,aAAO,SAAS;AAAA,IAClB;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,WAAW,QAAsB;AAC/C,YAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AACzC,gBAAc,aAAa,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,GAAM,OAAO;AAC5E;AAEO,SAAS,eAAqB;AACnC,MAAID,aAAW,WAAW,GAAG;AAC3B,eAAW,WAAW;AAAA,EACxB;AACF;AAEO,SAAS,oBAAoB,QAAwB;AAC1D,MAAI,OAAO,SAAU,QAAO,OAAO;AAEnC,QAAM,OAAO,WAAW;AACxB,aAAW,EAAE,GAAG,QAAQ,UAAU,KAAK,CAAC;AAExC,SAAO;AACT;AAEO,SAAS,eAAe,KAAsB;AACnD,SAAO,IAAI,WAAW,KAAK;AAC7B;AAEO,SAAS,iBAAiB,KAAsB;AACrD,SAAO,kBAAkB,SAAS,GAAG;AACvC;AAEO,SAAS,mBAA2B;AACzC,SAAO,QAAQ,IAAI,uBAAuB;AAC5C;;;AErFA,IAAM,WAAW,QAAQ,QAAQ,OAAO,SAAS,QAAQ,IAAI,aAAa,GAAG;AAE7E,SAAS,SAAS,MAAc,OAAuB;AACrD,MAAI,CAAC,SAAU,QAAO;AACtB,SAAO,QAAU,IAAI,IAAI,KAAK;AAChC;AAEO,SAAS,KAAK,OAAuB;AAC1C,SAAO,SAAS,KAAK,KAAK;AAC5B;AAEO,SAAS,IAAI,OAAuB;AACzC,SAAO,SAAS,KAAK,KAAK;AAC5B;AAEO,SAAS,KAAK,OAAuB;AAC1C,SAAO,SAAS,MAAM,KAAK;AAC7B;AAEO,SAAS,MAAM,OAAuB;AAC3C,SAAO,SAAS,MAAM,KAAK;AAC7B;AAEO,SAAS,OAAO,OAAuB;AAC5C,SAAO,SAAS,MAAM,KAAK;AAC7B;AAEO,SAAS,IAAI,OAAuB;AACzC,SAAO,SAAS,MAAM,KAAK;AAC7B;AAEO,SAAS,QAAQ,OAAuB;AAC7C,SAAO,SAAS,MAAM,KAAK;AAC7B;AAEO,SAAS,aAAa,OAAe,UAA2B;AACrE,QAAM,QAAQ,CAAC,GAAG,KAAK,QAAG,CAAC,IAAI,KAAK,KAAK,CAAC,EAAE;AAC5C,MAAI,UAAU;AACZ,UAAM,KAAK,IAAI,QAAQ,CAAC;AAAA,EAC1B;AACA,SAAO;AAAA,EAAK,MAAM,KAAK,IAAI,CAAC;AAC9B;AAEO,SAAS,cAAc,OAAuB;AACnD,SAAO;AAAA,EAAK,KAAK,KAAK,CAAC;AACzB;AAEO,SAAS,eAAe,OAAe,OAAuB;AACnE,SAAO,KAAK,IAAI,MAAM,OAAO,IAAI,GAAG,CAAC,CAAC,IAAI,KAAK;AACjD;AAEO,SAAS,aACd,OACA,OAAqD,WAC7C;AACR,QAAM,OACJ,SAAS,YACL,MAAM,QAAG,IACT,SAAS,YACP,OAAO,GAAG,IACV,SAAS,WACP,IAAI,QAAG,IACP,KAAK,QAAG;AAClB,SAAO,KAAK,IAAI,IAAI,KAAK;AAC3B;AAEO,SAAS,gBAAgB,MAAsB;AACpD,SAAO,IAAI,IAAI;AACjB;AAEO,SAAS,WAAW,OAAe,UAAU,GAAW;AAC7D,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI,MAAM,UAAU,QAAS,QAAO;AACpC,SAAO,GAAG,MAAM,MAAM,GAAG,OAAO,CAAC;AACnC;AAWO,SAAS,kBACd,OACA,OAAqD,WAC7C;AACR,MAAI,SAAS,UAAW,QAAO,MAAM,KAAK;AAC1C,MAAI,SAAS,UAAW,QAAO,OAAO,KAAK;AAC3C,MAAI,SAAS,SAAU,QAAO,IAAI,KAAK;AACvC,SAAO,QAAQ,KAAK;AACtB;;;AC7FA,SAAS,SAAS,OAAO,UAAU,cAAc;AAS1C,SAAS,wBAAiC;AAC/C,SAAO,QAAQ,QAAQ,MAAM,SAAS,QAAQ,OAAO,KAAK;AAC5D;AAEA,eAAsB,cAAc,SAGf;AACnB,SAAO,QAAQ;AAAA,IACb,SAAS,QAAQ;AAAA,IACjB,SAAS,QAAQ;AAAA,EACnB,CAAC;AACH;AAEA,eAAsB,WAAW,SAIb;AAClB,SAAO,MAAM;AAAA,IACX,SAAS,QAAQ;AAAA,IACjB,SAAS,QAAQ;AAAA,IACjB,UAAU,QAAQ;AAAA,EACpB,CAAC;AACH;AAEA,eAAsB,eAAe,SAIjB;AAClB,SAAO,SAAS;AAAA,IACd,SAAS,QAAQ;AAAA,IACjB,MAAM,QAAQ,QAAQ;AAAA,IACtB,UAAU,QAAQ;AAAA,EACpB,CAAC;AACH;AAEA,eAAsB,aAAgB,SAGvB;AACb,SAAO,OAAO;AAAA,IACZ,SAAS,QAAQ;AAAA,IACjB,SAAS,CAAC,GAAG,QAAQ,OAAO;AAAA,IAC5B,UAAU,KAAK,IAAI,KAAK,IAAI,QAAQ,QAAQ,QAAQ,CAAC,GAAG,EAAE;AAAA,EAC5D,CAAC;AACH;;;ACtDA,IAAM,aAAuC;AAAA,EAC3C,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AACT;AAEO,IAAM,SAAN,MAAa;AAAA,EACV;AAAA,EAER,YAAY,QAAkB,QAAQ;AACpC,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,SAAS,OAAuB;AAC9B,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,MAAM,KAAmB;AACvB,QAAI,WAAW,KAAK,KAAK,KAAK,WAAW,OAAO;AAC9C,cAAQ,OAAO,MAAM,WAAW,GAAG;AAAA,CAAI;AAAA,IACzC;AAAA,EACF;AAAA,EAEA,KAAK,KAAmB;AACtB,QAAI,WAAW,KAAK,KAAK,KAAK,WAAW,MAAM;AAC7C,cAAQ,OAAO,MAAM,GAAG,GAAG;AAAA,CAAI;AAAA,IACjC;AAAA,EACF;AAAA,EAEA,KAAK,KAAmB;AACtB,QAAI,WAAW,KAAK,KAAK,KAAK,WAAW,MAAM;AAC7C,cAAQ,OAAO,MAAM,SAAS,GAAG;AAAA,CAAI;AAAA,IACvC;AAAA,EACF;AAAA,EAEA,MAAM,KAAmB;AACvB,QAAI,WAAW,KAAK,KAAK,KAAK,WAAW,OAAO;AAC9C,cAAQ,OAAO,MAAM,UAAU,GAAG;AAAA,CAAI;AAAA,IACxC;AAAA,EACF;AAAA,EAEA,IAAI,KAAmB;AACrB,SAAK,KAAK,GAAG;AAAA,EACf;AACF;AAEO,IAAM,SAAS,IAAI,OAAO;;;AC3BjC,IAAM,aAAa,CAAC,UAAU,UAAU,gBAAgB,UAAU;AAK3D,SAAS,YAAY,OAAmC;AAC7D,SAAO,iBAAiB,KAAK,KAAK,WAAW,SAAS,KAAkB;AAC1E;AAEO,SAAS,kBAAkB,KAAgB,OAAwB;AACxE,MAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,IAAI;AACzD,WAAO;AAAA,EACT;AAEA,MAAI,QAAQ,UAAU;AACpB,WAAO,WAAW,OAAO,KAAK,CAAC;AAAA,EACjC;AAEA,MAAI,QAAQ,gBAAgB;AAC1B,UAAM,KAAK,OAAO,KAAK;AACvB,UAAM,UAAU,KAAK,MAAM,KAAK,GAAK;AACrC,WAAO,GAAG,OAAO,kBAAQ,EAAE;AAAA,EAC7B;AAEA,SAAO,OAAO,KAAK;AACrB;AAEA,eAAe,yBAAoD;AACjE,SAAO;AAAA,IACL,aAAa,4BAAQ,4GAAiC;AAAA,EACxD;AAEA,SAAO,aAA+B;AAAA,IACpC,SAAS;AAAA,IACT,SAAS;AAAA,MACP;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,aAAa;AAAA,MACf;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,aAAa;AAAA,MACf;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,eAAe,gBAAgB,SAAqC;AAClE,SAAO,aAAwB;AAAA,IAC7B;AAAA,IACA,SAAS;AAAA,MACP;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,aAAa;AAAA,MACf;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,aAAa;AAAA,MACf;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,aAAa;AAAA,MACf;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,eAAe,wBACb,eACiB;AACjB,QAAM,SAAS,MAAM,aAAqB;AAAA,IACxC,SAAS;AAAA,IACT,SAAS;AAAA,MACP;AAAA,QACE,MAAM;AAAA,QACN,OAAO,OAAO,KAAK,GAAM;AAAA,QACzB,aAAa;AAAA,MACf;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO,OAAO,KAAK,GAAM;AAAA,QACzB,aAAa;AAAA,MACf;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO,OAAO,KAAK,GAAM;AAAA,QACzB,aAAa;AAAA,MACf;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO,OAAO,KAAK,GAAM;AAAA,QACzB,aAAa;AAAA,MACf;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF,CAAC;AAED,MAAI,WAAW,UAAU;AACvB,WAAO;AAAA,EACT;AAEA,SAAO,WAAW;AAAA,IAChB,SAAS;AAAA,IACT,cAAc,gBAAgB,OAAO,aAAa,IAAI;AAAA,IACtD,UAAU,CAAC,UAAU;AACnB,YAAM,SAAS,OAAO,SAAS,OAAO,EAAE;AACxC,UAAI,OAAO,MAAM,MAAM,KAAK,UAAU,GAAG;AACvC,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AACH;AAEA,eAAe,kBACb,KACA,eACiB;AACjB,UAAQ,KAAK;AAAA,IACX,KAAK;AACH,aAAO,eAAe;AAAA,QACpB,SAAS;AAAA,QACT,UAAU,CAAC,UACT,eAAe,KAAK,KAAK;AAAA,MAC7B,CAAC;AAAA,IACH,KAAK;AACH,aAAO,WAAW;AAAA,QAChB,SAAS;AAAA,QACT,cACE,OAAO,kBAAkB,YAAY,cAAc,SAAS,IACxD,gBACA,iBAAiB;AAAA,QACvB,UAAU,CAAC,UAAU;AACnB,cAAI;AACF,kBAAM,MAAM,IAAI,IAAI,KAAK;AACzB,mBAAO,QAAQ,IAAI,YAAY,IAAI,IAAI,KAAK;AAAA,UAC9C,QAAQ;AACN,mBAAO;AAAA,UACT;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH,KAAK;AACH,aAAO;AAAA,QACL,OAAO,kBAAkB,WAAW,gBAAgB;AAAA,MACtD;AAAA,IACF,KAAK;AACH,aAAO,aAAqB;AAAA,QAC1B,SAAS;AAAA,QACT,SAAS;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,OAAO;AAAA,YACP,aAAa;AAAA,UACf;AAAA,UACA;AAAA,YACE,MAAM;AAAA,YACN,OAAO;AAAA,YACP,aAAa;AAAA,UACf;AAAA,UACA;AAAA,YACE,MAAM;AAAA,YACN,OAAO;AAAA,YACP,aAAa;AAAA,UACf;AAAA,UACA;AAAA,YACE,MAAM;AAAA,YACN,OAAO;AAAA,YACP,aAAa;AAAA,UACf;AAAA,QACF;AAAA,MACF,CAAC;AAAA,EACL;AACF;AAEA,SAAS,kBAAwB;AAC/B,QAAM,SAAS,WAAW;AAE1B,MAAI,CAAC,QAAQ;AACX,WAAO,KAAK,aAAa,4BAAQ,oEAAa,CAAC;AAC/C,WAAO,KAAK,aAAa,2EAA8B,SAAS,CAAC;AACjE;AAAA,EACF;AAEA,SAAO,KAAK,aAAa,0BAAM,CAAC;AAChC,SAAO,KAAK,cAAc,0BAAM,CAAC;AACjC,SAAO,KAAK,eAAe,WAAW,WAAW,OAAO,UAAU,EAAE,CAAC,CAAC;AACtE,SAAO;AAAA,IACL,eAAe,oBAAU,OAAO,UAAU,wBAAwB;AAAA,EACpE;AACA,SAAO;AAAA,IACL;AAAA,MACE;AAAA,MACA,OAAO,eACH,GAAG,KAAK,MAAM,OAAO,eAAe,GAAK,CAAC,kBAAQ,OAAO,YAAY,SACrE;AAAA,IACN;AAAA,EACF;AACA,SAAO,KAAK,eAAe,4BAAQ,OAAO,YAAY,MAAM,CAAC;AAC7D,MAAI,OAAO,UAAU;AACnB,WAAO,KAAK,eAAe,mBAAS,WAAW,OAAO,UAAU,EAAE,CAAC,CAAC;AAAA,EACtE;AACF;AAEA,eAAsB,aAAa,MAA+B;AAChE,QAAM,cAAc,sBAAsB;AAC1C,MAAI,MAAM,KAAK,CAAC;AAEhB,MAAI,CAAC,KAAK;AACR,QAAI,CAAC,aAAa;AAChB,aAAO,MAAM,yCAAyC;AACtD,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,UAAM,MAAM,uBAAuB;AAAA,EACrC;AAEA,UAAQ,KAAK;AAAA,IACX,KAAK,OAAO;AACV,UAAI,MAAM,KAAK,CAAC;AAChB,UAAI,CAAC,KAAK;AACR,YAAI,CAAC,aAAa;AAChB,iBAAO,MAAM,oCAAoC;AACjD,kBAAQ,KAAK,CAAC;AAAA,QAChB;AACA,cAAM,MAAM,gBAAgB,8DAAY;AAAA,MAC1C;AAEA,UAAI,CAAC,YAAY,GAAG,GAAG;AACrB,eAAO,MAAM,uBAAuB,GAAG,EAAE;AACzC,eAAO,MAAM,eAAe,WAAW,KAAK,IAAI,CAAC,EAAE;AACnD,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,YAAM,SAAS,WAAW;AAC1B,UAAI,CAAC,UAAU,EAAE,OAAO,SAAS;AAC/B,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,YAAM,SAAS;AACf,cAAQ,IAAI,OAAO,GAAG,KAAK,EAAE;AAC7B;AAAA,IACF;AAAA,IACA,KAAK,OAAO;AACV,UAAI,MAAM,KAAK,CAAC;AAChB,UAAI,CAAC,KAAK;AACR,YAAI,CAAC,aAAa;AAChB,iBAAO,MAAM,4CAA4C;AACzD,kBAAQ,KAAK,CAAC;AAAA,QAChB;AACA,cAAM,MAAM,gBAAgB,8DAAY;AAAA,MAC1C;AAEA,UAAI,CAAC,YAAY,GAAG,GAAG;AACrB,eAAO,MAAM,uBAAuB,GAAG,EAAE;AACzC,eAAO,MAAM,eAAe,WAAW,KAAK,IAAI,CAAC,EAAE;AACnD,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,YAAM,SAAS,WAAW,KAAK;AAAA,QAC7B,QAAQ;AAAA,QACR,QAAQ,iBAAiB;AAAA,MAC3B;AACA,YAAM,SAAS;AAEf,UAAI,QAAQ,KAAK,CAAC;AAClB,UAAI,UAAU,QAAW;AACvB,YAAI,CAAC,aAAa;AAChB,iBAAO,MAAM,4CAA4C;AACzD,kBAAQ,KAAK,CAAC;AAAA,QAChB;AACA,gBAAQ,MAAM,kBAAkB,KAAK,OAAO,GAAG,CAAC;AAAA,MAClD;AAEA,UAAI,aAA8B;AAClC,UAAI,QAAQ,YAAY,CAAC,eAAe,KAAK,GAAG;AAC9C,eAAO,MAAM,+BAA+B;AAC5C,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,UAAI,QAAQ,UAAU;AACpB,YAAI;AACF,gBAAM,MAAM,IAAI,IAAI,KAAK;AACzB,uBAAa,IAAI,SAAS,EAAE,QAAQ,OAAO,EAAE;AAAA,QAC/C,QAAQ;AACN,iBAAO,MAAM,4BAA4B;AACzC,kBAAQ,KAAK,CAAC;AAAA,QAChB;AAAA,MACF;AAEA,UAAI,QAAQ,gBAAgB;AAC1B,qBAAa,OAAO,SAAS,OAAO,EAAE;AACtC,YAAI,OAAO,MAAM,UAAU,KAAK,cAAc,GAAG;AAC/C,iBAAO,MAAM,uDAAuD;AACpE,kBAAQ,KAAK,CAAC;AAAA,QAChB;AAAA,MACF;AAEA,aAAO,GAAG,IAAI;AACd,iBAAW,MAAM;AAEjB,UAAI,aAAa;AACf,eAAO,KAAK,aAAa,gCAAO,CAAC;AACjC,eAAO,KAAK,eAAe,KAAK,kBAAkB,KAAK,UAAU,CAAC,CAAC;AAAA,MACrE,OAAO;AACL,eAAO,KAAK,OAAO,GAAG,MAAM,UAAU,EAAE;AAAA,MAC1C;AACA;AAAA,IACF;AAAA,IACA,KAAK,QAAQ;AACX,UAAI,aAAa;AACf,wBAAgB;AAAA,MAClB,OAAO;AACL,cAAM,SAAS,WAAW;AAC1B,gBAAQ,IAAI,SAAS,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,IAAI;AAAA,MAC7D;AACA;AAAA,IACF;AAAA,IACA;AACE,aAAO,MAAM,8BAA8B,OAAO,QAAQ,EAAE;AAC5D,aAAO,MAAM,yCAAyC;AACtD,cAAQ,KAAK,CAAC;AAAA,EAClB;AACF;;;AC1WA,SAAS,YAAAE,iBAAgB;;;ACAzB,SAAS,kBAAkB;AAEpB,SAAS,kBAAkBC,QAI/B;AACD,MAAIA,OAAM,SAAS,YAAY;AAC7B,WAAO,EAAE,YAAY,WAAW,cAAc,kBAAkB;AAAA,EAClE;AAEA,MAAIA,OAAM,SAAS,OAAO;AACxB,WAAO,EAAE,YAAYA,OAAM,SAAS,cAAcA,OAAM,QAAQ;AAAA,EAClE;AAEA,QAAM,aAAa,WAAW,UAAUA,OAAM,IAAI,EAC/C,OAAOA,OAAM,OAAO,EACpB,OAAO,KAAK,EACZ,MAAM,GAAG,EAAE;AAEd,SAAO;AAAA,IACL;AAAA,IACA,cAAc,WAAW,WAAW,MAAM,GAAG,CAAC,CAAC;AAAA,EACjD;AACF;;;ACxBA,SAAS,cAAAC,mBAAkB;AAO3B,IAAM,mBAAmB;AACzB,IAAM,4BAA4B;AAIlC,SAAS,YAAY,OAAuB;AAC1C,SAAOA,YAAW,QAAQ,EAAE,OAAO,KAAK,EAAE,OAAO,KAAK,EAAE,MAAM,GAAG,EAAE;AACrE;AAEA,SAAS,gBAAgB,QAAwB;AAC/C,MAAI,MAAM,OAAO;AACjB,SAAO,MAAM,KAAK,OAAO,MAAM,CAAC,MAAM,IAAK;AAC3C,SAAO,OAAO,MAAM,GAAG,GAAG,KAAK;AACjC;AAoCO,SAAS,yBAAyBC,QAKjB;AACtB,SAAO;AAAA,IACL,YAAY,YAAYA,OAAM,MAAM;AAAA,IACpC,QAAQ,gBAAgBA,OAAM,MAAM;AAAA,IACpC,UAAUA,OAAM;AAAA,IAChB,qBAAqB,YAAYA,OAAM,SAAS,eAAe;AAAA,IAC/D,aAAaA,OAAM,SAAS;AAAA,IAC5B,yBAAyB;AAAA,EAC3B;AACF;AAEO,SAAS,mCACd,UACA,SAC6B;AAC7B,QAAM,UAAuC,CAAC;AAE9C,MACE,SAAS,WAAW,QAAQ,UAC5B,SAAS,eAAe,QAAQ,YAChC;AACA,YAAQ,KAAK,mBAAmB;AAAA,EAClC;AAEA,MAAI,SAAS,aAAa,QAAQ,UAAU;AAC1C,YAAQ,KAAK,WAAW;AAAA,EAC1B;AAEA,MACE,SAAS,gBAAgB,QAAQ,eACjC,SAAS,wBAAwB,QAAQ,qBACzC;AACA,YAAQ,KAAK,kBAAkB;AAAA,EACjC;AAEA,MAAI,SAAS,4BAA4B,QAAQ,yBAAyB;AACxE,YAAQ,KAAK,mBAAmB;AAAA,EAClC;AAEA,SAAO;AACT;AAEO,SAAS,2BAA2B,QAAmC;AAC5E,SAAO;AAAA,IACL,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,EACT,EAAE,KAAK,GAAG;AACZ;AAEO,SAAS,4BACd,SACQ;AACR,SAAO,CAAC,QAAQ,UAAU,QAAQ,QAAQ,QAAQ,WAAW,EAAE,KAAK,GAAG;AACzE;AAEA,SAAS,2BAA2B,QAAmC;AACrE,SAAO;AAAA,IACL,KAAK,UAAU;AAAA,MACb,cAAc,OAAO;AAAA,MACrB,UAAU,OAAO;AAAA,MACjB,aAAa,OAAO;AAAA,MACpB,cAAc,OAAO;AAAA,MACrB,cAAc,OAAO;AAAA,MACrB,iBAAiB,OAAO;AAAA,MACxB,aAAa,OAAO;AAAA,IACtB,CAAC;AAAA,EACH;AACF;AAEA,SAAS,4BAA4B,SAAwC;AAC3E,SAAO;AAAA,IACL,KAAK,UAAU;AAAA,MACb,eAAe,QAAQ;AAAA,MACvB,cAAc,QAAQ;AAAA,MACtB,iBAAiB,QAAQ;AAAA,MACzB,gBAAgB,QAAQ;AAAA,MACxB,UAAU,QAAQ;AAAA,MAClB,aAAa,QAAQ;AAAA,MACrB,eAAe,QAAQ;AAAA,MACvB,cAAc,QAAQ;AAAA,MACtB,aAAa,QAAQ;AAAA,MACrB,cAAc,QAAQ;AAAA,MACtB,cAAc,QAAQ;AAAA,MACtB,YAAY,QAAQ;AAAA,MACpB,cAAc,QAAQ;AAAA,MACtB,iBAAiB,QAAQ;AAAA,MACzB,aAAa,QAAQ;AAAA,MACrB,kBAAkB,QAAQ;AAAA,IAC5B,CAAC;AAAA,EACH;AACF;AAEA,SAAS,kBACP,OACA,QACA,SACwB;AACxB,QAAM,SAAiC,CAAC;AAExC,aAAW,QAAQ,OAAO;AACxB,WAAO,OAAO,IAAI,CAAC,IAAI,QAAQ,IAAI;AAAA,EACrC;AAEA,SAAO;AACT;AAEO,SAAS,qBAAqBA,QAKlB;AACjB,SAAO;AAAA,IACL,SAAS;AAAA,MACPA,OAAM;AAAA,MACN;AAAA,MACA;AAAA,IACF;AAAA,IACA,OAAOA,OAAM;AAAA,IACb,UAAU;AAAA,MACRA,OAAM;AAAA,MACN;AAAA,MACA;AAAA,IACF;AAAA,IACA,WAAWA,OAAM,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,IACrD,SAAS;AAAA,EACX;AACF;AAEA,SAAS,oBACP,UACA,SACQ;AACR,MAAI,UAAU;AAEd,aAAW,OAAO,OAAO,KAAK,QAAQ,GAAG;AACvC,QAAI,EAAE,OAAO,UAAU;AACrB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,mBAAmBA,QAMZ;AACrB,QAAM,eAAe,qBAAqB;AAAA,IACxC,SAASA,OAAM;AAAA,IACf,OAAOA,OAAM;AAAA,IACb,UAAUA,OAAM;AAAA,IAChB,WAAWA,OAAM;AAAA,EACnB,CAAC;AAED,QAAM,sBAAsBA,OAAM,WAC9B,mCAAmCA,OAAM,SAAS,OAAOA,OAAM,KAAK,IACpE,CAAC;AAEL,QAAM,kBACJA,OAAM,YAAY,oBAAoB,WAAW,IAC7CA,OAAM,SAAS,UACf,CAAC;AACP,QAAM,mBACJA,OAAM,YAAY,oBAAoB,WAAW,IAC7CA,OAAM,SAAS,WACf,CAAC;AAEP,QAAM,kBAAkBA,OAAM,QAAQ,OAAO,CAAC,WAAW;AACvD,UAAM,MAAM,2BAA2B,MAAM;AAC7C,WAAO,gBAAgB,GAAG,MAAM,aAAa,QAAQ,GAAG;AAAA,EAC1D,CAAC;AACD,QAAM,mBAAmBA,OAAM,SAAS,OAAO,CAAC,YAAY;AAC1D,UAAM,MAAM,4BAA4B,OAAO;AAC/C,WAAO,iBAAiB,GAAG,MAAM,aAAa,SAAS,GAAG;AAAA,EAC5D,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,gBAAgB,oBAAoB,iBAAiB,aAAa,OAAO;AAAA,IACzE,iBAAiB;AAAA,MACf;AAAA,MACA,aAAa;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA,kBAAkBA,OAAM,QAAQ,SAAS,gBAAgB;AAAA,IACzD,mBAAmBA,OAAM,SAAS,SAAS,iBAAiB;AAAA,EAC9D;AACF;;;ACjQA,OAAO,UAAU;AACjB,OAAO,WAAW;AAClB,SAAS,OAAAC,YAAW;AASpB,IAAM,cAAc;AACpB,IAAM,gBAAgB;AACtB,IAAM,aAAa;AAEZ,SAAS,qBACd,QACA,SACA,UACQ;AACR,QAAM,UAAU;AAAA,IACd,eAAe;AAAA,IACf;AAAA,IACA;AAAA,IACA,UAAU,YAAY,CAAC;AAAA,EACzB;AAEA,SAAO,OAAO,WAAW,KAAK,UAAU,OAAO,CAAC;AAClD;AAEO,IAAM,YAAN,MAAgB;AAAA,EACrB,YACU,QACA,QACR;AAFQ;AACA;AAAA,EACP;AAAA,EAFO;AAAA,EACA;AAAA;AAAA;AAAA;AAAA,EAMV,MAAM,OACJ,QACA,SACA,UACA,YACmD;AACnD,QAAI;AACJ,aAAS,UAAU,GAAG,UAAU,aAAa,WAAW;AACtD,UAAI;AACF,eAAO,MAAM,KAAK,WAAW,QAAQ,SAAS,UAAU,UAAU;AAAA,MACpE,SAAS,KAAK;AACZ,oBAAY;AACZ,cAAM,UAAU;AAEhB,YACE,QAAQ,YAAY,kBACnB,QAAQ,cACP,QAAQ,cAAc,OACtB,QAAQ,aAAa,KACvB;AACA,gBAAM;AAAA,QACR;AACA,YAAI,UAAU,cAAc,GAAG;AAC7B,gBAAM,QAAQ,gBAAgB,KAAK;AACnC,gBAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,KAAK,CAAC;AAAA,QAC/C;AAAA,MACF;AAAA,IACF;AACA,UAAM;AAAA,EACR;AAAA,EAEQ,WACN,QACA,SACA,UACA,YACmD;AACnD,WAAO,IAAI,QAAQ,CAACC,UAAS,WAAW;AACtC,YAAM,MAAM,IAAID,KAAI,qBAAqB,KAAK,MAAM;AACpD,YAAM,OAAO,OAAO;AAAA,QAClB,KAAK,UAAU;AAAA,UACb,eAAe;AAAA,UACf;AAAA,UACA;AAAA,UACA,UAAU,YAAY,CAAC;AAAA,QACzB,CAAC;AAAA,MACH;AACA,YAAM,aAAa,KAAK;AACxB,YAAM,MAAM,IAAI,aAAa,WAAW,QAAQ;AAEhD,YAAM,MAAM,IAAI;AAAA,QACd;AAAA,QACA;AAAA,UACE,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,SAAS;AAAA,YACP,gBAAgB;AAAA,YAChB,eAAe,UAAU,KAAK,MAAM;AAAA,YACpC,kBAAkB;AAAA,UACpB;AAAA,QACF;AAAA,QACA,CAAC,QAAQ;AACP,cAAI,OAAO;AACX,cAAI,GAAG,QAAQ,CAAC,UAAU;AACxB,oBAAQ;AAAA,UACV,CAAC;AACD,cAAI,GAAG,OAAO,MAAM;AAClB,gBAAI,IAAI,eAAe,KAAK;AAC1B,qBAAO,IAAI,MAAM,cAAc,CAAC;AAChC;AAAA,YACF;AACA,gBACE,CAAC,IAAI,cACL,IAAI,aAAa,OACjB,IAAI,cAAc,KAClB;AACA,oBAAM,MAAM,IAAI;AAAA,gBACd,QAAQ,IAAI,UAAU,KAAK,IAAI;AAAA,cACjC;AAGA,kBAAI,aAAa,IAAI;AACrB,qBAAO,GAAG;AACV;AAAA,YACF;AACA,gBAAI;AACF,oBAAM,WAAW,KAAK,MAAM,IAAI;AAChC,cAAAC,SAAQ;AAAA,gBACN,UAAU,SAAS,eAAe,SAAS;AAAA,gBAC3C,UAAU,SAAS,gBAAgB,SAAS;AAAA,cAC9C,CAAC;AAAA,YACH,QAAQ;AACN,qBAAO,IAAI,MAAM,0BAA0B,IAAI,EAAE,CAAC;AAAA,YACpD;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAEA,UAAI,GAAG,SAAS,CAAC,QAAQ,OAAO,GAAG,CAAC;AACpC,UAAI,GAAG,WAAW,MAAM;AACtB,YAAI,QAAQ;AACZ,eAAO,IAAI,MAAM,yBAAyB,CAAC;AAAA,MAC7C,CAAC;AAGD,YAAM,QAAQ,KAAK;AACnB,UAAI,OAAO;AAEX,YAAM,YAAY,MAAM;AACtB,YAAI,KAAK;AACT,eAAO,MAAM,OAAO,YAAY;AAC9B,gBAAM,QAAQ,KAAK,SAAS,MAAM,OAAO,KAAK;AAC9C,kBAAQ,MAAM;AACd,cAAI,WAAY,YAAW,MAAM,UAAU;AAC3C,eAAK,IAAI,MAAM,KAAK;AAAA,QACtB;AACA,YAAI,OAAO,YAAY;AACrB,cAAI,KAAK,SAAS,SAAS;AAAA,QAC7B,OAAO;AACL,cAAI,IAAI;AAAA,QACV;AAAA,MACF;AAEA,gBAAU;AAAA,IACZ,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAA6C;AACjD,WAAO,IAAI,QAAQ,CAACA,UAAS,WAAW;AACtC,YAAM,MAAM,IAAID,KAAI,uBAAuB,KAAK,MAAM;AACtD,YAAM,MAAM,IAAI,aAAa,WAAW,QAAQ;AAEhD,YAAM,MAAM,IAAI;AAAA,QACd;AAAA,QACA;AAAA,UACE,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,SAAS;AAAA,YACP,eAAe,UAAU,KAAK,MAAM;AAAA,UACtC;AAAA,QACF;AAAA,QACA,CAAC,QAAQ;AACP,cAAI,OAAO;AACX,cAAI,GAAG,QAAQ,CAAC,UAAU;AACxB,oBAAQ;AAAA,UACV,CAAC;AACD,cAAI,GAAG,OAAO,MAAM;AAClB,gBAAI,IAAI,eAAe,KAAK;AAC1B,qBAAO,IAAI,MAAM,cAAc,CAAC;AAChC;AAAA,YACF;AACA,gBACE,CAAC,IAAI,cACL,IAAI,aAAa,OACjB,IAAI,cAAc,KAClB;AACA,cAAAC,SAAQ,IAAI;AACZ;AAAA,YACF;AACA,gBAAI;AACF,oBAAM,WAAW,KAAK,MAAM,IAAI;AAChC,kBACE,SAAS,kBAAkB,KAC3B,CAAC,SAAS,eACV,CAAC,SAAS,mBACV,CAAC,SAAS,UACV;AACA,gBAAAA,SAAQ,IAAI;AACZ;AAAA,cACF;AAEA,cAAAA,SAAQ,QAAQ;AAAA,YAClB,QAAQ;AACN,cAAAA,SAAQ,IAAI;AAAA,YACd;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAEA,UAAI,GAAG,SAAS,MAAMA,SAAQ,IAAI,CAAC;AACnC,UAAI,GAAG,WAAW,MAAM;AACtB,YAAI,QAAQ;AACZ,QAAAA,SAAQ,IAAI;AAAA,MACd,CAAC;AACD,UAAI,IAAI;AAAA,IACV,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,iBAAiB,UAGpB;AACD,WAAO,IAAI,QAAQ,CAACA,UAAS,WAAW;AACtC,YAAM,MAAM,IAAID,KAAI,qBAAqB,KAAK,MAAM;AACpD,UAAI,aAAa,IAAI,YAAY,QAAQ;AACzC,YAAM,MAAM,IAAI,aAAa,WAAW,QAAQ;AAEhD,YAAM,MAAM,IAAI;AAAA,QACd;AAAA,QACA;AAAA,UACE,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,SAAS;AAAA,YACP,eAAe,UAAU,KAAK,MAAM;AAAA,UACtC;AAAA,QACF;AAAA,QACA,CAAC,QAAQ;AACP,cAAI,OAAO;AACX,cAAI,GAAG,QAAQ,CAAC,UAAU;AACxB,oBAAQ;AAAA,UACV,CAAC;AACD,cAAI,GAAG,OAAO,MAAM;AAClB,gBAAI,IAAI,eAAe,KAAK;AAC1B,qBAAO,IAAI,MAAM,cAAc,CAAC;AAChC;AAAA,YACF;AACA,gBACE,CAAC,IAAI,cACL,IAAI,aAAa,OACjB,IAAI,cAAc,KAClB;AACA,oBAAM,MAAM,IAAI;AAAA,gBACd,QAAQ,IAAI,UAAU,KAAK,IAAI;AAAA,cACjC;AAGA,kBAAI,aAAa,IAAI;AACrB,qBAAO,GAAG;AACV;AAAA,YACF;AACA,gBAAI;AACF,cAAAC,SAAQ,KAAK,MAAM,IAAI,CAAC;AAAA,YAC1B,QAAQ;AACN,qBAAO,IAAI,MAAM,0BAA0B,IAAI,EAAE,CAAC;AAAA,YACpD;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAEA,UAAI,GAAG,SAAS,CAAC,QAAQ,OAAO,GAAG,CAAC;AACpC,UAAI,GAAG,WAAW,MAAM;AACtB,YAAI,QAAQ;AACZ,eAAO,IAAI,MAAM,yBAAyB,CAAC;AAAA,MAC7C,CAAC;AACD,UAAI,IAAI;AAAA,IACV,CAAC;AAAA,EACH;AACF;;;ACjSA;AAAA,EACE;AAAA,EACA,cAAAC;AAAA,EACA;AAAA,EACA,gBAAAC;AAAA,EACA,UAAAC;AAAA,EACA,iBAAAC;AAAA,OACK;;;ACPP,SAAS,aAAAC,kBAAiB;AAC1B,SAAS,QAAAC,cAAY;AAGrB,IAAM,WAAW;AAOV,SAAS,oBAA4B;AAC1C,SAAOC,OAAK,cAAc,GAAG,QAAQ;AACvC;AAEO,SAAS,cAAsB;AACpC,SAAOA,OAAK,aAAa,GAAG,QAAQ;AACtC;AAEO,SAAS,kBAA0B;AACxC,SAAOA,OAAK,kBAAkB,GAAG,WAAW;AAC9C;AAEO,SAAS,mBAA2B;AACzC,SAAOA,OAAK,YAAY,GAAG,aAAa;AAC1C;AAEO,SAAS,wBAAgC;AAC9C,SAAOA,OAAK,YAAY,GAAG,sBAAsB;AACnD;AAEO,SAAS,gBAAsB;AACpC,EAAAC,WAAU,kBAAkB,GAAG,EAAE,WAAW,KAAK,CAAC;AAClD,EAAAA,WAAU,YAAY,GAAG,EAAE,WAAW,KAAK,CAAC;AAC9C;;;ADbA,SAAS,eAAe,KAAsB;AAC5C,MAAI;AACF,YAAQ,KAAK,KAAK,CAAC;AACnB,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,OAAQ,MAAgC;AAC9C,WAAO,SAAS;AAAA,EAClB;AACF;AAEA,SAAS,iBAAiB,UAAuC;AAC/D,MAAI,CAACC,aAAW,QAAQ,GAAG;AACzB,WAAO;AAAA,EACT;AAEA,MAAI;AACF,WAAO,KAAK,MAAMC,eAAa,UAAU,OAAO,CAAC;AAAA,EACnD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,gBAAgB,UAAwB;AAC/C,QAAM,WAAW,iBAAiB,QAAQ;AAC1C,MAAI,CAAC,UAAU;AACb,IAAAC,QAAO,UAAU,EAAE,OAAO,KAAK,CAAC;AAChC;AAAA,EACF;AAEA,MAAI,CAAC,eAAe,SAAS,GAAG,GAAG;AACjC,IAAAA,QAAO,UAAU,EAAE,OAAO,KAAK,CAAC;AAAA,EAClC;AACF;AAEO,SAAS,mBAAmB,QAAqC;AACtE,gBAAc;AACd,QAAM,WAAW,gBAAgB;AAEjC,MAAI;AACF,UAAM,KAAK,SAAS,UAAU,IAAI;AAClC,UAAM,WAAyB;AAAA,MAC7B,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MAClC,KAAK,QAAQ;AAAA,MACb;AAAA,IACF;AACA,IAAAC,eAAc,IAAI,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AACnD,cAAU,EAAE;AAEZ,WAAO;AAAA,MACL,UAAU;AACR,QAAAD,QAAO,UAAU,EAAE,OAAO,KAAK,CAAC;AAAA,MAClC;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,UAAM,OAAQ,MAAgC;AAC9C,QAAI,SAAS,UAAU;AACrB,YAAM;AAAA,IACR;AAAA,EACF;AAEA,kBAAgB,QAAQ;AAExB,MAAI;AACF,UAAM,KAAK,SAAS,UAAU,IAAI;AAClC,UAAM,WAAyB;AAAA,MAC7B,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MAClC,KAAK,QAAQ;AAAA,MACb;AAAA,IACF;AACA,IAAAC,eAAc,IAAI,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AACnD,cAAU,EAAE;AAEZ,WAAO;AAAA,MACL,UAAU;AACR,QAAAD,QAAO,UAAU,EAAE,OAAO,KAAK,CAAC;AAAA,MAClC;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,UAAM,OAAQ,MAAgC;AAC9C,QAAI,SAAS,UAAU;AACrB,aAAO;AAAA,IACT;AACA,UAAM;AAAA,EACR;AACF;AAEO,SAAS,2BAA0C;AACxD,QAAM,WAAW,iBAAiB,gBAAgB,CAAC;AACnD,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AAEA,SAAO,OAAO,SAAS,GAAG,YAAY,SAAS,MAAM,eAAe,SAAS,SAAS;AACxF;;;AElHA,SAAS,cAAAE,cAAY,gBAAAC,gBAAc,iBAAAC,sBAAqB;AA2BxD,SAAS,kBAA6B;AACpC,SAAO,EAAE,QAAQ,OAAO;AAC1B;AAEO,SAAS,gBAA2B;AACzC,QAAM,OAAO,iBAAiB;AAC9B,MAAI,CAACC,aAAW,IAAI,GAAG;AACrB,WAAO,gBAAgB;AAAA,EACzB;AAEA,MAAI;AACF,WAAO;AAAA,MACL,GAAG,gBAAgB;AAAA,MACnB,GAAI,KAAK,MAAMC,eAAa,MAAM,OAAO,CAAC;AAAA,IAC5C;AAAA,EACF,QAAQ;AACN,WAAO,gBAAgB;AAAA,EACzB;AACF;AAEO,SAAS,cAAc,MAAuB;AACnD,gBAAc;AACd,EAAAC;AAAA,IACE,iBAAiB;AAAA,IACjB,GAAG,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAAA;AAAA,IAChC;AAAA,EACF;AACF;AAEO,SAAS,gBAAgB,QAA0B;AACxD,QAAM,UAAU,cAAc;AAC9B,gBAAc;AAAA,IACZ,GAAG;AAAA,IACH,KAAK,QAAQ;AAAA,IACb,gBAAe,oBAAI,KAAK,GAAE,YAAY;AAAA,IACtC,YAAY;AAAA,IACZ,QAAQ;AAAA,EACV,CAAC;AACH;AAEO,SAAS,kBACd,QACA,QACM;AACN,QAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,QAAM,UAAU,cAAc;AAC9B,gBAAc;AAAA,IACZ,GAAG;AAAA,IACH,iBAAiB;AAAA,IACjB,WAAW;AAAA,IACX,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,KAAK;AAAA,IACL,QAAQ;AAAA,EACV,CAAC;AACH;AAEO,SAAS,eACd,QACA,OACA,QACM;AACN,QAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,QAAM,UAAU,cAAc;AAC9B,gBAAc;AAAA,IACZ,GAAG;AAAA,IACH,iBAAiB;AAAA,IACjB,WAAW;AAAA,IACX,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,KAAK;AAAA,IACL;AAAA,EACF,CAAC;AACH;;;ACtGA,SAAS,cAAAC,cAAY,gBAAAC,gBAAc,iBAAAC,sBAAqB;AAOxD,SAAS,kBAAkB,OAAiD;AAC1E,MAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;AAC/D,WAAO;AAAA,EACT;AAEA,SAAO,OAAO,OAAO,KAAK,EAAE,MAAM,CAAC,UAAU,OAAO,UAAU,QAAQ;AACxE;AAQA,SAAS,iBAAiB,OAA+C;AACvE,MAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;AAC/D,WAAO;AAAA,EACT;AAEA,QAAM,WAAW;AAEjB,SACE,SAAS,YAAY,KACrB,CAAC,CAAC,SAAS,SACX,OAAO,SAAS,UAAU,YAC1B,OAAO,SAAS,MAAM,WAAW,YACjC,OAAO,SAAS,MAAM,eAAe,YACrC,OAAO,SAAS,MAAM,aAAa,YACnC,OAAO,SAAS,MAAM,gBAAgB,YACtC,OAAO,SAAS,MAAM,wBAAwB,aAC7C,SAAS,MAAM,4BAA4B,UAC1C,OAAO,SAAS,MAAM,4BAA4B,aACpD,OAAO,SAAS,cAAc,YAC9B,kBAAkB,SAAS,OAAO,KAClC,kBAAkB,SAAS,QAAQ;AAEvC;AAEO,SAAS,qBAA4C;AAC1D,QAAM,OAAO,sBAAsB;AACnC,MAAI,CAACC,aAAW,IAAI,GAAG;AACrB,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,SAAS,KAAK,MAAMC,eAAa,MAAM,OAAO,CAAC;AACrD,QAAI,CAAC,iBAAiB,MAAM,GAAG;AAC7B,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,MACL,GAAG;AAAA,MACH,OAAO;AAAA,QACL,GAAG,OAAO;AAAA,QACV,yBAAyB,OAAO,MAAM,2BAA2B;AAAA,MACnE;AAAA,IACF;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,mBAAmB,UAAgC;AACjE,gBAAc;AACd,EAAAC;AAAA,IACE,sBAAsB;AAAA,IACtB,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAAA;AAAA,IACpC;AAAA,EACF;AACF;;;ACrDA,eAAsB,gBAA2C;AAC/D,QAAM,aAA4B,CAAC;AACnC,QAAM,cAAiC,CAAC;AACxC,QAAM,gBAAgC,CAAC;AAEvC,aAAW,UAAU,cAAc,GAAG;AACpC,QAAI;AACF,YAAM,SAAsB,MAAM,OAAO,MAAM;AAC/C,YAAM,UAAU,OAAO;AACvB,YAAM,WAAW,OAAO;AAExB,UAAI,QAAQ,SAAS,EAAG,YAAW,KAAK,GAAG,OAAO;AAClD,UAAI,SAAS,SAAS,EAAG,aAAY,KAAK,GAAG,QAAQ;AAErD,UAAI,QAAQ,SAAS,KAAK,SAAS,SAAS,GAAG;AAC7C,sBAAc,KAAK;AAAA,UACjB,QAAQ,OAAO,KAAK;AAAA,UACpB,SAAS,QAAQ;AAAA,UACjB,UAAU,SAAS;AAAA,QACrB,CAAC;AAAA,MACH;AAAA,IACF,SAAS,KAAK;AACZ,aAAO,KAAK,GAAG,OAAO,KAAK,EAAE,mBAAoB,IAAc,OAAO,EAAE;AAAA,IAC1E;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,YAAY,UAAU,aAAa,cAAc;AACrE;AAKO,SAAS,mBAAmB;AACjC,SAAO,qBAAqB;AAC9B;;;ARnBA,IAAM,aAAa;AACnB,IAAM,qBAAqB;AAC3B,IAAM,qBAAqB;AAEpB,SAAS,YAAY,OAAuB;AACjD,MAAI,QAAQ,KAAM,QAAO,GAAG,KAAK;AACjC,MAAI,QAAQ,OAAO,KAAM,QAAO,IAAI,QAAQ,MAAM,QAAQ,CAAC,CAAC;AAC5D,SAAO,IAAI,SAAS,OAAO,OAAO,QAAQ,CAAC,CAAC;AAC9C;AAEO,SAAS,kBAAkB,UAA0B;AAC1D,QAAM,eAAe,KAAK,IAAI,GAAG,KAAK,IAAI,UAAU,CAAC,CAAC;AACtD,QAAM,SAAS,KAAK,MAAM,eAAe,kBAAkB;AAC3D,SAAO,GAAG,SAAI,OAAO,MAAM,CAAC,GAAG,SAAI,OAAO,qBAAqB,MAAM,CAAC;AACxE;AAEA,SAAS,oBACP,MACA,OACA,UACA,cACM;AACN,QAAM,MAAM,QAAQ,IAAI,KAAK,MAAO,OAAO,QAAS,GAAG,IAAI;AAC3D,QAAM,cAAc,kBAAkB,QAAQ,IAAI,OAAO,QAAQ,CAAC;AAClE,QAAM,aACJ,eAAe,IAAI,eAAY,QAAQ,IAAI,YAAY,KAAK;AAE9D,UAAQ,OAAO;AAAA,IACb,iBAAiB,WAAW,IAAI,OAAO,GAAG,EAAE,SAAS,GAAG,GAAG,CAAC,UAAO,YAAY,IAAI,CAAC,IAAI,YAAY,KAAK,CAAC,GAAG,UAAU;AAAA,EACzH;AACF;AAEA,SAAS,wBAAwB,QAA2C;AAC1E,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,EACX;AACF;AAEO,SAAS,6BAA6BC,QAG3B;AAChB,MAAI,CAACA,OAAM,UAAU;AACnB,WAAO;AAAA,EACT;AAEA,MAAIA,OAAM,oBAAoB,SAAS,mBAAmB,GAAG;AAC3D,WAAO;AAAA,EACT;AAEA,MACEA,OAAM,oBAAoB,SAAS,kBAAkB,KACrDA,OAAM,oBAAoB,SAAS,mBAAmB,GACtD;AACA,WAAOA,OAAM,SAAS,MAAM;AAAA,EAC9B;AAEA,SAAO;AACT;AAEA,SAAS,sBAAsB,UAA0B,OAAsB;AAC7E,MAAI;AACF,uBAAmB,QAAQ;AAAA,EAC7B,SAAS,OAAO;AACd,QAAI,CAAC,OAAO;AACV,aAAO;AAAA,QACL,gEAAiE,MAAgB,OAAO;AAAA,MAC1F;AAAA,IACF;AAAA,EACF;AACF;AAcA,SAAS,iBAAiB,QAAgC;AACxD,SAAO;AAAA,IACL,UAAU,oBAAoB,MAAM;AAAA,IACpC,UAAUC,UAAS,EAAE,QAAQ,YAAY,EAAE;AAAA,EAC7C;AACF;AAEO,SAAS,gBACd,SACA,UACA,QACqB;AACrB,QAAM,aAAa,oBAAI,IAA+B;AAEtD,aAAW,UAAU,SAAS;AAC5B,UAAM,UAAU,kBAAkB;AAAA,MAChC,SAAS,OAAO,WAAW;AAAA,MAC3B,MAAM,SAAS;AAAA,MACf,MAAM,SAAS;AAAA,IACjB,CAAC;AACD,UAAM,MAAM;AAAA,MACV,OAAO;AAAA,MACP,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,OAAO;AAAA,IACT,EAAE,KAAK,GAAG;AAEV,UAAM,WAAW,WAAW,IAAI,GAAG;AACnC,QAAI,UAAU;AACZ,eAAS,eAAe,OAAO;AAC/B,eAAS,gBAAgB,OAAO;AAChC,eAAS,mBAAmB,OAAO,mBAAmB;AACtD,eAAS,gBAAgB,OAAO,gBAAgB;AAChD,eAAS,eAAe,OAAO;AAC/B;AAAA,IACF;AAEA,eAAW,IAAI,KAAK;AAAA,MAClB,QAAQ,OAAO;AAAA,MACf,OAAO,OAAO;AAAA,MACd,YAAY,QAAQ;AAAA,MACpB,cAAc,QAAQ;AAAA,MACtB,aAAa,OAAO;AAAA,MACpB,UAAU,OAAO;AAAA,MACjB,UAAU,OAAO;AAAA,MACjB,aAAa,OAAO;AAAA,MACpB,cAAc,OAAO;AAAA,MACrB,iBAAiB,OAAO,mBAAmB;AAAA,MAC3C,cAAc,OAAO,gBAAgB;AAAA,MACrC,aAAa,OAAO;AAAA,IACtB,CAAC;AAAA,EACH;AAEA,SAAO,MAAM,KAAK,WAAW,OAAO,CAAC;AACvC;AAEO,SAAS,iBACd,UACA,UACA,QACyB;AACzB,SAAO,SAAS,IAAI,CAAC,YAAY;AAC/B,UAAM,UAAU,kBAAkB;AAAA,MAChC,SAAS,QAAQ,WAAW;AAAA,MAC5B,MAAM,SAAS;AAAA,MACf,MAAM,SAAS;AAAA,IACjB,CAAC;AAED,WAAO;AAAA,MACL,QAAQ,QAAQ;AAAA,MAChB,YAAY,QAAQ;AAAA,MACpB,cAAc,QAAQ;AAAA,MACtB,aAAa,QAAQ;AAAA,MACrB,UAAU,OAAO;AAAA,MACjB,UAAU,OAAO;AAAA,MACjB,gBAAgB,QAAQ;AAAA,MACxB,eAAe,QAAQ;AAAA,MACvB,iBAAiB,QAAQ;AAAA,MACzB,eAAe,QAAQ;AAAA,MACvB,cAAc,QAAQ;AAAA,MACtB,kBAAkB,QAAQ;AAAA,MAC1B,aAAa,QAAQ;AAAA,MACrB,cAAc,QAAQ;AAAA,MACtB,iBAAiB,QAAQ;AAAA,MACzB,cAAc,QAAQ;AAAA,MACtB,aAAa,QAAQ;AAAA,MACrB,cAAc,QAAQ;AAAA,MACtB,aAAa,QAAQ;AAAA,IACvB;AAAA,EACF,CAAC;AACH;AAEA,IAAM,cAAN,cAA0B,MAAM;AAAA,EAC9B,YACE,SACS,MACA,YACT;AACA,UAAM,OAAO;AAHJ;AACA;AAAA,EAGX;AAAA,EAJW;AAAA,EACA;AAIb;AAEA,eAAsB,QACpB,QACA,OAAoB,CAAC,GACA;AACrB,QAAM,EAAE,QAAQ,OAAO,SAAS,UAAU,SAAS,MAAM,IAAI;AAE7D,QAAM,OAAO,mBAAmB,MAAM;AACtC,MAAI,CAAC,MAAM;AACT,UAAM,SAAS,yBAAyB;AACxC,UAAM,UAAU,SACZ,oCAAoC,MAAM,iBAC1C;AAEJ,mBAAe,QAAQ,SAAS,gBAAgB;AAChD,WAAO,KAAK,OAAO;AACnB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,UAAU;AAAA,MACV,SAAS;AAAA,IACX;AAAA,EACF;AAEA,kBAAgB,MAAM;AAEtB,MAAI,gBAAgB;AACpB,MAAI,sBAAsB;AAC1B,MAAI,cAAkC;AAEtC,MAAI;AACF,UAAM;AAAA,MACJ,SAAS;AAAA,MACT,UAAU;AAAA,MACV;AAAA,IACF,IAAI,MAAM,cAAc;AAExB,QAAI,WAAW,WAAW,KAAK,YAAY,WAAW,GAAG;AACvD,UAAI,CAAC,OAAO;AACV,eAAO,KAAK,0BAA0B;AAAA,MACxC;AACA,wBAAkB,QAAQ,EAAE,SAAS,GAAG,UAAU,EAAE,CAAC;AACrD,aAAO,EAAE,SAAS,GAAG,UAAU,EAAE;AAAA,IACnC;AAEA,QAAI,CAAC,SAAS,cAAc,SAAS,GAAG;AACtC,iBAAW,KAAK,eAAe;AAC7B,cAAM,QAAkB,CAAC;AACzB,YAAI,EAAE,UAAU,EAAG,OAAM,KAAK,GAAG,EAAE,OAAO,UAAU;AACpD,YAAI,EAAE,WAAW,EAAG,OAAM,KAAK,GAAG,EAAE,QAAQ,WAAW;AACvD,eAAO,KAAK,KAAK,EAAE,MAAM,KAAK,MAAM,KAAK,IAAI,CAAC,EAAE;AAAA,MAClD;AAAA,IACF;AAEA,UAAM,SAAS,OAAO,UAAU;AAChC,UAAM,YAAY,IAAI,UAAU,QAAQ,OAAO,MAAM;AAErD,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,UAAU,cAAc;AAAA,IAC3C,SAAS,OAAO;AACd,UAAK,MAAgB,YAAY,gBAAgB;AAC/C,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAEA,iBAAW;AAAA,IACb;AAEA,QAAI,CAAC,UAAU;AACb,YAAM,IAAI;AAAA,QACR;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,SAAS,iBAAiB,MAAM;AACtC,UAAM,gBAAgB,yBAAyB;AAAA,MAC7C,QAAQ,OAAO;AAAA,MACf;AAAA,MACA,UAAU,OAAO;AAAA,MACjB;AAAA,IACF,CAAC;AACD,UAAM,gBAAgB,gBAAgB,YAAY,UAAU,MAAM;AAClE,UAAM,iBAAiB,iBAAiB,aAAa,UAAU,MAAM;AACrE,UAAM,mBAAmB,mBAAmB;AAC5C,UAAM,aAAa,mBAAmB;AAAA,MACpC,SAAS;AAAA,MACT,UAAU;AAAA,MACV,OAAO;AAAA,MACP,UAAU;AAAA,IACZ,CAAC;AACD,UAAM,iBAAiB,WAAW;AAClC,UAAM,kBAAkB,WAAW;AACnC,UAAM,wBAAwB,6BAA6B;AAAA,MACzD,UAAU;AAAA,MACV,qBAAqB,WAAW;AAAA,IAClC,CAAC;AAED,QAAI,CAAC,SAAS,WAAW,oBAAoB,SAAS,GAAG;AACvD,YAAM,eAAe,WAAW,oBAC7B,IAAI,uBAAuB,EAC3B,KAAK,IAAI;AACZ,UAAI,uBAAuB;AACzB,eAAO;AAAA,UACL,yBAAyB,YAAY;AAAA,QACvC;AAAA,MACF,OAAO;AACL,eAAO;AAAA,UACL,yBAAyB,YAAY;AAAA,QACvC;AAAA,MACF;AAAA,IACF;AAEA,QACE,CAAC,UACA,WAAW,iBAAiB,KAAK,WAAW,kBAAkB,IAC/D;AACA,YAAM,QAAkB,CAAC;AACzB,UAAI,WAAW,iBAAiB,GAAG;AACjC,cAAM,KAAK,GAAG,WAAW,cAAc,UAAU;AAAA,MACnD;AACA,UAAI,WAAW,kBAAkB,GAAG;AAClC,cAAM,KAAK,GAAG,WAAW,eAAe,WAAW;AAAA,MACrD;AACA,aAAO;AAAA,QACL,YAAY,MAAM,KAAK,KAAK,CAAC;AAAA,MAC/B;AAAA,IACF;AAEA,QAAI,uBAAuB;AACzB,YAAM,UAAU,MAAM,UAAU,iBAAiB,qBAAqB;AACtE,UAAI,CAAC,OAAO;AACV,cAAM,eAAyB,CAAC;AAChC,YAAI,QAAQ,iBAAiB,GAAG;AAC9B,uBAAa,KAAK,GAAG,QAAQ,cAAc,UAAU;AAAA,QACvD;AACA,YAAI,QAAQ,kBAAkB,GAAG;AAC/B,uBAAa,KAAK,GAAG,QAAQ,eAAe,WAAW;AAAA,QACzD;AAEA,eAAO;AAAA,UACL,aAAa,SAAS,IAClB,WAAW,aAAa,KAAK,KAAK,CAAC,4DACnC;AAAA,QACN;AAAA,MACF;AAAA,IACF;AAEA,QAAI,eAAe,WAAW,KAAK,gBAAgB,WAAW,GAAG;AAC/D,UAAI,CAAC,OAAO;AACV,cAAM,eAAyB,CAAC;AAChC,YAAI,WAAW,mBAAmB,GAAG;AACnC,uBAAa,KAAK,GAAG,WAAW,gBAAgB,oBAAoB;AAAA,QACtE;AACA,YAAI,WAAW,oBAAoB,GAAG;AACpC,uBAAa;AAAA,YACX,GAAG,WAAW,iBAAiB;AAAA,UACjC;AAAA,QACF;AACA,eAAO;AAAA,UACL,aAAa,SAAS,IAClB,mDAAmD,aAAa,KAAK,KAAK,CAAC,MAC3E;AAAA,QACN;AAAA,MACF;AACA,4BAAsB,WAAW,cAAc,KAAK;AACpD,wBAAkB,QAAQ,EAAE,SAAS,GAAG,UAAU,EAAE,CAAC;AACrD,aAAO,EAAE,SAAS,GAAG,UAAU,EAAE;AAAA,IACnC;AAEA,UAAM,gBAAgB,KAAK,KAAK,eAAe,SAAS,UAAU;AAClE,UAAM,iBAAiB,KAAK;AAAA,MAC1B,gBAAgB,SAAS;AAAA,IAC3B;AACA,UAAM,eAAe,KAAK,IAAI,eAAe,gBAAgB,CAAC;AAC9D,UAAM,oBAAoB,MAAM;AAAA,MAC9B,EAAE,QAAQ,aAAa;AAAA,MACvB,CAAC,GAAG,aACF;AAAA,QACE;AAAA,QACA,eAAe;AAAA,UACb,WAAW;AAAA,WACV,WAAW,KAAK;AAAA,QACnB;AAAA,QACA,gBAAgB;AAAA,UACd,WAAW;AAAA,WACV,WAAW,KAAK;AAAA,QACnB;AAAA,MACF;AAAA,IACJ;AACA,UAAM,oBAAoB,kBAAkB;AAAA,MAC1C,CAAC,KAAK,SAAS,MAAM;AAAA,MACrB;AAAA,IACF;AACA,QAAI,2BAA2B;AAE/B,QAAI,CAAC,OAAO;AACV,YAAM,QAAkB,CAAC;AACzB,UAAI,eAAe,SAAS,GAAG;AAC7B,cAAM,KAAK,GAAG,eAAe,MAAM,UAAU;AAAA,MAC/C;AACA,UAAI,gBAAgB,SAAS,GAAG;AAC9B,cAAM,KAAK,GAAG,gBAAgB,MAAM,WAAW;AAAA,MACjD;AACA,YAAM,eAAyB,CAAC;AAChC,UAAI,WAAW,mBAAmB,GAAG;AACnC,qBAAa,KAAK,GAAG,WAAW,gBAAgB,oBAAoB;AAAA,MACtE;AACA,UAAI,WAAW,oBAAoB,GAAG;AACpC,qBAAa,KAAK,GAAG,WAAW,iBAAiB,qBAAqB;AAAA,MACxE;AACA,aAAO;AAAA,QACL,aAAa,MAAM,KAAK,KAAK,CAAC,KAAK,YAAY,SAAS,eAAe,IAAI,OAAO,EAAE,GAAG,aAAa,SAAS,IAAI,aAAa,aAAa,KAAK,KAAK,CAAC,KAAK,EAAE;AAAA,MAC/J;AAAA,IACF;AAEA,aAAS,WAAW,GAAG,WAAW,cAAc,YAAY;AAC1D,YAAM,QAAQ,eAAe;AAAA,QAC3B,WAAW;AAAA,SACV,WAAW,KAAK;AAAA,MACnB;AACA,YAAM,gBAAgB,gBAAgB;AAAA,QACpC,WAAW;AAAA,SACV,WAAW,KAAK;AAAA,MACnB;AACA,YAAM,WAAW,WAAW;AAE5B,YAAM,SAAS,MAAM,UAAU;AAAA,QAC7B;AAAA,QACA;AAAA,QACA,cAAc,SAAS,IAAI,gBAAgB;AAAA,QAC3C,QACI,SACA,CAAC,MAAM,UAAU;AACf;AAAA,YACE,2BAA2B;AAAA,YAC3B,qBAAqB;AAAA,YACrB;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACN;AAEA,uBAAiB,OAAO,YAAY,MAAM;AAC1C,6BAAuB,OAAO,YAAY,cAAc;AACxD,kCAA4B,kBAAkB,QAAQ,KAAK;AAAA,IAC7D;AAEA,QAAI,CAAC,UAAU,eAAe,KAAK,eAAe,SAAS,IAAI;AAC7D;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,cAAQ,OAAO,MAAM,IAAI;AAAA,IAC3B;AAEA,UAAM,YAAY,CAAC,GAAG,aAAa,UAAU;AAC7C,QAAI,sBAAsB,GAAG;AAC3B,gBAAU,KAAK,GAAG,mBAAmB,WAAW;AAAA,IAClD;AACA,WAAO,KAAK,UAAU,UAAU,KAAK,KAAK,CAAC,GAAG;AAE9C,QAAI,CAAC,OAAO;AACV,aAAO,KAAK;AAAA,0BAA6B,MAAM,QAAQ;AAAA,IACzD;AAEA,0BAAsB,WAAW,cAAc,KAAK;AACpD,sBAAkB,QAAQ;AAAA,MACxB,SAAS;AAAA,MACT,UAAU;AAAA,IACZ,CAAC;AAED,WAAO;AAAA,MACL,SAAS;AAAA,MACT,UAAU;AAAA,IACZ;AAAA,EACF,SAAS,OAAO;AACd,UAAM,UAAU;AAEhB,QAAI,QAAQ,YAAY,gBAAgB;AACtC,oBAAc,IAAI;AAAA,QAChB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,WAAW,iBAAiB,aAAa;AACvC,oBAAc;AAAA,IAChB,WAAW,gBAAgB,GAAG;AAC5B,oBAAc,IAAI;AAAA,QAChB,6BAA6B,aAAa,uBAAuB,QAAQ,OAAO;AAAA,QAChF;AAAA,QACA;AAAA,MACF;AAAA,IACF,OAAO;AACL,oBAAc,IAAI;AAAA,QAChB,gBAAgB,QAAQ,OAAO;AAAA,QAC/B;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,mBAAe,QAAQ,YAAY,SAAS,YAAY,IAAI;AAAA,EAC9D,UAAE;AACA,SAAK,QAAQ;AAAA,EACf;AAEA,MAAI,CAAC,aAAa;AAChB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,UAAU;AAAA,IACZ;AAAA,EACF;AAEA,SAAO,MAAM,YAAY,OAAO;AAChC,MAAI,QAAQ;AACV,UAAM,YAAY,cAAc;AAAA,EAClC;AACA,UAAQ,KAAK,CAAC;AAChB;;;AS1iBA,SAAS,gBAAAC,eAAc,aAAa;AACpC,SAAS,cAAAC,oBAAkB;AAC3B,SAAS,YAAY,OAAO,gBAAgB;AAC5C,SAAS,WAAAC,WAAS,YAAAC,iBAAgB;AAClC,SAAS,WAAAC,UAAS,QAAAC,QAAM,SAAAC,QAAO,aAAa;;;ACJ5C,SAAS,YAAAC,iBAAgB;;;ACAzB,SAAS,gBAAAC,qBAAoB;AAC7B,SAAS,cAAAC,cAAY,aAAAC,YAAW,UAAAC,SAAQ,iBAAAC,sBAAqB;AAC7D,SAAS,WAAAC,WAAS,YAAAC,iBAAgB;AAClC,SAAS,aAAa;;;ACHtB,SAAS,gBAAgB;AACzB,SAAS,gBAAgB;AASlB,SAAS,mBAAmB,SAA0B;AAC3D,MAAI;AACF,UAAM,QACJ,SAAS,MAAM,UAAU,SAAS,OAAO,KAAK,cAAc,OAAO;AACrE,aAAS,OAAO,EAAE,OAAO,SAAS,CAAC;AACnC,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;ACnBA,IAAM,yBAAyB;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,mBAAmB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAOA,SAAS,YAAY,OAA2B;AAC9C,SAAO,CAAC,GAAG,IAAI,IAAI,MAAM,OAAO,OAAO,CAAC,CAAC;AAC3C;AAEO,SAAS,6BACd,MAAyB,QAAQ,KACT;AACxB,QAAM,cAAc,YAAY;AAAA,IAC9B,GAAI,IAAI,MAAM,MAAM,GAAG,KAAK,CAAC;AAAA,IAC7B,GAAG;AAAA,EACL,CAAC;AACD,QAAM,OAA+B;AAAA,IACnC,MAAM,YAAY,KAAK,GAAG;AAAA,EAC5B;AAEA,aAAW,OAAO,kBAAkB;AAClC,UAAM,QAAQ,IAAI,GAAG;AACrB,QAAI,OAAO;AACT,WAAK,GAAG,IAAI;AAAA,IACd;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,4BACd,WAAW,QAAQ,UACnB,OAAO,QAAQ,MACO;AACtB,QAAM,aAAa,KAAK,CAAC;AACzB,MAAI,CAAC,YAAY;AACf,UAAM,IAAI,MAAM,qIAAsC;AAAA,EACxD;AAEA,SAAO;AAAA,IACL;AAAA,IACA,MAAM,CAAC,YAAY,UAAU,WAAW;AAAA,EAC1C;AACF;AAEO,SAAS,wBAAwB,OAAuB;AAC7D,SAAO,MAAM,WAAW,MAAM,MAAM,EAAE,WAAW,KAAK,KAAK;AAC7D;AAEO,SAAS,UAAU,OAAuB;AAC/C,SAAO,MACJ,WAAW,KAAK,OAAO,EACvB,WAAW,KAAK,MAAM,EACtB,WAAW,KAAK,MAAM,EACtB,WAAW,KAAK,QAAQ,EACxB,WAAW,KAAK,QAAQ;AAC7B;;;AFpDA,IAAM,uBAAuB;AAQtB,SAAS,0BAA0B,WAAWC,UAAQ,GAAW;AACtE,SAAO,MAAM,KAAK,UAAU,WAAW,WAAW,MAAM;AAC1D;AAEO,SAAS,2BAA2B,WAAWA,UAAQ,GAAW;AACvE,SAAO,MAAM;AAAA,IACX,0BAA0B,QAAQ;AAAA,IAClC,GAAG,oBAAoB;AAAA,EACzB;AACF;AAEO,SAAS,2BACd,SACQ;AACR,QAAM,WAAW,OAAO,QAAQ,QAAQ,WAAW,EAChD;AAAA,IACC,CAAC,CAAC,KAAK,KAAK,MACV,gBAAgB,wBAAwB,GAAG,CAAC,IAAI,wBAAwB,KAAK,CAAC;AAAA,EAClF,EACC,KAAK,IAAI;AACZ,QAAM,WAAW,CAAC,QAAQ,UAAU,GAAG,QAAQ,IAAI,EAChD,IAAI,CAAC,UAAU,IAAI,wBAAwB,KAAK,CAAC,GAAG,EACpD,KAAK,GAAG;AAEX,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAOG,QAAQ;AAAA;AAAA;AAAA,EAGlB,QAAQ;AAAA;AAAA;AAAA;AAAA;AAKV;AAEA,SAAS,oBAAoC;AAC3C,MAAIC,UAAS,MAAM,SAAS;AAC1B,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,MAAI,CAAC,mBAAmB,WAAW,GAAG;AACpC,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,SAAO,EAAE,IAAI,KAAK;AACpB;AAEA,SAAS,cAAc,MAAsB;AAC3C,EAAAC,cAAa,aAAa,CAAC,UAAU,GAAG,IAAI,GAAG;AAAA,IAC7C,OAAO;AAAA,EACT,CAAC;AACH;AAEA,SAAS,yBAAkC;AACzC,QAAM,UAAU,kBAAkB;AAClC,MAAI,QAAQ,IAAI;AACd,WAAO;AAAA,EACT;AAEA,SAAO,KAAK,aAAa,mCAAe,QAAQ,MAAM,IAAI,SAAS,CAAC;AACpE,SAAO;AACT;AAEO,SAAS,mCAAmD;AACjE,WAAS,cAAuB;AAC9B,WAAOC,aAAW,2BAA2B,CAAC;AAAA,EAChD;AAEA,iBAAe,MAAM,aAAa,OAAsB;AACtD,QAAI,CAAC,uBAAuB,GAAG;AAC7B;AAAA,IACF;AAEA,UAAM,aAAa,0BAA0B;AAC7C,UAAM,cAAc,2BAA2B;AAE/C,WAAO,KAAK,aAAa,qCAAiB,mBAAmB,CAAC;AAE9D,QAAI,CAAC,YAAY;AACf,YAAM,cAAc,MAAM,cAAc;AAAA,QACtC,SAAS;AAAA,QACT,cAAc;AAAA,MAChB,CAAC;AAED,UAAI,CAAC,aAAa;AAChB,eAAO,KAAK,aAAa,kDAAU,CAAC;AACpC;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AACF,YAAM,UAAU,4BAA4B;AAC5C,YAAM,UAAU,2BAA2B;AAAA,QACzC,aAAa,6BAA6B;AAAA,QAC1C,UAAU,QAAQ;AAAA,QAClB,MAAM,QAAQ;AAAA,MAChB,CAAC;AAED,MAAAC,WAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AACzC,MAAAC,eAAc,aAAa,SAAS,OAAO;AAE3C,oBAAc,CAAC,eAAe,CAAC;AAC/B,oBAAc,CAAC,UAAU,oBAAoB,CAAC;AAC9C,oBAAc,CAAC,SAAS,oBAAoB,CAAC;AAE7C,aAAO,KAAK,cAAc,gCAAO,CAAC;AAClC,aAAO,KAAK,aAAa,6BAAS,WAAW,IAAI,SAAS,CAAC;AAC3D,aAAO,KAAK,aAAa,oDAAY,SAAS,CAAC;AAC/C,aAAO;AAAA,QACL,eAAe,4BAAQ,oCAAoC;AAAA,MAC7D;AAAA,IACF,SAAS,KAAK;AACZ,aAAO,MAAM,yCAAY,IAAc,OAAO,EAAE;AAChD,YAAM;AAAA,IACR;AAAA,EACF;AAEA,iBAAe,QAAuB;AACpC,QAAI,CAAC,uBAAuB,GAAG;AAC7B;AAAA,IACF;AAEA,QAAI,CAAC,YAAY,GAAG;AAClB,aAAO;AAAA,QACL;AAAA,UACE;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF;AAEA,QAAI;AACF,oBAAc,CAAC,SAAS,oBAAoB,CAAC;AAC7C,aAAO,KAAK,aAAa,kCAAS,SAAS,CAAC;AAAA,IAC9C,SAAS,KAAK;AACZ,aAAO,MAAM,yCAAY,IAAc,OAAO,EAAE;AAChD,YAAM;AAAA,IACR;AAAA,EACF;AAEA,iBAAe,OAAsB;AACnC,QAAI,CAAC,uBAAuB,GAAG;AAC7B;AAAA,IACF;AAEA,QAAI,CAAC,YAAY,GAAG;AAClB,aAAO;AAAA,QACL;AAAA,UACE;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF;AAEA,QAAI;AACF,oBAAc,CAAC,QAAQ,oBAAoB,CAAC;AAC5C,aAAO,KAAK,aAAa,kCAAS,SAAS,CAAC;AAAA,IAC9C,SAAS,KAAK;AACZ,aAAO,MAAM,yCAAY,IAAc,OAAO,EAAE;AAChD,YAAM;AAAA,IACR;AAAA,EACF;AAEA,iBAAe,UAAyB;AACtC,QAAI,CAAC,uBAAuB,GAAG;AAC7B;AAAA,IACF;AAEA,QAAI,CAAC,YAAY,GAAG;AAClB,aAAO;AAAA,QACL;AAAA,UACE;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF;AAEA,QAAI;AACF,oBAAc,CAAC,WAAW,oBAAoB,CAAC;AAC/C,aAAO,KAAK,aAAa,kCAAS,SAAS,CAAC;AAAA,IAC9C,SAAS,KAAK;AACZ,aAAO,MAAM,yCAAY,IAAc,OAAO,EAAE;AAChD,YAAM;AAAA,IACR;AAAA,EACF;AAEA,iBAAe,SAAwB;AACrC,QAAI,CAAC,uBAAuB,GAAG;AAC7B;AAAA,IACF;AAEA,QAAI,CAAC,YAAY,GAAG;AAClB,aAAO;AAAA,QACL;AAAA,UACE;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF;AAEA,QAAI;AACF,oBAAc,CAAC,UAAU,oBAAoB,CAAC;AAAA,IAChD,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,iBAAe,UAAU,aAAa,OAAsB;AAC1D,UAAM,cAAc,2BAA2B;AAC/C,QAAI,CAACF,aAAW,WAAW,GAAG;AAC5B,aAAO,KAAK,aAAa,oDAAY,SAAS,CAAC;AAC/C;AAAA,IACF;AAEA,QAAI,CAAC,YAAY;AACf,YAAM,kBAAkB,MAAM,cAAc;AAAA,QAC1C,SAAS;AAAA,QACT,cAAc;AAAA,MAChB,CAAC;AAED,UAAI,CAAC,iBAAiB;AACpB,eAAO,KAAK,aAAa,sCAAQ,CAAC;AAClC;AAAA,MACF;AAAA,IACF;AAEA,UAAM,UAAU,kBAAkB;AAClC,QAAI,QAAQ,IAAI;AACd,UAAI;AACF,sBAAc,CAAC,QAAQ,oBAAoB,CAAC;AAAA,MAC9C,QAAQ;AAAA,MAER;AAEA,UAAI;AACF,sBAAc,CAAC,WAAW,oBAAoB,CAAC;AAAA,MACjD,QAAQ;AAAA,MAER;AAAA,IACF,OAAO;AACL,aAAO;AAAA,QACL;AAAA,UACE,2GAA2B,QAAQ,MAAM;AAAA,UACzC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AACF,MAAAG,QAAO,WAAW;AAClB,UAAI,QAAQ,IAAI;AACd,sBAAc,CAAC,eAAe,CAAC;AAAA,MACjC;AAEA,aAAO,KAAK,cAAc,gCAAO,CAAC;AAClC,aAAO,KAAK,aAAa,oDAAY,SAAS,CAAC;AAAA,IACjD,SAAS,KAAK;AACZ,aAAO,MAAM,yCAAY,IAAc,OAAO,EAAE;AAChD,YAAM;AAAA,IACR;AAAA,EACF;AAEA,SAAO;AAAA,IACL,aAAa;AAAA,IACb,UAAU;AAAA,IACV;AAAA,IACA,mBAAmB;AAAA,IACnB,eAAe,MAAM;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AG/TA,SAAS,gBAAAC,qBAAoB;AAC7B,SAAS,cAAAC,cAAY,aAAAC,YAAW,UAAAC,SAAQ,iBAAAC,sBAAqB;AAC7D,SAAS,WAAAC,WAAS,YAAAC,iBAAgB;AAClC,SAAS,SAAAC,cAAa;AAkBf,IAAM,sBAAsB;AAWnC,SAAS,gBAA+B;AACtC,SAAO,OAAO,QAAQ,WAAW,aAAa,QAAQ,OAAO,IAAI;AACnE;AAEO,SAAS,uBAAuB,WAAWC,UAAQ,GAAW;AACnE,SAAOC,OAAM,KAAK,UAAU,WAAW,cAAc;AACvD;AAEO,SAAS,wBAAwB,WAAWD,UAAQ,GAAW;AACpE,SAAOC,OAAM;AAAA,IACX,uBAAuB,QAAQ;AAAA,IAC/B,GAAG,mBAAmB;AAAA,EACxB;AACF;AAEO,SAAS,sBAAsB,MAAM,cAAc,GAAW;AACnE,MAAI,OAAO,MAAM;AACf,UAAM,IAAI,MAAM,4DAAe;AAAA,EACjC;AAEA,SAAO,OAAO,GAAG;AACnB;AAEO,SAAS,6BAA6B,MAAM,cAAc,GAAW;AAC1E,SAAO,GAAG,sBAAsB,GAAG,CAAC,IAAI,mBAAmB;AAC7D;AAEO,SAAS,wBAAwB,WAAW,YAAY,GAG7D;AACA,SAAO;AAAA,IACL,YAAYA,OAAM,KAAK,UAAU,oBAAoB;AAAA,IACrD,YAAYA,OAAM,KAAK,UAAU,oBAAoB;AAAA,EACvD;AACF;AAEA,SAAS,iBAAiB,QAA0B;AAClD,SAAO,OACJ,IAAI,CAAC,UAAU,iBAAiB,UAAU,KAAK,CAAC,WAAW,EAC3D,KAAK,IAAI;AACd;AAEA,SAAS,gBAAgB,SAAyC;AAChE,SAAO,OAAO,QAAQ,OAAO,EAC1B;AAAA,IACC,CAAC,CAAC,KAAK,KAAK,MACV,cAAc,UAAU,GAAG,CAAC;AAAA,gBAAyB,UAAU,KAAK,CAAC;AAAA,EACzE,EACC,KAAK,IAAI;AACd;AAEO,SAAS,kBAAkB,SAAsC;AACtE,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA,cAKK,UAAU,QAAQ,KAAK,CAAC;AAAA;AAAA;AAAA,EAGpC,iBAAiB,QAAQ,gBAAgB,CAAC;AAAA;AAAA;AAAA,cAG9B,UAAU,QAAQ,gBAAgB,CAAC;AAAA;AAAA;AAAA,EAG/C,gBAAgB,QAAQ,WAAW,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,cAcxB,UAAU,QAAQ,eAAe,CAAC;AAAA;AAAA,cAElC,UAAU,QAAQ,iBAAiB,CAAC;AAAA;AAAA;AAAA;AAIlD;AAEA,SAAS,sBAAsC;AAC7C,MAAIC,UAAS,MAAM,UAAU;AAC3B,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,MAAI,CAAC,mBAAmB,WAAW,GAAG;AACpC,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,QAAM,MAAM,cAAc;AAC1B,MAAI,OAAO,MAAM;AACf,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,MAAI;AACF,IAAAC,cAAa,aAAa,CAAC,SAAS,sBAAsB,GAAG,CAAC,GAAG;AAAA,MAC/D,OAAO;AAAA,IACT,CAAC;AACD,WAAO,EAAE,IAAI,KAAK;AAAA,EACpB,QAAQ;AACN,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,QAAQ;AAAA,IACV;AAAA,EACF;AACF;AAEA,SAAS,cAAc,MAAgB,UAAU,MAAY;AAC3D,EAAAA,cAAa,aAAa,MAAM;AAAA,IAC9B,OAAO,UAAU,YAAY;AAAA,EAC/B,CAAC;AACH;AAEA,SAAS,WAAoB;AAC3B,MAAI;AACF,kBAAc,CAAC,SAAS,6BAA6B,CAAC,GAAG,KAAK;AAC9D,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,2BAAoC;AAC3C,QAAM,UAAU,oBAAoB;AACpC,MAAI,QAAQ,IAAI;AACd,WAAO;AAAA,EACT;AAEA,SAAO,KAAK,aAAa,mCAAe,QAAQ,MAAM,IAAI,SAAS,CAAC;AACpE,SAAO;AACT;AAEA,SAAS,wBAAgC;AACvC,QAAM,YAAY,wBAAwB;AAC1C,QAAM,EAAE,YAAY,WAAW,IAAI,wBAAwB;AAC3D,QAAM,UAAU,4BAA4B;AAC5C,QAAM,QAAQ,kBAAkB;AAAA,IAC9B,OAAO;AAAA,IACP,kBAAkB,CAAC,QAAQ,UAAU,GAAG,QAAQ,IAAI;AAAA,IACpD,aAAa,6BAA6B;AAAA,IAC1C,kBAAkBH,UAAQ;AAAA,IAC1B,iBAAiB;AAAA,IACjB,mBAAmB;AAAA,EACrB,CAAC;AAED,gBAAc;AACd,EAAAI,WAAU,uBAAuB,GAAG,EAAE,WAAW,KAAK,CAAC;AACvD,EAAAC,eAAc,WAAW,OAAO,OAAO;AAEvC,SAAO;AACT;AAEA,SAAS,uBAA6B;AACpC,QAAM,SAAS,sBAAsB;AACrC,QAAM,gBAAgB,6BAA6B;AACnD,QAAM,YAAY,wBAAwB;AAE1C,MAAI,SAAS,GAAG;AACd,QAAI;AACF,oBAAc,CAAC,WAAW,aAAa,CAAC;AAAA,IAC1C,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,gBAAc,CAAC,aAAa,QAAQ,SAAS,CAAC;AAC9C,gBAAc,CAAC,UAAU,aAAa,CAAC;AACvC,gBAAc,CAAC,aAAa,MAAM,aAAa,CAAC;AAClD;AAEO,SAAS,mCAAmD;AACjE,WAAS,cAAuB;AAC9B,WAAOC,aAAW,wBAAwB,CAAC;AAAA,EAC7C;AAEA,iBAAe,MAAM,aAAa,OAAsB;AACtD,QAAI,CAAC,yBAAyB,GAAG;AAC/B;AAAA,IACF;AAEA,WAAO,KAAK,aAAa,qCAAiB,mBAAmB,CAAC;AAE9D,QAAI,CAAC,YAAY;AACf,YAAM,cAAc,MAAM,cAAc;AAAA,QACtC,SAAS;AAAA,QACT,cAAc;AAAA,MAChB,CAAC;AAED,UAAI,CAAC,aAAa;AAChB,eAAO,KAAK,aAAa,kDAAU,CAAC;AACpC;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AACF,YAAM,YAAY,sBAAsB;AACxC,2BAAqB;AAErB,aAAO,KAAK,cAAc,gCAAO,CAAC;AAClC,aAAO,KAAK,aAAa,6BAAS,SAAS,IAAI,SAAS,CAAC;AACzD,aAAO,KAAK,aAAa,oDAAY,SAAS,CAAC;AAC/C,aAAO;AAAA,QACL;AAAA,UACE;AAAA,UACA,mBAAmB,6BAA6B,CAAC;AAAA,QACnD;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,aAAO,MAAM,yCAAY,IAAc,OAAO,EAAE;AAChD,YAAM;AAAA,IACR;AAAA,EACF;AAEA,iBAAe,QAAuB;AACpC,QAAI,CAAC,yBAAyB,GAAG;AAC/B;AAAA,IACF;AAEA,QAAI,CAAC,YAAY,GAAG;AAClB,aAAO;AAAA,QACL;AAAA,UACE;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF;AAEA,QAAI;AACF,UAAI,CAAC,SAAS,GAAG;AACf,sBAAc;AAAA,UACZ;AAAA,UACA,sBAAsB;AAAA,UACtB,wBAAwB;AAAA,QAC1B,CAAC;AAAA,MACH;AACA,oBAAc,CAAC,UAAU,6BAA6B,CAAC,CAAC;AACxD,oBAAc,CAAC,aAAa,MAAM,6BAA6B,CAAC,CAAC;AACjE,aAAO,KAAK,aAAa,kCAAS,SAAS,CAAC;AAAA,IAC9C,SAAS,KAAK;AACZ,aAAO,MAAM,yCAAY,IAAc,OAAO,EAAE;AAChD,YAAM;AAAA,IACR;AAAA,EACF;AAEA,iBAAe,OAAsB;AACnC,QAAI,CAAC,YAAY,GAAG;AAClB,aAAO;AAAA,QACL;AAAA,UACE;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF;AAEA,QAAI,CAAC,yBAAyB,GAAG;AAC/B;AAAA,IACF;AAEA,QAAI,CAAC,SAAS,GAAG;AACf,aAAO,KAAK,aAAa,oDAAY,SAAS,CAAC;AAC/C;AAAA,IACF;AAEA,QAAI;AACF,oBAAc,CAAC,WAAW,6BAA6B,CAAC,CAAC;AACzD,aAAO,KAAK,aAAa,kCAAS,SAAS,CAAC;AAAA,IAC9C,SAAS,KAAK;AACZ,aAAO,MAAM,yCAAY,IAAc,OAAO,EAAE;AAChD,YAAM;AAAA,IACR;AAAA,EACF;AAEA,iBAAe,UAAyB;AACtC,QAAI,CAAC,yBAAyB,GAAG;AAC/B;AAAA,IACF;AAEA,QAAI,CAAC,YAAY,GAAG;AAClB,aAAO;AAAA,QACL;AAAA,UACE;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF;AAEA,QAAI;AACF,UAAI,SAAS,GAAG;AACd,sBAAc,CAAC,aAAa,MAAM,6BAA6B,CAAC,CAAC;AAAA,MACnE,OAAO;AACL,sBAAc;AAAA,UACZ;AAAA,UACA,sBAAsB;AAAA,UACtB,wBAAwB;AAAA,QAC1B,CAAC;AACD,sBAAc,CAAC,UAAU,6BAA6B,CAAC,CAAC;AACxD,sBAAc,CAAC,aAAa,MAAM,6BAA6B,CAAC,CAAC;AAAA,MACnE;AACA,aAAO,KAAK,aAAa,kCAAS,SAAS,CAAC;AAAA,IAC9C,SAAS,KAAK;AACZ,aAAO,MAAM,yCAAY,IAAc,OAAO,EAAE;AAChD,YAAM;AAAA,IACR;AAAA,EACF;AAEA,iBAAe,SAAwB;AACrC,QAAI,CAAC,YAAY,GAAG;AAClB,aAAO;AAAA,QACL;AAAA,UACE;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF;AAEA,QAAI,CAAC,yBAAyB,GAAG;AAC/B;AAAA,IACF;AAEA,QAAI;AACF,oBAAc,CAAC,SAAS,6BAA6B,CAAC,CAAC;AAAA,IACzD,QAAQ;AACN,aAAO,KAAK,aAAa,oDAAY,SAAS,CAAC;AAC/C,aAAO,KAAK,eAAe,4BAAQ,wBAAwB,CAAC,CAAC;AAAA,IAC/D;AAAA,EACF;AAEA,iBAAe,UAAU,aAAa,OAAsB;AAC1D,UAAM,YAAY,wBAAwB;AAC1C,QAAI,CAACA,aAAW,SAAS,GAAG;AAC1B,aAAO,KAAK,aAAa,oDAAY,SAAS,CAAC;AAC/C;AAAA,IACF;AAEA,QAAI,CAAC,YAAY;AACf,YAAM,kBAAkB,MAAM,cAAc;AAAA,QAC1C,SAAS;AAAA,QACT,cAAc;AAAA,MAChB,CAAC;AAED,UAAI,CAAC,iBAAiB;AACpB,eAAO,KAAK,aAAa,sCAAQ,CAAC;AAClC;AAAA,MACF;AAAA,IACF;AAEA,UAAM,UAAU,oBAAoB;AACpC,QAAI,QAAQ,MAAM,SAAS,GAAG;AAC5B,UAAI;AACF,sBAAc,CAAC,WAAW,6BAA6B,CAAC,CAAC;AAAA,MAC3D,QAAQ;AAAA,MAER;AAAA,IACF,WAAW,CAAC,QAAQ,IAAI;AACtB,aAAO;AAAA,QACL;AAAA,UACE,wHAAmC,QAAQ,MAAM;AAAA,UACjD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AACF,YAAM,EAAE,YAAY,WAAW,IAAI,wBAAwB;AAC3D,MAAAC,QAAO,SAAS;AAChB,MAAAA,QAAO,YAAY,EAAE,OAAO,KAAK,CAAC;AAClC,MAAAA,QAAO,YAAY,EAAE,OAAO,KAAK,CAAC;AAElC,aAAO,KAAK,cAAc,gCAAO,CAAC;AAClC,aAAO,KAAK,aAAa,oDAAY,SAAS,CAAC;AAAA,IACjD,SAAS,KAAK;AACZ,aAAO,MAAM,yCAAY,IAAc,OAAO,EAAE;AAChD,YAAM;AAAA,IACR;AAAA,EACF;AAEA,SAAO;AAAA,IACL,aAAa;AAAA,IACb,UAAU;AAAA,IACV;AAAA,IACA,mBAAmB;AAAA,IACnB,eAAe,MAAM,mBAAmB,6BAA6B,CAAC;AAAA,IACtE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AJtbO,SAAS,kBACd,kBAAmCC,UAAS,GACrB;AACvB,UAAQ,iBAAiB;AAAA,IACvB,KAAK;AACH,aAAO,iCAAiC;AAAA,IAC1C,KAAK;AACH,aAAO,iCAAiC;AAAA,IAC1C;AACE,aAAO;AAAA,EACX;AACF;;;ADiCA,SAAS,gBACP,oBACG,OACK;AACR,SAAO,oBAAoB,UACvB,MAAM,KAAK,GAAG,KAAK,IACnBC,OAAM,KAAK,GAAG,KAAK;AACzB;AAEA,SAAS,kBAAkBC,QAAuB;AAChD,SACEA,OACG,MAAM,QAAQ,EACd,IAAI,GACH,QAAQ,WAAW,EAAE,KAAKA;AAElC;AAEO,SAAS,wBACd,KACA,kBAAmCC,UAAS,GACtB;AACtB,UAAQ,iBAAiB;AAAA,IACvB,KAAK;AACH,aAAO;AAAA,QACL,SAAS;AAAA,QACT,MAAM,CAAC,GAAG;AAAA,MACZ;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,SAAS;AAAA,QACT,MAAM,CAAC,MAAM,MAAM,MAAM,SAAS,IAAI,GAAG;AAAA,MAC3C;AAAA,IACF;AACE,aAAO;AAAA,QACL,SAAS;AAAA,QACT,MAAM,CAAC,GAAG;AAAA,MACZ;AAAA,EACJ;AACF;AAEA,SAAS,YAAY,KAAmB;AACtC,QAAM,EAAE,SAAS,KAAK,IAAI,wBAAwB,GAAG;AAErD,MAAI;AACF,UAAM,QAAQ,MAAM,SAAS,MAAM;AAAA,MACjC,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aAAa;AAAA,IACf,CAAC;AAED,UAAM,GAAG,SAAS,MAAM;AAAA,IAAC,CAAC;AAC1B,UAAM,MAAM;AAAA,EACd,QAAQ;AAAA,EAER;AACF;AAEA,SAAS,+BAA8C;AACrD,QAAM,aAAa,QAAQ,IAAI,cAAc;AAC7C,QAAM,aAAa;AAAA,IACjB;AAAA,IACAC,OAAK,YAAY,YAAY,qBAAqB,QAAQ,gBAAgB;AAAA,EAC5E;AAEA,aAAW,WAAW,YAAY;AAChC,QAAI;AACF,YAAM,SAASC;AAAA,QACb;AAAA,QACA;AAAA,UACE;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA;AAAA,UACE,UAAU;AAAA,UACV,SAAS;AAAA,UACT,aAAa;AAAA,QACf;AAAA,MACF,EAAE,KAAK;AAEP,UAAI,QAAQ;AACV,eAAO;AAAA,MACT;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,uBACd,UAAyC,CAAC,GAClB;AACxB,QAAM,kBAAkB,QAAQ,mBAAmBF,UAAS;AAC5D,QAAM,MAAM,QAAQ,OAAO,QAAQ;AACnC,QAAM,UAAU,QAAQ,WAAWG,UAAQ;AAC3C,QAAM,aAAa,QAAQ,UAAUC;AAErC,QAAM,eAAe,IAAI,QACrB,kBAAkB,IAAI,KAAK,EAAE,YAAY,IACzC;AACJ,QAAM,YACJ,iBAAiB,oBAAoB,UAAU,eAAe;AAChE,QAAM,YAAY;AAElB,UAAQ,WAAW;AAAA,IACjB,KAAK;AACH,aAAO;AAAA,QACL,WAAW,SAAS,SAAS;AAAA,QAC7B,eAAe,CAAC,SAAS,SAAS,KAAK,YAAY,SAAS,EAAE;AAAA,QAC9D,YAAY,gBAAgB,iBAAiB,SAAS,QAAQ;AAAA,QAC9D,YAAY;AAAA,QACZ,YAAY;AAAA,MACd;AAAA,IACF,KAAK,QAAQ;AACX,YAAM,cAAc;AAAA,QAClB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,YAAM,iBACJ,oBAAoB,YAAY,WAAW,WAAW;AAExD,aAAO;AAAA,QACL,WAAW,SAAS,SAAS;AAAA,QAC7B,eAAe,CAAC,SAAS,SAAS,KAAK,YAAY,SAAS,EAAE;AAAA,QAC9D,YAAY,iBACR,cACA,gBAAgB,iBAAiB,SAAS,SAAS;AAAA,QACvD,YAAY;AAAA,QACZ,YAAY,iBACR,2BACA;AAAA,MACN;AAAA,IACF;AAAA,IACA,KAAK;AACH,aAAO;AAAA,QACL,WAAW,SAAS,SAAS;AAAA,QAC7B,eAAe,CAAC,SAAS,SAAS,IAAI,YAAY,SAAS,EAAE;AAAA,QAC7D,YAAY;AAAA,UACV;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA,YAAY;AAAA,QACZ,YAAY;AAAA,MACd;AAAA,IACF,KAAK,cAAc;AACjB,YAAM,aACJ,QAAQ,+BAA+B,KACvC,6BAA6B,KAC7B;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEF,aAAO;AAAA,QACL,WAAW,mBAAmB,SAAS;AAAA,QACvC,eAAe;AAAA,UACb,mBAAmB,SAAS;AAAA,UAC5B,aAAa,SAAS;AAAA,UACtB,aAAa,SAAS;AAAA,UACtB,YAAY,SAAS;AAAA,QACvB;AAAA,QACA;AAAA,QACA,YAAY;AAAA,QACZ,YAAY;AAAA,MACd;AAAA,IACF;AAAA,IACA;AACE,aAAO;AAAA,EACX;AACF;AAMA,eAAsB,QAAQ,OAAoB,CAAC,GAAkB;AACnE,SAAO,KAAK,aAAa,+BAAgB,CAAC;AAE1C,QAAM,WAAW,WAAW;AAC5B,MAAI,UAAU,QAAQ;AACpB,WAAO,KAAK,cAAc,4CAAS,CAAC;AACpC,WAAO,KAAK,eAAe,wBAAc,WAAW,SAAS,MAAM,CAAC,CAAC;AACrE,WAAO;AAAA,MACL;AAAA,QACE;AAAA,QACA,SAAS,UAAU;AAAA,MACrB;AAAA,IACF;AAEA,UAAM,kBAAkB,MAAM,cAAc;AAAA,MAC1C,SAAS;AAAA,MACT,cAAc;AAAA,IAChB,CAAC;AAED,QAAI,CAAC,iBAAiB;AACpB,aAAO,KAAK,aAAa,8CAAW,SAAS,CAAC;AAC9C;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,KAAK,UAAU,iBAAiB;AAC/C,QAAM,aAAa,GAAG,MAAM;AAC5B,SAAO,KAAK,cAAc,2CAAkB,CAAC;AAC7C,SAAO,KAAK,aAAa,yFAAwB,CAAC;AAClD,SAAO,KAAK,eAAe,oBAAU,gBAAgB,UAAU,CAAC,CAAC;AACjE,cAAY,UAAU;AAEtB,QAAM,SAAS,MAAM,eAAe;AAAA,IAClC,SAAS;AAAA,IACT,UAAU,CAAC,UAAU,eAAe,KAAK,KAAK;AAAA,EAChD,CAAC;AAED,SAAO,KAAK,cAAc,2CAAkB,CAAC;AAC7C,SAAO,KAAK,eAAe,0BAAW,WAAW,MAAM,CAAC,CAAC;AACzD,MAAI;AACF,UAAM,SAAS,IAAI,UAAU,QAAQ,MAAM;AAC3C,UAAM,WAAW,MAAM,OAAO,cAAc;AAE5C,QAAI,CAAC,UAAU;AACb,aAAO;AAAA,QACL;AAAA,UACE;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF,OAAO;AACL,aAAO,KAAK,aAAa,0CAAiB,SAAS,CAAC;AAAA,IACtD;AAAA,EACF,SAAS,KAAK;AACZ,QAAK,IAAc,YAAY,gBAAgB;AAC7C,aAAO,MAAM,8CAA8C;AAC3D,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,WAAO;AAAA,MACL;AAAA,QACE;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAiB;AAAA,IACrB;AAAA,IACA;AAAA,IACA,GAAI,UAAU,WAAW,EAAE,UAAU,SAAS,SAAS,IAAI,CAAC;AAAA,EAC9D;AACA,aAAW,MAAM;AACjB,QAAM,WAAW,oBAAoB,MAAM;AAC3C,SAAO,WAAW;AAClB,SAAO,KAAK,cAAc,2DAAc,CAAC;AAEzC,QAAM,QAAQ,iBAAiB;AAC/B,MAAI,MAAM,SAAS,GAAG;AACpB,WAAO,KAAK,cAAc,iCAAa,CAAC;AACxC,eAAW,QAAQ,OAAO;AACxB,aAAO,KAAK,aAAa,KAAK,MAAM,SAAS,CAAC;AAAA,IAChD;AAAA,EACF,OAAO;AACL,WAAO,KAAK,cAAc,iCAAa,CAAC;AACxC,WAAO;AAAA,MACL;AAAA,QACE;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,KAAK,cAAc,0BAAM,CAAC;AACjC,SAAO,KAAK,aAAa,sFAAgB,CAAC;AAC1C,QAAM,QAAQ,QAAQ,EAAE,QAAQ,OAAO,CAAC;AAExC,SAAO,KAAK,cAAc,gCAAO,CAAC;AAClC,SAAO,KAAK,aAAa,mDAAqB,SAAS,CAAC;AACxD,SAAO,KAAK,eAAe,sBAAO,GAAG,MAAM,QAAQ,CAAC;AAEpD,QAAM,gBAAgB;AACtB,QAAM,uBAAuB;AAC/B;AAEA,eAAe,yBAAwC;AACrD,QAAM,UAAU,kBAAkB;AAClC,MAAI,CAAC,SAAS;AACZ;AAAA,EACF;AAEA,QAAM,UAAU,QAAQ,SAAS;AACjC,MAAI,CAAC,QAAQ,IAAI;AACf;AAAA,EACF;AAEA,QAAM,cAAc,MAAM,cAAc;AAAA,IACtC,SAAS,4BAAQ,QAAQ,WAAW;AAAA,IACpC,cAAc;AAAA,EAChB,CAAC;AAED,MAAI,CAAC,aAAa;AAChB,WAAO,KAAK,aAAa,8DAAY,CAAC;AACtC;AAAA,EACF;AAEA,MAAI;AACF,UAAM,QAAQ,MAAM,IAAI;AAAA,EAC1B,SAAS,KAAK;AACZ,WAAO,KAAK,GAAG,QAAQ,WAAW,8BAAW,IAAc,OAAO,EAAE;AAAA,EACtE;AACF;AAEA,eAAe,kBAAiC;AAC9C,QAAM,QAAQ,uBAAuB;AACrC,MAAI,CAAC,OAAO;AACV;AAAA,EACF;AAEA,QAAM,oBAAoB,MAAM,cAAc;AAAA,IAC5C,SAAS,sBAAO,MAAM,UAAU;AAAA,IAChC,cAAc;AAAA,EAChB,CAAC;AACD,MAAI,CAAC,mBAAmB;AACtB,WAAO,KAAK,aAAa,mDAAqB,CAAC;AAC/C;AAAA,EACF;AAEA,MAAI;AACF,UAAM,MAAMC,SAAQ,MAAM,UAAU,GAAG,EAAE,WAAW,KAAK,CAAC;AAE1D,QAAI,kBAAkB;AACtB,QAAID,aAAW,MAAM,UAAU,GAAG;AAChC,wBAAkB,MAAM,SAAS,MAAM,YAAY,OAAO;AAAA,IAC5D;AAEA,UAAM,oBAAoB,gBAAgB,YAAY;AACtD,UAAM,cAAc,MAAM,cAAc;AAAA,MAAK,CAAC,YAC5C,kBAAkB,SAAS,QAAQ,YAAY,CAAC;AAAA,IAClD;AAEA,QAAI,aAAa;AACf,aAAO,KAAK,aAAa,2CAAa,MAAM,UAAU,EAAE,CAAC;AACzD;AAAA,IACF;AAEA,UAAM,mBAAmB;AAAA;AAAA,EAAyB,MAAM,SAAS;AAAA;AACjE,UAAM,WAAW,MAAM,YAAY,kBAAkB,OAAO;AAE5D,WAAO,KAAK,cAAc,aAAa,CAAC;AACxC,WAAO,KAAK,aAAa,sBAAO,MAAM,UAAU,IAAI,SAAS,CAAC;AAC9D,WAAO;AAAA,MACL,eAAe,4BAAQ,iBAAO,MAAM,UAAU,kCAAS;AAAA,IACzD;AACA,WAAO,KAAK,eAAe,4BAAQ,SAAS,CAAC;AAAA,EAC/C,SAAS,KAAK;AACZ,WAAO,KAAK,cAAc,aAAa,CAAC;AACxC,WAAO;AAAA,MACL;AAAA,QACE,4BAAQ,MAAM,UAAU,KAAM,IAAc,OAAO;AAAA,QACnD;AAAA,MACF;AAAA,IACF;AACA,WAAO,KAAK,eAAe,kCAAS,MAAM,SAAS,CAAC;AAAA,EACtD;AACF;;;AMzZA,IAAM,mBAAmB,KAAK;AAE9B,SAAS,IAAI,KAAmB;AAC9B,QAAM,MAAK,oBAAI,KAAK,GAAE,mBAAmB,SAAS,EAAE,QAAQ,MAAM,CAAC;AACnE,UAAQ,OAAO,MAAM,IAAI,EAAE,KAAK,GAAG;AAAA,CAAI;AACzC;AAEA,SAAS,MAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,CAACE,aAAY,WAAWA,UAAS,EAAE,CAAC;AACzD;AAOO,SAAS,kBAAkB,OAAsB,CAAC,GAAW;AAClE,SAAO,KAAK,UAAU,IAAI;AAC5B;AAEA,eAAsB,UAAU,OAAsB,CAAC,GAAkB;AACvE,QAAM,SAAS,WAAW;AAC1B,MAAI,CAAC,QAAQ,QAAQ;AACnB,QAAI,sBAAsB,GAAG;AAC3B,aAAO;AAAA,QACL;AAAA,UACE;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA,YAAM,aAAa,MAAM,cAAc;AAAA,QACrC,SAAS;AAAA,QACT,cAAc;AAAA,MAChB,CAAC;AACD,UAAI,YAAY;AACd,cAAM,QAAQ;AACd;AAAA,MACF;AACA,aAAO,KAAK,aAAa,+CAAiB,SAAS,CAAC;AACpD;AAAA,IACF;AAEA,UAAM,UAAU,KAAK,UACjB,0CACA;AACJ,WAAO,MAAM,OAAO;AACpB,YAAQ,KAAK,kBAAkB,IAAI,CAAC;AAAA,EACtC;AAEA,QAAM,WAAW,KAAK,YAAY,OAAO,gBAAgB;AACzD,QAAM,cAAc,KAAK,MAAM,WAAW,GAAK;AAC/C,QAAM,WAAW,KAAK,UAAU,iBAAiB;AAEjD,MAAI,8BAA8B,WAAW,MAAM,QAAQ,GAAG;AAG9D,SAAO,MAAM;AACX,QAAI;AACF,YAAM,QAAQ,WAAW;AACzB,YAAM,QAAQ,SAAS,QAAQ;AAAA,QAC7B,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,UAAK,IAAc,YAAY,gBAAgB;AAC7C,cAAM,UAAU,KAAK,UACjB,2CACA;AACJ,YAAI,OAAO;AACX,gBAAQ,KAAK,kBAAkB,IAAI,CAAC;AAAA,MACtC;AACA,UAAI,eAAgB,IAAc,OAAO,EAAE;AAAA,IAC7C;AACA,UAAM,MAAM,QAAQ;AAAA,EACtB;AACF;;;AC3BA,SAAS,eAAiC;AACxC,SAAO;AAAA,IACL,aAAa;AAAA,IACb,cAAc;AAAA,IACd,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,SAAS;AAAA,IACT,UAAU;AAAA,IACV,UAAU;AAAA,IACV,QAAQ;AAAA,EACV;AACF;AAEA,SAAS,kBACP,QACA,QACM;AACN,SAAO,eAAe,OAAO,eAAe;AAC5C,SAAO,gBAAgB,OAAO,gBAAgB;AAC9C,SAAO,gBAAgB,OAAO,gBAAgB;AAC9C,SAAO,mBAAmB,OAAO,mBAAmB;AACpD,SAAO,eAAe,OAAO,eAAe;AAC5C,SAAO,WAAW;AACpB;AAEA,SAAS,gBACP,KACA,KACA,QACM;AACN,QAAM,OAAO,OAAO;AACpB,QAAM,UAAU,IAAI,IAAI,IAAI,KAAK;AAAA,IAC/B;AAAA,IACA,aAAa;AAAA,IACb,cAAc;AAAA,IACd,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAEA,UAAQ,eAAe,OAAO,eAAe;AAC7C,UAAQ,gBAAgB,OAAO,gBAAgB;AAC/C,UAAQ,gBAAgB,OAAO,gBAAgB;AAC/C,UAAQ,mBAAmB,OAAO,mBAAmB;AACrD,UAAQ,eAAe,OAAO,eAAe;AAC7C,MAAI,IAAI,MAAM,OAAO;AACvB;AAEA,SAAS,cACP,OACsB;AACtB,SAAO,MAAM,KAAK,KAAK,EAAE,KAAK,CAAC,MAAM,UAAU;AAC7C,QAAI,MAAM,gBAAgB,KAAK,aAAa;AAC1C,aAAO,MAAM,cAAc,KAAK;AAAA,IAClC;AACA,WAAO,KAAK,KAAK,cAAc,MAAM,IAAI;AAAA,EAC3C,CAAC;AACH;AAEA,SAAS,iBAAiBC,QAKA;AACxB,QAAM,SAAS,aAAa;AAC5B,QAAM,cAAc,oBAAI,IAAgC;AACxD,QAAM,gBAAgB,oBAAI,IAAgC;AAC1D,QAAM,WAAW,oBAAI,IAAY;AACjC,QAAM,SAAS,oBAAI,IAAY;AAE/B,aAAW,UAAUA,OAAM,SAAS;AAClC,sBAAkB,QAAQ,MAAM;AAChC,oBAAgB,aAAa,OAAO,OAAO,MAAM;AACjD,oBAAgB,eAAe,OAAO,SAAS,MAAM;AACrD,aAAS,IAAI,OAAO,WAAW,SAAS;AACxC,WAAO,IAAI,OAAO,SAAS,SAAS;AAAA,EACtC;AAEA,aAAW,WAAWA,OAAM,UAAU;AACpC,UAAM,cAAc,QAAQ,WAAW;AACvC,UAAM,YAAY,QAAQ,gBAAgB;AAC1C,aAAS,IAAI,WAAW;AACxB,WAAO,IAAI,SAAS;AAEpB,UAAM,UAAU,cAAc,IAAI,WAAW;AAC7C,QAAI,SAAS;AACX,cAAQ,YAAY;AAAA,IACtB,OAAO;AACL,oBAAc,IAAI,aAAa;AAAA,QAC7B,MAAM;AAAA,QACN,aAAa;AAAA,QACb,cAAc;AAAA,QACd,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,aAAa;AAAA,QACb,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAEA,UAAM,QAAQ,YAAY,IAAI,SAAS;AACvC,QAAI,OAAO;AACT,YAAM,YAAY;AAAA,IACpB,OAAO;AACL,kBAAY,IAAI,WAAW;AAAA,QACzB,MAAM;AAAA,QACN,aAAa;AAAA,QACb,cAAc;AAAA,QACd,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,aAAa;AAAA,QACb,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO,WAAWA,OAAM,SAAS;AACjC,SAAO,WAAW,SAAS;AAC3B,SAAO,SAAS,OAAO;AAEvB,SAAO;AAAA,IACL,QAAQA,OAAM;AAAA,IACd,MAAMA,OAAM;AAAA,IACZ;AAAA,IACA,WAAW,cAAc,YAAY,OAAO,CAAC,EAAE,MAAM,GAAG,CAAC;AAAA,IACzD,aAAa,cAAc,cAAc,OAAO,CAAC,EAAE,MAAM,GAAG,CAAC;AAAA,IAC7D,UAAUA,OAAM,SACb,MAAM,EACN;AAAA,MACC,CAAC,MAAM,UACL,IAAI,KAAK,MAAM,aAAa,EAAE,QAAQ,IACtC,IAAI,KAAK,KAAK,aAAa,EAAE,QAAQ;AAAA,IACzC,EACC,MAAM,GAAG,CAAC,EACV,IAAI,CAAC,aAAa;AAAA,MACjB,SAAS,QAAQ,WAAW;AAAA,MAC5B,cAAc,QAAQ,gBAAgB;AAAA,MACtC,eAAe,QAAQ;AAAA,MACvB,aAAa,QAAQ,eAAe;AAAA,MACpC,cAAc,QAAQ,gBAAgB;AAAA,MACtC,eAAe,QAAQ,iBAAiB;AAAA,IAC1C,EAAE;AAAA,EACN;AACF;AAEO,SAAS,6BACdA,QACyB;AACzB,QAAM,YAAY,IAAI,IAAIA,OAAM,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,KAAK,IAAI,CAAC,CAAC;AACzE,QAAM,gBAAgB,oBAAI,IAAY;AACtC,aAAW,UAAUA,OAAM,QAAS,eAAc,IAAI,OAAO,MAAM;AACnE,aAAW,WAAWA,OAAM,SAAU,eAAc,IAAI,QAAQ,MAAM;AAEtE,QAAM,UAAU,MAAM,KAAK,aAAa;AAExC,QAAM,QAAQ,QACX,KAAK,CAAC,MAAM,UAAU;AACrB,UAAM,gBAAgBA,OAAM,MAAM,UAAU,CAAC,SAAS,KAAK,OAAO,IAAI;AACtE,UAAM,iBAAiBA,OAAM,MAAM,UAAU,CAAC,SAAS,KAAK,OAAO,KAAK;AACxE,QAAI,kBAAkB,MAAM,mBAAmB,IAAI;AACjD,UAAI,kBAAkB,GAAI,QAAO;AACjC,UAAI,mBAAmB,GAAI,QAAO;AAClC,aAAO,gBAAgB;AAAA,IACzB;AACA,WAAO,KAAK,cAAc,KAAK;AAAA,EACjC,CAAC,EACA;AAAA,IAAI,CAAC,WACJ,iBAAiB;AAAA,MACf;AAAA,MACA,MAAM,UAAU,IAAI,MAAM,KAAK;AAAA,MAC/B,SAASA,OAAM,QAAQ,OAAO,CAAC,WAAW,OAAO,WAAW,MAAM;AAAA,MAClE,UAAUA,OAAM,SAAS,OAAO,CAAC,YAAY,QAAQ,WAAW,MAAM;AAAA,IACxE,CAAC;AAAA,EACH;AAEF,QAAM,SAAS,aAAa;AAC5B,QAAM,WAAW,oBAAI,IAAY;AACjC,QAAM,SAAS,oBAAI,IAAY;AAE/B,aAAW,UAAUA,OAAM,SAAS;AAClC,sBAAkB,QAAQ,MAAM;AAChC,aAAS,IAAI,OAAO,WAAW,SAAS;AACxC,WAAO,IAAI,OAAO,SAAS,SAAS;AAAA,EACtC;AACA,aAAW,WAAWA,OAAM,UAAU;AACpC,aAAS,IAAI,QAAQ,WAAW,SAAS;AACzC,WAAO,IAAI,QAAQ,gBAAgB,SAAS;AAAA,EAC9C;AAEA,SAAO,WAAWA,OAAM,SAAS;AACjC,SAAO,WAAW,SAAS;AAC3B,SAAO,SAAS,OAAO;AAEvB,SAAO;AAAA,IACL,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC;AAAA,IACA;AAAA,EACF;AACF;;;ACnQA,SAAS,gBAAAC,sBAAoB;AAC7B,SAAS,WAAAC,UAAS,QAAAC,cAAY;AAC9B,SAAS,qBAAqB;AAE9B,IAAM,mBAAmB;AAEzB,IAAI;AAEG,SAAS,cAAc,UAAU,YAAY,KAAa;AAC/D,MAAI,eAAe;AACjB,WAAO;AAAA,EACT;AAEA,QAAM,kBAAkBA;AAAA,IACtBD,SAAQ,cAAc,OAAO,CAAC;AAAA,IAC9B;AAAA,IACA;AAAA,EACF;AAEA,MAAI;AACF,UAAM,cAAc,KAAK,MAAMD,eAAa,iBAAiB,OAAO,CAAC;AAIrE,oBACE,OAAO,YAAY,YAAY,WAC3B,YAAY,UACZ;AAAA,EACR,QAAQ;AACN,oBAAgB;AAAA,EAClB;AAEA,SAAO;AACT;;;ACzBA,IAAM,gBAAgB;AACtB,IAAM,mBAAmB;AAEzB,SAAS,UAAU,OAAuB;AACxC,MAAI,SAAS;AACb,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,QAAI,MAAM,WAAW,KAAK,MAAM,MAAM,MAAM,QAAQ,CAAC,MAAM,KAAK;AAC9D,eAAS;AACT,aAAO,QAAQ,MAAM,UAAU,MAAM,KAAK,MAAM,KAAK;AACnD,iBAAS;AAAA,MACX;AACA;AAAA,IACF;AACA,cAAU,MAAM,KAAK;AAAA,EACvB;AACA,SAAO;AACT;AAEA,SAAS,cAAc,OAAuB;AAC5C,SAAO,UAAU,KAAK,EAAE;AAC1B;AAEA,SAAS,SAAS,OAAe,UAA0B;AACzD,MAAI,YAAY,EAAG,QAAO;AAC1B,MAAI,cAAc,KAAK,KAAK,SAAU,QAAO;AAE7C,QAAM,QAAQ,UAAU,KAAK;AAC7B,MAAI,YAAY,EAAG,QAAO;AAC1B,SAAO,GAAG,MAAM,MAAM,GAAG,WAAW,CAAC,CAAC;AACxC;AAEA,SAAS,IAAI,OAAe,OAAuB;AACjD,SAAO,GAAG,KAAK,GAAG,IAAI,OAAO,KAAK,IAAI,GAAG,QAAQ,cAAc,KAAK,CAAC,CAAC,CAAC;AACzE;AAEA,SAAS,aAAa,OAAe,OAAuB;AAC1D,UAAQ,QAAQ,GAAG;AAAA,IACjB,KAAK;AACH,aAAO,KAAK,KAAK;AAAA,IACnB,KAAK;AACH,aAAO,MAAM,KAAK;AAAA,IACpB,KAAK;AACH,aAAO,OAAO,KAAK;AAAA,IACrB;AACE,aAAO,QAAQ,KAAK;AAAA,EACxB;AACF;AAEA,SAAS,eACP,MACA,OACA,eACQ;AACR,QAAM,WAAW,IAAI,KAAK,IAAI;AAC9B,QAAM,YAAY,aAAa,UAAK,KAAK;AACzC,SAAO,UAAU,gBACb,GAAG,SAAS,IAAI,KAAK,QAAQ,CAAC,KAC9B,GAAG,SAAS,IAAI,IAAI,QAAQ,CAAC;AACnC;AAEA,SAAS,oBAAoB,OAAuB;AAClD,QAAM,YAAY,KAAK,MAAM,SAAS,CAAC;AACvC,MAAI,KAAK,IAAI,SAAS,KAAK,KAAe;AACxC,WAAO,IAAI,YAAY,KAAe,QAAQ,CAAC,CAAC;AAAA,EAClD;AACA,MAAI,KAAK,IAAI,SAAS,KAAK,KAAW;AACpC,WAAO,IAAI,YAAY,KAAW,QAAQ,CAAC,CAAC;AAAA,EAC9C;AACA,MAAI,KAAK,IAAI,SAAS,KAAK,KAAO;AAChC,WAAO,IAAI,YAAY,KAAO,QAAQ,CAAC,CAAC;AAAA,EAC1C;AACA,SAAO,OAAO,SAAS;AACzB;AAEA,SAAS,eAAe,OAAuB;AAC7C,QAAM,OAAO,IAAI,KAAK,KAAK;AAC3B,MAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,EAAG,QAAO,SAAS;AAClD,SAAO,KAAK,eAAe,QAAW;AAAA,IACpC,OAAO;AAAA,IACP,KAAK;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,EACV,CAAC;AACH;AAEA,SAAS,eAAe,SAAyB;AAC/C,QAAM,cAAc,KAAK,IAAI,GAAG,KAAK,MAAM,WAAW,CAAC,CAAC;AACxD,MAAI,cAAc,GAAI,QAAO,GAAG,WAAW;AAC3C,QAAM,UAAU,KAAK,MAAM,cAAc,EAAE;AAC3C,MAAI,UAAU,GAAI,QAAO,GAAG,OAAO;AACnC,QAAM,QAAQ,KAAK,MAAM,UAAU,EAAE;AACrC,QAAM,cAAc,UAAU;AAC9B,SAAO,cAAc,IAAI,GAAG,KAAK,IAAI,WAAW,MAAM,GAAG,KAAK;AAChE;AAEA,SAAS,WACP,OACA,eACA,OACQ;AACR,QAAM,YAAY,MAAM;AAAA,IAAI,CAAC,MAAM,UACjC,eAAe,MAAM,OAAO,aAAa;AAAA,EAC3C;AACA,QAAM,WAAW,UAAU,KAAK,GAAG;AACnC,MAAI,cAAc,QAAQ,KAAK,OAAO;AACpC,WAAO;AAAA,EACT;AAEA,QAAM,gBAAgB,gBAAgB,IAAI,IAAI,SAAI,IAAI;AACtD,QAAM,SAAmB,CAAC;AAC1B,MAAI,YAAY,cAAc,aAAa;AAE3C,WAAS,QAAQ,eAAe,QAAQ,MAAM,QAAQ,SAAS,GAAG;AAChE,UAAM,QAAQ,eAAe,MAAM,KAAK,GAAG,OAAO,aAAa;AAC/D,UAAM,iBAAiB,OAAO,SAAS,IAAI,IAAI;AAC/C,UAAM,UAAU,QAAQ,MAAM,SAAS;AACvC,UAAM,sBAAsB,UAAU,IAAI;AAE1C,QACE,YAAY,iBAAiB,cAAc,KAAK,IAAI,sBACpD,OACA;AACA,UAAI,OAAO,WAAW,GAAG;AACvB,eAAO;AAAA,UACL,SAAS,OAAO,KAAK,IAAI,GAAG,QAAQ,YAAY,mBAAmB,CAAC;AAAA,QACtE;AAAA,MACF;AACA;AAAA,IACF;AAEA,QAAI,OAAO,SAAS,GAAG;AACrB,mBAAa;AAAA,IACf;AACA,WAAO,KAAK,KAAK;AACjB,iBAAa,cAAc,KAAK;AAAA,EAClC;AAEA,QAAM,aAAa,gBAAgB,OAAO,SAAS,MAAM;AACzD,QAAM,iBAAiB,aAAa,IAAI,gBAAM,IAAI;AAClD,SAAO;AAAA,IACL,GAAG,aAAa,GAAG,OAAO,KAAK,GAAG,CAAC,GAAG,cAAc;AAAA,IACpD;AAAA,EACF;AACF;AAEA,SAAS,eAAe,MAAuC;AAC7D,SAAO;AAAA,IACL,GAAG,KAAK,UAAU,CAAC,IAAI,IAAI,KAAK,MAAM,CAAC;AAAA,IACvC,cAAc,oBAAoB,KAAK,OAAO,WAAW,CAAC,eAAY,oBAAoB,KAAK,OAAO,WAAW,CAAC,eAAY,oBAAoB,KAAK,OAAO,YAAY,CAAC;AAAA,IAC3K,cAAc,oBAAoB,KAAK,OAAO,YAAY,CAAC,gBAAa,oBAAoB,KAAK,OAAO,eAAe,CAAC;AAAA,IACxH,cAAc,KAAK,OAAO,QAAQ,kBAAe,KAAK,OAAO,OAAO,iBAAc,KAAK,OAAO,QAAQ,kBAAe,KAAK,OAAO,MAAM;AAAA,EACzI;AACF;AAEA,SAAS,gBAAgB,OAAe,OAAuC;AAC7E,QAAM,QAAQ,CAAC,KAAK,KAAK,CAAC;AAC1B,MAAI,MAAM,WAAW,GAAG;AACtB,UAAM,KAAK,IAAI,mBAAmB,CAAC;AACnC,WAAO;AAAA,EACT;AAEA,QAAM,KAAK,IAAI,KAAK,IAAI,QAAQ,EAAE,CAAC,IAAI,IAAI,UAAU,EAAE,CAAC,WAAW,CAAC;AACpE,aAAW,QAAQ,MAAM,MAAM,GAAG,aAAa,GAAG;AAChD,UAAM;AAAA,MACJ,KAAK,IAAI,SAAS,KAAK,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,oBAAoB,KAAK,WAAW,GAAG,EAAE,CAAC,IAAI,KAAK,QAAQ;AAAA,IAC1G;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,mBAAmB,OAA0C;AACpE,QAAM,QAAQ,CAAC,KAAK,iBAAiB,CAAC;AACtC,MAAI,MAAM,WAAW,GAAG;AACtB,UAAM,KAAK,IAAI,sBAAsB,CAAC;AACtC,WAAO;AAAA,EACT;AAEA,QAAM;AAAA,IACJ;AAAA,MACE,KAAK,IAAI,QAAQ,EAAE,CAAC,IAAI,IAAI,WAAW,EAAE,CAAC,IAAI,IAAI,SAAS,EAAE,CAAC,IAAI,IAAI,UAAU,CAAC,CAAC;AAAA,IACpF;AAAA,EACF;AACA,aAAW,WAAW,MAAM,MAAM,GAAG,gBAAgB,GAAG;AACtD,UAAM;AAAA,MACJ,KAAK,IAAI,eAAe,QAAQ,aAAa,GAAG,EAAE,CAAC,IAAI,IAAI,SAAS,QAAQ,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,SAAS,QAAQ,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,oBAAoB,QAAQ,WAAW,GAAG,CAAC,CAAC,IAAI,IAAI,OAAO,QAAQ,YAAY,GAAG,CAAC,CAAC,IAAI,eAAe,QAAQ,aAAa,CAAC;AAAA,IACnR;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,WACP,MACA,UACA,eACA,OACA,aACQ;AACR,QAAM,QAAQ;AAAA,IACZ,GAAG,KAAK,QAAG,CAAC,IAAI,KAAK,wBAAwB,CAAC;AAAA,IAC9C;AAAA,MACE,cACI,0EACA;AAAA,IACN;AAAA,IACA;AAAA,IACA,WAAW,UAAU,eAAe,KAAK;AAAA,IACzC;AAAA,IACA,GAAG,eAAe,IAAI;AAAA,IACtB;AAAA,IACA,GAAG,gBAAgB,cAAc,KAAK,SAAS;AAAA,IAC/C;AAAA,IACA,GAAG,gBAAgB,gBAAgB,KAAK,WAAW;AAAA,IACnD;AAAA,IACA,GAAG,mBAAmB,KAAK,QAAQ;AAAA,EACrC;AAEA,SAAO,MAAM,IAAI,CAAC,SAAS,SAAS,MAAM,KAAK,CAAC,EAAE,KAAK,IAAI;AAC7D;AAEO,SAAS,0BACd,MACA,gBAAgB,GAChB,UAAqD,CAAC,GAC9C;AACR,QAAM,QAAQ,KAAK,IAAI,IAAI,QAAQ,SAAS,QAAQ,OAAO,WAAW,GAAG;AAEzE,MAAI,KAAK,MAAM,WAAW,KAAK,KAAK,OAAO,gBAAgB,GAAG;AAC5D,WAAO;AAAA,MACL,GAAG,KAAK,QAAG,CAAC,IAAI,KAAK,wBAAwB,CAAC;AAAA,MAC9C,IAAI,oCAAoC;AAAA,MACxC;AAAA,MACA;AAAA,QACE;AAAA,MACF;AAAA,IACF,EACG,IAAI,CAAC,SAAS,SAAS,MAAM,KAAK,CAAC,EACnC,KAAK,IAAI;AAAA,EACd;AAEA,QAAM,YAAY,KAAK,IAAI,GAAG,KAAK,IAAI,eAAe,KAAK,MAAM,SAAS,CAAC,CAAC;AAC5E,SAAO;AAAA,IACL,KAAK,MAAM,SAAS;AAAA,IACpB,KAAK;AAAA,IACL;AAAA,IACA;AAAA,IACA,QAAQ,QAAQ,WAAW;AAAA,EAC7B;AACF;AAEA,SAAS,WAAW,OAAwB;AAC1C,SAAO,UAAU;AACnB;AAEA,SAAS,aAAa,OAAwB;AAC5C,SAAO,UAAU,OAAQ,UAAU;AACrC;AAEA,SAAS,iBAAiB,OAAwB;AAChD,SAAO,WAAW,KAAK,KAAK,UAAU;AACxC;AAEA,SAAS,OAAO,OAAwB;AACtC,SACE,UAAU,OAAO,UAAU,OAAO,UAAU,UAAY,UAAU;AAEtE;AAEA,eAAsB,wBACpB,MACe;AACf,MAAI,CAAC,QAAQ,MAAM,SAAS,CAAC,QAAQ,OAAO,OAAO;AACjD,YAAQ,OAAO,MAAM,GAAG,0BAA0B,IAAI,CAAC;AAAA,CAAI;AAC3D;AAAA,EACF;AAEA,MAAI,KAAK,MAAM,WAAW,KAAK,KAAK,OAAO,gBAAgB,GAAG;AAC5D,YAAQ,OAAO,MAAM,GAAG,0BAA0B,IAAI,CAAC;AAAA,CAAI;AAC3D;AAAA,EACF;AAEA,MAAI,gBAAgB;AACpB,QAAM,QAAQ,QAAQ;AACtB,QAAM,SAAS,QAAQ;AACvB,QAAM,SAAS,MAAM;AAErB,QAAM,IAAI,QAAc,CAACG,aAAY;AACnC,UAAM,SAAS,MAAM;AACnB,aAAO,MAAM,wBAA8B;AAC3C,aAAO;AAAA,QACL,0BAA0B,MAAM,eAAe;AAAA,UAC7C,aAAa;AAAA,UACb,OAAO,OAAO,WAAW;AAAA,QAC3B,CAAC;AAAA,MACH;AACA,aAAO,MAAM,IAAI;AAAA,IACnB;AAEA,UAAM,UAAU,MAAM;AACpB,aAAO,MAAM,wBAA8B;AAC3C,YAAM,IAAI,QAAQ,MAAM;AACxB,aAAO,IAAI,UAAU,MAAM;AAC3B,UAAI,MAAM,MAAO,OAAM,WAAW,MAAM;AACxC,YAAM,MAAM;AACZ,MAAAA,SAAQ;AAAA,IACV;AAEA,UAAM,SAAS,CAAC,UAA2B;AACzC,YAAM,QAAQ,MAAM,SAAS,MAAM;AACnC,UAAI,OAAO,KAAK,GAAG;AACjB,gBAAQ;AACR;AAAA,MACF;AACA,UAAI,aAAa,KAAK,GAAG;AACvB,yBAAiB,gBAAgB,KAAK,KAAK,MAAM;AACjD,eAAO;AACP;AAAA,MACF;AACA,UAAI,iBAAiB,KAAK,GAAG;AAC3B,yBACG,gBAAgB,IAAI,KAAK,MAAM,UAAU,KAAK,MAAM;AACvD,eAAO;AAAA,MACT;AAAA,IACF;AAEA,UAAM,WAAW,IAAI;AACrB,UAAM,OAAO;AACb,UAAM,YAAY,MAAM;AACxB,UAAM,GAAG,QAAQ,MAAM;AACvB,WAAO,GAAG,UAAU,MAAM;AAC1B,WAAO;AAAA,EACT,CAAC;AACH;;;AC1TA,SAAS,YAAY,OAAwB;AAC3C,SAAO,SAAS;AAClB;AAEA,eAAe,qBAAoC;AACjD,MAAI,CAAC,QAAQ,MAAM,SAAS,CAAC,QAAQ,OAAO,OAAO;AACjD,UAAMC,UAAS,MAAM,cAAc;AACnC,UAAM;AAAA,MACJ,6BAA6B;AAAA,QAC3B,SAASA,QAAO;AAAA,QAChB,UAAUA,QAAO;AAAA,QACjB,OAAO,YAAY;AAAA,MACrB,CAAC;AAAA,IACH;AACA;AAAA,EACF;AAEA,UAAQ,OAAO,MAAM,6BAAwB;AAC7C,QAAM,SAAS,MAAM,cAAc;AACnC,QAAM;AAAA,IACJ,6BAA6B;AAAA,MAC3B,SAAS,OAAO;AAAA,MAChB,UAAU,OAAO;AAAA,MACjB,OAAO,YAAY;AAAA,IACrB,CAAC;AAAA,EACH;AACF;AAEA,eAAsB,UACpB,OAA6B,CAAC,GACf;AACf,MAAI,KAAK,MAAM;AACb,UAAM,mBAAmB;AACzB;AAAA,EACF;AAEA,QAAM,SAAS,WAAW;AAC1B,SAAO;AAAA,IACL;AAAA,MACE;AAAA,MACA,gBAAM,cAAc,CAAC;AAAA,IACvB;AAAA,EACF;AAEA,SAAO,KAAK,cAAc,cAAI,CAAC;AAC/B,MAAI,CAAC,QAAQ,QAAQ;AACnB,WAAO,KAAK,eAAe,gBAAM,kBAAkB,sBAAO,SAAS,CAAC,CAAC;AACrE,WAAO,KAAK,aAAa,2EAA8B,SAAS,CAAC;AAAA,EACnE,OAAO;AACL,WAAO,KAAK,eAAe,gBAAM,kBAAkB,sBAAO,SAAS,CAAC,CAAC;AACrE,WAAO,KAAK,eAAe,4BAAQ,cAAc,CAAC,CAAC;AACnD,WAAO,KAAK,eAAe,WAAW,WAAW,OAAO,MAAM,CAAC,CAAC;AAChE,WAAO;AAAA,MACL,eAAe,WAAW,OAAO,UAAU,wBAAwB;AAAA,IACrE;AACA,QAAI,OAAO,cAAc;AACvB,aAAO;AAAA,QACL;AAAA,UACE;AAAA,UACA,GAAG,KAAK,MAAM,OAAO,eAAe,GAAK,CAAC;AAAA,QAC5C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,KAAK,cAAc,gCAAO,CAAC;AAClC,QAAM,WAAW,qBAAqB;AACtC,MAAI,SAAS,WAAW,GAAG;AACzB,WAAO,KAAK,aAAa,iEAAoB,SAAS,CAAC;AAAA,EACzD,OAAO;AACL,eAAW,QAAQ,UAAU;AAC3B,aAAO,KAAK,aAAa,KAAK,MAAM,SAAS,CAAC;AAAA,IAChD;AAAA,EACF;AAEA,SAAO,KAAK,cAAc,gCAAO,CAAC;AAClC,aAAW,QAAQ,YAAY,GAAG;AAChC,UAAM,YAAY,gBAAgB,KAAK,EAAE;AACzC,WAAO;AAAA,MACL;AAAA,QACE,GAAG,KAAK,IAAI,SAAM,YAAY,uBAAQ,oBAAK;AAAA,QAC3C,YAAY,YAAY;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AAEA,QAAM,YAAY,cAAc;AAChC,SAAO,KAAK,cAAc,0BAAM,CAAC;AACjC,QAAM,aACJ,UAAU,WAAW,SACjB,YACA,UAAU,WAAW,YACnB,YACA;AACR,SAAO;AAAA,IACL,eAAe,gBAAM,kBAAkB,UAAU,QAAQ,UAAU,CAAC;AAAA,EACtE;AACA,SAAO,KAAK,eAAe,4BAAQ,YAAY,UAAU,aAAa,CAAC,CAAC;AACxE,SAAO,KAAK,eAAe,4BAAQ,YAAY,UAAU,aAAa,CAAC,CAAC;AACxE,MAAI,UAAU,YAAY;AACxB,WAAO,KAAK,eAAe,4BAAQ,UAAU,UAAU,CAAC;AAAA,EAC1D;AACA,MAAI,UAAU,WAAW;AACvB,WAAO,KAAK,eAAe,4BAAQ,UAAU,SAAS,CAAC;AAAA,EACzD;AACA,MAAI,UAAU,YAAY;AACxB,WAAO;AAAA,MACL;AAAA,QACE;AAAA,QACA,GAAG,UAAU,WAAW,OAAO,aAAa,UAAU,WAAW,QAAQ;AAAA,MAC3E;AAAA,IACF;AAAA,EACF;AACF;;;AC5HA,eAAsB,eACpB,OAA2B,CAAC,GACb;AACf,QAAM,SAAS,WAAW;AAC1B,MAAI,CAAC,QAAQ,QAAQ;AACnB,QAAI,sBAAsB,GAAG;AAC3B,aAAO;AAAA,QACL,aAAa,8CAAW,kFAAsB;AAAA,MAChD;AACA,YAAM,aAAa,MAAM,cAAc;AAAA,QACrC,SAAS;AAAA,QACT,cAAc;AAAA,MAChB,CAAC;AACD,UAAI,YAAY;AACd,cAAM,QAAQ;AACd;AAAA,MACF;AACA,aAAO,KAAK,aAAa,wCAAU,SAAS,CAAC;AAC7C;AAAA,IACF;AAEA,WAAO,MAAM,8CAA8C;AAC3D,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,QAAQ,QAAQ;AAAA,IACpB,OAAO,KAAK;AAAA,IACZ,QAAQ;AAAA,EACV,CAAC;AACH;;;AC3CA,SAAS,cAAAC,cAAY,gBAAAC,gBAAc,UAAAC,SAAQ,iBAAAC,sBAAqB;AAChE,SAAS,WAAAC,WAAS,YAAAC,iBAAgB;AAsBlC,SAAS,mBAAyB;AAChC,QAAM,QAAQ,QAAQ,IAAI;AAC1B,MAAI,CAAC,MAAO;AAEZ,QAAM,YAAY,MAAM,MAAM,GAAG,EAAE,IAAI,KAAK;AAC5C,QAAM,YAAY;AAElB,MAAI;AAEJ,UAAQ,WAAW;AAAA,IACjB,KAAK;AACH,mBAAa,GAAGC,UAAQ,CAAC;AACzB;AAAA,IACF,KAAK;AACH,UAAIC,UAAS,MAAM,YAAYC,aAAW,GAAGF,UAAQ,CAAC,gBAAgB,GAAG;AACvE,qBAAa,GAAGA,UAAQ,CAAC;AAAA,MAC3B,OAAO;AACL,qBAAa,GAAGA,UAAQ,CAAC;AAAA,MAC3B;AACA;AAAA,IACF,KAAK;AACH,mBAAa,GAAGA,UAAQ,CAAC;AACzB;AAAA,IACF;AACE;AAAA,EACJ;AAEA,MAAI,CAACE,aAAW,UAAU,EAAG;AAE7B,MAAI;AACF,QAAI,UAAUC,eAAa,YAAY,OAAO;AAG9C,UAAM,gBAAgB;AAAA;AAAA,MAEpB,IAAI;AAAA,QACF,gDAAgD,SAAS;AAAA,QACzD;AAAA,MACF;AAAA;AAAA,MAEA,IAAI;AAAA,QACF,gDAAgD,SAAS;AAAA,QACzD;AAAA,MACF;AAAA;AAAA,MAEA,IAAI,OAAO,gBAAgB,SAAS,iCAAiC,GAAG;AAAA,MACxE,IAAI,OAAO,gBAAgB,SAAS,4BAA4B,GAAG;AAAA,IACrE;AAEA,eAAW,WAAW,eAAe;AACnC,YAAM,OAAO,QAAQ,QAAQ,SAAS,IAAI;AAC1C,UAAI,SAAS,SAAS;AACpB,kBAAU;AAAA,MACZ;AAAA,IACF;AAEA,IAAAC,eAAc,YAAY,SAAS,OAAO;AAC1C,WAAO,KAAK,4BAA4B,UAAU,EAAE;AAAA,EACtD,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,oBAAoB,UAAU,KAAM,IAAc,OAAO;AAAA,IAC3D;AAAA,EACF;AACF;AAEA,eAAsB,eAA8B;AAClD,QAAM,aAAa,cAAc;AACjC,QAAM,YAAY,aAAa;AAC/B,QAAM,WAAW,YAAY;AAC7B,QAAM,aAAa,kBAAkB;AACrC,QAAM,iBAAiB,kBAAkB;AACzC,QAAM,sBAAsB,gBAAgB,YAAY,KAAK;AAC7D,QAAM,oBACJF,aAAW,UAAU,KACrBA,aAAW,SAAS,KACpBA,aAAW,QAAQ,KACnBA,aAAW,UAAU,KACrB;AAEF,MAAI,CAAC,mBAAmB;AACtB,WAAO,KAAK,aAAa,yBAAe,CAAC;AACzC,WAAO,KAAK,aAAa,gFAAe,CAAC;AACzC;AAAA,EACF;AAEA,QAAM,SAAS,WAAW;AAC1B,SAAO;AAAA,IACL;AAAA,MACE;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,QAAQ,QAAQ;AAClB,WAAO,KAAK,eAAe,WAAW,WAAW,OAAO,MAAM,CAAC,CAAC;AAAA,EAClE;AACA,SAAO,KAAK,eAAe,4BAAQ,SAAS,CAAC;AAC7C,SAAO,KAAK,eAAe,4BAAQ,QAAQ,CAAC;AAC5C,SAAO,KAAK,eAAe,4BAAQ,UAAU,CAAC;AAC9C,MAAI,uBAAuB,gBAAgB;AACzC,WAAO,KAAK,eAAe,4BAAQ,eAAe,kBAAkB,CAAC,CAAC;AAAA,EACxE;AAEA,QAAM,kBAAkB,MAAM,cAAc;AAAA,IAC1C,SAAS;AAAA,IACT,cAAc;AAAA,EAChB,CAAC;AACD,MAAI,CAAC,iBAAiB;AACpB,WAAO,KAAK,aAAa,wCAAU,SAAS,CAAC;AAC7C;AAAA,EACF;AAEA,MAAI,uBAAuB,gBAAgB;AACzC,UAAM,sBAAsB,MAAM,cAAc;AAAA,MAC9C,SAAS,wCAAU,eAAe,WAAW;AAAA,MAC7C,cAAc;AAAA,IAChB,CAAC;AAED,QAAI,qBAAqB;AACvB,UAAI;AACF,cAAM,eAAe,UAAU,IAAI;AAAA,MACrC,SAAS,KAAK;AACZ,eAAO,KAAK,qDAAc,IAAc,OAAO,EAAE;AAAA,MACnD;AAAA,IACF;AAAA,EACF;AAGA,SAAO,KAAK,cAAc,0BAAM,CAAC;AACjC,MAAIA,aAAW,UAAU,GAAG;AAC1B,iBAAa;AACb,WAAO,KAAK,aAAa,oDAAY,SAAS,CAAC;AAAA,EACjD;AAGA,MAAIA,aAAW,SAAS,GAAG;AACzB,QAAI;AACF,MAAAG,QAAO,WAAW,EAAE,WAAW,OAAO,OAAO,KAAK,CAAC;AACnD,aAAO,KAAK,aAAa,oDAAY,SAAS,CAAC;AAAA,IACjD,QAAQ;AAAA,IAER;AAAA,EACF;AAGA,MAAIH,aAAW,QAAQ,GAAG;AACxB,IAAAG,QAAO,UAAU,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACjD,WAAO,KAAK,aAAa,oDAAY,SAAS,CAAC;AAAA,EACjD;AAGA,MAAIH,aAAW,UAAU,GAAG;AAC1B,IAAAG,QAAO,YAAY,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACnD,WAAO,KAAK,aAAa,0DAAa,SAAS,CAAC;AAAA,EAClD;AAGA,mBAAiB;AAEjB,SAAO,KAAK,cAAc,cAAI,CAAC;AAC/B,SAAO,KAAK,aAAa,qEAAwB,SAAS,CAAC;AAC7D;;;AC3JA,SAAS,iBAAuB;AAC9B,QAAM,SAAS,WAAW;AAC1B,QAAM,aAAa,QAAQ,QAAQ,MAAM;AAEzC,SAAO;AAAA,IACL;AAAA,MACE;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,SAAO;AAAA,IACL;AAAA,MACE;AAAA,MACA,aACI,kBAAkB,sBAAO,SAAS,IAClC,kBAAkB,sBAAO,SAAS;AAAA,IACxC;AAAA,EACF;AAEA,MAAI,cAAc,QAAQ;AACxB,WAAO,KAAK,eAAe,WAAW,WAAW,OAAO,MAAM,CAAC,CAAC;AAChE,WAAO;AAAA,MACL,eAAe,oBAAU,OAAO,UAAU,wBAAwB;AAAA,IACpE;AAAA,EACF,OAAO;AACL,WAAO,KAAK,aAAa,0FAAyB,SAAS,CAAC;AAAA,EAC9D;AACF;AAEA,eAAe,iBAAsC;AACnD,SAAO,aAAyB;AAAA,IAC9B,SAAS;AAAA,IACT,SAAS;AAAA,MACP;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,aAAa;AAAA,MACf;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,aAAa;AAAA,MACf;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,aAAa;AAAA,MACf;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,aAAa;AAAA,MACf;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,aAAa;AAAA,MACf;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,aAAa;AAAA,MACf;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,aAAa;AAAA,MACf;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,eAAsB,QAAQ,SAAiC;AAC7D,SAAO,MAAM;AACX,mBAAe;AAEf,UAAM,SAAS,MAAM,eAAe;AACpC,WAAO,KAAK,EAAE;AAEd,YAAQ,QAAQ;AAAA,MACd,KAAK;AACH,cAAM,QAAQ;AACd;AAAA,MACF,KAAK;AACH,cAAM,UAAU;AAChB;AAAA,MACF,KAAK;AACH,cAAM,eAAe;AACrB;AAAA,MACF,KAAK;AACH,cAAM,aAAa,CAAC,CAAC;AACrB;AAAA,MACF,KAAK;AACH,cAAM,UAAU;AAChB;AAAA,MACF,KAAK;AACH,cAAM,aAAa;AACnB;AAAA,MACF,KAAK;AACH,gBAAQ,WAAW;AACnB;AAAA,MACF,KAAK;AACH,eAAO,KAAK,aAAa,0DAAa,SAAS,CAAC;AAChD;AAAA,IACJ;AAEA,UAAM,iBAAiB,MAAM,cAAc;AAAA,MACzC,SAAS;AAAA,MACT,cAAc;AAAA,IAChB,CAAC;AAED,QAAI,CAAC,gBAAgB;AACnB,aAAO,KAAK,aAAa,4EAA0B,SAAS,CAAC;AAC7D;AAAA,IACF;AAAA,EACF;AACF;;;ACvIA,SAAS,WAAW,aAA4B;AAC9C,SAAO,KAAK,aAAa,iDAAmB,CAAC;AAC7C,MAAI,aAAa;AACf,WAAO,KAAK,eAAe,4BAAQ,WAAW,CAAC;AAAA,EACjD;AACA,SAAO,KAAK,cAAc,0BAAM,CAAC;AACjC,SAAO,KAAK,aAAa,wDAAqB,CAAC;AAC/C,SAAO,KAAK,aAAa,sCAAkB,CAAC;AAC5C,SAAO,KAAK,aAAa,sCAAkB,CAAC;AAC5C,SAAO,KAAK,aAAa,sCAAkB,CAAC;AAC5C,SAAO,KAAK,aAAa,kDAAoB,CAAC;AAC9C,SAAO,KAAK,aAAa,sCAAkB,CAAC;AAC9C;AAEA,eAAsB,kBACpB,MACe;AACf,QAAM,UAAU,kBAAkB;AAClC,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,MACL;AAAA,QACE;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA;AAAA,EACF;AAEA,QAAM,SAAS,KAAK,QAAQ,YAAY;AACxC,MAAI,CAAC,QAAQ;AACX,eAAW,QAAQ,WAAW;AAC9B,UAAM,UAAU,QAAQ,SAAS;AACjC,QAAI,CAAC,QAAQ,MAAM,QAAQ,QAAQ;AACjC,aAAO;AAAA,QACL,aAAa,2EAAe,QAAQ,MAAM,IAAI,SAAS;AAAA,MACzD;AAAA,IACF;AACA;AAAA,EACF;AAEA,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,YAAM,QAAQ,MAAM,KAAK,UAAU;AACnC;AAAA,IACF,KAAK;AACH,YAAM,QAAQ,MAAM;AACpB;AAAA,IACF,KAAK;AACH,YAAM,QAAQ,KAAK;AACnB;AAAA,IACF,KAAK;AACH,YAAM,QAAQ,QAAQ;AACtB;AAAA,IACF,KAAK;AACH,YAAM,QAAQ,OAAO;AACrB;AAAA,IACF,KAAK;AACH,YAAM,QAAQ,UAAU,KAAK,UAAU;AACvC;AAAA,IACF;AACE,aAAO,MAAM,6BAAS,MAAM,EAAE;AAC9B,cAAQ,KAAK,CAAC;AAAA,EAClB;AACF;;;A9BjEA,IAAM,cAAc,cAAc;AAE3B,SAAS,YAAqB;AACnC,QAAM,UAAU,IAAI,QAAQ;AAE5B,UACG,KAAK,YAAY,EACjB,YAAY,yCAAyC,EACrD,QAAQ,WAAW,EACnB,mBAAmB,EACnB,yBAAyB,EACzB,YAAY,kBAAkB,0BAA0B;AAG3D,UAAQ,OAAO,YAAY;AACzB,UAAM,WAAW,QAAQ,KAAK,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,CAAC;AACvE,QAAI,SAAS,SAAS,GAAG;AACvB,cAAQ,MAAM,oBAAoB,SAAS,CAAC,CAAC,GAAG;AAAA,IAClD;AACA,QAAI,sBAAsB,GAAG;AAC3B,YAAM,QAAQ,OAAO;AACrB;AAAA,IACF;AACA,YAAQ,KAAK;AAAA,EACf,CAAC;AAGD,UACG,QAAQ,MAAM,EACd,YAAY,uCAAuC,EACnD,OAAO,mBAAmB,uBAAuB,EACjD,OAAO,OAAO,SAAS;AACtB,UAAM,QAAQ,IAAI;AAAA,EACpB,CAAC;AAGH,UACG,QAAQ,MAAM,EACd,YAAY,oCAAoC,EAChD,UAAU,IAAI,OAAO,SAAS,EAAE,SAAS,CAAC,EAC1C,OAAO,OAAO,SAAS;AACtB,UAAM,eAAe,IAAI;AAAA,EAC3B,CAAC;AAGH,UACG,QAAQ,QAAQ,EAChB,YAAY,mDAAmD,EAC/D,OAAO,mBAAmB,iCAAiC,QAAQ,EACnE,UAAU,IAAI,OAAO,WAAW,EAAE,SAAS,CAAC,EAC5C,OAAO,OAAO,SAAS;AACtB,UAAM,UAAU,IAAI;AAAA,EACtB,CAAC;AAGH,UACG,QAAQ,kBAAkB,EAC1B;AAAA,IACC;AAAA,EACF,EACC,OAAO,OAAO,WAAW;AACxB,UAAM,kBAAkB,EAAE,OAAO,CAAC;AAAA,EACpC,CAAC;AAGH,UACG,QAAQ,QAAQ,EAChB,YAAY,uCAAuC,EACnD,OAAO,UAAU,wCAAwC,EACzD,OAAO,OAAO,SAAS;AACtB,UAAM,UAAU,IAAI;AAAA,EACtB,CAAC;AAGH,UACG,QAAQ,QAAQ,EAChB,YAAY,sBAAsB,EAClC,SAAS,gBAAgB,cAAc,EACvC,SAAS,SAAS,YAAY,EAC9B,SAAS,WAAW,cAAc,EAClC,mBAAmB,IAAI,EACvB,OAAO,OAAO,YAAY,KAAK,UAAU;AACxC,UAAM;AAAA,MACJ,CAAC,YAAY,KAAK,KAAK,EAAE;AAAA,QACvB,CAAC,SAAyB,OAAO,SAAS;AAAA,MAC5C;AAAA,IACF;AAAA,EACF,CAAC;AAGH,UACG,QAAQ,WAAW,EACnB,YAAY,yCAAyC,EACrD,OAAO,YAAY;AAClB,UAAM,aAAa;AAAA,EACrB,CAAC;AAEH,SAAO;AACT;;;A+B9GA,SAAS,cAAAC,cAAY,gBAAAC,qBAAoB;AACzC,SAAS,WAAAC,gBAAe;AACxB,SAAS,iBAAAC,sBAAqB;AAEvB,SAAS,aACd,YAAY,QAAQ,KAAK,CAAC,GAC1B,UAAU,YAAY,KACb;AACT,MAAI,CAAC,WAAW;AACd,WAAO;AAAA,EACT;AAEA,QAAM,oBAAoBA,eAAc,OAAO;AAE/C,MAAI;AACF,WAAOF,cAAa,SAAS,MAAMA,cAAa,iBAAiB;AAAA,EACnE,QAAQ;AACN,QAAI,CAACD,aAAW,SAAS,GAAG;AAC1B,aAAO;AAAA,IACT;AAEA,WAAOE,SAAQ,SAAS,MAAMA,SAAQ,iBAAiB;AAAA,EACzD;AACF;;;ACCO,SAAS,cAAc,MAAgB;AAC5C,SAAO,KAAK,OAAO,CAAC,KAAK,UAAU,QAAQ,KAAK,QAAQ,IAAI;AAC9D;AAEA,eAAsB,IAAI,OAAO,QAAQ,MAAM;AAC7C,QAAM,UAAU,UAAU;AAC1B,QAAM,QAAQ,WAAW,cAAc,IAAI,CAAC;AAC9C;AAEA,IAAI,aAAa,GAAG;AAClB,OAAK,IAAI;AACX;","names":["existsSync","join","sep","hostname","hostname","existsSync","existsSync","join","sep","existsSync","homedir","join","join","homedir","existsSync","homedir","join","TOOL_ID","TOOL_NAME","join","homedir","createToolDefinition","toSafeNumber","getPathLeaf","existsSync","existsSync","readdirSync","readFileSync","homedir","basename","join","TOOL","join","homedir","existsSync","readdirSync","readFileSync","basename","existsSync","homedir","join","TOOL_ID","TOOL_NAME","join","homedir","createToolDefinition","toSafeNumber","existsSync","existsSync","readdirSync","readFileSync","homedir","basename","dirname","join","join","homedir","TOOL","existsSync","readdirSync","basename","dirname","readFileSync","existsSync","homedir","join","TOOL_ID","TOOL_NAME","DEFAULT_SESSIONS_DIR","join","homedir","createToolDefinition","toSafeNumber","getPathLeaf","normalizeForPrefix","getUsageNumber","existsSync","execFileSync","existsSync","readdirSync","readFileSync","homedir","basename","join","DEFAULT_DATA_DIR","join","homedir","TOOL","withSuppressedSqliteWarning","readSqliteRowsWithBuiltin","readSqliteRowsWithCli","execFileSync","existsSync","basename","readdirSync","readFileSync","existsSync","readdirSync","readFileSync","homedir","join","TOOL_ID","TOOL_NAME","DEFAULT_DATA_DIR","join","homedir","TOOL","readdirSync","existsSync","readFileSync","existsSync","readdirSync","homedir","join","TOOL_ID","TOOL_NAME","DEFAULT_DATA_DIR","join","homedir","createToolDefinition","toSafeNumber","getPathLeaf","normalizeForPrefix","findSessionFiles","existsSync","readdirSync","existsSync","readdirSync","homedir","join","TOOL_ID","TOOL_NAME","DEFAULT_SESSIONS_DIR","join","homedir","createToolDefinition","toSafeNumber","getPathLeaf","existsSync","readdirSync","existsSync","readdirSync","homedir","basename","dirname","join","TOOL_ID","TOOL_NAME","DEFAULT_DATA_DIR","join","homedir","createToolDefinition","findSessionFiles","existsSync","readdirSync","toSafeNumber","basename","dirname","existsSync","homedir","join","TOOL_ID","TOOL_NAME","DEFAULT_SESSIONS_DIR","join","homedir","createToolDefinition","toSafeNumber","getPathLeaf","normalizeForPrefix","getUsageNumber","existsSync","existsSync","readdirSync","homedir","hostname","join","TOOL_ID","TOOL_NAME","join","homedir","createToolDefinition","toSafeNumber","existsSync","readdirSync","hostname","readFileSync","homedir","basename","join","TOOL","join","homedir","readFileSync","basename","execFileSync","existsSync","readdirSync","readFileSync","statSync","homedir","join","join","homedir","TOOL","existsSync","execFileSync","readFileSync","statSync","readdirSync","resolveModel","readdirSync","readFileSync","statSync","homedir","basename","join","EXTENSION_ID","HOSTS","getHostRoots","join","homedir","statSync","readJsonSafe","readFileSync","projectFromPath","basename","readdirSync","TOOL","execFileSync","copyFileSync","existsSync","mkdtempSync","rmSync","homedir","tmpdir","dirname","join","resolve","TOOL_ID","TOOL_NAME","join","homedir","resolve","existsSync","execFileSync","isLockError","mkdtempSync","tmpdir","copyFileSync","rmSync","createToolDefinition","dirname","createHash","existsSync","homedir","hostname","dirname","join","TOOL_ID","TOOL_NAME","DEFAULT_DB_PATH","join","homedir","createToolDefinition","dirname","toSafeNumber","getString","getPathLeaf","buildSessionUsage","input","hostname","createHash","existsSync","existsSync","readFileSync","join","homedir","join","join","homedir","join","existsSync","readFileSync","hostname","input","createHash","input","URL","resolve","existsSync","readFileSync","rmSync","writeFileSync","mkdirSync","join","join","mkdirSync","existsSync","readFileSync","rmSync","writeFileSync","existsSync","readFileSync","writeFileSync","existsSync","readFileSync","writeFileSync","existsSync","readFileSync","writeFileSync","existsSync","readFileSync","writeFileSync","input","hostname","execFileSync","existsSync","homedir","platform","dirname","join","posix","platform","execFileSync","existsSync","mkdirSync","rmSync","writeFileSync","homedir","platform","homedir","platform","execFileSync","existsSync","mkdirSync","writeFileSync","rmSync","execFileSync","existsSync","mkdirSync","rmSync","writeFileSync","homedir","platform","posix","homedir","posix","platform","execFileSync","mkdirSync","writeFileSync","existsSync","rmSync","platform","posix","input","platform","join","execFileSync","homedir","existsSync","dirname","resolve","input","readFileSync","dirname","join","resolve","result","existsSync","readFileSync","rmSync","writeFileSync","homedir","platform","homedir","platform","existsSync","readFileSync","writeFileSync","rmSync","existsSync","realpathSync","resolve","fileURLToPath"]}