@strideops/bridge 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{autostart-77BPPTEG.js → autostart-ASW5MDQS.js} +46 -14
- package/dist/autostart-ASW5MDQS.js.map +1 -0
- package/dist/{chunk-GBLMB3XB.js → chunk-6LRDE2ZS.js} +9 -3
- package/dist/chunk-6LRDE2ZS.js.map +1 -0
- package/dist/cli.js +1293 -187
- package/dist/cli.js.map +1 -1
- package/package.json +7 -2
- package/dist/autostart-77BPPTEG.js.map +0 -1
- package/dist/chunk-GBLMB3XB.js.map +0 -1
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/version.ts","../src/pair.ts","../src/api.ts","../src/hooks-writer.ts","../src/agents.ts","../src/session.ts","../src/runner.ts","../src/quota.ts","../src/poller.ts","../src/cli.ts"],"names":["mkdirSync","join","writeFileSync","existsSync","homedir","platform","release","sleep"],"mappings":"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","file":"cli.js","sourcesContent":["/**\n * Daemon version — keep in sync with package.json.\n * Single source of truth used in heartbeats, pair requests, and CLI output.\n */\nexport const VERSION = \"0.1.3\"\n","/**\n * pair.ts — Pair this machine with a StrideOps workspace via a pairing code.\n *\n * Sends machine info to /api/bridge/v1/pair and saves the returned\n * credentials to ~/.stride-bridge/config.json.\n */\n\nimport { hostname, platform, arch, cpus, totalmem, release } from \"node:os\"\nimport { VERSION } from \"./version.js\"\nimport { writeConfig } from \"./config.js\"\nimport { log } from \"./log.js\"\n\ninterface PairRequest {\n pairingCode: string\n daemonVersion: string\n machineInfo: {\n hostname: string\n platform: string\n arch: string\n cpus: number\n totalMemMb: number\n }\n osInfo: {\n platform: string\n release: string\n }\n}\n\ninterface PairResponseData {\n bridgeId: string\n orgId: string\n name: string\n authMode: \"claude_login\" | \"org_api_key\"\n bridgeToken: string\n}\n\ninterface RawPairResponse {\n success: boolean\n data?: PairResponseData\n error?: string\n}\n\n/**\n * Pair with the StrideOps server using a one-time pairing code.\n * On success, saves config and prints a confirmation.\n */\nexport async function runPair(\n pairingCode: string,\n apiBaseUrl: string,\n): Promise<void> {\n const url = `${apiBaseUrl.replace(/\\/$/, \"\")}/api/bridge/v1/pair`\n\n log(`Pairing with ${apiBaseUrl} ...`)\n\n const cpuCount = cpus().length\n const totalMemMb = Math.round(totalmem() / 1024 / 1024)\n\n const payload: PairRequest = {\n pairingCode,\n daemonVersion: VERSION,\n machineInfo: {\n hostname: hostname(),\n platform: platform(),\n arch: arch(),\n cpus: cpuCount,\n totalMemMb,\n },\n osInfo: {\n platform: platform(),\n release: release(),\n },\n }\n\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), 15_000)\n\n let res: Response\n try {\n res = await fetch(url, {\n method: \"POST\",\n signal: controller.signal,\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n })\n } catch (err: unknown) {\n clearTimeout(timer)\n if (err instanceof Error && err.name === \"AbortError\") {\n console.error(\"[stride-bridge] Pairing request timed out. Check your connection.\")\n process.exit(1)\n }\n console.error(\n `[stride-bridge] Network error during pairing: ${err instanceof Error ? err.message : String(err)}`,\n )\n process.exit(1)\n } finally {\n clearTimeout(timer)\n }\n\n let body: RawPairResponse\n try {\n body = (await res.json()) as RawPairResponse\n } catch {\n console.error(\n `[stride-bridge] Failed to parse pairing response (HTTP ${res.status}).`,\n )\n process.exit(1)\n }\n\n if (!res.ok || !body.success || !body.data) {\n console.error(\n `[stride-bridge] Pairing failed: ${body.error ?? `HTTP ${res.status}`}`,\n )\n process.exit(1)\n }\n\n const { bridgeId, orgId, name, authMode, bridgeToken } = body.data\n\n writeConfig({\n apiBaseUrl,\n bridgeToken,\n bridgeId,\n orgId,\n bridgeName: name,\n authMode,\n })\n\n console.log(`[stride-bridge] Connected successfully!`)\n console.log(` Bridge name : ${name}`)\n console.log(` Bridge ID : ${bridgeId}`)\n console.log(` Org ID : ${orgId}`)\n console.log(` Auth mode : ${authMode}`)\n console.log(` Config : ~/.stride-bridge/config.json`)\n console.log()\n console.log(`Run \\`stride-bridge start\\` to begin accepting work.`)\n}\n","/**\n * api.ts — Minimal authenticated HTTP client for the Bridge API.\n *\n * Uses the global fetch (Node >= 18) + AbortController for timeouts.\n * All responses are expected to be { success: boolean, data?: T, error?: string }.\n * Throws on network errors or when success === false.\n */\n\nimport type { BridgeConfig } from \"./config.js\"\n\nconst REQUEST_TIMEOUT_MS = 10_000\n\nexport class ApiError extends Error {\n constructor(\n public readonly status: number | null,\n message: string,\n ) {\n super(message)\n this.name = \"ApiError\"\n }\n}\n\nexport interface ApiResponse<T> {\n success: boolean\n data?: T\n error?: string\n}\n\n/**\n * Make an authenticated fetch to the Bridge API.\n * Adds Authorization: Bearer header from config.\n * Throws ApiError on non-2xx HTTP status or success:false response.\n */\nexport async function authedFetch<T>(\n config: BridgeConfig,\n path: string,\n init: RequestInit = {},\n): Promise<T> {\n const url = `${config.apiBaseUrl.replace(/\\/$/, \"\")}${path}`\n\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS)\n\n let res: Response\n try {\n res = await fetch(url, {\n ...init,\n signal: controller.signal,\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${config.bridgeToken}`,\n ...(init.headers as Record<string, string> | undefined),\n },\n })\n } catch (err: unknown) {\n clearTimeout(timer)\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new ApiError(null, `Request timed out after ${REQUEST_TIMEOUT_MS}ms: ${path}`)\n }\n throw new ApiError(null, `Network error: ${err instanceof Error ? err.message : String(err)}`)\n } finally {\n clearTimeout(timer)\n }\n\n let body: ApiResponse<T>\n try {\n body = (await res.json()) as ApiResponse<T>\n } catch {\n throw new ApiError(res.status, `Failed to parse JSON response from ${path} (HTTP ${res.status})`)\n }\n\n if (!res.ok || !body.success) {\n throw new ApiError(\n res.status,\n body.error ?? `API error from ${path} (HTTP ${res.status})`,\n )\n }\n\n return body.data as T\n}\n\n/**\n * POST JSON to a path. Convenience wrapper over authedFetch.\n */\nexport async function post<T>(\n config: BridgeConfig,\n path: string,\n body: unknown,\n): Promise<T> {\n return authedFetch<T>(config, path, {\n method: \"POST\",\n body: JSON.stringify(body),\n })\n}\n\n/**\n * GET a path. Convenience wrapper over authedFetch.\n */\nexport async function get<T>(config: BridgeConfig, path: string): Promise<T> {\n return authedFetch<T>(config, path, { method: \"GET\" })\n}\n\n/**\n * Like post() but swallows all errors (for best-effort fire-and-forget calls\n * such as daemon_stopping events).\n */\nexport async function postBestEffort(\n config: BridgeConfig,\n path: string,\n body: unknown,\n): Promise<void> {\n try {\n await post(config, path, body)\n } catch {\n // Intentionally swallowed — best-effort only.\n }\n}\n","/**\n * hooks-writer.ts — Generate .claude/settings.json with a signed PreToolUse hook.\n *\n * The signing scheme mirrors hook-signature.ts on the server:\n * HMAC-SHA256(`${unixSeconds}\\n${rawBody}`) → hex\n * with headers x-stride-hook-sig and x-stride-hook-ts.\n *\n * For local agents we generate a small Node.js script (hook-runner.mjs) that\n * Claude Code invokes as the hook command. This avoids bash dependency on\n * Windows and is consistent across platforms.\n *\n * The runner transforms Claude Code's hook input ({tool_name, tool_input,\n * session_id}) into the server's PreToolUse schema ({tool, args, sessionId})\n * and FORWARDS the server's decision — a budget/loop denial from Stride must\n * actually block the tool call. Fail-open on any error: if Stride is\n * unreachable the hook allows, so the agent is never blocked by an outage.\n *\n * Phase 1 wires PreToolUse only. Claude Code's Stop hook input carries no\n * usage/cost data, so per-turn usage reporting is deferred to Phase 2\n * (persistent sessions); run-level cost is reported by runner.ts via\n * POST /api/bridge/v1/runs/{runId} instead.\n */\n\nimport { join } from \"node:path\"\nimport { mkdirSync, writeFileSync, chmodSync } from \"node:fs\"\nimport { writeJsonAtomic } from \"./state.js\"\n\nexport interface HookWriterOptions {\n agentId: string\n hookSecret: string\n apiBaseUrl: string\n workspaceDir: string\n}\n\n/**\n * Generate the Node.js hook runner script content.\n * This script is written once per agent to their .claude/ directory.\n * It reads CLAUDE_HOOK_INPUT from stdin (Claude Code provides it),\n * computes the HMAC signature, and POSTs to the given URL.\n *\n * The script exits 0 (allow) regardless of Stride's response,\n * so the agent is never blocked by an unreachable server.\n */\nfunction buildHookRunnerScript(\n preToolUseUrl: string,\n hookSecret: string,\n): string {\n // We embed the secret directly into the per-agent script.\n // The script lives in the agent's workspace dir (~/.stride-bridge/agents/<id>/)\n // which is chmod 700 (POSIX) — not in the project directory Claude edits.\n // The secret is never printed to stdout/stderr.\n return `#!/usr/bin/env node\n// Auto-generated by stride-bridge. Do not edit.\n// Signed PreToolUse hook runner for Stride Build agents.\n// HMAC scheme: HMAC-SHA256(timestamp+\"\\\\n\"+body) -> hex\n// Headers: x-stride-hook-ts, x-stride-hook-sig\n\nimport { createHmac } from \"node:crypto\";\nimport { readFileSync } from \"node:fs\";\n\nconst HOOK_SECRET = ${JSON.stringify(hookSecret)};\nconst PRE_TOOL_USE_URL = ${JSON.stringify(preToolUseUrl)};\nconst TIMEOUT_MS = 8_000;\n\nfunction allow() {\n // No output + exit 0 = allow in Claude Code's hook protocol.\n process.exit(0);\n}\n\nasync function main() {\n // Claude Code writes the hook input to stdin as JSON. fd 0 works on\n // Windows too (\"/dev/stdin\" does not).\n let input = {};\n try {\n input = JSON.parse(readFileSync(0, \"utf-8\"));\n } catch {\n allow(); // unreadable input — fail-open\n }\n\n // Transform Claude Code's hook input into the server's PreToolUse schema.\n const body = JSON.stringify({\n tool: typeof input.tool_name === \"string\" && input.tool_name ? input.tool_name : \"unknown\",\n args: typeof input.tool_input === \"object\" && input.tool_input !== null ? input.tool_input : undefined,\n sessionId: typeof input.session_id === \"string\" ? input.session_id : undefined,\n });\n\n const ts = Math.floor(Date.now() / 1000).toString();\n const sig = createHmac(\"sha256\", HOOK_SECRET)\n .update(ts + \"\\\\n\" + body)\n .digest(\"hex\");\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);\n const res = await fetch(PRE_TOOL_USE_URL, {\n method: \"POST\",\n signal: controller.signal,\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-stride-hook-ts\": ts,\n \"x-stride-hook-sig\": sig,\n },\n body,\n });\n clearTimeout(timer);\n\n const decision = await res.json();\n if (decision && (decision.permissionDecision === \"deny\" || decision.permissionDecision === \"ask\")) {\n // Forward Stride's decision so Claude Code actually blocks the call.\n process.stdout.write(JSON.stringify({\n hookSpecificOutput: {\n hookEventName: \"PreToolUse\",\n permissionDecision: decision.permissionDecision,\n permissionDecisionReason: decision.permissionDecisionReason || \"Blocked by Stride policy\",\n },\n }) + \"\\\\n\");\n }\n process.exit(0);\n}\n\n// Fail-open: an unreachable server or unexpected error must never block the agent.\nmain().catch(() => allow());\n`\n}\n\n/**\n * Write .claude/settings.json and the hook-runner.mjs script to the agent's\n * workspace directory.\n *\n * settings.json wires PreToolUse (all tools, matcher \".*\") to the\n * hook-runner.mjs script via `node <path>`.\n */\nexport function writeAgentHooks(opts: HookWriterOptions): void {\n const { agentId, hookSecret, apiBaseUrl, workspaceDir } = opts\n\n const base = apiBaseUrl.replace(/\\/$/, \"\")\n const preToolUseUrl = `${base}/api/internal/build/agents/${agentId}/hook/pre-tool-use`\n\n const claudeDir = join(workspaceDir, \".claude\")\n mkdirSync(claudeDir, { recursive: true })\n\n // Write the hook runner script\n const runnerPath = join(claudeDir, \"hook-runner.mjs\")\n const runnerContent = buildHookRunnerScript(preToolUseUrl, hookSecret)\n writeFileSync(runnerPath, runnerContent, { encoding: \"utf-8\", mode: 0o700 })\n\n // Make executable on POSIX\n if (process.platform !== \"win32\") {\n try {\n chmodSync(runnerPath, 0o700)\n } catch {\n // Best effort.\n }\n }\n\n // Build the command that Claude Code will invoke.\n // Use `node <absolute-path>` so it works regardless of PATH. Quote both\n // paths — they regularly contain spaces on Windows (C:\\Users\\First Last\\...).\n const preToolUseCmd = `\"${process.execPath}\" \"${runnerPath}\"`\n\n const settingsJson = {\n hooks: {\n PreToolUse: [\n {\n matcher: \".*\",\n hooks: [\n {\n type: \"command\",\n command: preToolUseCmd,\n timeout: 10,\n },\n ],\n },\n ],\n },\n }\n\n writeJsonAtomic(join(claudeDir, \"settings.json\"), settingsJson)\n}\n\n/**\n * Write .claude/memory-sync.mjs — a Node script the agent runs (per its\n * CLAUDE.md memory protocol) to upload MEMORY.md and today's daily journal\n * to Stride's HMAC-authenticated memory-sync endpoint. Node instead of the\n * server's bash snippet because local agents run on Windows too.\n */\nexport function writeMemorySyncScript(opts: HookWriterOptions): void {\n const { agentId, hookSecret, apiBaseUrl, workspaceDir } = opts\n const base = apiBaseUrl.replace(/\\/$/, \"\")\n const syncUrl = `${base}/api/internal/build/agents/${agentId}/memory/sync`\n\n const script = `#!/usr/bin/env node\n// Auto-generated by stride-bridge. Do not edit.\n// Uploads MEMORY.md + today's daily journal to Stride (HMAC-signed).\n\nimport { createHmac } from \"node:crypto\";\nimport { readFileSync, existsSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst HOOK_SECRET = ${JSON.stringify(hookSecret)};\nconst SYNC_URL = ${JSON.stringify(syncUrl)};\nconst workspace = dirname(dirname(fileURLToPath(import.meta.url)));\n\nconst files = [];\nconst memoryMd = join(workspace, \"MEMORY.md\");\nif (existsSync(memoryMd)) {\n files.push({ type: \"learnings\", content: readFileSync(memoryMd, \"utf-8\").slice(0, 50000) });\n}\nconst today = new Date().toISOString().slice(0, 10);\nconst daily = join(workspace, \"memory\", today + \".md\");\nif (existsSync(daily)) {\n files.push({ type: \"daily\", date: today, content: readFileSync(daily, \"utf-8\").slice(0, 50000) });\n}\n\nif (files.length === 0) {\n console.log(\"memory-sync: nothing to sync\");\n process.exit(0);\n}\n\nconst body = JSON.stringify({ files });\nconst ts = Math.floor(Date.now() / 1000).toString();\nconst sig = createHmac(\"sha256\", HOOK_SECRET).update(ts + \"\\\\n\" + body).digest(\"hex\");\n\nconst res = await fetch(SYNC_URL, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-stride-hook-ts\": ts,\n \"x-stride-hook-sig\": sig,\n },\n body,\n}).catch((err) => ({ ok: false, statusText: String(err) }));\n\nconsole.log(res.ok ? \\`memory-sync: synced \\${files.length} file(s)\\` : \\`memory-sync: failed (\\${res.statusText ?? res.status})\\`);\n`\n\n const claudeDir = join(workspaceDir, \".claude\")\n mkdirSync(claudeDir, { recursive: true })\n writeFileSync(join(claudeDir, \"memory-sync.mjs\"), script, { encoding: \"utf-8\", mode: 0o700 })\n}\n\n/**\n * Write .claude/identity-sync.mjs — uploads the agent's identity files\n * (SOUL.md, IDENTITY.md, USER.md, HEARTBEAT.md, optional goals.json with\n * {goals: string[]}) to Stride's identity endpoint and marks onboarding\n * complete. The agent runs this once, at the end of its first-boot interview.\n */\nexport function writeIdentitySyncScript(opts: HookWriterOptions): void {\n const { agentId, hookSecret, apiBaseUrl, workspaceDir } = opts\n const base = apiBaseUrl.replace(/\\/$/, \"\")\n const identityUrl = `${base}/api/internal/build/agents/${agentId}/identity`\n\n const script = `#!/usr/bin/env node\n// Auto-generated by stride-bridge. Do not edit.\n// Uploads identity files + goals to Stride and marks onboarding complete.\n\nimport { createHmac } from \"node:crypto\";\nimport { readFileSync, existsSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst HOOK_SECRET = ${JSON.stringify(hookSecret)};\nconst IDENTITY_URL = ${JSON.stringify(identityUrl)};\nconst workspace = dirname(dirname(fileURLToPath(import.meta.url)));\n\nfunction readIf(name) {\n const p = join(workspace, name);\n return existsSync(p) ? readFileSync(p, \"utf-8\").slice(0, 20000) : undefined;\n}\n\nconst payload = {\n soulMd: readIf(\"SOUL.md\"),\n identityMd: readIf(\"IDENTITY.md\"),\n userMd: readIf(\"USER.md\"),\n heartbeatChecklist: readIf(\"HEARTBEAT.md\"),\n onboardingComplete: true,\n};\nconst goalsRaw = readIf(\"goals.json\");\nif (goalsRaw) {\n try {\n const parsed = JSON.parse(goalsRaw);\n if (Array.isArray(parsed.goals)) payload.goals = parsed.goals.slice(0, 5);\n } catch { /* ignore malformed goals.json */ }\n}\n\nconst body = JSON.stringify(payload);\nconst ts = Math.floor(Date.now() / 1000).toString();\nconst sig = createHmac(\"sha256\", HOOK_SECRET).update(ts + \"\\\\n\" + body).digest(\"hex\");\n\nconst res = await fetch(IDENTITY_URL, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-stride-hook-ts\": ts,\n \"x-stride-hook-sig\": sig,\n },\n body,\n}).catch((err) => ({ ok: false, statusText: String(err) }));\n\nconsole.log(res.ok ? \"identity-sync: onboarding recorded in Stride\" : \\`identity-sync: failed (\\${res.statusText ?? res.status})\\`);\n`\n\n const claudeDir = join(workspaceDir, \".claude\")\n mkdirSync(claudeDir, { recursive: true })\n writeFileSync(join(claudeDir, \"identity-sync.mjs\"), script, { encoding: \"utf-8\", mode: 0o700 })\n}\n\n/**\n * Write .claude/memory-search.mjs — semantic search over the agent's own\n * synced memory (Phase D). Usage: node .claude/memory-search.mjs \"query\"\n */\nexport function writeMemorySearchScript(opts: HookWriterOptions): void {\n const { agentId, hookSecret, apiBaseUrl, workspaceDir } = opts\n const base = apiBaseUrl.replace(/\\/$/, \"\")\n const searchUrl = `${base}/api/internal/build/agents/${agentId}/memory/search`\n\n const script = `#!/usr/bin/env node\n// Auto-generated by stride-bridge. Do not edit.\n// Semantically searches this agent's synced memory in Stride.\n\nimport { createHmac } from \"node:crypto\";\n\nconst HOOK_SECRET = ${JSON.stringify(hookSecret)};\nconst SEARCH_URL = ${JSON.stringify(searchUrl)};\n\nconst query = process.argv.slice(2).join(\" \").trim();\nif (!query) {\n console.log(\"usage: node memory-search.mjs <query>\");\n process.exit(0);\n}\n\nconst body = JSON.stringify({ query, limit: 5 });\nconst ts = Math.floor(Date.now() / 1000).toString();\nconst sig = createHmac(\"sha256\", HOOK_SECRET).update(ts + \"\\n\" + body).digest(\"hex\");\n\nconst res = await fetch(SEARCH_URL, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-stride-hook-ts\": ts,\n \"x-stride-hook-sig\": sig,\n },\n body,\n}).catch(() => null);\n\nif (!res || !res.ok) {\n console.log(\"memory-search: unavailable\");\n process.exit(0);\n}\nconst data = await res.json();\nconst results = data?.data?.results ?? [];\nif (results.length === 0) {\n console.log(\"memory-search: no matches\");\n} else {\n for (const r of results) {\n console.log(\"--- \" + (r.label ?? \"memory\") + \" ---\");\n console.log(String(r.content ?? \"\").slice(0, 600));\n }\n}\n`\n\n const claudeDir = join(workspaceDir, \".claude\")\n mkdirSync(claudeDir, { recursive: true })\n writeFileSync(join(claudeDir, \"memory-search.mjs\"), script, { encoding: \"utf-8\", mode: 0o700 })\n}\n","/**\n * agents.ts — Fetch agent configs from Stride and provision local workspaces.\n *\n * At startup and every 5 minutes, fetches the list of agents assigned to this\n * bridge. For each agent, ensures:\n * ~/.stride-bridge/agents/<agentId>/workspace/\n * ~/.stride-bridge/agents/<agentId>/workspace/CLAUDE.md\n * ~/.stride-bridge/agents/<agentId>/workspace/.claude/settings.json\n * ~/.stride-bridge/agents/<agentId>/workspace/.claude/hook-runner.mjs\n */\n\nimport { join } from \"node:path\"\nimport { mkdirSync, writeFileSync, existsSync } from \"node:fs\"\nimport { get } from \"./api.js\"\nimport type { BridgeConfig } from \"./config.js\"\nimport { AGENTS_DIR } from \"./config.js\"\nimport {\n writeAgentHooks,\n writeMemorySyncScript,\n writeIdentitySyncScript,\n writeMemorySearchScript,\n} from \"./hooks-writer.js\"\nimport { log, logError } from \"./log.js\"\n\nexport interface BridgeAgent {\n id: string\n name: string\n status: string\n model: string\n systemPrompt: string\n soulMd?: string | null\n allowedTools: string[]\n maxBudgetUsd: number\n localSessionMode: string\n hookSecret: string\n // Phase 3 identity + memory layer (server-rendered templates)\n identityMd?: string | null\n userMd?: string | null\n heartbeatChecklist?: string | null\n memoryProtocolMd?: string | null\n defaultSoulMd?: string | null\n // Phase 4 first-boot onboarding\n onboardedAt?: string | null\n onboardingMd?: string | null\n}\n\ninterface AgentsResponseData {\n agents: BridgeAgent[]\n}\n\n// In-memory cache of agent configs, refreshed periodically.\nlet cachedAgents: BridgeAgent[] = []\nconst REFRESH_INTERVAL_MS = 5 * 60 * 1000 // 5 minutes\nlet refreshTimer: ReturnType<typeof setInterval> | null = null\n\n/**\n * Fetch agent list from server and provision local workspaces.\n * Errors are caught and logged — a refresh failure must not crash the daemon.\n */\nexport async function refreshAgents(config: BridgeConfig): Promise<void> {\n try {\n const data = await get<AgentsResponseData>(config, \"/api/bridge/v1/agents\")\n cachedAgents = data.agents ?? []\n log(`Refreshed ${cachedAgents.length} agent(s)`)\n for (const agent of cachedAgents) {\n await ensureAgentWorkspace(config, agent)\n }\n } catch (err: unknown) {\n logError(\"Failed to refresh agents\", err)\n }\n}\n\n/**\n * Return the cached agent list (may be stale if refresh failed).\n */\nexport function getCachedAgents(): BridgeAgent[] {\n return cachedAgents\n}\n\n/**\n * Find a cached agent by ID.\n */\nexport function findAgent(agentId: string): BridgeAgent | undefined {\n return cachedAgents.find((a) => a.id === agentId)\n}\n\n/**\n * Ensure the local workspace directory exists for an agent, writing\n * CLAUDE.md and .claude/settings.json (with signed hooks).\n */\nasync function ensureAgentWorkspace(\n config: BridgeConfig,\n agent: BridgeAgent,\n): Promise<void> {\n const workspaceDir = agentWorkspaceDir(agent.id)\n mkdirSync(workspaceDir, { recursive: true })\n // Daily-journal directory (Layer 1 memory) — agent-written, never clobbered.\n mkdirSync(join(workspaceDir, \"memory\"), { recursive: true })\n\n // CLAUDE.md is fully generated — safe to overwrite on every refresh.\n const sections: string[] = []\n if (agent.systemPrompt) sections.push(agent.systemPrompt)\n sections.push(agent.soulMd ?? agent.defaultSoulMd ?? \"\")\n if (agent.memoryProtocolMd) sections.push(agent.memoryProtocolMd)\n sections.push(\n \"## Memory sync (local agent)\\n\\n\" +\n \"After updating MEMORY.md or today's daily journal, sync them to Stride by running:\\n\\n\" +\n \"```\\nnode .claude/memory-sync.mjs\\n```\\n\\n\" +\n \"Before re-researching something you may have learned before, search your \" +\n \"own past memory semantically:\\n\\n\" +\n '```\\nnode .claude/memory-search.mjs \"your question\"\\n```\\n',\n )\n if (!agent.onboardedAt && agent.onboardingMd) {\n sections.push(\n \"## FIRST BOOT — onboarding required\\n\\n\" +\n \"You have not been onboarded. Read ONBOARDING.md in this workspace and \" +\n \"complete the interview BEFORE regular work. To sync your identity after \" +\n \"the interview, run:\\n\\n```\\nnode .claude/identity-sync.mjs\\n```\\n\",\n )\n }\n writeFileSync(join(workspaceDir, \"CLAUDE.md\"), sections.filter(Boolean).join(\"\\n\\n\"), \"utf-8\")\n\n // ONBOARDING.md present only until the agent completes its interview.\n if (!agent.onboardedAt && agent.onboardingMd) {\n writeFileSync(join(workspaceDir, \"ONBOARDING.md\"), agent.onboardingMd, \"utf-8\")\n }\n\n // Identity files: server-rendered, overwrite (dashboard is source of truth).\n if (agent.identityMd) writeFileSync(join(workspaceDir, \"IDENTITY.md\"), agent.identityMd, \"utf-8\")\n if (agent.userMd) writeFileSync(join(workspaceDir, \"USER.md\"), agent.userMd, \"utf-8\")\n if (agent.heartbeatChecklist) {\n writeFileSync(join(workspaceDir, \"HEARTBEAT.md\"), agent.heartbeatChecklist, \"utf-8\")\n }\n\n // MEMORY.md is AGENT-written (Layer 2) — scaffold once, never overwrite.\n const memoryMdPath = join(workspaceDir, \"MEMORY.md\")\n if (!existsSync(memoryMdPath)) {\n writeFileSync(\n memoryMdPath,\n \"# Long-term memory\\n\\nDurable learnings only — format: `## Topic — YYYY-MM-DD` followed by what you learned.\\n\",\n \"utf-8\",\n )\n }\n\n // .claude/settings.json with HMAC-signed PreToolUse hook\n writeAgentHooks({\n agentId: agent.id,\n hookSecret: agent.hookSecret,\n apiBaseUrl: config.apiBaseUrl,\n workspaceDir,\n })\n\n // .claude/memory-sync.mjs — signed memory uploader (node, Windows-safe)\n writeMemorySyncScript({\n agentId: agent.id,\n hookSecret: agent.hookSecret,\n apiBaseUrl: config.apiBaseUrl,\n workspaceDir,\n })\n\n // .claude/identity-sync.mjs — uploads identity files after onboarding\n writeIdentitySyncScript({\n agentId: agent.id,\n hookSecret: agent.hookSecret,\n apiBaseUrl: config.apiBaseUrl,\n workspaceDir,\n })\n\n // .claude/memory-search.mjs — semantic search over synced memory (Phase D)\n writeMemorySearchScript({\n agentId: agent.id,\n hookSecret: agent.hookSecret,\n apiBaseUrl: config.apiBaseUrl,\n workspaceDir,\n })\n\n log(`Provisioned workspace for agent \"${agent.name}\" (${agent.id})`)\n}\n\n/**\n * Return the workspace directory path for an agent.\n */\nexport function agentWorkspaceDir(agentId: string): string {\n return join(AGENTS_DIR, agentId, \"workspace\")\n}\n\n/**\n * Start the periodic agent refresh timer. Call once from the daemon loop.\n * Cleans up the timer when the process exits.\n */\nexport function startAgentRefreshTimer(config: BridgeConfig): void {\n if (refreshTimer !== null) return // already running\n\n refreshTimer = setInterval(() => {\n void refreshAgents(config)\n }, REFRESH_INTERVAL_MS)\n\n // Do not hold the event loop open if all other work is done.\n if (refreshTimer.unref) {\n refreshTimer.unref()\n }\n}\n\n/**\n * Stop the agent refresh timer.\n */\nexport function stopAgentRefreshTimer(): void {\n if (refreshTimer !== null) {\n clearInterval(refreshTimer)\n refreshTimer = null\n }\n}\n","/**\n * session.ts — Persistent-session state for local agents (Phase 2).\n *\n * Agents with localSessionMode === \"persistent\" carry conversation context\n * across work items via `claude -p --resume <sessionId>`. We track the\n * session per agent in agents/<id>/session.json and rotate (start fresh)\n * when the session gets old or has accumulated many runs — the headless\n * equivalent of cortex-os's 71-hour context rotation, defaulting lower\n * because -p turns are denser than interactive chat.\n */\n\nimport { join, dirname } from \"node:path\"\nimport { agentWorkspaceDir } from \"./agents.js\"\nimport { readJsonSafe, writeJsonAtomic } from \"./state.js\"\n\nexport interface AgentSessionState {\n sessionId: string | null\n sessionStartedAt: number | null\n runCount: number\n}\n\nexport interface RotationOptions {\n /** Max session age before rotation. Default 24h. */\n maxAgeMs?: number\n /** Max work items in one session before rotation. Default 40. */\n maxRuns?: number\n}\n\nconst EMPTY_STATE: AgentSessionState = {\n sessionId: null,\n sessionStartedAt: null,\n runCount: 0,\n}\n\n/**\n * Pure rotation decision: start a fresh session when there is no usable\n * session, the session is too old, or it has absorbed too many runs.\n */\nexport function shouldRotateSession(\n state: AgentSessionState,\n nowMs: number,\n opts: RotationOptions = {},\n): boolean {\n const { maxAgeMs = 24 * 60 * 60_000, maxRuns = 40 } = opts\n if (!state.sessionId || state.sessionStartedAt === null) return true\n if (nowMs - state.sessionStartedAt >= maxAgeMs) return true\n if (state.runCount >= maxRuns) return true\n return false\n}\n\nfunction sessionStatePath(agentId: string): string {\n // agents/<id>/session.json — sibling of the workspace dir\n return join(dirname(agentWorkspaceDir(agentId)), \"session.json\")\n}\n\nexport function loadSessionState(agentId: string): AgentSessionState {\n const parsed = readJsonSafe<Partial<AgentSessionState>>(sessionStatePath(agentId))\n if (!parsed) return { ...EMPTY_STATE }\n return {\n sessionId: typeof parsed.sessionId === \"string\" ? parsed.sessionId : null,\n sessionStartedAt:\n typeof parsed.sessionStartedAt === \"number\" ? parsed.sessionStartedAt : null,\n runCount: typeof parsed.runCount === \"number\" ? parsed.runCount : 0,\n }\n}\n\nexport function saveSessionState(agentId: string, state: AgentSessionState): void {\n writeJsonAtomic(sessionStatePath(agentId), state)\n}\n\n/**\n * Record a completed run's session id. Continuing an existing session bumps\n * runCount; a new session id resets the clock.\n */\nexport function recordRunSession(\n agentId: string,\n newSessionId: string | undefined,\n previous: AgentSessionState,\n nowMs: number,\n): AgentSessionState {\n if (!newSessionId) return previous\n const continued = previous.sessionId === newSessionId\n const next: AgentSessionState = continued\n ? { ...previous, runCount: previous.runCount + 1 }\n : { sessionId: newSessionId, sessionStartedAt: nowMs, runCount: 1 }\n saveSessionState(agentId, next)\n return next\n}\n","/**\n * runner.ts — Execute a single work item via Claude Code CLI.\n *\n * Spawns `claude -p --output-format json --max-turns 25 --model <model>\n * --settings <workspace>/.claude/settings.json` and writes the PROMPT VIA\n * STDIN. Two reasons stdin matters:\n * 1. On Windows `claude` is a .cmd shim, which requires shell:true — and\n * with a shell, an arbitrary prompt in argv would be an injection risk.\n * Via stdin the prompt never touches the shell; the remaining argv\n * tokens are fixed strings (model ids, paths) we quote ourselves.\n * 2. Long prompts can exceed Windows' command-line length limit.\n *\n * --settings always points at the agent workspace so the Stride PreToolUse\n * hook applies even when cwd is a project folder elsewhere on disk.\n *\n * Timeout: 15 minutes (SIGTERM then SIGKILL).\n * Phase 1: authMode is always \"claude_login\" (uses local OAuth session).\n * TODO Phase 2: inject ANTHROPIC_API_KEY when authMode === \"org_api_key\".\n */\n\nimport { spawn } from \"node:child_process\"\nimport { existsSync } from \"node:fs\"\nimport { join } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport { post } from \"./api.js\"\nimport type { BridgeConfig } from \"./config.js\"\nimport { PENDING_REPORTS_PATH } from \"./config.js\"\nimport { agentWorkspaceDir, findAgent } from \"./agents.js\"\nimport { readJsonSafe, writeJsonAtomic } from \"./state.js\"\nimport {\n loadSessionState,\n shouldRotateSession,\n recordRunSession,\n} from \"./session.js\"\nimport { log, logError, logWarn } from \"./log.js\"\n\nconst RUN_TIMEOUT_MS = 15 * 60 * 1000 // 15 minutes\nconst STDOUT_CAP = 10_000 // chars\nconst STDERR_CAP = 4_000 // chars\nconst REPORT_RETRY_COUNT = 3\nconst REPORT_RETRY_BASE_MS = 2_000\n\n/**\n * Resolve how to launch Claude Code.\n *\n * Windows landmine (found in E2E testing): npm installs a `claude` bash-script\n * shim that EATS BACKSLASHES from arguments, silently corrupting paths like\n * --settings C:\\Users\\... → C:Users.... The native installer's claude.exe has\n * no such problem and can be spawned directly without a shell. Preference:\n * 1. ~/.local/bin/claude.exe (native installer) — shell:false\n * 2. `claude` via shell — last-resort fallback for npm-only installs\n */\nexport function resolveClaudeCommand(): { cmd: string; shell: boolean } {\n if (process.platform !== \"win32\") return { cmd: \"claude\", shell: false }\n const nativeExe = join(homedir(), \".local\", \"bin\", \"claude.exe\")\n if (existsSync(nativeExe)) return { cmd: nativeExe, shell: false }\n return { cmd: \"claude\", shell: true }\n}\n\nexport interface WorkItem {\n wakeupId: string\n runId: string\n issueId?: string\n prompt: string\n workingDir?: string\n agent: {\n id: string\n name: string\n model: string\n allowedTools: string[]\n maxBudgetUsd: number\n localSessionMode: string\n }\n}\n\ninterface RunReport {\n runId: string\n wakeupId: string\n failureKind?: string\n status: \"completed\" | \"failed\"\n stdoutExcerpt: string\n stderrExcerpt: string\n error?: string\n exitCode: number | null\n costUsd?: number\n tokensInput?: number\n tokensOutput?: number\n sessionId?: string\n}\n\n/**\n * Parse the JSON output emitted by `claude -p --output-format json`.\n * Defensive: all fields are optional.\n */\nfunction parseClaudeOutput(raw: string): {\n costUsd?: number\n tokensInput?: number\n tokensOutput?: number\n sessionId?: string\n isError?: boolean\n resultText?: string\n apiErrorStatus?: number\n} {\n // claude -p --output-format json emits a JSON object on stdout.\n // Find the last complete JSON object in the output (may have log lines before it).\n const trimmed = raw.trim()\n // Try to find the last '{...}' block\n const lastBrace = trimmed.lastIndexOf(\"}\")\n if (lastBrace === -1) return {}\n\n // Walk back to find the matching opening brace\n let depth = 0\n let start = -1\n for (let i = lastBrace; i >= 0; i--) {\n if (trimmed[i] === \"}\") depth++\n else if (trimmed[i] === \"{\") {\n depth--\n if (depth === 0) {\n start = i\n break\n }\n }\n }\n if (start === -1) return {}\n\n try {\n const parsed = JSON.parse(trimmed.slice(start, lastBrace + 1)) as Record<\n string,\n unknown\n >\n const result: {\n costUsd?: number\n tokensInput?: number\n tokensOutput?: number\n sessionId?: string\n isError?: boolean\n resultText?: string\n apiErrorStatus?: number\n } = {}\n\n if (typeof parsed[\"total_cost_usd\"] === \"number\") {\n result.costUsd = parsed[\"total_cost_usd\"]\n }\n if (typeof parsed[\"session_id\"] === \"string\") {\n result.sessionId = parsed[\"session_id\"]\n }\n // Claude Code reports API-level failures (bad model, auth) as exit 0 with\n // is_error: true — those must count as failed runs, not successes.\n if (typeof parsed[\"is_error\"] === \"boolean\") {\n result.isError = parsed[\"is_error\"]\n }\n if (typeof parsed[\"result\"] === \"string\") {\n result.resultText = parsed[\"result\"]\n }\n if (typeof parsed[\"api_error_status\"] === \"number\") {\n result.apiErrorStatus = parsed[\"api_error_status\"]\n }\n\n // usage.input_tokens / usage.output_tokens\n const usage = parsed[\"usage\"]\n if (usage && typeof usage === \"object\") {\n const u = usage as Record<string, unknown>\n if (typeof u[\"input_tokens\"] === \"number\") result.tokensInput = u[\"input_tokens\"]\n if (typeof u[\"output_tokens\"] === \"number\") result.tokensOutput = u[\"output_tokens\"]\n }\n\n return result\n } catch {\n return {}\n }\n}\n\n/**\n * Classify a failed run so the cloud can react appropriately — rate-limited\n * failures must NOT count toward the crash-loop breaker (the agent isn't\n * broken, Anthropic is just busy / the subscription window is exhausted).\n * Pure — unit tested.\n */\nexport function classifyFailure(\n stderr: string,\n resultText: string | undefined,\n apiErrorStatus: number | undefined,\n): \"rate_limited\" | \"environment\" | \"error\" {\n const haystack = `${stderr}\\n${resultText ?? \"\"}`.toLowerCase()\n if (\n apiErrorStatus === 429 ||\n apiErrorStatus === 529 ||\n /rate.?limit|overloaded|too many requests|usage limit|quota|exhausted/.test(haystack)\n ) {\n return \"rate_limited\"\n }\n if (/enoent|not recognized|command not found|login|authenticate|credentials|api key/.test(haystack)) {\n return \"environment\"\n }\n return \"error\"\n}\n\nconst HANDOFF_TIMEOUT_MS = 4 * 60 * 1000\n\n/**\n * One short turn in the OLD session before rotation: write HANDOFF.md.\n * Best-effort — any failure is logged and rotation proceeds.\n */\nasync function runHandoffTurn(\n claude: { cmd: string; shell: boolean },\n agentWorkspace: string,\n settingsPath: string,\n model: string,\n oldSessionId: string,\n): Promise<void> {\n const rawArgs = [\n \"-p\",\n \"--output-format\",\n \"json\",\n \"--max-turns\",\n \"6\",\n \"--model\",\n model,\n \"--settings\",\n settingsPath,\n \"--resume\",\n oldSessionId,\n ]\n const args = claude.shell\n ? rawArgs.map((a) => (/[\\s\"^&|<>%]/.test(a) ? `\"${a.replace(/\"/g, '\"\"')}\"` : a))\n : rawArgs\n\n await new Promise<void>((resolve) => {\n let child: ReturnType<typeof spawn>\n try {\n child = spawn(claude.cmd, args, {\n cwd: agentWorkspace,\n env: { ...process.env },\n shell: claude.shell,\n stdio: [\"pipe\", \"ignore\", \"ignore\"],\n })\n child.stdin?.write(\n \"Your session is about to be rotated (context limit). Write or overwrite \" +\n \"HANDOFF.md in your workspace root RIGHT NOW: what you were working on, \" +\n \"current state, decisions in flight, and the immediate next step. \" +\n \"Max 60 lines. Do nothing else.\",\n )\n child.stdin?.end()\n } catch (err) {\n logWarn(`Handoff turn failed to spawn: ${err instanceof Error ? err.message : String(err)}`)\n resolve()\n return\n }\n const timer = setTimeout(() => {\n logWarn(\"Handoff turn timed out — rotating without handoff doc\")\n try {\n child.kill(\"SIGTERM\")\n } catch {\n // ignore\n }\n }, HANDOFF_TIMEOUT_MS)\n child.on(\"close\", () => {\n clearTimeout(timer)\n log(\"Handoff turn complete\")\n resolve()\n })\n child.on(\"error\", () => {\n clearTimeout(timer)\n resolve()\n })\n })\n}\n\n/**\n * Execute a work item. Returns when the run is complete (or timed out).\n * Reports results to the Stride API, with retry + local persistence on failure.\n */\nexport async function runWorkItem(\n config: BridgeConfig,\n work: WorkItem,\n): Promise<void> {\n const agent = findAgent(work.agent.id)\n const model = agent?.model ?? work.agent.model\n const agentWorkspace = agentWorkspaceDir(work.agent.id)\n\n // Determine working directory: prefer explicit workingDir if it exists.\n let cwd = agentWorkspace\n if (work.workingDir && existsSync(work.workingDir)) {\n cwd = work.workingDir\n } else if (work.workingDir) {\n logWarn(\n `workingDir \"${work.workingDir}\" does not exist; falling back to agent workspace`,\n )\n }\n\n log(`Starting run ${work.runId} (agent \"${work.agent.name}\", model \"${model}\")`)\n log(` cwd: ${cwd}`)\n\n const claude = resolveClaudeCommand()\n // Forward slashes survive every launch path (Windows APIs accept them;\n // bash-based npm shims EAT backslashes — confirmed in E2E testing).\n const settingsPath = join(agentWorkspace, \".claude\", \"settings.json\").replace(/\\\\/g, \"/\")\n // Fixed tokens only — the prompt goes via stdin, never argv.\n const rawArgs = [\n \"-p\",\n \"--output-format\",\n \"json\",\n \"--max-turns\",\n \"25\",\n \"--model\",\n model,\n \"--settings\",\n settingsPath,\n ]\n\n // Persistent mode: resume the agent's ongoing session so context carries\n // across work items; rotate to a fresh session when stale (see session.ts).\n const persistent = work.agent.localSessionMode === \"persistent\"\n let sessionState = loadSessionState(work.agent.id)\n let rotated = false\n if (persistent) {\n if (shouldRotateSession(sessionState, Date.now())) {\n if (sessionState.sessionId) {\n log(`Rotating session for agent \"${work.agent.name}\" (age/run limit reached)`)\n // Context handoff (cortex pattern): give the OLD session one short\n // turn to write HANDOFF.md before we abandon it, so the fresh session\n // doesn't start blind. Fail-soft — rotation proceeds regardless.\n await runHandoffTurn(claude, agentWorkspace, settingsPath, model, sessionState.sessionId)\n rotated = true\n }\n sessionState = { sessionId: null, sessionStartedAt: null, runCount: 0 }\n } else if (sessionState.sessionId) {\n rawArgs.push(\"--resume\", sessionState.sessionId)\n }\n }\n // When falling back to a shell shim, quote args defensively since Node\n // concatenates them without quoting when shell is enabled.\n const args = claude.shell\n ? rawArgs.map((a) => (/[\\s\"^&|<>%]/.test(a) ? `\"${a.replace(/\"/g, '\"\"')}\"` : a))\n : rawArgs\n\n // After a rotation the fresh session starts blind — point it at the\n // handoff doc the old session just wrote.\n const promptText = rotated\n ? `## Session rotated\\nYour previous session ended (context rotation). Read HANDOFF.md and your recent memory/ journal entries before starting.\\n\\n---\\n\\n${work.prompt}`\n : work.prompt\n\n // TODO Phase 2: if config.authMode === \"org_api_key\", inject ANTHROPIC_API_KEY\n const env: NodeJS.ProcessEnv = { ...process.env }\n\n let stdoutBuf = \"\"\n let stderrBuf = \"\"\n let exitCode: number | null = null\n let spawnError: string | undefined\n\n await new Promise<void>((resolve) => {\n let child: ReturnType<typeof spawn>\n\n try {\n child = spawn(claude.cmd, args, {\n cwd,\n env,\n // shell only as a last resort (Windows .cmd shim). Safe because argv\n // contains only our fixed, pre-quoted tokens.\n shell: claude.shell,\n // stdin: pipe — the prompt is delivered via stdin, not argv.\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n })\n child.stdin?.write(promptText)\n child.stdin?.end()\n } catch (err: unknown) {\n spawnError = err instanceof Error ? err.message : String(err)\n resolve()\n return\n }\n\n // 15-minute hard timeout\n const timeoutHandle = setTimeout(() => {\n logWarn(`Run ${work.runId} exceeded timeout — sending SIGTERM`)\n try {\n child.kill(\"SIGTERM\")\n } catch {\n // ignore\n }\n setTimeout(() => {\n try {\n child.kill(\"SIGKILL\")\n } catch {\n // ignore\n }\n }, 5_000)\n }, RUN_TIMEOUT_MS)\n\n child.stdout?.on(\"data\", (chunk: Buffer) => {\n stdoutBuf += chunk.toString(\"utf-8\")\n })\n child.stderr?.on(\"data\", (chunk: Buffer) => {\n stderrBuf += chunk.toString(\"utf-8\")\n })\n\n child.on(\"close\", (code) => {\n clearTimeout(timeoutHandle)\n exitCode = code\n resolve()\n })\n\n child.on(\"error\", (err) => {\n clearTimeout(timeoutHandle)\n spawnError = err.message\n resolve()\n })\n })\n\n // Cap output sizes\n const stdoutExcerpt =\n stdoutBuf.length > STDOUT_CAP\n ? stdoutBuf.slice(-STDOUT_CAP)\n : stdoutBuf\n\n const stderrExcerpt =\n stderrBuf.length > STDERR_CAP\n ? stderrBuf.slice(-STDERR_CAP)\n : stderrBuf\n\n // Parse output even on non-zero exit — Claude Code sometimes emits its\n // JSON result before failing, and API-level errors (bad model, auth) come\n // back as exit 0 with is_error: true.\n const parsed = parseClaudeOutput(stdoutBuf)\n const succeeded =\n spawnError === undefined && exitCode === 0 && parsed.isError !== true\n\n // Build the most useful error message available for the dashboard.\n const errorMessage = succeeded\n ? undefined\n : spawnError ??\n (parsed.isError ? parsed.resultText?.slice(0, 1000) : undefined) ??\n (stderrExcerpt.trim() ? stderrExcerpt.trim().slice(-1000) : undefined) ??\n `claude exited with code ${exitCode ?? \"unknown\"}`\n\n const failureKind = succeeded\n ? undefined\n : classifyFailure(stderrExcerpt, parsed.resultText, parsed.apiErrorStatus)\n const {\n isError: _isError,\n resultText: _resultText,\n apiErrorStatus: _apiErrorStatus,\n ...reportFields\n } = parsed\n const report: RunReport = {\n runId: work.runId,\n wakeupId: work.wakeupId,\n status: succeeded ? \"completed\" : \"failed\",\n failureKind,\n stdoutExcerpt,\n stderrExcerpt,\n error: errorMessage,\n exitCode,\n ...reportFields,\n }\n\n log(\n `Run ${work.runId} ${report.status} (exit ${exitCode ?? \"n/a\"}${parsed.costUsd !== undefined ? `, cost $${parsed.costUsd.toFixed(4)}` : \"\"})`,\n )\n\n if (persistent && report.status === \"completed\") {\n recordRunSession(work.agent.id, parsed.sessionId, sessionState, Date.now())\n }\n\n await sendReport(config, report)\n}\n\n/**\n * POST a run report to the server with retry logic.\n * If all retries fail, persist to pending-reports.json for later retry.\n */\nasync function sendReport(\n config: BridgeConfig,\n report: RunReport,\n): Promise<void> {\n const path = `/api/bridge/v1/runs/${report.runId}`\n\n for (let attempt = 1; attempt <= REPORT_RETRY_COUNT; attempt++) {\n try {\n await post(config, path, report)\n log(`Reported run ${report.runId} (attempt ${attempt})`)\n // On success, remove from pending if it was there from a previous attempt.\n removePendingReport(report.runId)\n return\n } catch (err: unknown) {\n logError(`Failed to report run ${report.runId} (attempt ${attempt})`, err)\n if (attempt < REPORT_RETRY_COUNT) {\n const delay = REPORT_RETRY_BASE_MS * Math.pow(2, attempt - 1)\n await sleep(delay)\n }\n }\n }\n\n // All retries exhausted — persist locally for next poll iteration.\n logWarn(`Persisting failed report for run ${report.runId} to pending-reports.json`)\n appendPendingReport(report)\n}\n\n/**\n * Retry any pending reports from previous failures.\n * Called each poll iteration.\n */\nexport async function retryPendingReports(config: BridgeConfig): Promise<void> {\n const pending = readJsonSafe<RunReport[]>(PENDING_REPORTS_PATH)\n if (!pending || pending.length === 0) return\n\n log(`Retrying ${pending.length} pending report(s)`)\n for (const report of pending) {\n await sendReport(config, report)\n }\n}\n\nfunction appendPendingReport(report: RunReport): void {\n const existing = readJsonSafe<RunReport[]>(PENDING_REPORTS_PATH) ?? []\n // Avoid duplicates\n const deduped = existing.filter((r) => r.runId !== report.runId)\n deduped.push(report)\n writeJsonAtomic(PENDING_REPORTS_PATH, deduped)\n}\n\nfunction removePendingReport(runId: string): void {\n const existing = readJsonSafe<RunReport[]>(PENDING_REPORTS_PATH)\n if (!existing || existing.length === 0) return\n const filtered = existing.filter((r) => r.runId !== runId)\n if (filtered.length !== existing.length) {\n writeJsonAtomic(PENDING_REPORTS_PATH, filtered)\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n","/**\n * quota.ts — Claude subscription quota snapshot (Phase 2).\n *\n * In claude_login mode the daemon runs on the customer's Claude Code OAuth\n * session, which is rate-limited in 5-hour and 7-day windows. We read the\n * OAuth token from ~/.claude/.credentials.json and query Anthropic's usage\n * endpoint, reporting \"% remaining\" in heartbeats so the dashboard can show\n * a capacity chip per bridge. Pattern ported from cortex-os dashboard\n * lib/quota.ts (MIT).\n *\n * Everything here is fail-soft: no credentials / API errors → null quota.\n */\n\nimport { join } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport { readJsonSafe } from \"./state.js\"\nimport { logWarn } from \"./log.js\"\n\nexport interface QuotaSnapshot {\n fiveHourRemainingPct: number | null\n sevenDayRemainingPct: number | null\n fetchedAt: string\n}\n\ninterface OauthUsageResponse {\n five_hour?: { utilization?: number }\n seven_day?: { utilization?: number }\n}\n\nconst USAGE_URL = \"https://api.anthropic.com/api/oauth/usage\"\nconst CACHE_TTL_MS = 60_000\nconst FETCH_TIMEOUT_MS = 5_000\n\n/** Pure: utilization (0..1) → whole-number percent remaining, clamped. */\nexport function remainingPct(utilization: unknown): number | null {\n if (typeof utilization !== \"number\" || !Number.isFinite(utilization)) return null\n return Math.max(0, Math.min(100, Math.round((1 - utilization) * 100)))\n}\n\n/** Pure: map the usage API response to a snapshot. */\nexport function parseUsageResponse(body: OauthUsageResponse, nowIso: string): QuotaSnapshot {\n return {\n fiveHourRemainingPct: remainingPct(body.five_hour?.utilization),\n sevenDayRemainingPct: remainingPct(body.seven_day?.utilization),\n fetchedAt: nowIso,\n }\n}\n\nfunction readOauthToken(): string | null {\n if (process.env.CLAUDE_CODE_OAUTH_TOKEN) return process.env.CLAUDE_CODE_OAUTH_TOKEN\n const creds = readJsonSafe<{ claudeAiOauth?: { accessToken?: string } }>(\n join(homedir(), \".claude\", \".credentials.json\"),\n )\n return creds?.claudeAiOauth?.accessToken ?? null\n}\n\nlet cached: { snapshot: QuotaSnapshot; at: number } | null = null\nlet warnedNoToken = false\n\n/**\n * Fetch the current quota snapshot, cached for 60s. Returns null when no\n * OAuth token is available (org_api_key mode, or Claude not logged in).\n */\nexport async function getQuotaSnapshot(): Promise<QuotaSnapshot | null> {\n if (cached && Date.now() - cached.at < CACHE_TTL_MS) return cached.snapshot\n\n const token = readOauthToken()\n if (!token) {\n if (!warnedNoToken) {\n logWarn(\"No Claude OAuth token found — quota reporting disabled\")\n warnedNoToken = true\n }\n return null\n }\n\n try {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS)\n const res = await fetch(USAGE_URL, {\n headers: { Authorization: `Bearer ${token}` },\n signal: controller.signal,\n })\n clearTimeout(timer)\n if (!res.ok) return cached?.snapshot ?? null\n\n const body = (await res.json()) as OauthUsageResponse\n const snapshot = parseUsageResponse(body, new Date().toISOString())\n cached = { snapshot, at: Date.now() }\n return snapshot\n } catch {\n // Stale-but-present beats nothing; otherwise null.\n return cached?.snapshot ?? null\n }\n}\n","/**\n * poller.ts — Main daemon loop for `stride-bridge start`.\n *\n * Polls /api/bridge/v1/work every 2.5 seconds.\n * Handles one work item at a time (single-flight Phase 1).\n * Sends heartbeat every 60 seconds independently.\n * Exponential backoff on fetch errors: 2.5s → 5 → 10 → 30s cap.\n * Posts daemon_started on startup and daemon_stopping on SIGINT/SIGTERM.\n */\n\nimport { platform, release } from \"node:os\"\nimport { post, postBestEffort } from \"./api.js\"\nimport type { BridgeConfig } from \"./config.js\"\nimport {\n refreshAgents,\n startAgentRefreshTimer,\n stopAgentRefreshTimer,\n} from \"./agents.js\"\nimport { runWorkItem, retryPendingReports } from \"./runner.js\"\nimport type { WorkItem } from \"./runner.js\"\nimport { getQuotaSnapshot } from \"./quota.js\"\nimport type { QuotaSnapshot } from \"./quota.js\"\nimport { VERSION } from \"./version.js\"\nimport { log, logError, logWarn } from \"./log.js\"\n\nconst POLL_INTERVAL_MS = 2_500\nconst HEARTBEAT_INTERVAL_MS = 60_000\nconst BACKOFF_STEPS_MS = [2_500, 5_000, 10_000, 30_000]\n\ninterface WorkResponse {\n work: WorkItem | null\n}\n\ninterface HeartbeatPayload {\n daemonVersion: string\n osInfo: { platform: string; release: string }\n agents: unknown[]\n quota?: QuotaSnapshot\n}\n\nlet running = false\n\n/**\n * Start the daemon loop. Blocks until SIGINT/SIGTERM.\n */\nexport async function startDaemon(config: BridgeConfig): Promise<void> {\n running = true\n\n // Register signal handlers first so they fire even if startup work fails.\n const shutdown = async (signal: string) => {\n if (!running) return\n running = false\n log(`Received ${signal} — shutting down gracefully`)\n stopAgentRefreshTimer()\n await postBestEffort(config, \"/api/bridge/v1/events\", {\n kind: \"daemon_stopping\",\n message: `Daemon stopping (${signal})`,\n daemonVersion: VERSION,\n })\n process.exit(0)\n }\n\n process.on(\"SIGINT\", () => void shutdown(\"SIGINT\"))\n process.on(\"SIGTERM\", () => void shutdown(\"SIGTERM\"))\n\n // Announce startup\n await postBestEffort(config, \"/api/bridge/v1/events\", {\n kind: \"daemon_started\",\n message: \"Daemon started\",\n daemonVersion: VERSION,\n osInfo: { platform: platform(), release: release() },\n })\n\n log(`Daemon started (v${VERSION}, bridge ${config.bridgeId})`)\n\n // Fetch agents on startup\n await refreshAgents(config)\n startAgentRefreshTimer(config)\n\n // Heartbeat timer — runs independently of the poll loop\n const sendHeartbeat = async () => {\n const payload: HeartbeatPayload = {\n daemonVersion: VERSION,\n osInfo: { platform: platform(), release: release() },\n agents: [],\n }\n const quota = await getQuotaSnapshot()\n if (quota) payload.quota = quota\n try {\n await post(config, \"/api/bridge/v1/heartbeat\", payload)\n } catch (err: unknown) {\n logWarn(`Heartbeat failed: ${err instanceof Error ? err.message : String(err)}`)\n }\n }\n\n // First heartbeat immediately so the dashboard flips to connected fast.\n void sendHeartbeat()\n const heartbeatTimer = setInterval(() => void sendHeartbeat(), HEARTBEAT_INTERVAL_MS)\n\n if (heartbeatTimer.unref) heartbeatTimer.unref()\n\n // Main poll loop\n let backoffIndex = 0\n\n while (running) {\n // Retry any persisted failed reports before fetching new work\n try {\n await retryPendingReports(config)\n } catch {\n // Non-fatal\n }\n\n try {\n const data = await post<WorkResponse>(config, \"/api/bridge/v1/work\", {})\n backoffIndex = 0 // reset backoff on success\n\n if (data.work) {\n log(`Received work item: run ${data.work.runId}`)\n // Single-flight: await the run before polling again\n try {\n await runWorkItem(config, data.work)\n } catch (err: unknown) {\n logError(`Unhandled error in runWorkItem for run ${data.work.runId}`, err)\n }\n // Poll immediately after completing a run (don't wait full interval)\n continue\n }\n } catch (err: unknown) {\n const delay = BACKOFF_STEPS_MS[Math.min(backoffIndex, BACKOFF_STEPS_MS.length - 1)]\n logError(\n `Poll error (backoff ${delay}ms)`,\n err,\n )\n backoffIndex = Math.min(backoffIndex + 1, BACKOFF_STEPS_MS.length - 1)\n await sleep(delay)\n continue\n }\n\n await sleep(POLL_INTERVAL_MS)\n }\n\n clearInterval(heartbeatTimer)\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n","/**\n * cli.ts — Stride Bridge CLI entry point.\n *\n * Commands:\n * connect <pairingCode> [--api-url <url>] — Pair this machine with StrideOps\n * start — Start the daemon loop (foreground)\n * status — Print config + connectivity info\n * doctor — Run prerequisite checks\n */\n\nimport { Command } from \"commander\"\nimport { VERSION } from \"./version.js\"\nimport { runPair } from \"./pair.js\"\nimport { startDaemon } from \"./poller.js\"\nimport { readConfig, requireConfig, CONFIG_PATH, isConfigured } from \"./config.js\"\nimport { log } from \"./log.js\"\nimport { execSync } from \"node:child_process\"\nimport { existsSync, accessSync, constants, mkdirSync } from \"node:fs\"\nimport { join } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport { post } from \"./api.js\"\n\nconst DEFAULT_API_URL = \"https://app.strideops.ai\"\n\nconst program = new Command()\n\nprogram\n .name(\"stride-bridge\")\n .description(\"Stride Bridge daemon — run StrideOps Build agents locally\")\n .version(VERSION)\n\n// ---------------------------------------------------------------------------\n// connect\n// ---------------------------------------------------------------------------\n\nprogram\n .command(\"connect <pairingCode>\")\n .description(\"Pair this machine with StrideOps using a one-time pairing code\")\n .option(\n \"--api-url <url>\",\n \"StrideOps API base URL\",\n DEFAULT_API_URL,\n )\n .action(async (pairingCode: string, opts: { apiUrl: string }) => {\n await runPair(pairingCode, opts.apiUrl)\n })\n\n// ---------------------------------------------------------------------------\n// start\n// ---------------------------------------------------------------------------\n\nprogram\n .command(\"start\")\n .description(\"Start the daemon (foreground; press Ctrl+C to stop)\")\n .action(async () => {\n const config = requireConfig()\n log(`Starting daemon with bridge \"${config.bridgeName}\" (${config.bridgeId})`)\n await startDaemon(config)\n })\n\n// ---------------------------------------------------------------------------\n// status\n// ---------------------------------------------------------------------------\n\nprogram\n .command(\"status\")\n .description(\"Print current configuration and server connectivity\")\n .action(async () => {\n const config = readConfig()\n\n console.log(\"=== Stride Bridge Status ===\")\n console.log()\n\n if (!config) {\n console.log(\"Status : NOT CONNECTED\")\n console.log(`Config path : ${CONFIG_PATH}`)\n console.log()\n console.log(\"Run `stride-bridge connect <PAIRING_CODE>` to get started.\")\n return\n }\n\n console.log(`Status : CONNECTED`)\n console.log(`Bridge name : ${config.bridgeName}`)\n console.log(`Bridge ID : ${config.bridgeId}`)\n console.log(`Org ID : ${config.orgId}`)\n console.log(`API URL : ${config.apiBaseUrl}`)\n console.log(`Auth mode : ${config.authMode}`)\n console.log(`Config path : ${CONFIG_PATH}`)\n console.log()\n\n // Check server reachability\n process.stdout.write(\"Server : checking... \")\n try {\n await post(config, \"/api/bridge/v1/heartbeat\", {\n daemonVersion: VERSION,\n osInfo: {},\n agents: [],\n })\n console.log(\"REACHABLE\")\n } catch (err: unknown) {\n console.log(\n `UNREACHABLE (${err instanceof Error ? err.message : String(err)})`,\n )\n }\n console.log()\n })\n\n// ---------------------------------------------------------------------------\n// autostart\n// ---------------------------------------------------------------------------\n\nprogram\n .command(\"autostart <action>\")\n .description(\"Manage start-at-logon: install | remove | status (Windows Task Scheduler)\")\n .action(async (action: string) => {\n const { autostartInstall, autostartRemove, autostartStatus } = await import(\"./autostart.js\")\n if (action === \"install\") autostartInstall()\n else if (action === \"remove\") autostartRemove()\n else if (action === \"status\") autostartStatus()\n else {\n console.error(`Unknown action \"${action}\" — use install, remove, or status`)\n process.exitCode = 1\n }\n })\n\n// ---------------------------------------------------------------------------\n// doctor\n// ---------------------------------------------------------------------------\n\nprogram\n .command(\"doctor\")\n .description(\"Check all prerequisites for running the bridge daemon\")\n .action(async () => {\n console.log(\"=== Stride Bridge Doctor ===\")\n console.log()\n\n let allGood = true\n\n // 1. Node version\n const nodeVersion = process.versions.node\n const [major] = nodeVersion.split(\".\").map(Number)\n const nodeOk = major >= 20\n printCheck(\n \"Node.js >= 20\",\n nodeOk,\n `Found v${nodeVersion}`,\n `Found v${nodeVersion} — upgrade to Node.js 20+`,\n )\n if (!nodeOk) allGood = false\n\n // 2. claude CLI on PATH\n let claudeVersion = \"\"\n let claudeOnPath = false\n try {\n claudeVersion = execSync(\"claude --version\", {\n encoding: \"utf-8\",\n timeout: 5_000,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }).trim()\n claudeOnPath = true\n } catch {\n claudeOnPath = false\n }\n printCheck(\n \"claude CLI on PATH\",\n claudeOnPath,\n claudeVersion || \"found\",\n \"claude not found — install Claude Code CLI from https://docs.anthropic.com/claude-code\",\n )\n if (!claudeOnPath) allGood = false\n\n // 3. Claude authenticated (config presence heuristic)\n let claudeAuthed = false\n let claudeAuthNote = \"\"\n if (claudeOnPath) {\n // Claude Code stores its config under ~/.claude/ or %APPDATA%/claude/\n const possiblePaths = [\n join(homedir(), \".claude\", \"settings.json\"),\n join(homedir(), \".config\", \"claude\", \"settings.json\"),\n join(\n process.env[\"APPDATA\"] ?? join(homedir(), \"AppData\", \"Roaming\"),\n \"Claude\",\n \"settings.json\",\n ),\n ]\n claudeAuthed = possiblePaths.some(existsSync)\n claudeAuthNote = claudeAuthed\n ? \"config found\"\n : \"no config found — run `claude` to authenticate\"\n } else {\n claudeAuthNote = \"skipped (claude not on PATH)\"\n }\n printCheck(\n \"Claude authenticated\",\n claudeAuthed,\n claudeAuthNote,\n claudeAuthNote,\n )\n if (!claudeAuthed && claudeOnPath) allGood = false\n\n // 4. Config file valid\n const configured = isConfigured()\n const configData = readConfig()\n const configValid = configured && configData !== null\n printCheck(\n \"Bridge config\",\n configValid,\n configValid\n ? `${CONFIG_PATH} (bridge: ${configData?.bridgeName})`\n : configured\n ? `${CONFIG_PATH} exists but could not be parsed`\n : \"not found — run `stride-bridge connect <CODE>`\",\n configured\n ? `${CONFIG_PATH} could not be parsed — re-run connect`\n : \"not found — run `stride-bridge connect <CODE>`\",\n )\n if (!configValid) allGood = false\n\n // 5. Server reachable\n if (configData) {\n process.stdout.write(\"[ ] StrideOps server reachable ... \")\n try {\n await post(configData, \"/api/bridge/v1/heartbeat\", {\n daemonVersion: VERSION,\n osInfo: {},\n agents: [],\n })\n clearLine()\n printCheck(\"StrideOps server reachable\", true, configData.apiBaseUrl, \"\")\n } catch (err: unknown) {\n clearLine()\n printCheck(\n \"StrideOps server reachable\",\n false,\n \"\",\n `${configData.apiBaseUrl} — ${err instanceof Error ? err.message : String(err)}`,\n )\n allGood = false\n }\n } else {\n printCheck(\n \"StrideOps server reachable\",\n false,\n \"\",\n \"skipped (not configured)\",\n )\n }\n\n // 6. Workspace dir writable\n const bridgeDir = join(homedir(), \".stride-bridge\")\n try {\n mkdirSync(bridgeDir, { recursive: true })\n accessSync(bridgeDir, constants.W_OK)\n printCheck(\"Bridge workspace writable\", true, bridgeDir, \"\")\n } catch {\n printCheck(\n \"Bridge workspace writable\",\n false,\n \"\",\n `${bridgeDir} is not writable`,\n )\n allGood = false\n }\n\n console.log()\n if (allGood) {\n console.log(\"All checks passed. Run `stride-bridge start` to launch the daemon.\")\n } else {\n console.log(\n \"Some checks failed. Fix the issues above, then re-run `stride-bridge doctor`.\",\n )\n process.exit(1)\n }\n })\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction printCheck(\n label: string,\n ok: boolean,\n successNote: string,\n failureNote: string,\n): void {\n const icon = ok ? \"[ok]\" : \"[!!]\"\n const note = ok ? successNote : failureNote\n console.log(`${icon} ${label}${note ? \" — \" + note : \"\"}`)\n}\n\nfunction clearLine(): void {\n // Move cursor up one line and clear it (for the \"checking...\" line)\n process.stdout.write(\"\\r\\x1b[K\")\n}\n\n// ---------------------------------------------------------------------------\n// Parse\n// ---------------------------------------------------------------------------\n\nprogram.parseAsync(process.argv).catch((err: unknown) => {\n console.error(\n `[stride-bridge] Fatal: ${err instanceof Error ? err.message : String(err)}`,\n )\n process.exit(1)\n})\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/version.ts","../src/pair.ts","../src/api.ts","../src/hooks-writer.ts","../src/detect-runtimes.ts","../src/agents.ts","../src/session.ts","../src/prompt.ts","../src/report-queue.ts","../src/runner.ts","../src/exec.ts","../src/terminal-pty.ts","../src/quota.ts","../src/metrics.ts","../src/poller.ts","../src/cli.ts"],"names":["mkdirSync","join","writeFileSync","existsSync","spawn","report","STDOUT_CAP","STDERR_CAP","CACHE_TTL_MS","homedir","cached","cpus","totalmem","platform","release","cachedAgents","sleep"],"mappings":";;;;;;;;;;AAIO,IAAM,OAAA,GAAU,OAAA;AC0CvB,eAAsB,OAAA,CACpB,aACA,UAAA,EACe;AACf,EAAA,MAAM,MAAM,CAAA,EAAG,UAAA,CAAW,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAC,CAAA,mBAAA,CAAA;AAE5C,EAAA,GAAA,CAAI,CAAA,aAAA,EAAgB,UAAU,CAAA,IAAA,CAAM,CAAA;AAEpC,EAAA,MAAM,QAAA,GAAW,MAAK,CAAE,MAAA;AACxB,EAAA,MAAM,aAAa,IAAA,CAAK,KAAA,CAAM,QAAA,EAAS,GAAI,OAAO,IAAI,CAAA;AAEtD,EAAA,MAAM,OAAA,GAAuB;AAAA,IAC3B,WAAA;AAAA,IACA,aAAA,EAAe,OAAA;AAAA,IACf,WAAA,EAAa;AAAA,MACX,UAAU,QAAA,EAAS;AAAA,MACnB,UAAU,QAAA,EAAS;AAAA,MACnB,MAAM,IAAA,EAAK;AAAA,MACX,IAAA,EAAM,QAAA;AAAA,MACN;AAAA,KACF;AAAA,IACA,MAAA,EAAQ;AAAA,MACN,UAAU,QAAA,EAAS;AAAA,MACnB,SAAS,OAAA;AAAQ;AACnB,GACF;AAEA,EAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,EAAA,MAAM,QAAQ,UAAA,CAAW,MAAM,UAAA,CAAW,KAAA,IAAS,IAAM,CAAA;AAEzD,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI;AACF,IAAA,GAAA,GAAM,MAAM,MAAM,GAAA,EAAK;AAAA,MACrB,MAAA,EAAQ,MAAA;AAAA,MACR,QAAQ,UAAA,CAAW,MAAA;AAAA,MACnB,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AAAA,MAC9C,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAO;AAAA,KAC7B,CAAA;AAAA,EACH,SAAS,GAAA,EAAc;AACrB,IAAA,YAAA,CAAa,KAAK,CAAA;AAClB,IAAA,IAAI,GAAA,YAAe,KAAA,IAAS,GAAA,CAAI,IAAA,KAAS,YAAA,EAAc;AACrD,MAAA,OAAA,CAAQ,MAAM,mEAAmE,CAAA;AACjF,MAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,IAChB;AACA,IAAA,OAAA,CAAQ,KAAA;AAAA,MACN,iDAAiD,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,KACnG;AACA,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB,CAAA,SAAE;AACA,IAAA,YAAA,CAAa,KAAK,CAAA;AAAA,EACpB;AAEA,EAAA,IAAI,IAAA;AACJ,EAAA,IAAI;AACF,IAAA,IAAA,GAAQ,MAAM,IAAI,IAAA,EAAK;AAAA,EACzB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAA,CAAQ,KAAA;AAAA,MACN,CAAA,uDAAA,EAA0D,IAAI,MAAM,CAAA,EAAA;AAAA,KACtE;AACA,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AAEA,EAAA,IAAI,CAAC,IAAI,EAAA,IAAM,CAAC,KAAK,OAAA,IAAW,CAAC,KAAK,IAAA,EAAM;AAC1C,IAAA,OAAA,CAAQ,KAAA;AAAA,MACN,mCAAmC,IAAA,CAAK,KAAA,IAAS,CAAA,KAAA,EAAQ,GAAA,CAAI,MAAM,CAAA,CAAE,CAAA;AAAA,KACvE;AACA,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AAEA,EAAA,MAAM,EAAE,QAAA,EAAU,KAAA,EAAO,MAAM,QAAA,EAAU,WAAA,KAAgB,IAAA,CAAK,IAAA;AAE9D,EAAA,WAAA,CAAY;AAAA,IACV,UAAA;AAAA,IACA,WAAA;AAAA,IACA,QAAA;AAAA,IACA,KAAA;AAAA,IACA,UAAA,EAAY,IAAA;AAAA,IACZ;AAAA,GACD,CAAA;AAED,EAAA,OAAA,CAAQ,IAAI,CAAA,uCAAA,CAAyC,CAAA;AACrD,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,gBAAA,EAAmB,IAAI,CAAA,CAAE,CAAA;AACrC,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,gBAAA,EAAmB,QAAQ,CAAA,CAAE,CAAA;AACzC,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,gBAAA,EAAmB,KAAK,CAAA,CAAE,CAAA;AACtC,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,gBAAA,EAAmB,QAAQ,CAAA,CAAE,CAAA;AACzC,EAAA,OAAA,CAAQ,IAAI,CAAA,4CAAA,CAA8C,CAAA;AAC1D,EAAA,OAAA,CAAQ,GAAA,EAAI;AAIZ,EAAA,MAAM,cAAA,EAAe;AAErB,EAAA,OAAA,CAAQ,IAAI,CAAA,oDAAA,CAAsD,CAAA;AACpE;AAGA,eAAe,cAAA,GAAgC;AAC7C,EAAA,IAAI,QAAQ,QAAA,KAAa,OAAA,IAAW,CAAC,OAAA,CAAQ,MAAM,KAAA,EAAO;AACxD,IAAA,IAAI,OAAA,CAAQ,aAAa,OAAA,EAAS;AAChC,MAAA,OAAA,CAAQ,GAAA;AAAA,QACN,CAAA,2EAAA;AAAA,OACF;AACA,MAAA,OAAA,CAAQ,GAAA,EAAI;AAAA,IACd;AACA,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,EAAE,eAAA,EAAgB,GAAI,MAAM,OAAO,mBAAwB,CAAA;AACjE,EAAA,MAAM,EAAA,GAAK,gBAAgB,EAAE,KAAA,EAAO,QAAQ,KAAA,EAAO,MAAA,EAAQ,OAAA,CAAQ,MAAA,EAAQ,CAAA;AAC3E,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAA,CACJ,MAAM,EAAA,CAAG,QAAA;AAAA,MACP;AAAA,KACF,EAEC,IAAA,EAAK,CACL,WAAA,EAAY;AACf,IAAA,IAAI,MAAA,KAAW,EAAA,IAAM,MAAA,KAAW,GAAA,IAAO,WAAW,KAAA,EAAO;AACvD,MAAA,MAAM,EAAE,gBAAA,EAAiB,GAAI,MAAM,OAAO,yBAAgB,CAAA;AAC1D,MAAA,gBAAA,EAAiB;AAAA,IACnB,CAAA,MAAO;AACL,MAAA,OAAA,CAAQ,GAAA;AAAA,QACN,CAAA,0EAAA;AAAA,OACF;AAAA,IACF;AAAA,EACF,CAAA,SAAE;AACA,IAAA,EAAA,CAAG,KAAA,EAAM;AACT,IAAA,OAAA,CAAQ,GAAA,EAAI;AAAA,EACd;AACF;;;ACrKA,IAAM,kBAAA,GAAqB,GAAA;AAEpB,IAAM,QAAA,GAAN,cAAuB,KAAA,CAAM;AAAA,EAClC,WAAA,CACkB,QAChB,OAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAO,CAAA;AAHG,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAIhB,IAAA,IAAA,CAAK,IAAA,GAAO,UAAA;AAAA,EACd;AAAA,EALkB,MAAA;AAMpB,CAAA;AAaA,eAAsB,WAAA,CACpB,MAAA,EACA,IAAA,EACA,IAAA,GAAoB,EAAC,EACT;AACZ,EAAA,MAAM,GAAA,GAAM,GAAG,MAAA,CAAO,UAAA,CAAW,QAAQ,KAAA,EAAO,EAAE,CAAC,CAAA,EAAG,IAAI,CAAA,CAAA;AAE1D,EAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,EAAA,MAAM,QAAQ,UAAA,CAAW,MAAM,UAAA,CAAW,KAAA,IAAS,kBAAkB,CAAA;AAErE,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI;AACF,IAAA,GAAA,GAAM,MAAM,MAAM,GAAA,EAAK;AAAA,MACrB,GAAG,IAAA;AAAA,MACH,QAAQ,UAAA,CAAW,MAAA;AAAA,MACnB,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB,kBAAA;AAAA,QAChB,aAAA,EAAe,CAAA,OAAA,EAAU,MAAA,CAAO,WAAW,CAAA,CAAA;AAAA,QAC3C,GAAI,IAAA,CAAK;AAAA;AACX,KACD,CAAA;AAAA,EACH,SAAS,GAAA,EAAc;AACrB,IAAA,YAAA,CAAa,KAAK,CAAA;AAClB,IAAA,IAAI,GAAA,YAAe,KAAA,IAAS,GAAA,CAAI,IAAA,KAAS,YAAA,EAAc;AACrD,MAAA,MAAM,IAAI,QAAA,CAAS,IAAA,EAAM,2BAA2B,kBAAkB,CAAA,IAAA,EAAO,IAAI,CAAA,CAAE,CAAA;AAAA,IACrF;AACA,IAAA,MAAM,IAAI,QAAA,CAAS,IAAA,EAAM,CAAA,eAAA,EAAkB,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAE,CAAA;AAAA,EAC/F,CAAA,SAAE;AACA,IAAA,YAAA,CAAa,KAAK,CAAA;AAAA,EACpB;AAEA,EAAA,IAAI,IAAA;AACJ,EAAA,IAAI;AACF,IAAA,IAAA,GAAQ,MAAM,IAAI,IAAA,EAAK;AAAA,EACzB,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,SAAS,GAAA,CAAI,MAAA,EAAQ,sCAAsC,IAAI,CAAA,OAAA,EAAU,GAAA,CAAI,MAAM,CAAA,CAAA,CAAG,CAAA;AAAA,EAClG;AAEA,EAAA,IAAI,CAAC,GAAA,CAAI,EAAA,IAAM,CAAC,KAAK,OAAA,EAAS;AAC5B,IAAA,MAAM,IAAI,QAAA;AAAA,MACR,GAAA,CAAI,MAAA;AAAA,MACJ,KAAK,KAAA,IAAS,CAAA,eAAA,EAAkB,IAAI,CAAA,OAAA,EAAU,IAAI,MAAM,CAAA,CAAA;AAAA,KAC1D;AAAA,EACF;AAEA,EAAA,OAAO,IAAA,CAAK,IAAA;AACd;AAKA,eAAsB,IAAA,CACpB,MAAA,EACA,IAAA,EACA,IAAA,EACY;AACZ,EAAA,OAAO,WAAA,CAAe,QAAQ,IAAA,EAAM;AAAA,IAClC,MAAA,EAAQ,MAAA;AAAA,IACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,IAAI;AAAA,GAC1B,CAAA;AACH;AAKA,eAAsB,GAAA,CAAO,QAAsB,IAAA,EAA0B;AAC3E,EAAA,OAAO,YAAe,MAAA,EAAQ,IAAA,EAAM,EAAE,MAAA,EAAQ,OAAO,CAAA;AACvD;AAMA,eAAsB,cAAA,CACpB,MAAA,EACA,IAAA,EACA,IAAA,EACe;AACf,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,CAAK,MAAA,EAAQ,IAAA,EAAM,IAAI,CAAA;AAAA,EAC/B,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;ACzEA,SAAS,qBAAA,CACP,eACA,UAAA,EACQ;AAKR,EAAA,OAAO,CAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA,oBAAA,EASa,IAAA,CAAK,SAAA,CAAU,UAAU,CAAC,CAAA;AAAA,yBAAA,EACrB,IAAA,CAAK,SAAA,CAAU,aAAa,CAAC,CAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,CAAA;AA6DxD;AASO,SAAS,gBAAgB,IAAA,EAA+B;AAC7D,EAAA,MAAM,EAAE,OAAA,EAAS,UAAA,EAAY,UAAA,EAAY,cAAa,GAAI,IAAA;AAE1D,EAAA,MAAM,IAAA,GAAO,UAAA,CAAW,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AACzC,EAAA,MAAM,aAAA,GAAgB,CAAA,EAAG,IAAI,CAAA,2BAAA,EAA8B,OAAO,CAAA,kBAAA,CAAA;AAElE,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,YAAA,EAAc,SAAS,CAAA;AAC9C,EAAA,SAAA,CAAU,SAAA,EAAW,EAAE,SAAA,EAAW,IAAA,EAAM,CAAA;AAGxC,EAAA,MAAM,UAAA,GAAa,IAAA,CAAK,SAAA,EAAW,iBAAiB,CAAA;AACpD,EAAA,MAAM,aAAA,GAAgB,qBAAA,CAAsB,aAAA,EAAe,UAAU,CAAA;AACrE,EAAA,aAAA,CAAc,YAAY,aAAA,EAAe,EAAE,UAAU,OAAA,EAAS,IAAA,EAAM,KAAO,CAAA;AAG3E,EAAA,IAAI,OAAA,CAAQ,aAAa,OAAA,EAAS;AAChC,IAAA,IAAI;AACF,MAAA,SAAA,CAAU,YAAY,GAAK,CAAA;AAAA,IAC7B,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AAKA,EAAA,MAAM,aAAA,GAAgB,CAAA,CAAA,EAAI,OAAA,CAAQ,QAAQ,MAAM,UAAU,CAAA,CAAA,CAAA;AAE1D,EAAA,MAAM,YAAA,GAAe;AAAA,IACnB,KAAA,EAAO;AAAA,MACL,UAAA,EAAY;AAAA,QACV;AAAA,UACE,OAAA,EAAS,IAAA;AAAA,UACT,KAAA,EAAO;AAAA,YACL;AAAA,cACE,IAAA,EAAM,SAAA;AAAA,cACN,OAAA,EAAS,aAAA;AAAA,cACT,OAAA,EAAS;AAAA;AACX;AACF;AACF;AACF;AACF,GACF;AAEA,EAAA,eAAA,CAAgB,IAAA,CAAK,SAAA,EAAW,eAAe,CAAA,EAAG,YAAY,CAAA;AAChE;AAQO,SAAS,sBAAsB,IAAA,EAA+B;AACnE,EAAA,MAAM,EAAE,OAAA,EAAS,UAAA,EAAY,UAAA,EAAY,cAAa,GAAI,IAAA;AAC1D,EAAA,MAAM,IAAA,GAAO,UAAA,CAAW,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AACzC,EAAA,MAAM,OAAA,GAAU,CAAA,EAAG,IAAI,CAAA,2BAAA,EAA8B,OAAO,CAAA,YAAA,CAAA;AAE5D,EAAA,MAAM,MAAA,GAAS,CAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA,oBAAA,EASK,IAAA,CAAK,SAAA,CAAU,UAAU,CAAC,CAAA;AAAA,iBAAA,EAC7B,IAAA,CAAK,SAAA,CAAU,OAAO,CAAC,CAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA,CAAA;AAoCxC,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,YAAA,EAAc,SAAS,CAAA;AAC9C,EAAA,SAAA,CAAU,SAAA,EAAW,EAAE,SAAA,EAAW,IAAA,EAAM,CAAA;AACxC,EAAA,aAAA,CAAc,IAAA,CAAK,SAAA,EAAW,iBAAiB,CAAA,EAAG,MAAA,EAAQ,EAAE,QAAA,EAAU,OAAA,EAAS,IAAA,EAAM,GAAA,EAAO,CAAA;AAC9F;AAQO,SAAS,wBAAwB,IAAA,EAA+B;AACrE,EAAA,MAAM,EAAE,OAAA,EAAS,UAAA,EAAY,UAAA,EAAY,cAAa,GAAI,IAAA;AAC1D,EAAA,MAAM,IAAA,GAAO,UAAA,CAAW,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AACzC,EAAA,MAAM,WAAA,GAAc,CAAA,EAAG,IAAI,CAAA,2BAAA,EAA8B,OAAO,CAAA,SAAA,CAAA;AAEhE,EAAA,MAAM,MAAA,GAAS,CAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA,oBAAA,EASK,IAAA,CAAK,SAAA,CAAU,UAAU,CAAC,CAAA;AAAA,qBAAA,EACzB,IAAA,CAAK,SAAA,CAAU,WAAW,CAAC,CAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA,CAAA;AAwChD,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,YAAA,EAAc,SAAS,CAAA;AAC9C,EAAA,SAAA,CAAU,SAAA,EAAW,EAAE,SAAA,EAAW,IAAA,EAAM,CAAA;AACxC,EAAA,aAAA,CAAc,IAAA,CAAK,SAAA,EAAW,mBAAmB,CAAA,EAAG,MAAA,EAAQ,EAAE,QAAA,EAAU,OAAA,EAAS,IAAA,EAAM,GAAA,EAAO,CAAA;AAChG;AAMO,SAAS,wBAAwB,IAAA,EAA+B;AACrE,EAAA,MAAM,EAAE,OAAA,EAAS,UAAA,EAAY,UAAA,EAAY,cAAa,GAAI,IAAA;AAC1D,EAAA,MAAM,IAAA,GAAO,UAAA,CAAW,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AACzC,EAAA,MAAM,SAAA,GAAY,CAAA,EAAG,IAAI,CAAA,2BAAA,EAA8B,OAAO,CAAA,cAAA,CAAA;AAE9D,EAAA,MAAM,MAAA,GAAS,CAAA;AAAA;AAAA;;AAAA;;AAAA,oBAAA,EAMK,IAAA,CAAK,SAAA,CAAU,UAAU,CAAC,CAAA;AAAA,mBAAA,EAC3B,IAAA,CAAK,SAAA,CAAU,SAAS,CAAC,CAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAsC5C,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,YAAA,EAAc,SAAS,CAAA;AAC9C,EAAA,SAAA,CAAU,SAAA,EAAW,EAAE,SAAA,EAAW,IAAA,EAAM,CAAA;AACxC,EAAA,aAAA,CAAc,IAAA,CAAK,SAAA,EAAW,mBAAmB,CAAA,EAAG,MAAA,EAAQ,EAAE,QAAA,EAAU,OAAA,EAAS,IAAA,EAAM,GAAA,EAAO,CAAA;AAChG;AAcO,SAAS,2BAA2B,IAAA,EAA+B;AACxE,EAAA,MAAM,EAAE,OAAA,EAAS,UAAA,EAAY,UAAA,EAAY,cAAa,GAAI,IAAA;AAC1D,EAAA,MAAM,IAAA,GAAO,UAAA,CAAW,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AACzC,EAAA,MAAM,YAAA,GAAe,CAAA,EAAG,IAAI,CAAA,2BAAA,EAA8B,OAAO,CAAA,UAAA,CAAA;AAEjE,EAAA,MAAM,MAAA,GAAS,CAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA,oBAAA,EAQK,IAAA,CAAK,SAAA,CAAU,UAAU,CAAC,CAAA;AAAA,sBAAA,EACxB,IAAA,CAAK,SAAA,CAAU,YAAY,CAAC,CAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA,CAAA;AAoClD,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,YAAA,EAAc,SAAS,CAAA;AAC9C,EAAA,SAAA,CAAU,SAAA,EAAW,EAAE,SAAA,EAAW,IAAA,EAAM,CAAA;AACxC,EAAA,aAAA,CAAc,IAAA,CAAK,SAAA,EAAW,sBAAsB,CAAA,EAAG,MAAA,EAAQ,EAAE,QAAA,EAAU,OAAA,EAAS,IAAA,EAAM,GAAA,EAAO,CAAA;AACnG;AChZA,IAAM,gBAAA,GAAmB,GAAA;AACzB,IAAM,YAAA,GAAe,IAAI,EAAA,GAAK,GAAA;AAY9B,IAAM,MAAA,GAAsB;AAAA,EAC1B,EAAE,SAAS,aAAA,EAAe,GAAA,EAAK,UAAU,IAAA,EAAM,CAAC,WAAW,CAAA,EAAE;AAAA,EAC7D,EAAE,SAAS,OAAA,EAAS,GAAA,EAAK,SAAS,IAAA,EAAM,CAAC,WAAW,CAAA,EAAE;AAAA,EACtD,EAAE,SAAS,QAAA,EAAU,GAAA,EAAK,UAAU,IAAA,EAAM,CAAC,WAAW,CAAA;AACxD,CAAA;AAOO,SAAS,YAAA,CAAa,KAAa,IAAA,EAAiC;AACzE,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,KAAY;AAC9B,IAAA,IAAI,KAAA;AACJ,IAAA,IAAI,QAAA,GAAW,KAAA;AAEf,IAAA,MAAM,IAAA,GAAO,CAAC,KAAA,KAAkB;AAC9B,MAAA,IAAI,CAAC,QAAA,EAAU;AACb,QAAA,QAAA,GAAW,IAAA;AACX,QAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,MACf;AAAA,IACF,CAAA;AAGA,IAAA,MAAM,QAAA,GAAW,QAAQ,QAAA,KAAa,OAAA;AAEtC,IAAA,IAAI;AACF,MAAA,KAAA,GAAQ,KAAA,CAAM,KAAK,IAAA,EAAM;AAAA,QACvB,KAAA,EAAO,QAAA;AAAA,QACP,KAAA,EAAO,CAAC,QAAA,EAAU,MAAA,EAAQ,QAAQ,CAAA;AAAA,QAClC,KAAK,OAAA,CAAQ;AAAA,OACd,CAAA;AAAA,IACH,CAAA,CAAA,MAAQ;AACN,MAAA,IAAA,CAAK,EAAE,CAAA;AAAG,MAAA;AAAA,IACZ;AAEA,IAAA,IAAI,SAAA,GAAY,EAAA;AAChB,IAAA,KAAA,CAAM,MAAA,EAAQ,EAAA,CAAG,MAAA,EAAQ,CAAC,KAAA,KAAkB;AAC1C,MAAA,SAAA,IAAa,KAAA,CAAM,SAAS,OAAO,CAAA;AAAA,IACrC,CAAC,CAAA;AAED,IAAA,MAAM,KAAA,GAAQ,WAAW,MAAM;AAC7B,MAAA,IAAI;AAAE,QAAA,KAAA,CAAM,KAAK,SAAS,CAAA;AAAA,MAAE,CAAA,CAAA,MAAQ;AAAA,MAAe;AACnD,MAAA,IAAA,CAAK,EAAE,CAAA;AAAA,IACT,GAAG,gBAAgB,CAAA;AAEnB,IAAA,KAAA,CAAM,EAAA,CAAG,SAAS,MAAM;AACtB,MAAA,YAAA,CAAa,KAAK,CAAA;AAElB,MAAA,MAAM,YAAY,SAAA,CACf,KAAA,CAAM,IAAI,CAAA,CACV,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,EAAM,EACnB,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,MAAA,GAAS,CAAC,CAAA,IAAK,EAAA;AAChC,MAAA,IAAA,CAAK,SAAS,CAAA;AAAA,IAChB,CAAC,CAAA;AAED,IAAA,KAAA,CAAM,EAAA,CAAG,SAAS,MAAM;AACtB,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,IAAA,CAAK,EAAE,CAAA;AAAA,IACT,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AACH;AAaO,SAAS,eAAe,GAAA,EAAqB;AAClD,EAAA,IAAI,CAAC,GAAA,CAAI,IAAA,EAAK,EAAG,OAAO,EAAA;AAExB,EAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,KAAA,CAAM,oBAAoB,CAAA;AAC5C,EAAA,OAAO,KAAA,GAAQ,KAAA,CAAM,CAAC,CAAA,GAAI,GAAA,CAAI,IAAA,EAAK,CAAE,KAAA,CAAM,KAAK,CAAA,CAAE,GAAA,EAAI,IAAK,EAAA;AAC7D;AAEA,IAAI,MAAA,GAAmE,IAAA;AAYvE,eAAsB,cAAA,CAAe,QAAQ,KAAA,EAAqC;AAChF,EAAA,IAAI,CAAC,SAAS,MAAA,IAAU,IAAA,CAAK,KAAI,GAAI,MAAA,CAAO,KAAK,YAAA,EAAc;AAC7D,IAAA,OAAO,MAAA,CAAO,YAAA;AAAA,EAChB;AAEA,EAAA,MAAM,UAA+B,EAAC;AAEtC,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,IAAI;AACF,MAAA,MAAM,MAAM,MAAM,YAAA,CAAa,KAAA,CAAM,GAAA,EAAK,MAAM,IAAI,CAAA;AACpD,MAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,OAAA,EAAS,KAAA,CAAM,SAAS,OAAA,EAAS,cAAA,CAAe,GAAG,CAAA,EAAG,CAAA;AAAA,IACvE,SAAS,GAAA,EAAc;AACrB,MAAA,OAAA;AAAA,QACE,CAAA,0BAAA,EAA6B,KAAA,CAAM,OAAO,CAAA,GAAA,EAAM,GAAA,YAAe,QAAQ,GAAA,CAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,OAClG;AACA,MAAA,OAAA,CAAQ,KAAK,EAAE,OAAA,EAAS,MAAM,OAAA,EAAS,OAAA,EAAS,IAAI,CAAA;AAAA,IACtD;AAAA,EACF;AAEA,EAAA,MAAA,GAAS,EAAE,YAAA,EAAc,OAAA,EAAS,EAAA,EAAI,IAAA,CAAK,KAAI,EAAE;AACjD,EAAA,OAAO,OAAA;AACT;AAMO,SAAS,sBAAA,GAA+B;AAC7C,EAAA,MAAA,GAAS,IAAA;AACX;;;ACrGA,IAAI,eAA8B,EAAC;AACnC,IAAM,mBAAA,GAAsB,IAAI,EAAA,GAAK,GAAA;AACrC,IAAI,YAAA,GAAsD,IAAA;AAM1D,eAAsB,cAAc,MAAA,EAAqC;AACvE,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAwB,MAAA,EAAQ,uBAAuB,CAAA;AAC1E,IAAA,YAAA,GAAe,IAAA,CAAK,UAAU,EAAC;AAC/B,IAAA,GAAA,CAAI,CAAA,UAAA,EAAa,YAAA,CAAa,MAAM,CAAA,SAAA,CAAW,CAAA;AAC/C,IAAA,KAAA,MAAW,SAAS,YAAA,EAAc;AAChC,MAAA,MAAM,oBAAA,CAAqB,QAAQ,KAAK,CAAA;AAAA,IAC1C;AAIA,IAAA,sBAAA,EAAuB;AAAA,EACzB,SAAS,GAAA,EAAc;AACrB,IAAA,QAAA,CAAS,4BAA4B,GAAG,CAAA;AAAA,EAC1C;AACF;AAKO,SAAS,eAAA,GAAiC;AAC/C,EAAA,OAAO,YAAA;AACT;AAKO,SAAS,UAAU,OAAA,EAA0C;AAClE,EAAA,OAAO,aAAa,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,OAAO,CAAA;AAClD;AAMA,eAAe,oBAAA,CACb,QACA,KAAA,EACe;AACf,EAAA,MAAM,YAAA,GAAe,iBAAA,CAAkB,KAAA,CAAM,EAAE,CAAA;AAC/C,EAAAA,SAAAA,CAAU,YAAA,EAAc,EAAE,SAAA,EAAW,MAAM,CAAA;AAE3C,EAAAA,SAAAA,CAAUC,KAAK,YAAA,EAAc,QAAQ,GAAG,EAAE,SAAA,EAAW,MAAM,CAAA;AAG3D,EAAA,MAAM,WAAqB,EAAC;AAC5B,EAAA,IAAI,KAAA,CAAM,YAAA,EAAc,QAAA,CAAS,IAAA,CAAK,MAAM,YAAY,CAAA;AACxD,EAAA,QAAA,CAAS,IAAA,CAAK,KAAA,CAAM,MAAA,IAAU,KAAA,CAAM,iBAAiB,EAAE,CAAA;AACvD,EAAA,IAAI,KAAA,CAAM,gBAAA,EAAkB,QAAA,CAAS,IAAA,CAAK,MAAM,gBAAgB,CAAA;AAChE,EAAA,QAAA,CAAS,IAAA;AAAA,IACP;AAAA,GAMF;AAEA,EAAA,IAAI,MAAM,kBAAA,EAAoB;AAC5B,IAAA,QAAA,CAAS,IAAA;AAAA,MACP,MAAM,kBAAA,GACJ;AAAA,KAIJ;AAAA,EACF;AAEA,EAAA,IAAI,MAAM,oBAAA,EAAsB;AAC9B,IAAA,QAAA,CAAS,IAAA,CAAK,MAAM,oBAAoB,CAAA;AACxC,IAAA,IAAI,MAAM,iBAAA,EAAmB;AAC3B,MAAA,QAAA,CAAS,IAAA,CAAK,MAAM,iBAAiB,CAAA;AAAA,IACvC;AAAA,EACF;AACA,EAAA,IAAI,CAAC,KAAA,CAAM,WAAA,IAAe,KAAA,CAAM,YAAA,EAAc;AAC5C,IAAA,QAAA,CAAS,IAAA;AAAA,MACP;AAAA,KAIF;AAAA,EACF;AACA,EAAA,MAAM,kBAAkB,QAAA,CAAS,MAAA,CAAO,OAAO,CAAA,CAAE,KAAK,MAAM,CAAA;AAC5D,EAAAC,cAAcD,IAAAA,CAAK,YAAA,EAAc,WAAW,CAAA,EAAG,iBAAiB,OAAO,CAAA;AAOvE,EAAAC,cAAcD,IAAAA,CAAK,YAAA,EAAc,WAAW,CAAA,EAAG,iBAAiB,OAAO,CAAA;AAGvE,EAAA,IAAI,CAAC,KAAA,CAAM,WAAA,IAAe,KAAA,CAAM,YAAA,EAAc;AAC5C,IAAAC,cAAcD,IAAAA,CAAK,YAAA,EAAc,eAAe,CAAA,EAAG,KAAA,CAAM,cAAc,OAAO,CAAA;AAAA,EAChF;AAKA,EAAA,MAAM,WAAA,GAAc,KAAA,CAAM,MAAA,IAAU,KAAA,CAAM,aAAA;AAC1C,EAAA,IAAI,WAAA,EAAaC,aAAAA,CAAcD,IAAAA,CAAK,cAAc,SAAS,CAAA,EAAG,aAAa,OAAO,CAAA;AAClF,EAAA,IAAI,KAAA,CAAM,UAAA,EAAYC,aAAAA,CAAcD,IAAAA,CAAK,cAAc,aAAa,CAAA,EAAG,KAAA,CAAM,UAAA,EAAY,OAAO,CAAA;AAChG,EAAA,IAAI,KAAA,CAAM,MAAA,EAAQC,aAAAA,CAAcD,IAAAA,CAAK,cAAc,SAAS,CAAA,EAAG,KAAA,CAAM,MAAA,EAAQ,OAAO,CAAA;AACpF,EAAA,IAAI,MAAM,kBAAA,EAAoB;AAC5B,IAAAC,cAAcD,IAAAA,CAAK,YAAA,EAAc,cAAc,CAAA,EAAG,KAAA,CAAM,oBAAoB,OAAO,CAAA;AAAA,EACrF;AAGA,EAAA,MAAM,YAAA,GAAeA,IAAAA,CAAK,YAAA,EAAc,WAAW,CAAA;AACnD,EAAA,IAAI,CAAC,UAAA,CAAW,YAAY,CAAA,EAAG;AAC7B,IAAAC,aAAAA;AAAA,MACE,YAAA;AAAA,MACA,0HAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF;AAGA,EAAA,eAAA,CAAgB;AAAA,IACd,SAAS,KAAA,CAAM,EAAA;AAAA,IACf,YAAY,KAAA,CAAM,UAAA;AAAA,IAClB,YAAY,MAAA,CAAO,UAAA;AAAA,IACnB;AAAA,GACD,CAAA;AAGD,EAAA,qBAAA,CAAsB;AAAA,IACpB,SAAS,KAAA,CAAM,EAAA;AAAA,IACf,YAAY,KAAA,CAAM,UAAA;AAAA,IAClB,YAAY,MAAA,CAAO,UAAA;AAAA,IACnB;AAAA,GACD,CAAA;AAGD,EAAA,uBAAA,CAAwB;AAAA,IACtB,SAAS,KAAA,CAAM,EAAA;AAAA,IACf,YAAY,KAAA,CAAM,UAAA;AAAA,IAClB,YAAY,MAAA,CAAO,UAAA;AAAA,IACnB;AAAA,GACD,CAAA;AAGD,EAAA,uBAAA,CAAwB;AAAA,IACtB,SAAS,KAAA,CAAM,EAAA;AAAA,IACf,YAAY,KAAA,CAAM,UAAA;AAAA,IAClB,YAAY,MAAA,CAAO,UAAA;AAAA,IACnB;AAAA,GACD,CAAA;AAID,EAAA,0BAAA,CAA2B;AAAA,IACzB,SAAS,KAAA,CAAM,EAAA;AAAA,IACf,YAAY,KAAA,CAAM,UAAA;AAAA,IAClB,YAAY,MAAA,CAAO,UAAA;AAAA,IACnB;AAAA,GACD,CAAA;AAED,EAAA,GAAA,CAAI,oCAAoC,KAAA,CAAM,IAAI,CAAA,GAAA,EAAM,KAAA,CAAM,EAAE,CAAA,CAAA,CAAG,CAAA;AACrE;AAKO,SAAS,kBAAkB,OAAA,EAAyB;AACzD,EAAA,OAAOD,IAAAA,CAAK,UAAA,EAAY,OAAA,EAAS,WAAW,CAAA;AAC9C;AAMO,SAAS,uBAAuB,MAAA,EAA4B;AACjE,EAAA,IAAI,iBAAiB,IAAA,EAAM;AAE3B,EAAA,YAAA,GAAe,YAAY,MAAM;AAC/B,IAAA,KAAK,cAAc,MAAM,CAAA;AAAA,EAC3B,GAAG,mBAAmB,CAAA;AAGtB,EAAA,IAAI,aAAa,KAAA,EAAO;AACtB,IAAA,YAAA,CAAa,KAAA,EAAM;AAAA,EACrB;AACF;AAKO,SAAS,qBAAA,GAA8B;AAC5C,EAAA,IAAI,iBAAiB,IAAA,EAAM;AACzB,IAAA,aAAA,CAAc,YAAY,CAAA;AAC1B,IAAA,YAAA,GAAe,IAAA;AAAA,EACjB;AACF;AC/OA,IAAM,WAAA,GAAiC;AAAA,EACrC,SAAA,EAAW,IAAA;AAAA,EACX,gBAAA,EAAkB,IAAA;AAAA,EAClB,QAAA,EAAU;AACZ,CAAA;AAMO,SAAS,mBAAA,CACd,KAAA,EACA,KAAA,EACA,IAAA,GAAwB,EAAC,EAChB;AACT,EAAA,MAAM,EAAE,QAAA,GAAW,EAAA,GAAK,KAAK,GAAA,EAAQ,OAAA,GAAU,IAAG,GAAI,IAAA;AACtD,EAAA,IAAI,CAAC,KAAA,CAAM,SAAA,IAAa,KAAA,CAAM,gBAAA,KAAqB,MAAM,OAAO,IAAA;AAChE,EAAA,IAAI,KAAA,GAAQ,KAAA,CAAM,gBAAA,IAAoB,QAAA,EAAU,OAAO,IAAA;AACvD,EAAA,IAAI,KAAA,CAAM,QAAA,IAAY,OAAA,EAAS,OAAO,IAAA;AACtC,EAAA,OAAO,KAAA;AACT;AAEA,SAAS,iBAAiB,OAAA,EAAyB;AAEjD,EAAA,OAAOA,KAAK,OAAA,CAAQ,iBAAA,CAAkB,OAAO,CAAC,GAAG,cAAc,CAAA;AACjE;AAEO,SAAS,iBAAiB,OAAA,EAAoC;AACnE,EAAA,MAAM,MAAA,GAAS,YAAA,CAAyC,gBAAA,CAAiB,OAAO,CAAC,CAAA;AACjF,EAAA,IAAI,CAAC,MAAA,EAAQ,OAAO,EAAE,GAAG,WAAA,EAAY;AACrC,EAAA,OAAO;AAAA,IACL,WAAW,OAAO,MAAA,CAAO,SAAA,KAAc,QAAA,GAAW,OAAO,SAAA,GAAY,IAAA;AAAA,IACrE,kBACE,OAAO,MAAA,CAAO,gBAAA,KAAqB,QAAA,GAAW,OAAO,gBAAA,GAAmB,IAAA;AAAA,IAC1E,UAAU,OAAO,MAAA,CAAO,QAAA,KAAa,QAAA,GAAW,OAAO,QAAA,GAAW;AAAA,GACpE;AACF;AAEO,SAAS,gBAAA,CAAiB,SAAiB,KAAA,EAAgC;AAChF,EAAA,eAAA,CAAgB,gBAAA,CAAiB,OAAO,CAAA,EAAG,KAAK,CAAA;AAClD;AAMO,SAAS,gBAAA,CACd,OAAA,EACA,YAAA,EACA,QAAA,EACA,KAAA,EACmB;AACnB,EAAA,IAAI,CAAC,cAAc,OAAO,QAAA;AAC1B,EAAA,MAAM,SAAA,GAAY,SAAS,SAAA,KAAc,YAAA;AACzC,EAAA,MAAM,OAA0B,SAAA,GAC5B,EAAE,GAAG,QAAA,EAAU,UAAU,QAAA,CAAS,QAAA,GAAW,CAAA,EAAE,GAC/C,EAAE,SAAA,EAAW,YAAA,EAAc,gBAAA,EAAkB,KAAA,EAAO,UAAU,CAAA,EAAE;AACpE,EAAA,gBAAA,CAAiB,SAAS,IAAI,CAAA;AAC9B,EAAA,OAAO,IAAA;AACT;;;AC9BO,SAAS,gBAAgB,IAAA,EAA+B;AAC7D,EAAA,IAAI;AACF,IAAA,MAAM,EAAE,UAAA,EAAY,KAAA,EAAO,GAAA,EAAK,cAAA,EAAgB,SAAQ,GAAI,IAAA;AAE5D,IAAA,MAAM,QAAkB,EAAC;AAQzB,IAAA,MAAM,QAAA,GAAW,KAAA,EAAO,MAAA,IAAU,KAAA,EAAO,aAAA;AACzC,IAAA,MAAM,gBAAA,GACJ,QAAQ,cAAA,IACR,QAAA,IAAY,QAAQ,QAAA,CAAS,IAAA,GAAO,MAAA,GAAS,CAAA;AAE/C,IAAA,IAAI,gBAAA,EAAkB;AAEpB,MAAA,IAAI,aAAA,GAAgB,CAAA;;AAAA,EAAqB,QAAQ,CAAA,CAAA;AACjD,MAAA,IAAI,OAAO,UAAA,IAAc,KAAA,CAAM,WAAW,IAAA,EAAK,CAAE,SAAS,CAAA,EAAG;AAC3D,QAAA,aAAA,IAAiB;;AAAA,EAAO,MAAM,UAAU,CAAA,CAAA;AAAA,MAC1C;AACA,MAAA,KAAA,CAAM,KAAK,aAAa,CAAA;AAAA,IAC1B;AAGA,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,KAAA,CAAM,IAAA;AAAA,QACJ;AAAA,OAGF;AAAA,IACF;AAIA,IAAA,KAAA,CAAM,KAAK,UAAU,CAAA;AAErB,IAAA,OAAO,KAAA,CAAM,KAAK,aAAa,CAAA;AAAA,EACjC,CAAA,CAAA,MAAQ;AAGN,IAAA,OAAO,IAAA,CAAK,UAAA;AAAA,EACd;AACF;AC9EO,IAAM,iBAAA,GAAoBA,IAAAA,CAAK,UAAA,EAAY,mBAAmB,CAAA;AAErE,IAAM,YAAA,GAAe,EAAA;AAwCd,SAAS,uBAAuB,GAAA,EAAuB;AAC5D,EAAA,IAAI,EAAE,GAAA,YAAe,QAAA,CAAA,EAAW,OAAO,KAAA;AACvC,EAAA,MAAM,EAAE,QAAO,GAAI,GAAA;AACnB,EAAA,IAAI,MAAA,KAAW,MAAM,OAAO,KAAA;AAC5B,EAAA,IAAI,MAAA,GAAS,GAAA,IAAO,MAAA,IAAU,GAAA,EAAK,OAAO,KAAA;AAE1C,EAAA,IAAI,MAAA,KAAW,GAAA,IAAO,MAAA,KAAW,GAAA,EAAK,OAAO,KAAA;AAC7C,EAAA,OAAO,IAAA;AACT;AAiBO,SAAS,eAAe,GAAA,EAAmC;AAChE,EAAA,IAAI,GAAA,KAAQ,QAAQ,OAAO,GAAA,KAAQ,YAAY,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA,EAAG;AACjE,IAAA,OAAA,CAAQ,kEAAkE,CAAA;AAC1E,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,CAAA,GAAI,GAAA;AAGV,EAAA,IAAI,OAAO,EAAE,OAAO,CAAA,KAAM,YAAY,CAAC,CAAA,CAAE,OAAO,CAAA,EAAG;AACjD,IAAA,OAAA,CAAQ,mDAAmD,CAAA;AAC3D,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,KAAA,GAAQ,EAAE,OAAO,CAAA;AAGvB,EAAA,IAAI,OAAO,CAAA,CAAE,QAAQ,CAAA,KAAM,QAAA,KAAa,CAAA,CAAE,QAAQ,CAAA,KAAM,MAAA,IAAa,CAAA,CAAE,QAAQ,CAAA,KAAM,IAAA,CAAA,EAAO;AAC1F,IAAA,OAAA;AAAA,MACE,4DAA4D,KAAK,CAAA,iBAAA;AAAA,KACnE;AACA,IAAA,OAAO;AAAA,MACL,KAAA;AAAA,MACA,MAAA,EAAQ,CAAA;AAAA,MACR,QAAA,EAAU,CAAA;AAAA,MACV,aAAA,EAAA,iBAAe,IAAI,IAAA,EAAK,EAAE,WAAA;AAAY,KACxC;AAAA,EACF;AAGA,EAAA,IAAI,CAAA,CAAE,QAAQ,CAAA,KAAM,IAAA,IAAQ,OAAO,CAAA,CAAE,QAAQ,CAAA,KAAM,QAAA,IAAY,KAAA,CAAM,OAAA,CAAQ,CAAA,CAAE,QAAQ,CAAC,CAAA,EAAG;AACzF,IAAA,OAAA,CAAQ,CAAA,4CAAA,EAA+C,KAAK,CAAA,uBAAA,CAAyB,CAAA;AACrF,IAAA,OAAO,IAAA;AAAA,EACT;AAGA,EAAA,MAAM,WAAA,GAAc,EAAE,UAAU,CAAA;AAChC,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,QAAA,CAAS,WAAqB,IAAK,WAAA,GAAyB,CAAA;AAEpF,EAAA,MAAM,aAAA,GACJ,OAAO,CAAA,CAAE,eAAe,CAAA,KAAM,QAAA,GAAW,CAAA,CAAE,eAAe,CAAA,GAAA,iBAAI,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAEvF,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IACA,MAAA,EAAQ,EAAE,QAAQ,CAAA;AAAA,IAClB,QAAA;AAAA,IACA;AAAA,GACF;AACF;AAEA,SAAS,UAAU,IAAA,EAA8B;AAC/C,EAAA,MAAM,GAAA,GAAM,aAAwB,IAAI,CAAA;AACxC,EAAA,IAAI,CAAC,GAAA,EAAK,OAAO,EAAC;AAClB,EAAA,MAAM,aAA6B,EAAC;AACpC,EAAA,KAAA,MAAW,SAAS,GAAA,EAAK;AACvB,IAAA,MAAM,IAAA,GAAO,eAAe,KAAK,CAAA;AACjC,IAAA,IAAI,IAAA,KAAS,IAAA,EAAM,UAAA,CAAW,IAAA,CAAK,IAAI,CAAA;AAAA,EACzC;AACA,EAAA,OAAO,UAAA;AACT;AAEA,SAAS,UAAA,CAAW,MAAc,KAAA,EAA6B;AAC7D,EAAA,eAAA,CAAgB,MAAM,KAAK,CAAA;AAC7B;AAEA,SAAS,iBAAA,CAAkB,OAAe,IAAA,EAAoB;AAC5D,EAAA,MAAM,KAAA,GAAQ,UAAU,IAAI,CAAA;AAC5B,EAAA,MAAM,WAAW,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,UAAU,KAAK,CAAA;AACtD,EAAA,IAAI,QAAA,CAAS,MAAA,KAAW,KAAA,CAAM,MAAA,EAAQ;AACpC,IAAA,UAAA,CAAW,MAAM,QAAQ,CAAA;AAAA,EAC3B;AACF;AAEA,SAAS,aAAA,CAAc,MAAoB,IAAA,EAAoB;AAC7D,EAAA,MAAM,KAAA,GAAQ,UAAU,IAAI,CAAA;AAC5B,EAAA,MAAM,OAAA,GAAU,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAO,EAAE,KAAA,KAAU,IAAA,CAAK,KAAA,GAAQ,IAAA,GAAO,CAAE,CAAA;AACpE,EAAA,UAAA,CAAW,MAAM,OAAO,CAAA;AAC1B;AAEA,SAAS,UAAA,CAAW,MAAoB,MAAA,EAAsB;AAC5D,EAAA,QAAA;AAAA,IACE,qCAAqC,IAAA,CAAK,KAAK,KAAK,MAAM,CAAA,WAAA,EAAc,KAAK,QAAQ,CAAA,CAAA;AAAA,GACvF;AACA,EAAA,MAAM,QAAA,GAAW,UAAU,iBAAiB,CAAA;AAC5C,EAAA,MAAM,OAAA,GAAU,SAAS,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,KAAA,KAAU,KAAK,KAAK,CAAA;AAC7D,EAAA,OAAA,CAAQ,KAAK,IAAI,CAAA;AACjB,EAAA,UAAA,CAAW,mBAAmB,OAAO,CAAA;AACvC;AASO,SAAS,QAAQ,IAAA,EAA0B;AAChD,EAAA,MAAM,QAAA,GAAW,UAAU,oBAAoB,CAAA;AAC/C,EAAA,MAAM,OAAA,GAAU,SAAS,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,KAAA,KAAU,KAAK,KAAK,CAAA;AAC7D,EAAA,OAAA,CAAQ,KAAK,IAAI,CAAA;AACjB,EAAA,UAAA,CAAW,sBAAsB,OAAO,CAAA;AAC1C;AAMO,SAAS,oBAAoB,KAAA,EAAqB;AACvD,EAAA,iBAAA,CAAkB,OAAO,oBAAoB,CAAA;AAC/C;AAUA,eAAsB,MACpB,IAAA,EACe;AACf,EAAA,MAAM,KAAA,GAAQ,UAAU,oBAAoB,CAAA;AAC5C,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AAExB,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,IAAI;AACF,MAAA,MAAM,KAAK,IAAI,CAAA;AAEf,MAAA,iBAAA,CAAkB,IAAA,CAAK,OAAO,oBAAoB,CAAA;AAAA,IACpD,SAAS,GAAA,EAAc;AACrB,MAAA,IAAI,sBAAA,CAAuB,GAAG,CAAA,EAAG;AAE/B,QAAA,iBAAA,CAAkB,IAAA,CAAK,OAAO,oBAAoB,CAAA;AAClD,QAAA,UAAA,CAAW,IAAA,EAAM,CAAA,UAAA,EAAc,GAAA,CAAiB,MAAM,CAAA,CAAE,CAAA;AAAA,MAC1D,CAAA,MAAO;AAEL,QAAA,MAAM,UAAwB,EAAE,GAAG,MAAM,QAAA,EAAU,IAAA,CAAK,WAAW,CAAA,EAAE;AACrE,QAAA,IAAI,OAAA,CAAQ,YAAY,YAAA,EAAc;AAEpC,UAAA,iBAAA,CAAkB,IAAA,CAAK,OAAO,oBAAoB,CAAA;AAClD,UAAA,UAAA,CAAW,SAAS,uBAAuB,CAAA;AAAA,QAC7C,CAAA,MAAO;AAEL,UAAA,aAAA,CAAc,SAAS,oBAAoB,CAAA;AAC3C,UAAA,OAAA;AAAA,YACE,4CAA4C,IAAA,CAAK,KAAK,aAAa,OAAA,CAAQ,QAAQ,IAAI,YAAY,CAAA,CAAA;AAAA,WACrG;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AC7MA,IAAM,cAAA,GAAiB,KAAK,EAAA,GAAK,GAAA;AACjC,IAAM,UAAA,GAAa,GAAA;AACnB,IAAM,UAAA,GAAa,GAAA;AACnB,IAAM,kBAAA,GAAqB,CAAA;AAC3B,IAAM,oBAAA,GAAuB,GAAA;AAWtB,SAAS,oBAAA,GAAwD;AACtE,EAAA,IAAI,OAAA,CAAQ,aAAa,OAAA,EAAS,OAAO,EAAE,GAAA,EAAK,QAAA,EAAU,OAAO,KAAA,EAAM;AACvE,EAAA,MAAM,YAAYA,IAAAA,CAAK,OAAA,EAAQ,EAAG,QAAA,EAAU,OAAO,YAAY,CAAA;AAC/D,EAAA,IAAIE,UAAAA,CAAW,SAAS,CAAA,EAAG,OAAO,EAAE,GAAA,EAAK,SAAA,EAAW,OAAO,KAAA,EAAM;AACjE,EAAA,OAAO,EAAE,GAAA,EAAK,QAAA,EAAU,KAAA,EAAO,IAAA,EAAK;AACtC;AAaO,SAAS,gBAAgB,IAAA,EAA0B;AACxD,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAO,cAAc,IAAA,CAAK,CAAC,CAAA,GAAI,CAAA,CAAA,EAAI,EAAE,OAAA,CAAQ,IAAA,EAAM,IAAI,CAAC,MAAM,CAAE,CAAA;AACnF;AAWO,SAAS,iBAAiB,KAAA,EAAwB;AACvD,EAAA,OAAO,sBAAA,CAAuB,KAAK,KAAK,CAAA;AAC1C;AAsEA,SAAS,kBAAkB,GAAA,EAQzB;AACA,EAAA,MAAM,OAAA,GAAU,IAAI,IAAA,EAAK;AACzB,EAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,WAAA,CAAY,GAAG,CAAA;AACzC,EAAA,IAAI,SAAA,KAAc,EAAA,EAAI,OAAO,EAAC;AAC9B,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,IAAI,KAAA,GAAQ,EAAA;AACZ,EAAA,KAAA,IAAS,CAAA,GAAI,SAAA,EAAW,CAAA,IAAK,CAAA,EAAG,CAAA,EAAA,EAAK;AACnC,IAAA,IAAI,OAAA,CAAQ,CAAC,CAAA,KAAM,GAAA,EAAK,KAAA,EAAA;AAAA,SAAA,IACf,OAAA,CAAQ,CAAC,CAAA,KAAM,GAAA,EAAK;AAC3B,MAAA,KAAA,EAAA;AACA,MAAA,IAAI,UAAU,CAAA,EAAG;AAAE,QAAA,KAAA,GAAQ,CAAA;AAAG,QAAA;AAAA,MAAM;AAAA,IACtC;AAAA,EACF;AACA,EAAA,IAAI,KAAA,KAAU,EAAA,EAAI,OAAO,EAAC;AAC1B,EAAA,IAAI;AACF,IAAA,MAAM,CAAA,GAAI,KAAK,KAAA,CAAM,OAAA,CAAQ,MAAM,KAAA,EAAO,SAAA,GAAY,CAAC,CAAC,CAAA;AACxD,IAAA,MAAM,IAA0C,EAAC;AACjD,IAAA,IAAI,OAAO,EAAE,gBAAgB,CAAA,KAAM,UAAU,CAAA,CAAE,OAAA,GAAU,EAAE,gBAAgB,CAAA;AAC3E,IAAA,IAAI,OAAO,EAAE,YAAY,CAAA,KAAM,UAAU,CAAA,CAAE,SAAA,GAAY,EAAE,YAAY,CAAA;AACrE,IAAA,IAAI,OAAO,EAAE,UAAU,CAAA,KAAM,WAAW,CAAA,CAAE,OAAA,GAAU,EAAE,UAAU,CAAA;AAChE,IAAA,IAAI,OAAO,EAAE,QAAQ,CAAA,KAAM,UAAU,CAAA,CAAE,UAAA,GAAa,EAAE,QAAQ,CAAA;AAC9D,IAAA,IAAI,OAAO,EAAE,kBAAkB,CAAA,KAAM,UAAU,CAAA,CAAE,cAAA,GAAiB,EAAE,kBAAkB,CAAA;AACtF,IAAA,MAAM,CAAA,GAAI,EAAE,OAAO,CAAA;AACnB,IAAA,IAAI,CAAA,IAAK,OAAO,CAAA,KAAM,QAAA,EAAU;AAC9B,MAAA,MAAM,EAAA,GAAK,CAAA;AACX,MAAA,IAAI,OAAO,GAAG,cAAc,CAAA,KAAM,UAAU,CAAA,CAAE,WAAA,GAAc,GAAG,cAAc,CAAA;AAC7E,MAAA,IAAI,OAAO,GAAG,eAAe,CAAA,KAAM,UAAU,CAAA,CAAE,YAAA,GAAe,GAAG,eAAe,CAAA;AAAA,IAClF;AACA,IAAA,OAAO,CAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AAAE,IAAA,OAAO,EAAC;AAAA,EAAE;AACtB;AAOO,SAAS,eAAA,CACd,MAAA,EACA,UAAA,EACA,cAAA,EAC0C;AAC1C,EAAA,MAAM,CAAA,GAAI,GAAG,MAAM;AAAA,EAAK,UAAA,IAAc,EAAE,CAAA,CAAA,CAAG,WAAA,EAAY;AACvD,EAAA,IACE,cAAA,KAAmB,OACnB,cAAA,KAAmB,GAAA,IACnB,uEAAuE,IAAA,CAAK,CAAC,GAC7E,OAAO,cAAA;AACT,EAAA,IAAI,gFAAA,CAAiF,KAAK,CAAC,CAAA;AACzF,IAAA,OAAO,aAAA;AACT,EAAA,OAAO,OAAA;AACT;AAUO,SAAS,eAAe,YAAA,EAA6E;AAC1G,EAAA,QAAQ,YAAA;AAAc,IACpB,KAAK,OAAA;AAAS,MAAA,OAAO,OAAA;AAAA,IACrB,KAAK,QAAA;AAAU,MAAA,OAAO,QAAA;AAAA,IACtB;AAAS,MAAA,OAAO,aAAA;AAAA;AAEpB;AAWO,SAAS,iBAAiB,GAAA,EAI/B;AACA,EAAA,MAAM,OAAA,GAAU,IAAI,IAAA,EAAK;AAEzB,EAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,WAAA,CAAY,GAAG,CAAA;AACzC,EAAA,IAAI,SAAA,KAAc,EAAA,EAAI,OAAO,EAAC;AAC9B,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,IAAI,KAAA,GAAQ,EAAA;AACZ,EAAA,KAAA,IAAS,CAAA,GAAI,SAAA,EAAW,CAAA,IAAK,CAAA,EAAG,CAAA,EAAA,EAAK;AACnC,IAAA,IAAI,OAAA,CAAQ,CAAC,CAAA,KAAM,GAAA,EAAK,KAAA,EAAA;AAAA,SAAA,IACf,OAAA,CAAQ,CAAC,CAAA,KAAM,GAAA,EAAK;AAC3B,MAAA,KAAA,EAAA;AACA,MAAA,IAAI,UAAU,CAAA,EAAG;AAAE,QAAA,KAAA,GAAQ,CAAA;AAAG,QAAA;AAAA,MAAM;AAAA,IACtC;AAAA,EACF;AACA,EAAA,IAAI,KAAA,KAAU,EAAA,EAAI,OAAO,EAAC;AAC1B,EAAA,IAAI;AACF,IAAA,MAAM,CAAA,GAAI,KAAK,KAAA,CAAM,OAAA,CAAQ,MAAM,KAAA,EAAO,SAAA,GAAY,CAAC,CAAC,CAAA;AACxD,IAAA,MAAM,IAAyC,EAAC;AAChD,IAAA,IAAI,OAAO,EAAE,QAAQ,CAAA,KAAM,UAAU,CAAA,CAAE,UAAA,GAAa,EAAE,QAAQ,CAAA;AAC9D,IAAA,IAAI,OAAO,EAAE,QAAQ,CAAA,KAAM,UAAU,CAAA,CAAE,UAAA,GAAa,EAAE,QAAQ,CAAA;AAC9D,IAAA,IAAI,OAAO,EAAE,MAAM,CAAA,KAAM,UAAU,CAAA,CAAE,OAAA,GAAU,EAAE,MAAM,CAAA;AACvD,IAAA,IAAI,CAAA,CAAE,OAAO,CAAA,KAAM,KAAA,CAAA,IAAa,OAAA,GAAU,IAAA;AAC1C,IAAA,OAAO,CAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AAAE,IAAA,OAAO,EAAC;AAAA,EAAE;AACtB;AAEA,IAAM,kBAAA,GAAqB,IAAI,EAAA,GAAK,GAAA;AAGpC,eAAe,cAAA,CACb,MAAA,EACA,cAAA,EACA,YAAA,EACA,OACA,YAAA,EACe;AACf,EAAA,MAAM,OAAA,GAAU;AAAA,IAAC,IAAA;AAAA,IAAM,iBAAA;AAAA,IAAmB,MAAA;AAAA,IAAQ,aAAA;AAAA,IAAe,GAAA;AAAA,IAC/D,SAAA;AAAA,IAAW,KAAA;AAAA,IAAO,YAAA;AAAA,IAAc,YAAA;AAAA,IAAc,UAAA;AAAA,IAAY;AAAA,GAAY;AACxE,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,KAAA,GAAQ,eAAA,CAAgB,OAAO,CAAA,GAAI,OAAA;AACvD,EAAA,MAAM,IAAI,OAAA,CAAc,CAAC,OAAA,KAAY;AACnC,IAAA,IAAI,KAAA;AACJ,IAAA,IAAI;AACF,MAAA,KAAA,GAAQC,KAAAA,CAAM,MAAA,CAAO,GAAA,EAAK,IAAA,EAAM;AAAA,QAC9B,GAAA,EAAK,cAAA;AAAA,QAAgB,GAAA,EAAK,EAAE,GAAG,OAAA,CAAQ,GAAA,EAAI;AAAA,QAC3C,OAAO,MAAA,CAAO,KAAA;AAAA,QAAO,KAAA,EAAO,CAAC,MAAA,EAAQ,QAAA,EAAU,QAAQ;AAAA,OACxD,CAAA;AACD,MAAA,KAAA,CAAM,KAAA,EAAO,KAAA;AAAA,QACX;AAAA,OAIF;AACA,MAAA,KAAA,CAAM,OAAO,GAAA,EAAI;AAAA,IACnB,SAAS,GAAA,EAAK;AACZ,MAAA,OAAA,CAAQ,CAAA,8BAAA,EAAiC,eAAe,KAAA,GAAQ,GAAA,CAAI,UAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAE,CAAA;AAC3F,MAAA,OAAA,EAAQ;AAAG,MAAA;AAAA,IACb;AACA,IAAA,MAAM,KAAA,GAAQ,WAAW,MAAM;AAC7B,MAAA,OAAA,CAAQ,4DAAuD,CAAA;AAC/D,MAAA,IAAI;AAAE,QAAA,KAAA,CAAM,KAAK,SAAS,CAAA;AAAA,MAAE,CAAA,CAAA,MAAQ;AAAA,MAAe;AAAA,IACrD,GAAG,kBAAkB,CAAA;AACrB,IAAA,KAAA,CAAM,EAAA,CAAG,SAAS,MAAM;AAAE,MAAA,YAAA,CAAa,KAAK,CAAA;AAAG,MAAA,GAAA,CAAI,uBAAuB,CAAA;AAAG,MAAA,OAAA,EAAQ;AAAA,IAAE,CAAC,CAAA;AACxF,IAAA,KAAA,CAAM,EAAA,CAAG,SAAS,MAAM;AAAE,MAAA,YAAA,CAAa,KAAK,CAAA;AAAG,MAAA,OAAA,EAAQ;AAAA,IAAE,CAAC,CAAA;AAAA,EAC5D,CAAC,CAAA;AACH;AAMA,eAAe,gBAAgB,cAAA,EAAuC;AACpE,EAAA,MAAM,UAAA,GAAaH,IAAAA,CAAK,cAAA,EAAgB,SAAA,EAAW,iBAAiB,CAAA;AACpE,EAAA,IAAI,CAACE,UAAAA,CAAW,UAAU,CAAA,EAAG;AAC7B,EAAA,MAAM,IAAI,OAAA,CAAc,CAAC,OAAA,KAAY;AACnC,IAAA,IAAI,KAAA;AACJ,IAAA,IAAI;AACF,MAAA,KAAA,GAAQC,KAAAA,CAAM,OAAA,CAAQ,QAAA,EAAU,CAAC,UAAU,CAAA,EAAG;AAAA,QAC5C,GAAA,EAAK,cAAA;AAAA,QAAgB,GAAA,EAAK,EAAE,GAAG,OAAA,CAAQ,GAAA,EAAI;AAAA,QAC3C,KAAA,EAAO,KAAA;AAAA,QAAO,KAAA,EAAO,CAAC,QAAA,EAAU,QAAA,EAAU,MAAM;AAAA,OACjD,CAAA;AAAA,IACH,SAAS,GAAA,EAAK;AACZ,MAAA,OAAA,CAAQ,CAAA,0BAAA,EAA6B,eAAe,KAAA,GAAQ,GAAA,CAAI,UAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAE,CAAA;AACvF,MAAA,OAAA,EAAQ;AAAG,MAAA;AAAA,IACb;AACA,IAAA,IAAI,SAAA,GAAY,EAAA;AAChB,IAAA,KAAA,CAAM,MAAA,EAAQ,EAAA,CAAG,MAAA,EAAQ,CAAC,CAAA,KAAc;AAAE,MAAA,SAAA,IAAa,CAAA,CAAE,SAAS,OAAO,CAAA;AAAA,IAAE,CAAC,CAAA;AAC5E,IAAA,MAAM,KAAA,GAAQ,WAAW,MAAM;AAC7B,MAAA,OAAA,CAAQ,gDAA2C,CAAA;AACnD,MAAA,IAAI;AAAE,QAAA,KAAA,CAAM,KAAK,SAAS,CAAA;AAAA,MAAE,CAAA,CAAA,MAAQ;AAAA,MAAe;AAAA,IACrD,GAAG,GAAM,CAAA;AACT,IAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,IAAA,KAAS;AAC1B,MAAA,YAAA,CAAa,KAAK,CAAA;AAClB,MAAA,IAAI,SAAS,CAAA,EAAG,OAAA,CAAQ,CAAA,mBAAA,EAAsB,MAAA,CAAO,IAAI,CAAC,CAAA,EAAG,SAAA,GAAY,CAAA,EAAA,EAAK,UAAU,KAAA,CAAM,IAAI,CAAC,CAAA,CAAA,GAAK,EAAE,CAAA,CAAE,CAAA;AAC5G,MAAA,OAAA,EAAQ;AAAA,IACV,CAAC,CAAA;AACD,IAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAQ;AAAE,MAAA,YAAA,CAAa,KAAK,CAAA;AAAG,MAAA,OAAA,CAAQ,CAAA,mBAAA,EAAsB,GAAA,CAAI,OAAO,CAAA,CAAE,CAAA;AAAG,MAAA,OAAA,EAAQ;AAAA,IAAE,CAAC,CAAA;AAAA,EAC7G,CAAC,CAAA;AACH;AAqCA,SAAS,qBAAA,CAAsB,OAAe,YAAA,EAAqC;AACjF,EAAA,MAAM,QAAA,GAAW,QAAQ,QAAA,KAAa,OAAA;AAKtC,EAAA,MAAM,OAAA,GAAU,CAAC,MAAA,EAAQ,QAAQ,CAAA;AACjC,EAAA,IAAI,KAAA,IAAS,KAAA,CAAM,IAAA,EAAK,CAAE,SAAS,CAAA,EAAG;AACpC,IAAA,OAAA,CAAQ,IAAA,CAAK,WAAW,KAAK,CAAA;AAAA,EAC/B;AAGA,EAAA,IAAI,YAAA,CAAa,SAAS,CAAA,EAAG;AAC3B,IAAA,GAAA,CAAI,CAAA,+BAAA,EAAkC,YAAA,CAAa,IAAA,CAAK,GAAG,CAAC,CAAA,iFAAA,CAAmF,CAAA;AAAA,EACjJ;AAGA,EAAA,MAAM,IAAA,GAAO,QAAA,GAAW,eAAA,CAAgB,OAAO,CAAA,GAAI,OAAA;AACnD,EAAA,OAAO,EAAE,GAAA,EAAK,OAAA,EAAS,MAAM,KAAA,EAAO,QAAA,EAAU,aAAa,KAAA,EAAM;AACnE;AA2BA,SAAS,sBAAA,CAAuB,OAAe,YAAA,EAAqC;AAClF,EAAA,MAAM,QAAA,GAAW,QAAQ,QAAA,KAAa,OAAA;AAOtC,EAAA,MAAM,OAAA,GAAU,CAAC,IAAI,CAAA;AACrB,EAAA,IAAI,KAAA,IAAS,KAAA,CAAM,IAAA,EAAK,CAAE,SAAS,CAAA,EAAG;AACpC,IAAA,OAAA,CAAQ,IAAA,CAAK,WAAW,KAAK,CAAA;AAAA,EAC/B;AACA,EAAA,IAAI,YAAA,CAAa,SAAS,CAAA,EAAG;AAK3B,IAAA,MAAM,iBAAiB,YAAA,CAAa,MAAA;AAAA,MAAO,CAAC,CAAA,KAC1C,gFAAA,CAAiF,IAAA,CAAK,CAAC;AAAA,KACzF;AACA,IAAA,IAAI,cAAA,CAAe,SAAS,CAAA,EAAG;AAC7B,MAAA,OAAA,CAAQ,IAAA,CAAK,YAAA,EAAc,cAAA,CAAe,IAAA,CAAK,GAAG,CAAC,CAAA;AAAA,IACrD,CAAA,MAAO;AACL,MAAA,GAAA,CAAI,CAAA,8BAAA,EAAiC,YAAA,CAAa,IAAA,CAAK,GAAG,CAAC,CAAA,mDAAA,CAAqD,CAAA;AAAA,IAClH;AAAA,EACF;AAGA,EAAA,MAAM,IAAA,GAAO,QAAA,GAAW,eAAA,CAAgB,OAAO,CAAA,GAAI,OAAA;AACnD,EAAA,OAAO,EAAE,GAAA,EAAK,QAAA,EAAU,MAAM,KAAA,EAAO,QAAA,EAAU,aAAa,KAAA,EAAM;AACpE;AAeA,eAAsB,WAAA,CAAY,QAAsB,IAAA,EAA+B;AAKrF,EAAA,IAAI,CAAC,KAAK,KAAA,EAAO;AACf,IAAA,OAAA,CAAQ,CAAA,IAAA,EAAO,IAAA,CAAK,KAAK,CAAA,yDAAA,CAAsD,CAAA;AAC/E,IAAA,MAAM,WAAW,MAAA,EAAQ;AAAA,MACvB,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,MAAA,EAAQ,QAAA;AAAA,MACR,WAAA,EAAa,cAAA;AAAA,MACb,aAAA,EAAe,EAAA;AAAA,MACf,aAAA,EAAe,EAAA;AAAA,MACf,KAAA,EAAO,yDAAA;AAAA,MACP,QAAA,EAAU;AAAA,KACX,CAAA;AACD,IAAA;AAAA,EACF;AACA,EAAA,MAAM,YAAY,IAAA,CAAK,KAAA;AACvB,EAAA,MAAM,KAAA,GAAQ,SAAA,CAAU,SAAA,CAAU,EAAE,CAAA;AACpC,EAAA,MAAM,KAAA,GAAQ,KAAA,EAAO,KAAA,IAAS,SAAA,CAAU,KAAA;AACxC,EAAA,MAAM,cAAA,GAAiB,iBAAA,CAAkB,SAAA,CAAU,EAAE,CAAA;AAIrD,EAAA,MAAM,OAAA,GAAU,cAAA;AAAA,IACd,SAAA,CAAU,gBAAgB,KAAA,EAAO;AAAA,GACnC;AAEA,EAAA,IAAI,GAAA,GAAM,cAAA;AACV,EAAA,IAAI,IAAA,CAAK,UAAA,IAAcD,UAAAA,CAAW,IAAA,CAAK,UAAU,CAAA,EAAG;AAClD,IAAA,GAAA,GAAM,IAAA,CAAK,UAAA;AAAA,EACb,CAAA,MAAA,IAAW,KAAK,UAAA,EAAY;AAC1B,IAAA,OAAA,CAAQ,CAAA,YAAA,EAAe,IAAA,CAAK,UAAU,CAAA,iDAAA,CAAmD,CAAA;AAAA,EAC3F;AAEA,EAAA,GAAA,CAAI,CAAA,aAAA,EAAgB,IAAA,CAAK,KAAK,CAAA,SAAA,EAAY,SAAA,CAAU,IAAI,CAAA,YAAA,EAAe,OAAO,CAAA,UAAA,EAAa,KAAK,CAAA,EAAA,CAAI,CAAA;AACpG,EAAA,GAAA,CAAI,CAAA,OAAA,EAAU,GAAG,CAAA,CAAE,CAAA;AAGnB,EAAA,MAAM,GAAA,GAAyB,EAAE,GAAG,OAAA,CAAQ,GAAA,EAAI;AAKhD,EAAA,IAAI,YAAY,QAAA,EAAU;AACxB,IAAA,GAAA,CAAI,aAAa,CAAA,GAAIF,IAAAA,CAAK,cAAA,EAAgB,SAAS,CAAA;AAAA,EACrD;AAQA,EAAA,MAAM,aAAa,eAAA,CAAgB;AAAA,IACjC,YAAY,IAAA,CAAK,MAAA;AAAA,IACjB,KAAA;AAAA,IACA,GAAA;AAAA,IACA,cAAA;AAAA,IACA,OAAA,EAAS;AAAA,GACV,CAAA;AAED,EAAA,IAAI,SAAA,GAAY,IAAI,SAAA,GAAY,EAAA;AAChC,EAAA,IAAI,QAAA,GAA0B,IAAA;AAC9B,EAAA,IAAI,UAAA;AAEJ,EAAA,IAAI,YAAY,aAAA,EAAe;AAE7B,IAAA,MAAM,SAAS,oBAAA,EAAqB;AAGpC,IAAA,MAAM,YAAA,GAAeA,KAAK,cAAA,EAAgB,SAAA,EAAW,eAAe,CAAA,CAAE,OAAA,CAAQ,OAAO,GAAG,CAAA;AACxF,IAAA,MAAM,OAAA,GAAU;AAAA,MAAC,IAAA;AAAA,MAAM,iBAAA;AAAA,MAAmB,MAAA;AAAA,MAAQ,aAAA;AAAA,MAAe,IAAA;AAAA,MAC/D,SAAA;AAAA,MAAW,KAAA;AAAA,MAAO,YAAA;AAAA,MAAc;AAAA,KAAY;AAG9C,IAAA,IAAI,KAAA,CAAM,QAAQ,SAAA,CAAU,YAAY,KAAK,SAAA,CAAU,YAAA,CAAa,SAAS,CAAA,EAAG;AAC9E,MAAA,OAAA,CAAQ,KAAK,gBAAA,EAAkB,SAAA,CAAU,YAAA,CAAa,IAAA,CAAK,GAAG,CAAC,CAAA;AAAA,IACjE;AAEA,IAAA,MAAM,UAAA,GAAa,UAAU,gBAAA,KAAqB,YAAA;AAClD,IAAA,IAAI,YAAA,GAAe,gBAAA,CAAiB,SAAA,CAAU,EAAE,CAAA;AAChD,IAAA,IAAI,OAAA,GAAU,KAAA;AACd,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,IAAI,mBAAA,CAAoB,YAAA,EAAc,IAAA,CAAK,GAAA,EAAK,CAAA,EAAG;AACjD,QAAA,IAAI,aAAa,SAAA,EAAW;AAC1B,UAAA,GAAA,CAAI,CAAA,4BAAA,EAA+B,SAAA,CAAU,IAAI,CAAA,yBAAA,CAA2B,CAAA;AAC5E,UAAA,MAAM,eAAe,MAAA,EAAQ,cAAA,EAAgB,YAAA,EAAc,KAAA,EAAO,aAAa,SAAS,CAAA;AACxF,UAAA,OAAA,GAAU,IAAA;AAAA,QACZ;AACA,QAAA,YAAA,GAAe,EAAE,SAAA,EAAW,IAAA,EAAM,gBAAA,EAAkB,IAAA,EAAM,UAAU,CAAA,EAAE;AAAA,MACxE,CAAA,MAAA,IAAW,aAAa,SAAA,EAAW;AACjC,QAAA,OAAA,CAAQ,IAAA,CAAK,UAAA,EAAY,YAAA,CAAa,SAAS,CAAA;AAAA,MACjD;AAAA,IACF;AAGA,IAAA,MAAM,mBAAmB,eAAA,CAAgB;AAAA,MACvC,YAAY,IAAA,CAAK,MAAA;AAAA,MAAQ,KAAA;AAAA,MAAO,GAAA;AAAA,MAAK,cAAA;AAAA,MAAgB;AAAA,KACtD,CAAA;AAED,IAAA,MAAM,IAAA,GAAO,MAAA,CAAO,KAAA,GAAQ,eAAA,CAAgB,OAAO,CAAA,GAAI,OAAA;AAEvD,IAAA,MAAM,IAAI,OAAA,CAAc,CAAC,OAAA,KAAY;AACnC,MAAA,IAAI,KAAA;AACJ,MAAA,IAAI;AACF,QAAA,KAAA,GAAQG,KAAAA,CAAM,MAAA,CAAO,GAAA,EAAK,IAAA,EAAM;AAAA,UAC9B,GAAA;AAAA,UAAK,GAAA;AAAA,UAAK,OAAO,MAAA,CAAO,KAAA;AAAA,UACxB,KAAA,EAAO,CAAC,MAAA,EAAQ,MAAA,EAAQ,MAAM;AAAA,SAC/B,CAAA;AACD,QAAA,KAAA,CAAM,KAAA,EAAO,MAAM,gBAAgB,CAAA;AACnC,QAAA,KAAA,CAAM,OAAO,GAAA,EAAI;AAAA,MACnB,SAAS,GAAA,EAAc;AACrB,QAAA,UAAA,GAAa,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC5D,QAAA,OAAA,EAAQ;AAAG,QAAA;AAAA,MACb;AACA,MAAA,MAAM,aAAA,GAAgB,WAAW,MAAM;AACrC,QAAA,OAAA,CAAQ,CAAA,IAAA,EAAO,IAAA,CAAK,KAAK,CAAA,wCAAA,CAAqC,CAAA;AAC9D,QAAA,IAAI;AAAE,UAAA,KAAA,CAAM,KAAK,SAAS,CAAA;AAAA,QAAE,CAAA,CAAA,MAAQ;AAAA,QAAe;AACnD,QAAA,UAAA,CAAW,MAAM;AAAE,UAAA,IAAI;AAAE,YAAA,KAAA,CAAM,KAAK,SAAS,CAAA;AAAA,UAAE,CAAA,CAAA,MAAQ;AAAA,UAAe;AAAA,QAAE,GAAG,GAAK,CAAA;AAAA,MAClF,GAAG,cAAc,CAAA;AACjB,MAAA,KAAA,CAAM,MAAA,EAAQ,EAAA,CAAG,MAAA,EAAQ,CAAC,CAAA,KAAc;AAAE,QAAA,SAAA,IAAa,CAAA,CAAE,SAAS,OAAO,CAAA;AAAA,MAAE,CAAC,CAAA;AAC5E,MAAA,KAAA,CAAM,MAAA,EAAQ,EAAA,CAAG,MAAA,EAAQ,CAAC,CAAA,KAAc;AAAE,QAAA,SAAA,IAAa,CAAA,CAAE,SAAS,OAAO,CAAA;AAAA,MAAE,CAAC,CAAA;AAC5E,MAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,IAAA,KAAS;AAAE,QAAA,YAAA,CAAa,aAAa,CAAA;AAAG,QAAA,QAAA,GAAW,IAAA;AAAM,QAAA,OAAA,EAAQ;AAAA,MAAE,CAAC,CAAA;AACvF,MAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAQ;AAAE,QAAA,YAAA,CAAa,aAAa,CAAA;AAAG,QAAA,UAAA,GAAa,GAAA,CAAI,OAAA;AAAS,QAAA,OAAA,EAAQ;AAAA,MAAE,CAAC,CAAA;AAAA,IACjG,CAAC,CAAA;AAED,IAAA,MAAM,aAAA,GAAgB,UAAU,MAAA,GAAS,UAAA,GAAa,UAAU,KAAA,CAAM,CAAC,UAAU,CAAA,GAAI,SAAA;AACrF,IAAA,MAAM,aAAA,GAAgB,UAAU,MAAA,GAAS,UAAA,GAAa,UAAU,KAAA,CAAM,CAAC,UAAU,CAAA,GAAI,SAAA;AAErF,IAAA,MAAM,MAAA,GAAS,kBAAkB,SAAS,CAAA;AAC1C,IAAA,MAAM,YAAY,UAAA,KAAe,MAAA,IAAa,QAAA,KAAa,CAAA,IAAK,OAAO,OAAA,KAAY,IAAA;AACnF,IAAA,MAAM,YAAA,GAAe,SAAA,GAAY,MAAA,GAC7B,UAAA,KACI,MAAA,CAAO,UAAU,MAAA,CAAO,UAAA,EAAY,KAAA,CAAM,CAAA,EAAG,GAAI,CAAA,GAAI,YACrD,aAAA,CAAc,IAAA,EAAK,GAAI,aAAA,CAAc,IAAA,EAAK,CAAE,KAAA,CAAM,IAAK,CAAA,GAAI,MAAA,CAAA,IAC5D,CAAA,wBAAA,EAA2B,QAAA,IAAY,SAAS,CAAA,CAAA;AACvD,IAAA,MAAM,WAAA,GAAc,YAChB,MAAA,GACA,eAAA,CAAgB,eAAe,MAAA,CAAO,UAAA,EAAY,OAAO,cAAc,CAAA;AAE3E,IAAA,MAAM,EAAE,SAAS,GAAA,EAAK,UAAA,EAAY,KAAK,cAAA,EAAgB,IAAA,EAAM,GAAG,YAAA,EAAa,GAAI,MAAA;AACjF,IAAA,MAAM,MAAA,GAAoB;AAAA,MACxB,OAAO,IAAA,CAAK,KAAA;AAAA,MAAO,UAAU,IAAA,CAAK,QAAA;AAAA,MAClC,MAAA,EAAQ,YAAY,WAAA,GAAc,QAAA;AAAA,MAClC,WAAA;AAAA,MAAa,aAAA;AAAA,MAAe,aAAA;AAAA,MAC5B,KAAA,EAAO,YAAA;AAAA,MAAc,QAAA;AAAA,MAAU,GAAG;AAAA,KACpC;AAEA,IAAA,GAAA,CAAI,CAAA,IAAA,EAAO,KAAK,KAAK,CAAA,CAAA,EAAI,OAAO,MAAM,CAAA,OAAA,EAAU,YAAY,KAAK,CAAA,EAC/D,OAAO,OAAA,KAAY,MAAA,GAAY,WAAW,MAAA,CAAO,OAAA,CAAQ,QAAQ,CAAC,CAAC,CAAA,CAAA,GAAK,EAAE,CAAA,CAAA,CAAG,CAAA;AAE/E,IAAA,IAAI,UAAA,IAAc,MAAA,CAAO,MAAA,KAAW,WAAA,EAAa;AAC/C,MAAA,gBAAA,CAAiB,UAAU,EAAA,EAAI,MAAA,CAAO,WAAW,YAAA,EAAc,IAAA,CAAK,KAAK,CAAA;AAAA,IAC3E;AAEA,IAAA,MAAM,UAAA,CAAW,QAAQ,MAAM,CAAA;AAE/B,IAAA,IAAI,MAAA,CAAO,WAAW,WAAA,EAAa;AACjC,MAAA,MAAM,gBAAgB,cAAc,CAAA;AAAA,IACtC;AAAA,EAEF,CAAA,MAAA,IAAW,YAAY,OAAA,EAAS;AAM9B,IAAA,IAAI,CAAC,gBAAA,CAAiB,KAAK,CAAA,EAAG;AAC5B,MAAA,OAAA,CAAQ,CAAA,IAAA,EAAO,IAAA,CAAK,KAAK,CAAA,+CAAA,EAA6C,KAAK,CAAA,CAAA,CAAG,CAAA;AAC9E,MAAA,MAAMC,OAAAA,GAAoB;AAAA,QACxB,OAAO,IAAA,CAAK,KAAA;AAAA,QAAO,UAAU,IAAA,CAAK,QAAA;AAAA,QAClC,MAAA,EAAQ,QAAA;AAAA,QACR,WAAA,EAAa,cAAA;AAAA,QACb,aAAA,EAAe,EAAA;AAAA,QACf,aAAA,EAAe,EAAA;AAAA,QACf,KAAA,EAAO,wBAAwB,KAAK,CAAA,wCAAA,CAAA;AAAA,QACpC,QAAA,EAAU;AAAA,OACZ;AACA,MAAA,MAAM,UAAA,CAAW,QAAQA,OAAM,CAAA;AAC/B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,WAAW,qBAAA,CAAsB,KAAA,EAAO,SAAA,CAAU,YAAA,IAAgB,EAAE,CAAA;AAG1E,IAAA,MAAM,IAAA,GAA+D,QAAA,CAAS,IAAA;AAE9E,IAAA,MAAM,IAAI,OAAA,CAAc,CAAC,OAAA,KAAY;AACnC,MAAA,IAAI,KAAA;AACJ,MAAA,IAAI;AACF,QAAA,KAAA,GAAQD,KAAAA,CAAM,QAAA,CAAS,GAAA,EAAK,IAAA,EAAM;AAAA,UAChC,GAAA;AAAA,UAAK,GAAA;AAAA,UAAK,OAAO,QAAA,CAAS,KAAA;AAAA,UAC1B,KAAA,EAAO,CAAC,MAAA,EAAQ,MAAA,EAAQ,MAAM;AAAA,SAC/B,CAAA;AACD,QAAA,IAAI,CAAC,SAAS,WAAA,EAAa;AACzB,UAAA,KAAA,CAAM,KAAA,EAAO,MAAM,UAAU,CAAA;AAAA,QAC/B;AACA,QAAA,KAAA,CAAM,OAAO,GAAA,EAAI;AAAA,MACnB,SAAS,GAAA,EAAc;AACrB,QAAA,UAAA,GAAa,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC5D,QAAA,OAAA,EAAQ;AAAG,QAAA;AAAA,MACb;AACA,MAAA,MAAM,aAAA,GAAgB,WAAW,MAAM;AACrC,QAAA,OAAA,CAAQ,CAAA,IAAA,EAAO,IAAA,CAAK,KAAK,CAAA,wCAAA,CAAqC,CAAA;AAC9D,QAAA,IAAI;AAAE,UAAA,KAAA,CAAM,KAAK,SAAS,CAAA;AAAA,QAAE,CAAA,CAAA,MAAQ;AAAA,QAAe;AACnD,QAAA,UAAA,CAAW,MAAM;AAAE,UAAA,IAAI;AAAE,YAAA,KAAA,CAAM,KAAK,SAAS,CAAA;AAAA,UAAE,CAAA,CAAA,MAAQ;AAAA,UAAe;AAAA,QAAE,GAAG,GAAK,CAAA;AAAA,MAClF,GAAG,cAAc,CAAA;AACjB,MAAA,KAAA,CAAM,MAAA,EAAQ,EAAA,CAAG,MAAA,EAAQ,CAAC,CAAA,KAAc;AAAE,QAAA,SAAA,IAAa,CAAA,CAAE,SAAS,OAAO,CAAA;AAAA,MAAE,CAAC,CAAA;AAC5E,MAAA,KAAA,CAAM,MAAA,EAAQ,EAAA,CAAG,MAAA,EAAQ,CAAC,CAAA,KAAc;AAAE,QAAA,SAAA,IAAa,CAAA,CAAE,SAAS,OAAO,CAAA;AAAA,MAAE,CAAC,CAAA;AAC5E,MAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,IAAA,KAAS;AAAE,QAAA,YAAA,CAAa,aAAa,CAAA;AAAG,QAAA,QAAA,GAAW,IAAA;AAAM,QAAA,OAAA,EAAQ;AAAA,MAAE,CAAC,CAAA;AACvF,MAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAQ;AAAE,QAAA,YAAA,CAAa,aAAa,CAAA;AAAG,QAAA,UAAA,GAAa,GAAA,CAAI,OAAA;AAAS,QAAA,OAAA,EAAQ;AAAA,MAAE,CAAC,CAAA;AAAA,IACjG,CAAC,CAAA;AAED,IAAA,MAAM,aAAA,GAAgB,UAAU,MAAA,GAAS,UAAA,GAAa,UAAU,KAAA,CAAM,CAAC,UAAU,CAAA,GAAI,SAAA;AACrF,IAAA,MAAM,aAAA,GAAgB,UAAU,MAAA,GAAS,UAAA,GAAa,UAAU,KAAA,CAAM,CAAC,UAAU,CAAA,GAAI,SAAA;AAGrF,IAAA,MAAM,MAAA,GAAS,iBAAiB,SAAS,CAAA;AACzC,IAAA,MAAM,YAAY,UAAA,KAAe,MAAA,IAAa,QAAA,KAAa,CAAA,IAAK,OAAO,OAAA,KAAY,IAAA;AACnF,IAAA,MAAM,eAAe,SAAA,GAAY,MAAA,GAC7B,UAAA,KACI,aAAA,CAAc,MAAK,GAAI,aAAA,CAAc,IAAA,EAAK,CAAE,MAAM,IAAK,CAAA,GAAI,MAAA,CAAA,IAC5D,CAAA,uBAAA,EAA0B,YAAY,SAAS,CAAA,CAAA;AACtD,IAAA,MAAM,WAAA,GAAc,SAAA,GAChB,MAAA,GACA,eAAA,CAAgB,aAAA,EAAe,MAAA,CAAO,UAAA,IAAc,SAAA,CAAU,KAAA,CAAM,CAAA,EAAG,GAAG,CAAA,EAAG,MAAS,CAAA;AAE1F,IAAA,MAAM,MAAA,GAAoB;AAAA,MACxB,OAAO,IAAA,CAAK,KAAA;AAAA,MAAO,UAAU,IAAA,CAAK,QAAA;AAAA,MAClC,MAAA,EAAQ,YAAY,WAAA,GAAc,QAAA;AAAA,MAClC,WAAA;AAAA,MAAa,aAAA;AAAA,MAAe,aAAA;AAAA,MAC5B,KAAA,EAAO,YAAA;AAAA,MAAc,QAAA;AAAA,MACrB,SAAS,MAAA,CAAO;AAAA,KAClB;AAEA,IAAA,GAAA,CAAI,CAAA,IAAA,EAAO,KAAK,KAAK,CAAA,CAAA,EAAI,OAAO,MAAM,CAAA,oBAAA,EAAkB,YAAY,KAAK,CAAA,EACvE,OAAO,OAAA,KAAY,MAAA,GAAY,WAAW,MAAA,CAAO,OAAA,CAAQ,QAAQ,CAAC,CAAC,CAAA,CAAA,GAAK,EAAE,CAAA,CAAA,CAAG,CAAA;AAE/E,IAAA,MAAM,UAAA,CAAW,QAAQ,MAAM,CAAA;AAE/B,IAAA,IAAI,MAAA,CAAO,WAAW,WAAA,EAAa;AACjC,MAAA,MAAM,gBAAgB,cAAc,CAAA;AAAA,IACtC;AAAA,EAEF,CAAA,MAAO;AAKL,IAAA,GAAA,CAAI,CAAA,2GAAA,CAAwG,CAAA;AAC5G,IAAA,GAAA,CAAI,CAAA,eAAA,EAAkB,GAAA,CAAI,aAAa,CAAA,IAAK,WAAW,CAAA,CAAE,CAAA;AAGzD,IAAA,IAAI,CAAC,gBAAA,CAAiB,KAAK,CAAA,EAAG;AAC5B,MAAA,OAAA,CAAQ,CAAA,IAAA,EAAO,IAAA,CAAK,KAAK,CAAA,+CAAA,EAA6C,KAAK,CAAA,CAAA,CAAG,CAAA;AAC9E,MAAA,MAAMC,OAAAA,GAAoB;AAAA,QACxB,OAAO,IAAA,CAAK,KAAA;AAAA,QAAO,UAAU,IAAA,CAAK,QAAA;AAAA,QAClC,MAAA,EAAQ,QAAA;AAAA,QACR,WAAA,EAAa,cAAA;AAAA,QACb,aAAA,EAAe,EAAA;AAAA,QACf,aAAA,EAAe,EAAA;AAAA,QACf,KAAA,EAAO,wBAAwB,KAAK,CAAA,wCAAA,CAAA;AAAA,QACpC,QAAA,EAAU;AAAA,OACZ;AACA,MAAA,MAAM,UAAA,CAAW,QAAQA,OAAM,CAAA;AAC/B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,WAAW,sBAAA,CAAuB,KAAA,EAAO,SAAA,CAAU,YAAA,IAAgB,EAAE,CAAA;AAI3E,IAAA,MAAM,OAAO,QAAA,CAAS,IAAA;AAEtB,IAAA,MAAM,IAAI,OAAA,CAAc,CAAC,OAAA,KAAY;AACnC,MAAA,IAAI,KAAA;AACJ,MAAA,IAAI;AACF,QAAA,KAAA,GAAQD,KAAAA,CAAM,QAAA,CAAS,GAAA,EAAK,IAAA,EAAM;AAAA,UAChC,GAAA;AAAA,UAAK,GAAA;AAAA,UAAK,OAAO,QAAA,CAAS,KAAA;AAAA,UAC1B,KAAA,EAAO,CAAC,MAAA,EAAQ,MAAA,EAAQ,MAAM;AAAA,SAC/B,CAAA;AACD,QAAA,KAAA,CAAM,KAAA,EAAO,MAAM,UAAU,CAAA;AAC7B,QAAA,KAAA,CAAM,OAAO,GAAA,EAAI;AAAA,MACnB,SAAS,GAAA,EAAc;AACrB,QAAA,UAAA,GAAa,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC5D,QAAA,OAAA,EAAQ;AAAG,QAAA;AAAA,MACb;AACA,MAAA,MAAM,aAAA,GAAgB,WAAW,MAAM;AACrC,QAAA,OAAA,CAAQ,CAAA,IAAA,EAAO,IAAA,CAAK,KAAK,CAAA,wCAAA,CAAqC,CAAA;AAC9D,QAAA,IAAI;AAAE,UAAA,KAAA,CAAM,KAAK,SAAS,CAAA;AAAA,QAAE,CAAA,CAAA,MAAQ;AAAA,QAAe;AACnD,QAAA,UAAA,CAAW,MAAM;AAAE,UAAA,IAAI;AAAE,YAAA,KAAA,CAAM,KAAK,SAAS,CAAA;AAAA,UAAE,CAAA,CAAA,MAAQ;AAAA,UAAe;AAAA,QAAE,GAAG,GAAK,CAAA;AAAA,MAClF,GAAG,cAAc,CAAA;AACjB,MAAA,KAAA,CAAM,MAAA,EAAQ,EAAA,CAAG,MAAA,EAAQ,CAAC,CAAA,KAAc;AAAE,QAAA,SAAA,IAAa,CAAA,CAAE,SAAS,OAAO,CAAA;AAAA,MAAE,CAAC,CAAA;AAC5E,MAAA,KAAA,CAAM,MAAA,EAAQ,EAAA,CAAG,MAAA,EAAQ,CAAC,CAAA,KAAc;AAAE,QAAA,SAAA,IAAa,CAAA,CAAE,SAAS,OAAO,CAAA;AAAA,MAAE,CAAC,CAAA;AAC5E,MAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,IAAA,KAAS;AAAE,QAAA,YAAA,CAAa,aAAa,CAAA;AAAG,QAAA,QAAA,GAAW,IAAA;AAAM,QAAA,OAAA,EAAQ;AAAA,MAAE,CAAC,CAAA;AACvF,MAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAQ;AAAE,QAAA,YAAA,CAAa,aAAa,CAAA;AAAG,QAAA,UAAA,GAAa,GAAA,CAAI,OAAA;AAAS,QAAA,OAAA,EAAQ;AAAA,MAAE,CAAC,CAAA;AAAA,IACjG,CAAC,CAAA;AAED,IAAA,MAAM,aAAA,GAAgB,UAAU,MAAA,GAAS,UAAA,GAAa,UAAU,KAAA,CAAM,CAAC,UAAU,CAAA,GAAI,SAAA;AACrF,IAAA,MAAM,aAAA,GAAgB,UAAU,MAAA,GAAS,UAAA,GAAa,UAAU,KAAA,CAAM,CAAC,UAAU,CAAA,GAAI,SAAA;AAKrF,IAAA,MAAM,SAAA,GAAY,UAAA,KAAe,MAAA,IAAa,QAAA,KAAa,CAAA;AAC3D,IAAA,MAAM,eAAe,SAAA,GAAY,MAAA,GAC7B,UAAA,KACI,aAAA,CAAc,MAAK,GAAI,aAAA,CAAc,IAAA,EAAK,CAAE,MAAM,IAAK,CAAA,GAAI,MAAA,CAAA,IAC5D,CAAA,wBAAA,EAA2B,YAAY,SAAS,CAAA,CAAA;AAIvD,IAAA,MAAM,WAAA,GAAc,SAAA,GAChB,MAAA,GACA,eAAA,CAAgB,aAAA,EAAe,UAAU,KAAA,CAAM,CAAA,EAAG,GAAG,CAAA,EAAG,MAAS,CAAA;AAErE,IAAA,MAAM,MAAA,GAAoB;AAAA,MACxB,OAAO,IAAA,CAAK,KAAA;AAAA,MAAO,UAAU,IAAA,CAAK,QAAA;AAAA,MAClC,MAAA,EAAQ,YAAY,WAAA,GAAc,QAAA;AAAA,MAClC,WAAA;AAAA,MAAa,aAAA;AAAA,MAAe,aAAA;AAAA,MAC5B,KAAA,EAAO,YAAA;AAAA,MAAc;AAAA;AAAA,KAEvB;AAEA,IAAA,GAAA,CAAI,CAAA,IAAA,EAAO,KAAK,KAAK,CAAA,CAAA,EAAI,OAAO,MAAM,CAAA,qBAAA,EAAmB,QAAA,IAAY,KAAK,CAAA,CAAA,CAAG,CAAA;AAE7E,IAAA,MAAM,UAAA,CAAW,QAAQ,MAAM,CAAA;AAE/B,IAAA,IAAI,MAAA,CAAO,WAAW,WAAA,EAAa;AACjC,MAAA,MAAM,gBAAgB,cAAc,CAAA;AAAA,IACtC;AAAA,EACF;AACF;AAKA,eAAe,UAAA,CAAW,QAAsB,MAAA,EAAkC;AAChF,EAAA,MAAM,IAAA,GAAO,CAAA,oBAAA,EAAuB,MAAA,CAAO,KAAK,CAAA,CAAA;AAChD,EAAA,KAAA,IAAS,OAAA,GAAU,CAAA,EAAG,OAAA,IAAW,kBAAA,EAAoB,OAAA,EAAA,EAAW;AAC9D,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,MAAA,EAAQ,IAAA,EAAM,MAAM,CAAA;AAC/B,MAAA,GAAA,CAAI,CAAA,aAAA,EAAgB,MAAA,CAAO,KAAK,CAAA,UAAA,EAAa,OAAO,CAAA,CAAA,CAAG,CAAA;AACvD,MAAA,mBAAA,CAAoB,OAAO,KAAK,CAAA;AAChC,MAAA;AAAA,IACF,SAAS,GAAA,EAAc;AACrB,MAAA,QAAA,CAAS,wBAAwB,MAAA,CAAO,KAAK,CAAA,UAAA,EAAa,OAAO,KAAK,GAAG,CAAA;AACzE,MAAA,IAAI,OAAA,GAAU,kBAAA,EAAoB,MAAM,KAAA,CAAM,oBAAA,GAAuB,KAAK,GAAA,CAAI,CAAA,EAAG,OAAA,GAAU,CAAC,CAAC,CAAA;AAAA,IAC/F;AAAA,EACF;AACA,EAAA,OAAA,CAAQ,CAAA,iCAAA,EAAoC,MAAA,CAAO,KAAK,CAAA,wBAAA,CAA0B,CAAA;AAClF,EAAA,OAAA,CAAQ,EAAE,KAAA,EAAO,MAAA,CAAO,KAAA,EAAO,MAAA,EAAQ,QAAA,EAAU,kBAAA,EAAoB,aAAA,EAAA,iBAAe,IAAI,IAAA,EAAK,EAAE,WAAA,IAAe,CAAA;AAChH;AAMA,eAAsB,oBAAoB,MAAA,EAAqC;AAC7E,EAAA,MAAM,KAAA,CAAM,OAAO,IAAA,KAAuB;AACxC,IAAA,MAAM,IAAA,GAAO,CAAA,oBAAA,EAAuB,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA,CAAA;AACrD,IAAA,MAAM,IAAA,CAAK,MAAA,EAAQ,IAAA,EAAM,IAAA,CAAK,MAAM,CAAA;AACpC,IAAA,GAAA,CAAI,CAAA,aAAA,EAAgB,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA,aAAA,CAAe,CAAA;AAAA,EACtD,CAAC,CAAA;AACH;AAEA,SAAS,MAAM,EAAA,EAA2B;AACxC,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,EAAE,CAAC,CAAA;AACzD;ACjzBO,IAAME,WAAAA,GAAa,GAAA;AACnB,IAAMC,WAAAA,GAAa,GAAA;AAGnB,IAAM,uBAAA,GAA0B,GAAA;AAChC,IAAM,mBAAA,GAAsB,GAAA;AAGnC,IAAM,aAAA,GAAgB,GAAA;AA0Bf,SAAS,mBAAmB,SAAA,EAAuC;AACxE,EAAA,IAAI,OAAO,cAAc,QAAA,IAAY,CAAC,OAAO,QAAA,CAAS,SAAS,CAAA,IAAK,SAAA,IAAa,CAAA,EAAG;AAClF,IAAA,OAAO,uBAAA;AAAA,EACT;AACA,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,SAAA,EAAW,mBAAmB,CAAA;AAChD;AAMO,SAAS,UAAA,CAAW,KAAa,GAAA,EAAqB;AAC3D,EAAA,OAAO,IAAI,MAAA,GAAS,GAAA,GAAM,IAAI,KAAA,CAAM,CAAC,GAAG,CAAA,GAAI,GAAA;AAC9C;AAMO,SAAS,aAAa,IAAA,EAIuB;AAClD,EAAA,IAAI,IAAA,CAAK,UAAU,OAAO,EAAE,UAAU,IAAA,CAAK,QAAA,EAAU,QAAQ,SAAA,EAAU;AACvE,EAAA,IAAI,IAAA,CAAK,eAAe,MAAA,EAAW,OAAO,EAAE,QAAA,EAAU,IAAA,CAAK,QAAA,EAAU,MAAA,EAAQ,QAAA,EAAS;AACtF,EAAA,IAAI,IAAA,CAAK,aAAa,CAAA,EAAG,OAAO,EAAE,QAAA,EAAU,CAAA,EAAG,QAAQ,WAAA,EAAY;AACnE,EAAA,OAAO,EAAE,QAAA,EAAU,IAAA,CAAK,QAAA,EAAU,QAAQ,QAAA,EAAS;AACrD;AAMO,SAAS,iBAAiB,OAAA,EAAkE;AACjG,EAAA,IAAI,OAAA,CAAQ,aAAa,OAAA,EAAS;AAGhC,IAAA,OAAO,EAAE,GAAA,EAAK,OAAA,CAAQ,GAAA,CAAI,SAAS,CAAA,IAAK,SAAA,EAAW,IAAA,EAAM,CAAC,MAAM,IAAA,EAAM,IAAA,EAAM,OAAO,CAAA,EAAG,OAAO,KAAA,EAAM;AAAA,EACrG;AACA,EAAA,MAAM,EAAA,GAAK,OAAA,CAAQ,GAAA,CAAI,OAAO,CAAA,IAAK,SAAA;AACnC,EAAA,OAAO,EAAE,KAAK,EAAA,EAAI,IAAA,EAAM,CAAC,IAAA,EAAM,OAAO,CAAA,EAAG,KAAA,EAAO,KAAA,EAAM;AACxD;AAUA,eAAsB,gBAAA,CAAiB,OAAA,EAAiB,OAAA,GAAuB,EAAC,EAAwB;AACtG,EAAA,MAAM,SAAA,GAAY,kBAAA,CAAmB,OAAA,CAAQ,SAAS,CAAA;AACtD,EAAA,MAAM,EAAE,GAAA,EAAK,IAAA,EAAM,KAAA,EAAM,GAAI,iBAAiB,OAAO,CAAA;AAIrD,EAAA,MAAM,QAAA,GAAW,QAAQ,GAAA,IAAO,OAAA,CAAQ,IAAI,MAAA,GAAS,CAAA,GAAI,QAAQ,GAAA,GAAM,MAAA;AAEvE,EAAA,IAAI,SAAA,GAAY,EAAA;AAChB,EAAA,IAAI,SAAA,GAAY,EAAA;AAChB,EAAA,IAAI,QAAA,GAA0B,IAAA;AAC9B,EAAA,IAAI,UAAA;AACJ,EAAA,IAAI,QAAA,GAAW,KAAA;AAEf,EAAA,MAAM,IAAI,OAAA,CAAc,CAAC,OAAA,KAAY;AACnC,IAAA,IAAI,KAAA;AACJ,IAAA,IAAI;AACF,MAAA,KAAA,GAAQH,KAAAA,CAAM,KAAK,IAAA,EAAM;AAAA,QACvB,GAAA,EAAK,QAAA;AAAA,QACL,GAAA,EAAK,EAAE,GAAG,OAAA,CAAQ,GAAA,EAAI;AAAA,QACtB,KAAA;AAAA,QACA,KAAA,EAAO,CAAC,QAAA,EAAU,MAAA,EAAQ,MAAM,CAAA;AAAA,QAChC,WAAA,EAAa;AAAA,OACd,CAAA;AAAA,IACH,SAAS,GAAA,EAAc;AACrB,MAAA,UAAA,GAAa,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC5D,MAAA,OAAA,EAAQ;AACR,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,aAAA,GAAgB,WAAW,MAAM;AACrC,MAAA,QAAA,GAAW,IAAA;AACX,MAAA,IAAI;AACF,QAAA,KAAA,CAAM,KAAK,SAAS,CAAA;AAAA,MACtB,CAAA,CAAA,MAAQ;AAAA,MAER;AACA,MAAA,UAAA,CAAW,MAAM;AACf,QAAA,IAAI;AACF,UAAA,KAAA,CAAM,KAAK,SAAS,CAAA;AAAA,QACtB,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACF,GAAG,aAAa,CAAA;AAAA,IAClB,GAAG,SAAS,CAAA;AAEZ,IAAA,KAAA,CAAM,MAAA,EAAQ,EAAA,CAAG,MAAA,EAAQ,CAAC,CAAA,KAAc;AACtC,MAAA,SAAA,IAAa,CAAA,CAAE,SAAS,OAAO,CAAA;AAAA,IACjC,CAAC,CAAA;AACD,IAAA,KAAA,CAAM,MAAA,EAAQ,EAAA,CAAG,MAAA,EAAQ,CAAC,CAAA,KAAc;AACtC,MAAA,SAAA,IAAa,CAAA,CAAE,SAAS,OAAO,CAAA;AAAA,IACjC,CAAC,CAAA;AACD,IAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,IAAA,KAAS;AAC1B,MAAA,YAAA,CAAa,aAAa,CAAA;AAC1B,MAAA,QAAA,GAAW,IAAA;AACX,MAAA,OAAA,EAAQ;AAAA,IACV,CAAC,CAAA;AACD,IAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAQ;AACzB,MAAA,YAAA,CAAa,aAAa,CAAA;AAC1B,MAAA,UAAA,GAAa,GAAA,CAAI,OAAA;AACjB,MAAA,OAAA,EAAQ;AAAA,IACV,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AAED,EAAA,MAAM,aAAA,GAAgB,UAAA,CAAW,SAAA,EAAWE,WAAU,CAAA;AAGtD,EAAA,MAAM,eAAe,UAAA,KAAe,MAAA,IAAa,SAAA,CAAU,MAAA,KAAW,IAAI,UAAA,GAAa,SAAA;AACvF,EAAA,MAAM,aAAA,GAAgB,UAAA,CAAW,YAAA,EAAcC,WAAU,CAAA;AAEzD,EAAA,MAAM,EAAE,QAAA,EAAU,SAAA,EAAW,MAAA,EAAO,GAAI,aAAa,EAAE,QAAA,EAAU,UAAA,EAAY,QAAA,EAAU,CAAA;AAEvF,EAAA,OAAO,EAAE,QAAA,EAAU,SAAA,EAAW,aAAA,EAAe,eAAe,MAAA,EAAO;AACrE;AC1GA,IAAM,YAAA,GAAe,GAAA;AACrB,IAAM,YAAA,GAAe,EAAA;AAuBd,SAAS,WAAA,GAAoC;AAClD,EAAA,IAAI;AAEF,IAAA,OAAO,UAAQ,UAAU,CAAA;AAAA,EAC3B,SAAS,GAAA,EAAc;AACrB,IAAA,OAAA,CAAQ,CAAA,sBAAA,EAAyB,eAAe,KAAA,GAAQ,GAAA,CAAI,UAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAE,CAAA;AACnF,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAOO,SAAS,aAAa,QAAA,EAAsD;AACjF,EAAA,IAAI,QAAA,IAAY,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG;AACnC,IAAA,OAAO,EAAE,KAAA,EAAO,QAAA,EAAU,IAAA,EAAM,EAAA,CAAG,QAAA,EAAS,KAAM,OAAA,GAAU,EAAC,GAAI,CAAC,SAAS,CAAA,EAAE;AAAA,EAC/E;AACA,EAAA,IAAI,EAAA,CAAG,QAAA,EAAS,KAAM,OAAA,EAAS;AAC7B,IAAA,MAAM,YAAA,GAAe;AAAA,MACnB,uCAAA;AAAA,MACA;AAAA,KACF;AACA,IAAA,MAAM,WAAW,YAAA,CAAa,IAAA,CAAK,CAAC,CAAA,KAAMJ,UAAAA,CAAW,CAAC,CAAC,CAAA;AACvD,IAAA,IAAI,QAAA,SAAiB,EAAE,KAAA,EAAO,UAAU,IAAA,EAAM,CAAC,SAAA,EAAW,IAAI,CAAA,EAAE;AAChE,IAAA,OAAO,EAAE,KAAA,EAAO,gBAAA,EAAkB,IAAA,EAAM,CAAC,SAAS,CAAA,EAAE;AAAA,EACtD;AACA,EAAA,OAAO,EAAE,KAAA,EAAO,OAAA,CAAQ,GAAA,CAAI,OAAO,KAAK,WAAA,EAAa,IAAA,EAAM,CAAC,SAAS,CAAA,EAAE;AACzE;AAMO,SAAS,kBAAA,CAAmB,YAAoB,SAAA,EAA2B;AAChF,EAAA,MAAM,IAAA,GAAO,UAAA,CAAW,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA;AAC1C,EAAA,OAAO,CAAA,EAAG,IAAI,CAAA,cAAA,EAAiB,kBAAA,CAAmB,SAAS,CAAC,CAAA,CAAA;AAC9D;AAmBA,eAAsB,oBACpB,IAAA,EACgC;AAChC,EAAA,MAAM,EAAE,SAAA,EAAU,GAAI,MAAM,OAAO,IAAI,CAAA;AACvC,EAAA,MAAM,GAAA,GAAM,kBAAA,CAAmB,IAAA,CAAK,UAAA,EAAY,KAAK,SAAS,CAAA;AAC9D,EAAA,MAAM,OAAO,IAAA,CAAK,IAAA,IAAQ,KAAK,IAAA,GAAO,CAAA,GAAI,KAAK,IAAA,GAAO,YAAA;AACtD,EAAA,MAAM,OAAO,IAAA,CAAK,IAAA,IAAQ,KAAK,IAAA,GAAO,CAAA,GAAI,KAAK,IAAA,GAAO,YAAA;AAEtD,EAAA,MAAM,EAAA,GAAkB,IAAI,SAAA,CAAU,GAAG,CAAA;AACzC,EAAA,IAAI,GAAA,GAAyB,IAAA;AAC7B,EAAA,IAAI,MAAA,GAAS,KAAA;AAEb,EAAA,MAAM,IAAA,GAAO,CAAC,KAAA,KAA0B;AACtC,IAAA,IAAI,EAAA,CAAG,UAAA,KAAe,SAAA,CAAU,IAAA,EAAM;AACpC,MAAA,EAAA,CAAG,IAAA,CAAK,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAAA,IAC/B;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,OAAA,GAAU,CAAC,MAAA,KAAyB;AACxC,IAAA,IAAI,MAAA,EAAQ;AACZ,IAAA,MAAA,GAAS,IAAA;AACT,IAAA,IAAI,GAAA,EAAK;AACP,MAAA,IAAI;AACF,QAAA,GAAA,CAAI,IAAA,EAAK;AAAA,MACX,CAAA,CAAA,MAAQ;AAAA,MAER;AACA,MAAA,GAAA,GAAM,IAAA;AAAA,IACR;AACA,IAAA,IAAI;AACF,MAAA,EAAA,CAAG,KAAA,EAAM;AAAA,IACX,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA,GAAA,CAAI,CAAA,mBAAA,EAAsB,IAAA,CAAK,SAAS,CAAA,SAAA,EAAY,MAAM,CAAA,CAAA,CAAG,CAAA;AAI7D,IAAA,IAAI,KAAK,QAAA,EAAU;AACjB,MAAA,IAAI;AACF,QAAA,IAAA,CAAK,QAAA,CAAS,KAAK,SAAS,CAAA;AAAA,MAC9B,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,MAAA,GAAgC;AAAA,IACpC,WAAW,IAAA,CAAK,SAAA;AAAA,IAChB,KAAA,EAAO,MAAM,OAAA,CAAQ,cAAc;AAAA,GACrC;AAEA,EAAA,EAAA,CAAG,EAAA,CAAG,QAAQ,MAAM;AAIlB,IAAA,IAAA,CAAK,EAAE,MAAM,MAAA,EAAQ,SAAA,EAAW,KAAK,SAAA,EAAW,SAAA,EAAW,IAAA,CAAK,SAAA,EAAW,CAAA;AAE3E,IAAA,MAAM,UAAU,WAAA,EAAY;AAC5B,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,IAAA,CAAK;AAAA,QACH,IAAA,EAAM,QAAA;AAAA,QACN,IAAA,EACE;AAAA,OAGH,CAAA;AACD,MAAA,IAAA,CAAK,EAAE,IAAA,EAAM,OAAA,EAAS,OAAA,EAAS,uCAAuC,CAAA;AACtE,MAAA,OAAA,CAAQ,sBAAsB,CAAA;AAC9B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,EAAE,KAAA,EAAO,IAAA,EAAK,GAAI,YAAA,CAAa,KAAK,KAAK,CAAA;AAC/C,IAAA,IAAI;AACF,MAAA,GAAA,GAAM,OAAA,CAAQ,KAAA,CAAM,KAAA,EAAO,IAAA,EAAM;AAAA,QAC/B,IAAA,EAAM,gBAAA;AAAA,QACN,IAAA;AAAA,QACA,IAAA;AAAA,QACA,GAAA,EAAK,IAAA,CAAK,GAAA,IAAO,IAAA,CAAK,GAAA,CAAI,SAAS,CAAA,GAAI,IAAA,CAAK,GAAA,GAAM,EAAA,CAAG,OAAA,EAAQ;AAAA,QAC7D,KAAK,OAAA,CAAQ;AAAA,OACd,CAAA;AAAA,IACH,SAAS,GAAA,EAAc;AACrB,MAAA,IAAA,CAAK;AAAA,QACH,IAAA,EAAM,OAAA;AAAA,QACN,OAAA,EAAS,0BAA0B,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,OACpF,CAAA;AACD,MAAA,OAAA,CAAQ,kBAAkB,CAAA;AAC1B,MAAA;AAAA,IACF;AAEA,IAAA,GAAA,CAAI,MAAA,CAAO,CAAC,IAAA,KAAiB;AAC3B,MAAA,IAAA,CAAK,EAAE,IAAA,EAAM,QAAA,EAAU,IAAA,EAAM,CAAA;AAAA,IAC/B,CAAC,CAAA;AACD,IAAA,GAAA,CAAI,MAAA,CAAO,CAAC,EAAE,QAAA,EAAS,KAA4B;AACjD,MAAA,IAAA,CAAK,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,UAAU,CAAA;AACrC,MAAA,OAAA,CAAQ,CAAA,SAAA,EAAY,QAAQ,CAAA,CAAE,CAAA;AAAA,IAChC,CAAC,CAAA;AAGD,IAAA,IAAA,CAAK,EAAE,IAAA,EAAM,OAAA,EAAS,CAAA;AACtB,IAAA,GAAA,CAAI,CAAA,mBAAA,EAAsB,IAAA,CAAK,SAAS,CAAA,QAAA,EAAW,KAAK,CAAA,CAAA,CAAG,CAAA;AAAA,EAC7D,CAAC,CAAA;AAED,EAAA,EAAA,CAAG,EAAA,CAAG,SAAA,EAAW,CAAC,GAAA,KAAyC;AACzD,IAAA,MAAM,IAAA,GAAO,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA,GAC5B,IAAI,QAAA,CAAS,OAAO,CAAA,GACpB,KAAA,CAAM,OAAA,CAAQ,GAAG,IACf,MAAA,CAAO,MAAA,CAAO,GAAG,CAAA,CAAE,QAAA,CAAS,OAAO,CAAA,GACnC,MAAA,CAAO,IAAA,CAAK,GAAG,CAAA,CAAE,QAAA,CAAS,OAAO,CAAA;AACvC,IAAA,IAAI,KAAA;AACJ,IAAA,IAAI;AACF,MAAA,KAAA,GAAQ,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,IACzB,CAAA,CAAA,MAAQ;AAEN,MAAA,IAAI,GAAA,EAAK,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA;AACvB,MAAA;AAAA,IACF;AACA,IAAA,IAAI,MAAM,IAAA,KAAS,OAAA,IAAW,OAAO,KAAA,CAAM,SAAS,QAAA,EAAU;AAC5D,MAAA,IAAI,GAAA,EAAK,GAAA,CAAI,KAAA,CAAM,KAAA,CAAM,IAAI,CAAA;AAAA,IAC/B,CAAA,MAAA,IACE,KAAA,CAAM,IAAA,KAAS,QAAA,IACf,OAAO,KAAA,CAAM,IAAA,KAAS,QAAA,IACtB,OAAO,KAAA,CAAM,IAAA,KAAS,QAAA,EACtB;AACA,MAAA,IAAI,GAAA,EAAK;AACP,QAAA,IAAI;AACF,UAAA,GAAA,CAAI,MAAA,CAAO,KAAA,CAAM,IAAA,EAAM,KAAA,CAAM,IAAI,CAAA;AAAA,QACnC,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF,CAAA,MAAA,IAAW,KAAA,CAAM,IAAA,KAAS,MAAA,EAAQ;AAChC,MAAA,IAAA,CAAK,EAAE,IAAA,EAAM,MAAA,EAAQ,CAAA;AAAA,IACvB;AAAA,EACF,CAAC,CAAA;AAED,EAAA,EAAA,CAAG,EAAA,CAAG,OAAA,EAAS,MAAM,OAAA,CAAQ,UAAU,CAAC,CAAA;AACxC,EAAA,EAAA,CAAG,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAe;AAC7B,IAAA,OAAA,CAAQ,sBAAsB,IAAA,CAAK,SAAS,CAAA,WAAA,EAAc,GAAA,CAAI,OAAO,CAAA,CAAE,CAAA;AACvE,IAAA,OAAA,CAAQ,UAAU,CAAA;AAAA,EACpB,CAAC,CAAA;AAED,EAAA,OAAO,MAAA;AACT;AC/QA,IAAM,SAAA,GAAY,2CAAA;AAClB,IAAMK,aAAAA,GAAe,GAAA;AACrB,IAAM,gBAAA,GAAmB,GAAA;AAQlB,SAAS,aAAa,WAAA,EAAqC;AAChE,EAAA,IAAI,OAAO,gBAAgB,QAAA,IAAY,CAAC,OAAO,QAAA,CAAS,WAAW,GAAG,OAAO,IAAA;AAC7E,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,IAAA,CAAK,KAAA,CAAM,GAAA,GAAM,WAAW,CAAC,CAAC,CAAA;AACjE;AAGO,SAAS,kBAAA,CAAmB,MAA0B,MAAA,EAA+B;AAC1F,EAAA,OAAO;AAAA,IACL,oBAAA,EAAsB,YAAA,CAAa,IAAA,CAAK,SAAA,EAAW,WAAW,CAAA;AAAA,IAC9D,oBAAA,EAAsB,YAAA,CAAa,IAAA,CAAK,SAAA,EAAW,WAAW,CAAA;AAAA,IAC9D,SAAA,EAAW;AAAA,GACb;AACF;AAEA,SAAS,cAAA,GAAgC;AACvC,EAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,uBAAA,EAAyB,OAAO,QAAQ,GAAA,CAAI,uBAAA;AAC5D,EAAA,MAAM,KAAA,GAAQ,YAAA;AAAA,IACZP,IAAAA,CAAKQ,OAAAA,EAAQ,EAAG,SAAA,EAAW,mBAAmB;AAAA,GAChD;AACA,EAAA,OAAO,KAAA,EAAO,eAAe,WAAA,IAAe,IAAA;AAC9C;AAEA,IAAIC,OAAAA,GAAyD,IAAA;AAC7D,IAAI,aAAA,GAAgB,KAAA;AAMpB,eAAsB,gBAAA,GAAkD;AACtE,EAAA,IAAIA,OAAAA,IAAU,KAAK,GAAA,EAAI,GAAIA,QAAO,EAAA,GAAKF,aAAAA,SAAqBE,OAAAA,CAAO,QAAA;AAEnE,EAAA,MAAM,QAAQ,cAAA,EAAe;AAC7B,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,IAAI,CAAC,aAAA,EAAe;AAClB,MAAA,OAAA,CAAQ,6DAAwD,CAAA;AAChE,MAAA,aAAA,GAAgB,IAAA;AAAA,IAClB;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,IAAA,MAAM,QAAQ,UAAA,CAAW,MAAM,UAAA,CAAW,KAAA,IAAS,gBAAgB,CAAA;AACnE,IAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,SAAA,EAAW;AAAA,MACjC,OAAA,EAAS,EAAE,aAAA,EAAe,CAAA,OAAA,EAAU,KAAK,CAAA,CAAA,EAAG;AAAA,MAC5C,QAAQ,UAAA,CAAW;AAAA,KACpB,CAAA;AACD,IAAA,YAAA,CAAa,KAAK,CAAA;AAClB,IAAA,IAAI,CAAC,GAAA,CAAI,EAAA,EAAI,OAAOA,SAAQ,QAAA,IAAY,IAAA;AAExC,IAAA,MAAM,IAAA,GAAQ,MAAM,GAAA,CAAI,IAAA,EAAK;AAC7B,IAAA,MAAM,WAAW,kBAAA,CAAmB,IAAA,EAAA,qBAAU,IAAA,EAAK,EAAE,aAAa,CAAA;AAClE,IAAAA,UAAS,EAAE,QAAA,EAAU,EAAA,EAAI,IAAA,CAAK,KAAI,EAAE;AACpC,IAAA,OAAO,QAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AAEN,IAAA,OAAOA,SAAQ,QAAA,IAAY,IAAA;AAAA,EAC7B;AACF;AC3DO,SAAS,aAAA,GAA2B;AACzC,EAAA,IAAI,IAAA,GAAO,CAAA;AACX,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,KAAA,MAAW,GAAA,IAAOC,MAAK,EAAG;AACxB,IAAA,IAAA,IAAQ,IAAI,KAAA,CAAM,IAAA;AAClB,IAAA,KAAA,IAAS,GAAA,CAAI,KAAA,CAAM,IAAA,GAAO,GAAA,CAAI,KAAA,CAAM,IAAA,GAAO,GAAA,CAAI,KAAA,CAAM,GAAA,GAAM,GAAA,CAAI,KAAA,CAAM,IAAA,GAAO,IAAI,KAAA,CAAM,GAAA;AAAA,EACxF;AACA,EAAA,OAAO,EAAE,MAAM,KAAA,EAAM;AACvB;AAGO,SAAS,aAAA,CAAc,MAAiB,IAAA,EAAqC;AAClF,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,GAAQ,IAAA,CAAK,KAAA;AACjC,EAAA,IAAI,MAAA,IAAU,GAAG,OAAO,MAAA;AACxB,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK,IAAA;AAC/B,EAAA,MAAM,GAAA,GAAM,GAAA,IAAO,CAAA,GAAI,KAAA,GAAQ,MAAA,CAAA;AAC/B,EAAA,OAAO,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,GAAG,CAAC,CAAA,GAAI,EAAE,CAAA,GAAI,EAAA;AAC5D;AAKO,SAAS,aAAa,OAAA,EAAwE;AACnG,EAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,KAAA,CAAM,wBAAwB,CAAA;AACzD,EAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,KAAA,CAAM,4BAA4B,CAAA;AAC7D,EAAA,IAAI,CAAC,UAAA,IAAc,CAAC,UAAA,EAAY,OAAO,MAAA;AACvC,EAAA,MAAM,OAAA,GAAU,KAAK,KAAA,CAAM,MAAA,CAAO,WAAW,CAAC,CAAC,IAAI,IAAI,CAAA;AACvD,EAAA,MAAM,OAAA,GAAU,KAAK,KAAA,CAAM,MAAA,CAAO,WAAW,CAAC,CAAC,IAAI,IAAI,CAAA;AACvD,EAAA,OAAO,EAAE,SAAA,EAAW,OAAA,GAAU,OAAA,EAAS,YAAY,OAAA,EAAQ;AAC7D;AAWO,SAAS,YAAY,OAAA,EAAuD;AACjF,EAAA,IAAI,OAAA,GAAU,CAAA;AACd,EAAA,IAAI,OAAA,GAAU,CAAA;AACd,EAAA,KAAA,MAAW,IAAA,IAAQ,OAAA,CAAQ,KAAA,CAAM,IAAI,CAAA,EAAG;AACtC,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,6CAA6C,CAAA;AACtE,IAAA,IAAI,CAAC,KAAA,IAAS,KAAA,CAAM,CAAC,MAAM,IAAA,EAAM;AACjC,IAAA,OAAA,IAAW,MAAA,CAAO,KAAA,CAAM,CAAC,CAAC,CAAA;AAC1B,IAAA,OAAA,IAAW,MAAA,CAAO,KAAA,CAAM,CAAC,CAAC,CAAA;AAAA,EAC5B;AACA,EAAA,OAAO,EAAE,SAAS,OAAA,EAAQ;AAC5B;AAEO,SAAS,cAAA,CACd,MACA,IAAA,EACsD;AACtD,EAAA,MAAM,OAAA,GAAA,CAAW,IAAA,CAAK,EAAA,GAAK,IAAA,CAAK,EAAA,IAAM,GAAA;AACtC,EAAA,IAAI,OAAA,IAAW,GAAG,OAAO,MAAA;AACzB,EAAA,MAAM,EAAA,GAAA,CAAM,IAAA,CAAK,OAAA,GAAU,IAAA,CAAK,WAAW,IAAA,GAAO,OAAA;AAClD,EAAA,MAAM,EAAA,GAAA,CAAM,IAAA,CAAK,OAAA,GAAU,IAAA,CAAK,WAAW,IAAA,GAAO,OAAA;AAClD,EAAA,IAAI,EAAA,GAAK,CAAA,IAAK,EAAA,GAAK,CAAA,EAAG,OAAO,MAAA;AAC7B,EAAA,OAAO,EAAE,SAAA,EAAW,IAAA,CAAK,KAAA,CAAM,KAAK,EAAE,CAAA,GAAI,EAAA,EAAI,SAAA,EAAW,IAAA,CAAK,KAAA,CAAM,EAAA,GAAK,EAAE,IAAI,EAAA,EAAG;AACpF;AAIA,IAAI,OAAA,GAA4B,IAAA;AAChC,IAAI,OAAA,GAA4B,IAAA;AAQhC,eAAsB,kBAAA,GAA2C;AAC/D,EAAA,MAAM,UAAuB,EAAC;AAG9B,EAAA,IAAI;AACF,IAAA,MAAM,OAAO,aAAA,EAAc;AAC3B,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,MAAM,GAAA,GAAM,aAAA,CAAc,OAAA,EAAS,IAAI,CAAA;AACvC,MAAA,IAAI,GAAA,KAAQ,KAAA,CAAA,EAAW,OAAA,CAAQ,MAAA,GAAS,GAAA;AAAA,IAC1C;AACA,IAAA,OAAA,GAAU,IAAA;AAAA,EACZ,CAAA,CAAA,MAAQ;AAAA,EAER;AAGA,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,OAAA,EAAQ,CAAE,CAAC,CAAA;AACxB,IAAA,IAAI,MAAA,CAAO,QAAA,CAAS,IAAI,CAAA,EAAG,OAAA,CAAQ,QAAQ,IAAA,CAAK,KAAA,CAAM,IAAA,GAAO,GAAG,CAAA,GAAI,GAAA;AAAA,EACtE,CAAA,CAAA,MAAQ;AAAA,EAER;AAGA,EAAA,IAAI;AACF,IAAA,MAAM,UAAU,YAAA,CAAa,MAAM,QAAA,CAAS,eAAA,EAAiB,MAAM,CAAC,CAAA;AACpE,IAAA,IAAI,OAAA,EAAS,MAAA,CAAO,MAAA,CAAO,OAAA,EAAS,OAAO,CAAA;AAAA,EAC7C,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,UAAU,IAAA,CAAK,KAAA,CAAMC,QAAAA,EAAS,GAAI,OAAO,IAAI,CAAA;AACnD,IAAA,OAAA,CAAQ,UAAA,GAAa,OAAA;AACrB,IAAA,OAAA,CAAQ,YAAY,OAAA,GAAU,IAAA,CAAK,MAAM,OAAA,EAAQ,GAAI,OAAO,IAAI,CAAA;AAAA,EAClE;AAGA,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAOC,QAAAA,EAAS,KAAM,OAAA,GAAU,MAAA,GAAS,GAAA;AAC/C,IAAA,MAAM,KAAA,GAAQ,MAAM,MAAA,CAAO,IAAI,CAAA;AAC/B,IAAA,MAAM,OAAA,GAAW,KAAA,CAAM,MAAA,GAAS,KAAA,CAAM,QAAS,IAAA,IAAQ,CAAA;AACvD,IAAA,MAAM,MAAA,GAAU,KAAA,CAAM,KAAA,GAAQ,KAAA,CAAM,QAAS,IAAA,IAAQ,CAAA;AACrD,IAAA,OAAA,CAAQ,WAAA,GAAc,IAAA,CAAK,KAAA,CAAM,OAAA,GAAU,EAAE,CAAA,GAAI,EAAA;AACjD,IAAA,OAAA,CAAQ,aAAa,IAAA,CAAK,KAAA,CAAA,CAAO,OAAA,GAAU,MAAA,IAAU,EAAE,CAAA,GAAI,EAAA;AAAA,EAC7D,CAAA,CAAA,MAAQ;AAAA,EAER;AAGA,EAAA,IAAI;AACF,IAAA,MAAM,SAAS,WAAA,CAAY,MAAM,QAAA,CAAS,eAAA,EAAiB,MAAM,CAAC,CAAA;AAClE,IAAA,MAAM,OAAkB,EAAE,GAAG,QAAQ,EAAA,EAAI,IAAA,CAAK,KAAI,EAAE;AACpD,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,MAAM,IAAA,GAAO,cAAA,CAAe,OAAA,EAAS,IAAI,CAAA;AACzC,MAAA,IAAI,IAAA,EAAM,MAAA,CAAO,MAAA,CAAO,OAAA,EAAS,IAAI,CAAA;AAAA,IACvC;AACA,IAAA,OAAA,GAAU,IAAA;AAAA,EACZ,CAAA,CAAA,MAAQ;AAAA,EAER;AAEA,EAAA,OAAO,OAAA;AACT;;;AC5IA,IAAM,gBAAA,GAAmB,IAAA;AACzB,IAAM,qBAAA,GAAwB,GAAA;AAC9B,IAAM,gBAAA,GAAmB,CAAC,IAAA,EAAO,GAAA,EAAO,KAAQ,GAAM,CAAA;AAmDtD,IAAI,gBAAA,GAAkC,IAAA;AACtC,IAAI,aAAA,GAAoC,MAAA;AAQxC,IAAM,sBAAA,uBAA6B,GAAA,EAAmC;AACtE,IAAM,wBAAA,GAA2B,CAAA;AA4B1B,SAAS,iBAAiB,IAAA,EAA8B;AAC7D,EAAA,QAAQ,KAAK,IAAA;AAAM,IACjB,KAAK,MAAA;AACH,MAAA,OAAO,MAAA;AAAA,IACT,KAAK,eAAA;AACH,MAAA,OAAO,eAAA;AAAA,IACT;AACE,MAAA,OAAO,WAAA;AAAA;AAEb;AAQA,eAAsB,cAAA,CAAe,QAAsB,IAAA,EAA+B;AACxF,EAAA,IAAI,CAAC,IAAA,CAAK,MAAA,IAAU,OAAO,IAAA,CAAK,YAAY,QAAA,EAAU;AACpD,IAAA,OAAA,CAAQ,CAAA,2CAAA,EAA8C,IAAA,CAAK,KAAK,CAAA,WAAA,CAAa,CAAA;AAC7E,IAAA;AAAA,EACF;AACA,EAAA,MAAM,SAAS,IAAA,CAAK,MAAA;AACpB,EAAA,GAAA,CAAI,CAAA,aAAA,EAAgB,MAAM,CAAA,CAAE,CAAA;AAC5B,EAAA,MAAM,MAAA,GAAS,MAAM,gBAAA,CAAiB,IAAA,CAAK,OAAA,EAAS;AAAA,IAClD,KAAK,IAAA,CAAK,GAAA;AAAA,IACV,WAAW,IAAA,CAAK;AAAA,GACjB,CAAA;AACD,EAAA,MAAM,OAAA,GAA6B;AAAA,IACjC,MAAA;AAAA,IACA,QAAQ,MAAA,CAAO,MAAA;AAAA,IACf,UAAU,MAAA,CAAO,QAAA;AAAA,IACjB,eAAe,MAAA,CAAO,aAAA;AAAA,IACtB,eAAe,MAAA,CAAO;AAAA,GACxB;AACA,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,CAAK,MAAA,EAAQ,CAAA,oBAAA,EAAuB,MAAM,IAAI,OAAO,CAAA;AAC3D,IAAA,GAAA,CAAI,CAAA,cAAA,EAAiB,MAAM,CAAA,EAAA,EAAK,MAAA,CAAO,MAAM,CAAA,CAAA,CAAG,CAAA;AAAA,EAClD,SAAS,GAAA,EAAc;AACrB,IAAA,QAAA,CAAS,CAAA,sBAAA,EAAyB,MAAM,CAAA,CAAA,EAAI,GAAG,CAAA;AAAA,EACjD;AACF;AAOO,SAAS,qBAAqB,IAAA,EAAsB;AACzD,EAAA,IAAI,CAAC,KAAK,SAAA,IAAa,CAAC,KAAK,UAAA,IAAc,CAAC,KAAK,SAAA,EAAW;AAC1D,IAAA,OAAA,CAAQ,CAAA,oEAAA,EAAuE,IAAA,CAAK,KAAK,CAAA,WAAA,CAAa,CAAA;AACtG,IAAA;AAAA,EACF;AACA,EAAA,MAAM,YAAY,IAAA,CAAK,SAAA;AAMvB,EAAA,IAAI,sBAAA,CAAuB,GAAA,CAAI,SAAS,CAAA,EAAG;AAEzC,IAAA;AAAA,EACF;AACA,EAAA,IAAI,sBAAA,CAAuB,QAAQ,wBAAA,EAA0B;AAC3D,IAAA,OAAA;AAAA,MACE,yDAAoD,wBAAwB,CAAA,iBAAA;AAAA,KAC9E;AACA,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,aAAa,IAAA,CAAK,UAAA;AACxB,EAAA,MAAM,YAAY,IAAA,CAAK,SAAA;AAIvB,EAAA,MAAM,QAAA,GAAW,CAAC,EAAA,KAAqB;AACrC,IAAA,sBAAA,CAAuB,OAAO,EAAE,CAAA;AAAA,EAClC,CAAA;AAKA,EAAA,IAAI,UAAA,GAA2C,IAAA;AAC/C,EAAA,sBAAA,CAAuB,IAAI,SAAA,EAAW;AAAA,IACpC,SAAA;AAAA,IACA,OAAO,MAAM;AACX,MAAA,IAAI,UAAA,aAAuB,KAAA,EAAM;AACjC,MAAA,sBAAA,CAAuB,OAAO,SAAS,CAAA;AAAA,IACzC;AAAA,GACD,CAAA;AAED,EAAA,GAAA,CAAI,CAAA,yBAAA,EAA4B,SAAS,CAAA,WAAA,CAAa,CAAA;AACtD,EAAA,KAAK,mBAAA,CAAoB;AAAA,IACvB,UAAA;AAAA,IACA,SAAA;AAAA,IACA,SAAA;AAAA,IACA,MAAM,IAAA,CAAK,IAAA;AAAA,IACX,MAAM,IAAA,CAAK,IAAA;AAAA,IACX,OAAO,IAAA,CAAK,KAAA;AAAA,IACZ,KAAK,IAAA,CAAK,GAAA;AAAA,IACV;AAAA,GACD,CAAA,CACE,IAAA,CAAK,CAAC,MAAA,KAAW;AAChB,IAAA,UAAA,GAAa,MAAA;AAGb,IAAA,IAAI,CAAC,sBAAA,CAAuB,GAAA,CAAI,SAAS,CAAA,EAAG;AAC1C,MAAA,MAAA,CAAO,KAAA,EAAM;AAAA,IACf;AAAA,EACF,CAAC,CAAA,CACA,KAAA,CAAM,CAAC,GAAA,KAAiB;AAGvB,IAAA,QAAA,CAAS,CAAA,gCAAA,EAAmC,SAAS,CAAA,CAAA,EAAI,GAAG,CAAA;AAC5D,IAAA,sBAAA,CAAuB,OAAO,SAAS,CAAA;AAAA,EACzC,CAAC,CAAA;AACL;AAGA,SAAS,wBAAA,GAAiC;AACxC,EAAA,IAAI,sBAAA,CAAuB,SAAS,CAAA,EAAG;AACvC,EAAA,GAAA,CAAI,CAAA,QAAA,EAAW,sBAAA,CAAuB,IAAI,CAAA,oBAAA,CAAsB,CAAA;AAChE,EAAA,KAAA,MAAW,MAAA,IAAU,sBAAA,CAAuB,MAAA,EAAO,EAAG;AACpD,IAAA,IAAI;AACF,MAAA,MAAA,CAAO,KAAA,EAAM;AAAA,IACf,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AACA,EAAA,sBAAA,CAAuB,KAAA,EAAM;AAC/B;AASO,SAAS,kBAAkB,IAAA,EAOjB;AACf,EAAA,MAAM,OAAA,GAAmC;AAAA,IACvC,eAAe,IAAA,CAAK,aAAA;AAAA,IACpB,GAAI,KAAK,MAAA,GAAS,EAAE,QAAQ,IAAA,CAAK,MAAA,KAAW,EAAC;AAAA,IAC7C,GAAI,IAAA,CAAK,KAAA,IAAS;AAAC,GACrB;AACA,EAAA,MAAM,OAAA,GAAwB;AAAA,IAC5B,MAAM,IAAA,CAAK,IAAA;AAAA,IACX,SAAS,IAAA,CAAK,OAAA;AAAA,IACd;AAAA,GACF;AACA,EAAA,IAAI,IAAA,CAAK,OAAA,KAAY,MAAA,EAAW,OAAA,CAAQ,UAAU,IAAA,CAAK,OAAA;AACvD,EAAA,OAAO,OAAA;AACT;AAWO,SAAS,sBAAsB,IAAA,EAWjB;AACnB,EAAA,MAAM,MAAA,GAAyB,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,CAAC,OAAA,KAAY;AAC5D,IAAA,IAAI,OAAA,KAAY,KAAK,aAAA,EAAe;AAClC,MAAA,MAAM,KAAA,GAAsB,EAAE,OAAA,EAAS,MAAA,EAAQ,SAAA,EAAU;AACzD,MAAA,IAAI,IAAA,CAAK,UAAA,EAAY,KAAA,CAAM,WAAA,GAAc,IAAA,CAAK,UAAA;AAC9C,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,OAAO,EAAE,OAAA,EAAS,MAAA,EAAQ,MAAA,EAAO;AAAA,EACnC,CAAC,CAAA;AAED,EAAA,MAAM,OAAA,GAA4B;AAAA,IAChC,eAAe,IAAA,CAAK,aAAA;AAAA,IACpB,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb;AAAA,GACF;AACA,EAAA,IAAI,IAAA,CAAK,KAAA,KAAU,MAAA,EAAW,OAAA,CAAQ,QAAQ,IAAA,CAAK,KAAA;AACnD,EAAA,IAAI,IAAA,CAAK,QAAA,KAAa,MAAA,EAAW,OAAA,CAAQ,eAAe,IAAA,CAAK,QAAA;AAC7D,EAAA,IAAI,IAAA,CAAK,gBAAgB,MAAA,IAAa,MAAA,CAAO,KAAK,IAAA,CAAK,WAAW,CAAA,CAAE,MAAA,GAAS,CAAA,EAAG;AAC9E,IAAA,OAAA,CAAQ,cAAc,IAAA,CAAK,WAAA;AAAA,EAC7B;AACA,EAAA,OAAO,OAAA;AACT;AAEA,IAAI,OAAA,GAAU,KAAA;AAKd,eAAsB,YAAY,MAAA,EAAqC;AACrE,EAAA,OAAA,GAAU,IAAA;AAGV,EAAA,MAAM,QAAA,GAAW,OAAO,MAAA,KAAmB;AACzC,IAAA,IAAI,CAAC,OAAA,EAAS;AACd,IAAA,OAAA,GAAU,KAAA;AACV,IAAA,GAAA,CAAI,CAAA,SAAA,EAAY,MAAM,CAAA,gCAAA,CAA6B,CAAA;AACnD,IAAA,qBAAA,EAAsB;AAEtB,IAAA,wBAAA,EAAyB;AACzB,IAAA,MAAM,cAAA;AAAA,MACJ,MAAA;AAAA,MACA,uBAAA;AAAA,MACA,iBAAA,CAAkB;AAAA,QAChB,IAAA,EAAM,iBAAA;AAAA,QACN,OAAA,EAAS,oBAAoB,MAAM,CAAA,CAAA,CAAA;AAAA,QACnC,aAAA,EAAe;AAAA,OAChB;AAAA,KACH;AACA,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB,CAAA;AAEA,EAAA,OAAA,CAAQ,GAAG,QAAA,EAAU,MAAM,KAAK,QAAA,CAAS,QAAQ,CAAC,CAAA;AAClD,EAAA,OAAA,CAAQ,GAAG,SAAA,EAAW,MAAM,KAAK,QAAA,CAAS,SAAS,CAAC,CAAA;AAGpD,EAAA,MAAM,cAAA;AAAA,IACJ,MAAA;AAAA,IACA,uBAAA;AAAA,IACA,iBAAA,CAAkB;AAAA,MAChB,IAAA,EAAM,gBAAA;AAAA,MACN,OAAA,EAAS,gBAAA;AAAA,MACT,aAAA,EAAe,OAAA;AAAA,MACf,QAAQ,EAAE,QAAA,EAAUA,UAAS,EAAG,OAAA,EAASC,SAAQ;AAAE,KACpD;AAAA,GACH;AAEA,EAAA,GAAA,CAAI,CAAA,iBAAA,EAAoB,OAAO,CAAA,SAAA,EAAY,MAAA,CAAO,QAAQ,CAAA,CAAA,CAAG,CAAA;AAG7D,EAAA,MAAM,cAAc,MAAM,CAAA;AAC1B,EAAA,sBAAA,CAAuB,MAAM,CAAA;AAG7B,EAAA,MAAM,gBAAgB,YAAY;AAChC,IAAA,MAAMC,gBAAe,eAAA,EAAgB;AACrC,IAAA,MAAM,WAAWA,aAAAA,CAAa,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,EAAE,CAAA;AAC7C,IAAA,MAAM,KAAA,GAAQ,MAAM,gBAAA,EAAiB;AAKrC,IAAA,IAAI,QAAA;AACJ,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,MAAM,cAAA,EAAe;AACjC,MAAA,MAAM,OAAA,GAAU,IAAI,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,OAAA,CAAQ,SAAS,CAAC,CAAA;AACtD,MAAA,QAAA,GAAW,OAAA,CAAQ,MAAA,GAAS,CAAA,GAAI,OAAA,GAAU,KAAA,CAAA;AAAA,IAC5C,CAAA,CAAA,MAAQ;AAAA,IAER;AAEA,IAAA,IAAI,WAAA;AACJ,IAAA,IAAI;AACF,MAAA,WAAA,GAAc,MAAM,kBAAA,EAAmB;AAAA,IACzC,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA,MAAM,UAAU,qBAAA,CAAsB;AAAA,MACpC,aAAA,EAAe,OAAA;AAAA,MACf,QAAQ,EAAE,QAAA,EAAUF,UAAS,EAAG,OAAA,EAASC,SAAQ,EAAE;AAAA,MACnD,QAAA;AAAA,MACA,aAAA,EAAe,gBAAA;AAAA,MACf,UAAA,EAAY,aAAA;AAAA,MACZ,OAAO,KAAA,IAAS,MAAA;AAAA,MAChB,QAAA;AAAA,MACA;AAAA,KACD,CAAA;AACD,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,MAAA,EAAQ,0BAAA,EAA4B,OAAO,CAAA;AAAA,IACxD,SAAS,GAAA,EAAc;AACrB,MAAA,OAAA,CAAQ,CAAA,kBAAA,EAAqB,eAAe,KAAA,GAAQ,GAAA,CAAI,UAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAE,CAAA;AAAA,IACjF;AAAA,EACF,CAAA;AAGA,EAAA,KAAK,aAAA,EAAc;AACnB,EAAA,MAAM,iBAAiB,WAAA,CAAY,MAAM,KAAK,aAAA,IAAiB,qBAAqB,CAAA;AAEpF,EAAA,IAAI,cAAA,CAAe,KAAA,EAAO,cAAA,CAAe,KAAA,EAAM;AAG/C,EAAA,IAAI,YAAA,GAAe,CAAA;AAEnB,EAAA,OAAO,OAAA,EAAS;AAEd,IAAA,IAAI;AACF,MAAA,MAAM,oBAAoB,MAAM,CAAA;AAAA,IAClC,CAAA,CAAA,MAAQ;AAAA,IAER;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,OAAO,MAAM,IAAA,CAAmB,MAAA,EAAQ,qBAAA,EAAuB,EAAE,CAAA;AACvE,MAAA,YAAA,GAAe,CAAA;AAEf,MAAA,IAAI,KAAK,IAAA,EAAM;AACb,QAAA,MAAM,OAAO,IAAA,CAAK,IAAA;AAClB,QAAA,MAAM,IAAA,GAAO,iBAAiB,IAAI,CAAA;AAClC,QAAA,GAAA,CAAI,CAAA,wBAAA,EAA2B,IAAA,CAAK,KAAK,CAAA,OAAA,EAAU,IAAI,CAAA,CAAA,CAAG,CAAA;AAI1D,QAAA,IAAI,SAAS,eAAA,EAAiB;AAG5B,UAAA,oBAAA,CAAqB,IAAI,CAAA;AAEzB,UAAA;AAAA,QACF;AAEA,QAAA,IAAI,SAAS,MAAA,EAAQ;AAEnB,UAAA,IAAI;AACF,YAAA,MAAM,cAAA,CAAe,QAAQ,IAAI,CAAA;AAAA,UACnC,SAAS,GAAA,EAAc;AACrB,YAAA,QAAA,CAAS,CAAA,0CAAA,EAA6C,IAAA,CAAK,KAAK,CAAA,CAAA,EAAI,GAAG,CAAA;AAAA,UACzE;AACA,UAAA;AAAA,QACF;AAIA,QAAA,gBAAA,GAAmB,IAAA,CAAK,OAAO,EAAA,IAAM,IAAA;AACrC,QAAA,aAAA,GAAgB,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,GAAG,CAAA;AAExC,QAAA,IAAI;AACF,UAAA,MAAM,WAAA,CAAY,QAAQ,IAAI,CAAA;AAAA,QAChC,SAAS,GAAA,EAAc;AACrB,UAAA,QAAA,CAAS,CAAA,uCAAA,EAA0C,IAAA,CAAK,KAAK,CAAA,CAAA,EAAI,GAAG,CAAA;AAAA,QACtE,CAAA,SAAE;AACA,UAAA,gBAAA,GAAmB,IAAA;AACnB,UAAA,aAAA,GAAgB,KAAA,CAAA;AAAA,QAClB;AAEA,QAAA;AAAA,MACF;AAAA,IACF,SAAS,GAAA,EAAc;AACrB,MAAA,MAAM,KAAA,GAAQ,iBAAiB,IAAA,CAAK,GAAA,CAAI,cAAc,gBAAA,CAAiB,MAAA,GAAS,CAAC,CAAC,CAAA;AAClF,MAAA,QAAA;AAAA,QACE,uBAAuB,KAAK,CAAA,GAAA,CAAA;AAAA,QAC5B;AAAA,OACF;AACA,MAAA,YAAA,GAAe,KAAK,GAAA,CAAI,YAAA,GAAe,CAAA,EAAG,gBAAA,CAAiB,SAAS,CAAC,CAAA;AACrE,MAAA,MAAME,OAAM,KAAK,CAAA;AACjB,MAAA;AAAA,IACF;AAEA,IAAA,MAAMA,OAAM,gBAAgB,CAAA;AAAA,EAC9B;AAEA,EAAA,aAAA,CAAc,cAAc,CAAA;AAC9B;AAEA,SAASA,OAAM,EAAA,EAA2B;AACxC,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,EAAE,CAAC,CAAA;AACzD;AC7dA,IAAM,eAAA,GAAkB,0BAAA;AAExB,IAAM,OAAA,GAAU,IAAI,OAAA,EAAQ;AAE5B,OAAA,CACG,KAAK,eAAe,CAAA,CACpB,YAAY,gEAA2D,CAAA,CACvE,QAAQ,OAAO,CAAA;AAMlB,OAAA,CACG,OAAA,CAAQ,uBAAuB,CAAA,CAC/B,WAAA,CAAY,gEAAgE,CAAA,CAC5E,MAAA;AAAA,EACC,iBAAA;AAAA,EACA,wBAAA;AAAA,EACA;AACF,CAAA,CACC,MAAA,CAAO,OAAO,WAAA,EAAqB,IAAA,KAA6B;AAC/D,EAAA,MAAM,OAAA,CAAQ,WAAA,EAAa,IAAA,CAAK,MAAM,CAAA;AACxC,CAAC,CAAA;AAMH,OAAA,CACG,QAAQ,OAAO,CAAA,CACf,YAAY,qDAAqD,CAAA,CACjE,OAAO,YAAY;AAClB,EAAA,MAAM,SAAS,aAAA,EAAc;AAC7B,EAAA,GAAA,CAAI,gCAAgC,MAAA,CAAO,UAAU,CAAA,GAAA,EAAM,MAAA,CAAO,QAAQ,CAAA,CAAA,CAAG,CAAA;AAC7E,EAAA,MAAM,YAAY,MAAM,CAAA;AAC1B,CAAC,CAAA;AAMH,OAAA,CACG,QAAQ,QAAQ,CAAA,CAChB,YAAY,qDAAqD,CAAA,CACjE,OAAO,YAAY;AAClB,EAAA,MAAM,SAAS,UAAA,EAAW;AAE1B,EAAA,OAAA,CAAQ,IAAI,8BAA8B,CAAA;AAC1C,EAAA,OAAA,CAAQ,GAAA,EAAI;AAEZ,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAA,CAAQ,IAAI,+BAA+B,CAAA;AAC3C,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,gBAAA,EAAmB,WAAW,CAAA,CAAE,CAAA;AAC5C,IAAA,OAAA,CAAQ,GAAA,EAAI;AACZ,IAAA,OAAA,CAAQ,IAAI,4DAA4D,CAAA;AACxE,IAAA;AAAA,EACF;AAEA,EAAA,OAAA,CAAQ,IAAI,CAAA,yBAAA,CAA2B,CAAA;AACvC,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,gBAAA,EAAmB,MAAA,CAAO,UAAU,CAAA,CAAE,CAAA;AAClD,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,gBAAA,EAAmB,MAAA,CAAO,QAAQ,CAAA,CAAE,CAAA;AAChD,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,gBAAA,EAAmB,MAAA,CAAO,KAAK,CAAA,CAAE,CAAA;AAC7C,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,gBAAA,EAAmB,MAAA,CAAO,UAAU,CAAA,CAAE,CAAA;AAClD,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,gBAAA,EAAmB,MAAA,CAAO,QAAQ,CAAA,CAAE,CAAA;AAChD,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,gBAAA,EAAmB,WAAW,CAAA,CAAE,CAAA;AAC5C,EAAA,OAAA,CAAQ,GAAA,EAAI;AAGZ,EAAA,OAAA,CAAQ,MAAA,CAAO,MAAM,8BAA8B,CAAA;AACnD,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,CAAK,QAAQ,0BAAA,EAA4B;AAAA,MAC7C,aAAA,EAAe,OAAA;AAAA,MACf,QAAQ,EAAC;AAAA,MACT,QAAQ;AAAC,KACV,CAAA;AACD,IAAA,OAAA,CAAQ,IAAI,WAAW,CAAA;AAAA,EACzB,SAAS,GAAA,EAAc;AACrB,IAAA,OAAA,CAAQ,GAAA;AAAA,MACN,gBAAgB,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAA;AAAA,KAClE;AAAA,EACF;AACA,EAAA,OAAA,CAAQ,GAAA,EAAI;AACd,CAAC,CAAA;AAMH,OAAA,CACG,OAAA,CAAQ,oBAAoB,CAAA,CAC5B,WAAA,CAAY,2EAA2E,CAAA,CACvF,MAAA,CAAO,OAAO,MAAA,KAAmB;AAChC,EAAA,MAAM,EAAE,gBAAA,EAAkB,eAAA,EAAiB,iBAAgB,GAAI,MAAM,OAAO,yBAAgB,CAAA;AAC5F,EAAA,IAAI,MAAA,KAAW,WAAW,gBAAA,EAAiB;AAAA,OAAA,IAClC,MAAA,KAAW,UAAU,eAAA,EAAgB;AAAA,OAAA,IACrC,MAAA,KAAW,UAAU,eAAA,EAAgB;AAAA,OACzC;AACH,IAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,gBAAA,EAAmB,MAAM,CAAA,uCAAA,CAAoC,CAAA;AAC3E,IAAA,OAAA,CAAQ,QAAA,GAAW,CAAA;AAAA,EACrB;AACF,CAAC,CAAA;AAMH,OAAA,CACG,QAAQ,QAAQ,CAAA,CAChB,YAAY,uDAAuD,CAAA,CACnE,OAAO,YAAY;AAClB,EAAA,OAAA,CAAQ,IAAI,8BAA8B,CAAA;AAC1C,EAAA,OAAA,CAAQ,GAAA,EAAI;AAEZ,EAAA,IAAI,OAAA,GAAU,IAAA;AAGd,EAAA,MAAM,WAAA,GAAc,QAAQ,QAAA,CAAS,IAAA;AACrC,EAAA,MAAM,CAAC,KAAK,CAAA,GAAI,WAAA,CAAY,MAAM,GAAG,CAAA,CAAE,IAAI,MAAM,CAAA;AACjD,EAAA,MAAM,SAAS,KAAA,IAAS,EAAA;AACxB,EAAA,UAAA;AAAA,IACE,eAAA;AAAA,IACA,MAAA;AAAA,IACA,UAAU,WAAW,CAAA,CAAA;AAAA,IACrB,UAAU,WAAW,CAAA,8BAAA;AAAA,GACvB;AACA,EAAA,IAAI,CAAC,QAAQ,OAAA,GAAU,KAAA;AAGvB,EAAA,IAAI,aAAA,GAAgB,EAAA;AACpB,EAAA,IAAI,YAAA,GAAe,KAAA;AACnB,EAAA,IAAI;AACF,IAAA,aAAA,GAAgB,SAAS,kBAAA,EAAoB;AAAA,MAC3C,QAAA,EAAU,OAAA;AAAA,MACV,OAAA,EAAS,GAAA;AAAA,MACT,KAAA,EAAO,CAAC,QAAA,EAAU,MAAA,EAAQ,QAAQ;AAAA,KACnC,EAAE,IAAA,EAAK;AACR,IAAA,YAAA,GAAe,IAAA;AAAA,EACjB,CAAA,CAAA,MAAQ;AACN,IAAA,YAAA,GAAe,KAAA;AAAA,EACjB;AACA,EAAA,UAAA;AAAA,IACE,oBAAA;AAAA,IACA,YAAA;AAAA,IACA,aAAA,IAAiB,OAAA;AAAA,IACjB;AAAA,GACF;AACA,EAAA,IAAI,CAAC,cAAc,OAAA,GAAU,KAAA;AAG7B,EAAA,IAAI,YAAA,GAAe,KAAA;AACnB,EAAA,IAAI,cAAA,GAAiB,EAAA;AACrB,EAAA,IAAI,YAAA,EAAc;AAEhB,IAAA,MAAM,aAAA,GAAgB;AAAA,MACpBf,IAAAA,CAAKQ,OAAAA,EAAQ,EAAG,SAAA,EAAW,eAAe,CAAA;AAAA,MAC1CR,IAAAA,CAAKQ,OAAAA,EAAQ,EAAG,SAAA,EAAW,UAAU,eAAe,CAAA;AAAA,MACpDR,IAAAA;AAAA,QACE,OAAA,CAAQ,IAAI,SAAS,CAAA,IAAKA,KAAKQ,OAAAA,EAAQ,EAAG,WAAW,SAAS,CAAA;AAAA,QAC9D,QAAA;AAAA,QACA;AAAA;AACF,KACF;AACA,IAAA,YAAA,GAAe,aAAA,CAAc,KAAKN,UAAU,CAAA;AAC5C,IAAA,cAAA,GAAiB,eACb,cAAA,GACA,qDAAA;AAAA,EACN,CAAA,MAAO;AACL,IAAA,cAAA,GAAiB,8BAAA;AAAA,EACnB;AACA,EAAA,UAAA;AAAA,IACE,sBAAA;AAAA,IACA,YAAA;AAAA,IACA,cAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,IAAI,CAAC,YAAA,IAAgB,YAAA,EAAc,OAAA,GAAU,KAAA;AAG7C,EAAA,MAAM,aAAa,YAAA,EAAa;AAChC,EAAA,MAAM,aAAa,UAAA,EAAW;AAC9B,EAAA,MAAM,WAAA,GAAc,cAAc,UAAA,KAAe,IAAA;AACjD,EAAA,UAAA;AAAA,IACE,eAAA;AAAA,IACA,WAAA;AAAA,IACA,WAAA,GACI,CAAA,EAAG,WAAW,CAAA,UAAA,EAAa,UAAA,EAAY,UAAU,CAAA,CAAA,CAAA,GACjD,UAAA,GACE,CAAA,EAAG,WAAW,CAAA,+BAAA,CAAA,GACd,qDAAA;AAAA,IACN,UAAA,GACI,CAAA,EAAG,WAAW,CAAA,0CAAA,CAAA,GACd;AAAA,GACN;AACA,EAAA,IAAI,CAAC,aAAa,OAAA,GAAU,KAAA;AAG5B,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,OAAA,CAAQ,MAAA,CAAO,MAAM,qCAAqC,CAAA;AAC1D,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,YAAY,0BAAA,EAA4B;AAAA,QACjD,aAAA,EAAe,OAAA;AAAA,QACf,QAAQ,EAAC;AAAA,QACT,QAAQ;AAAC,OACV,CAAA;AACD,MAAA,SAAA,EAAU;AACV,MAAA,UAAA,CAAW,4BAAA,EAA8B,IAAA,EAAM,UAAA,CAAW,UAAA,EAAY,EAAE,CAAA;AAAA,IAC1E,SAAS,GAAA,EAAc;AACrB,MAAA,SAAA,EAAU;AACV,MAAA,UAAA;AAAA,QACE,4BAAA;AAAA,QACA,KAAA;AAAA,QACA,EAAA;AAAA,QACA,CAAA,EAAG,UAAA,CAAW,UAAU,CAAA,QAAA,EAAM,GAAA,YAAe,QAAQ,GAAA,CAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,OAChF;AACA,MAAA,OAAA,GAAU,KAAA;AAAA,IACZ;AAAA,EACF,CAAA,MAAO;AACL,IAAA,UAAA;AAAA,MACE,4BAAA;AAAA,MACA,KAAA;AAAA,MACA,EAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF;AAGA,EAAA,MAAM,SAAA,GAAYF,IAAAA,CAAKQ,OAAAA,EAAQ,EAAG,gBAAgB,CAAA;AAClD,EAAA,IAAI;AACF,IAAAT,SAAAA,CAAU,SAAA,EAAW,EAAE,SAAA,EAAW,MAAM,CAAA;AACxC,IAAA,UAAA,CAAW,SAAA,EAAW,UAAU,IAAI,CAAA;AACpC,IAAA,UAAA,CAAW,2BAAA,EAA6B,IAAA,EAAM,SAAA,EAAW,EAAE,CAAA;AAAA,EAC7D,CAAA,CAAA,MAAQ;AACN,IAAA,UAAA;AAAA,MACE,2BAAA;AAAA,MACA,KAAA;AAAA,MACA,EAAA;AAAA,MACA,GAAG,SAAS,CAAA,gBAAA;AAAA,KACd;AACA,IAAA,OAAA,GAAU,KAAA;AAAA,EACZ;AAEA,EAAA,OAAA,CAAQ,GAAA,EAAI;AACZ,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,OAAA,CAAQ,IAAI,oEAAoE,CAAA;AAAA,EAClF,CAAA,MAAO;AACL,IAAA,OAAA,CAAQ,GAAA;AAAA,MACN;AAAA,KACF;AACA,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AACF,CAAC,CAAA;AAMH,SAAS,UAAA,CACP,KAAA,EACA,EAAA,EACA,WAAA,EACA,WAAA,EACM;AACN,EAAA,MAAM,IAAA,GAAO,KAAK,MAAA,GAAS,MAAA;AAC3B,EAAA,MAAM,IAAA,GAAO,KAAK,WAAA,GAAc,WAAA;AAChC,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,KAAK,GAAG,IAAA,GAAO,UAAA,GAAQ,IAAA,GAAO,EAAE,CAAA,CAAE,CAAA;AAC3D;AAEA,SAAS,SAAA,GAAkB;AAEzB,EAAA,OAAA,CAAQ,MAAA,CAAO,MAAM,UAAU,CAAA;AACjC;AAMA,OAAA,CAAQ,WAAW,OAAA,CAAQ,IAAI,CAAA,CAAE,KAAA,CAAM,CAAC,GAAA,KAAiB;AACvD,EAAA,OAAA,CAAQ,KAAA;AAAA,IACN,0BAA0B,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,GAC5E;AACA,EAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAChB,CAAC,CAAA","file":"cli.js","sourcesContent":["/**\n * Daemon version — keep in sync with package.json.\n * Single source of truth used in heartbeats, pair requests, and CLI output.\n */\nexport const VERSION = \"0.1.5\"\n","/**\n * pair.ts — Pair this machine with a StrideOps workspace via a pairing code.\n *\n * Sends machine info to /api/bridge/v1/pair and saves the returned\n * credentials to ~/.stride-bridge/config.json.\n */\n\nimport { hostname, platform, arch, cpus, totalmem, release } from \"node:os\"\nimport { VERSION } from \"./version.js\"\nimport { writeConfig } from \"./config.js\"\nimport { log } from \"./log.js\"\n\ninterface PairRequest {\n pairingCode: string\n daemonVersion: string\n machineInfo: {\n hostname: string\n platform: string\n arch: string\n cpus: number\n totalMemMb: number\n }\n osInfo: {\n platform: string\n release: string\n }\n}\n\ninterface PairResponseData {\n bridgeId: string\n orgId: string\n name: string\n authMode: \"claude_login\" | \"org_api_key\"\n bridgeToken: string\n}\n\ninterface RawPairResponse {\n success: boolean\n data?: PairResponseData\n error?: string\n}\n\n/**\n * Pair with the StrideOps server using a one-time pairing code.\n * On success, saves config and prints a confirmation.\n */\nexport async function runPair(\n pairingCode: string,\n apiBaseUrl: string,\n): Promise<void> {\n const url = `${apiBaseUrl.replace(/\\/$/, \"\")}/api/bridge/v1/pair`\n\n log(`Pairing with ${apiBaseUrl} ...`)\n\n const cpuCount = cpus().length\n const totalMemMb = Math.round(totalmem() / 1024 / 1024)\n\n const payload: PairRequest = {\n pairingCode,\n daemonVersion: VERSION,\n machineInfo: {\n hostname: hostname(),\n platform: platform(),\n arch: arch(),\n cpus: cpuCount,\n totalMemMb,\n },\n osInfo: {\n platform: platform(),\n release: release(),\n },\n }\n\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), 15_000)\n\n let res: Response\n try {\n res = await fetch(url, {\n method: \"POST\",\n signal: controller.signal,\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n })\n } catch (err: unknown) {\n clearTimeout(timer)\n if (err instanceof Error && err.name === \"AbortError\") {\n console.error(\"[stride-bridge] Pairing request timed out. Check your connection.\")\n process.exit(1)\n }\n console.error(\n `[stride-bridge] Network error during pairing: ${err instanceof Error ? err.message : String(err)}`,\n )\n process.exit(1)\n } finally {\n clearTimeout(timer)\n }\n\n let body: RawPairResponse\n try {\n body = (await res.json()) as RawPairResponse\n } catch {\n console.error(\n `[stride-bridge] Failed to parse pairing response (HTTP ${res.status}).`,\n )\n process.exit(1)\n }\n\n if (!res.ok || !body.success || !body.data) {\n console.error(\n `[stride-bridge] Pairing failed: ${body.error ?? `HTTP ${res.status}`}`,\n )\n process.exit(1)\n }\n\n const { bridgeId, orgId, name, authMode, bridgeToken } = body.data\n\n writeConfig({\n apiBaseUrl,\n bridgeToken,\n bridgeId,\n orgId,\n bridgeName: name,\n authMode,\n })\n\n console.log(`[stride-bridge] Connected successfully!`)\n console.log(` Bridge name : ${name}`)\n console.log(` Bridge ID : ${bridgeId}`)\n console.log(` Org ID : ${orgId}`)\n console.log(` Auth mode : ${authMode}`)\n console.log(` Config : ~/.stride-bridge/config.json`)\n console.log()\n\n // A daemon that dies on reboot silently strands every assigned agent —\n // offer always-on right here so nobody has to discover `autostart` later.\n await offerAutostart()\n\n console.log(`Run \\`stride-bridge start\\` to begin accepting work.`)\n}\n\n/** Interactive Y/n autostart offer (Windows only; skipped when not a TTY). */\nasync function offerAutostart(): Promise<void> {\n if (process.platform !== \"win32\" || !process.stdin.isTTY) {\n if (process.platform === \"win32\") {\n console.log(\n `Tip: run \\`stride-bridge autostart install\\` so the daemon starts at login.`,\n )\n console.log()\n }\n return\n }\n\n const { createInterface } = await import(\"node:readline/promises\")\n const rl = createInterface({ input: process.stdin, output: process.stdout })\n try {\n const answer = (\n await rl.question(\n \"Start the daemon automatically at Windows login? [Y/n] \",\n )\n )\n .trim()\n .toLowerCase()\n if (answer === \"\" || answer === \"y\" || answer === \"yes\") {\n const { autostartInstall } = await import(\"./autostart.js\")\n autostartInstall()\n } else {\n console.log(\n `Skipped. You can enable it later with \\`stride-bridge autostart install\\`.`,\n )\n }\n } finally {\n rl.close()\n console.log()\n }\n}\n","/**\n * api.ts — Minimal authenticated HTTP client for the Bridge API.\n *\n * Uses the global fetch (Node >= 18) + AbortController for timeouts.\n * All responses are expected to be { success: boolean, data?: T, error?: string }.\n * Throws on network errors or when success === false.\n */\n\nimport type { BridgeConfig } from \"./config.js\"\n\nconst REQUEST_TIMEOUT_MS = 10_000\n\nexport class ApiError extends Error {\n constructor(\n public readonly status: number | null,\n message: string,\n ) {\n super(message)\n this.name = \"ApiError\"\n }\n}\n\nexport interface ApiResponse<T> {\n success: boolean\n data?: T\n error?: string\n}\n\n/**\n * Make an authenticated fetch to the Bridge API.\n * Adds Authorization: Bearer header from config.\n * Throws ApiError on non-2xx HTTP status or success:false response.\n */\nexport async function authedFetch<T>(\n config: BridgeConfig,\n path: string,\n init: RequestInit = {},\n): Promise<T> {\n const url = `${config.apiBaseUrl.replace(/\\/$/, \"\")}${path}`\n\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS)\n\n let res: Response\n try {\n res = await fetch(url, {\n ...init,\n signal: controller.signal,\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${config.bridgeToken}`,\n ...(init.headers as Record<string, string> | undefined),\n },\n })\n } catch (err: unknown) {\n clearTimeout(timer)\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new ApiError(null, `Request timed out after ${REQUEST_TIMEOUT_MS}ms: ${path}`)\n }\n throw new ApiError(null, `Network error: ${err instanceof Error ? err.message : String(err)}`)\n } finally {\n clearTimeout(timer)\n }\n\n let body: ApiResponse<T>\n try {\n body = (await res.json()) as ApiResponse<T>\n } catch {\n throw new ApiError(res.status, `Failed to parse JSON response from ${path} (HTTP ${res.status})`)\n }\n\n if (!res.ok || !body.success) {\n throw new ApiError(\n res.status,\n body.error ?? `API error from ${path} (HTTP ${res.status})`,\n )\n }\n\n return body.data as T\n}\n\n/**\n * POST JSON to a path. Convenience wrapper over authedFetch.\n */\nexport async function post<T>(\n config: BridgeConfig,\n path: string,\n body: unknown,\n): Promise<T> {\n return authedFetch<T>(config, path, {\n method: \"POST\",\n body: JSON.stringify(body),\n })\n}\n\n/**\n * GET a path. Convenience wrapper over authedFetch.\n */\nexport async function get<T>(config: BridgeConfig, path: string): Promise<T> {\n return authedFetch<T>(config, path, { method: \"GET\" })\n}\n\n/**\n * Like post() but swallows all errors (for best-effort fire-and-forget calls\n * such as daemon_stopping events).\n */\nexport async function postBestEffort(\n config: BridgeConfig,\n path: string,\n body: unknown,\n): Promise<void> {\n try {\n await post(config, path, body)\n } catch {\n // Intentionally swallowed — best-effort only.\n }\n}\n","/**\r\n * hooks-writer.ts — Generate .claude/settings.json with a signed PreToolUse hook.\r\n *\r\n * The signing scheme mirrors hook-signature.ts on the server:\r\n * HMAC-SHA256(`${unixSeconds}\\n${rawBody}`) → hex\r\n * with headers x-stride-hook-sig and x-stride-hook-ts.\r\n *\r\n * For local agents we generate a small Node.js script (hook-runner.mjs) that\r\n * Claude Code invokes as the hook command. This avoids bash dependency on\r\n * Windows and is consistent across platforms.\r\n *\r\n * The runner transforms Claude Code's hook input ({tool_name, tool_input,\r\n * session_id}) into the server's PreToolUse schema ({tool, args, sessionId})\r\n * and FORWARDS the server's decision — a budget/loop denial from Stride must\r\n * actually block the tool call. Fail-open on any error: if Stride is\r\n * unreachable the hook allows, so the agent is never blocked by an outage.\r\n *\r\n * Phase 1 wires PreToolUse only. Claude Code's Stop hook input carries no\r\n * usage/cost data, so per-turn usage reporting is deferred to Phase 2\r\n * (persistent sessions); run-level cost is reported by runner.ts via\r\n * POST /api/bridge/v1/runs/{runId} instead.\r\n */\r\n\r\nimport { join } from \"node:path\"\r\nimport { mkdirSync, writeFileSync, chmodSync } from \"node:fs\"\r\nimport { writeJsonAtomic } from \"./state.js\"\r\n\r\nexport interface HookWriterOptions {\r\n agentId: string\r\n hookSecret: string\r\n apiBaseUrl: string\r\n workspaceDir: string\r\n}\r\n\r\n/**\r\n * Generate the Node.js hook runner script content.\r\n * This script is written once per agent to their .claude/ directory.\r\n * It reads CLAUDE_HOOK_INPUT from stdin (Claude Code provides it),\r\n * computes the HMAC signature, and POSTs to the given URL.\r\n *\r\n * The script exits 0 (allow) regardless of Stride's response,\r\n * so the agent is never blocked by an unreachable server.\r\n */\r\nfunction buildHookRunnerScript(\r\n preToolUseUrl: string,\r\n hookSecret: string,\r\n): string {\r\n // We embed the secret directly into the per-agent script.\r\n // The script lives in the agent's workspace dir (~/.stride-bridge/agents/<id>/)\r\n // which is chmod 700 (POSIX) — not in the project directory Claude edits.\r\n // The secret is never printed to stdout/stderr.\r\n return `#!/usr/bin/env node\r\n// Auto-generated by stride-bridge. Do not edit.\r\n// Signed PreToolUse hook runner for Stride Build agents.\r\n// HMAC scheme: HMAC-SHA256(timestamp+\"\\\\n\"+body) -> hex\r\n// Headers: x-stride-hook-ts, x-stride-hook-sig\r\n\r\nimport { createHmac } from \"node:crypto\";\r\nimport { readFileSync } from \"node:fs\";\r\n\r\nconst HOOK_SECRET = ${JSON.stringify(hookSecret)};\r\nconst PRE_TOOL_USE_URL = ${JSON.stringify(preToolUseUrl)};\r\nconst TIMEOUT_MS = 8_000;\r\n\r\nfunction allow() {\r\n // No output + exit 0 = allow in Claude Code's hook protocol.\r\n process.exit(0);\r\n}\r\n\r\nasync function main() {\r\n // Claude Code writes the hook input to stdin as JSON. fd 0 works on\r\n // Windows too (\"/dev/stdin\" does not).\r\n let input = {};\r\n try {\r\n input = JSON.parse(readFileSync(0, \"utf-8\"));\r\n } catch {\r\n allow(); // unreadable input — fail-open\r\n }\r\n\r\n // Transform Claude Code's hook input into the server's PreToolUse schema.\r\n const body = JSON.stringify({\r\n tool: typeof input.tool_name === \"string\" && input.tool_name ? input.tool_name : \"unknown\",\r\n args: typeof input.tool_input === \"object\" && input.tool_input !== null ? input.tool_input : undefined,\r\n sessionId: typeof input.session_id === \"string\" ? input.session_id : undefined,\r\n });\r\n\r\n const ts = Math.floor(Date.now() / 1000).toString();\r\n const sig = createHmac(\"sha256\", HOOK_SECRET)\r\n .update(ts + \"\\\\n\" + body)\r\n .digest(\"hex\");\r\n\r\n const controller = new AbortController();\r\n const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);\r\n const res = await fetch(PRE_TOOL_USE_URL, {\r\n method: \"POST\",\r\n signal: controller.signal,\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n \"x-stride-hook-ts\": ts,\r\n \"x-stride-hook-sig\": sig,\r\n },\r\n body,\r\n });\r\n clearTimeout(timer);\r\n\r\n const decision = await res.json();\r\n if (decision && (decision.permissionDecision === \"deny\" || decision.permissionDecision === \"ask\")) {\r\n // Forward Stride's decision so Claude Code actually blocks the call.\r\n process.stdout.write(JSON.stringify({\r\n hookSpecificOutput: {\r\n hookEventName: \"PreToolUse\",\r\n permissionDecision: decision.permissionDecision,\r\n permissionDecisionReason: decision.permissionDecisionReason || \"Blocked by Stride policy\",\r\n },\r\n }) + \"\\\\n\");\r\n }\r\n process.exit(0);\r\n}\r\n\r\n// Fail-open: an unreachable server or unexpected error must never block the agent.\r\nmain().catch(() => allow());\r\n`\r\n}\r\n\r\n/**\r\n * Write .claude/settings.json and the hook-runner.mjs script to the agent's\r\n * workspace directory.\r\n *\r\n * settings.json wires PreToolUse (all tools, matcher \".*\") to the\r\n * hook-runner.mjs script via `node <path>`.\r\n */\r\nexport function writeAgentHooks(opts: HookWriterOptions): void {\r\n const { agentId, hookSecret, apiBaseUrl, workspaceDir } = opts\r\n\r\n const base = apiBaseUrl.replace(/\\/$/, \"\")\r\n const preToolUseUrl = `${base}/api/internal/build/agents/${agentId}/hook/pre-tool-use`\r\n\r\n const claudeDir = join(workspaceDir, \".claude\")\r\n mkdirSync(claudeDir, { recursive: true })\r\n\r\n // Write the hook runner script\r\n const runnerPath = join(claudeDir, \"hook-runner.mjs\")\r\n const runnerContent = buildHookRunnerScript(preToolUseUrl, hookSecret)\r\n writeFileSync(runnerPath, runnerContent, { encoding: \"utf-8\", mode: 0o700 })\r\n\r\n // Make executable on POSIX\r\n if (process.platform !== \"win32\") {\r\n try {\r\n chmodSync(runnerPath, 0o700)\r\n } catch {\r\n // Best effort.\r\n }\r\n }\r\n\r\n // Build the command that Claude Code will invoke.\r\n // Use `node <absolute-path>` so it works regardless of PATH. Quote both\r\n // paths — they regularly contain spaces on Windows (C:\\Users\\First Last\\...).\r\n const preToolUseCmd = `\"${process.execPath}\" \"${runnerPath}\"`\r\n\r\n const settingsJson = {\r\n hooks: {\r\n PreToolUse: [\r\n {\r\n matcher: \".*\",\r\n hooks: [\r\n {\r\n type: \"command\",\r\n command: preToolUseCmd,\r\n timeout: 10,\r\n },\r\n ],\r\n },\r\n ],\r\n },\r\n }\r\n\r\n writeJsonAtomic(join(claudeDir, \"settings.json\"), settingsJson)\r\n}\r\n\r\n/**\r\n * Write .claude/memory-sync.mjs — a Node script the agent runs (per its\r\n * CLAUDE.md memory protocol) to upload MEMORY.md and today's daily journal\r\n * to Stride's HMAC-authenticated memory-sync endpoint. Node instead of the\r\n * server's bash snippet because local agents run on Windows too.\r\n */\r\nexport function writeMemorySyncScript(opts: HookWriterOptions): void {\r\n const { agentId, hookSecret, apiBaseUrl, workspaceDir } = opts\r\n const base = apiBaseUrl.replace(/\\/$/, \"\")\r\n const syncUrl = `${base}/api/internal/build/agents/${agentId}/memory/sync`\r\n\r\n const script = `#!/usr/bin/env node\r\n// Auto-generated by stride-bridge. Do not edit.\r\n// Uploads MEMORY.md + today's daily journal to Stride (HMAC-signed).\r\n\r\nimport { createHmac } from \"node:crypto\";\r\nimport { readFileSync, existsSync } from \"node:fs\";\r\nimport { join, dirname } from \"node:path\";\r\nimport { fileURLToPath } from \"node:url\";\r\n\r\nconst HOOK_SECRET = ${JSON.stringify(hookSecret)};\r\nconst SYNC_URL = ${JSON.stringify(syncUrl)};\r\nconst workspace = dirname(dirname(fileURLToPath(import.meta.url)));\r\n\r\nconst files = [];\r\nconst memoryMd = join(workspace, \"MEMORY.md\");\r\nif (existsSync(memoryMd)) {\r\n files.push({ type: \"learnings\", content: readFileSync(memoryMd, \"utf-8\").slice(0, 50000) });\r\n}\r\nconst today = new Date().toISOString().slice(0, 10);\r\nconst daily = join(workspace, \"memory\", today + \".md\");\r\nif (existsSync(daily)) {\r\n files.push({ type: \"daily\", date: today, content: readFileSync(daily, \"utf-8\").slice(0, 50000) });\r\n}\r\n\r\nif (files.length === 0) {\r\n console.log(\"memory-sync: nothing to sync\");\r\n process.exit(0);\r\n}\r\n\r\nconst body = JSON.stringify({ files });\r\nconst ts = Math.floor(Date.now() / 1000).toString();\r\nconst sig = createHmac(\"sha256\", HOOK_SECRET).update(ts + \"\\\\n\" + body).digest(\"hex\");\r\n\r\nconst res = await fetch(SYNC_URL, {\r\n method: \"POST\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n \"x-stride-hook-ts\": ts,\r\n \"x-stride-hook-sig\": sig,\r\n },\r\n body,\r\n}).catch((err) => ({ ok: false, statusText: String(err) }));\r\n\r\nconsole.log(res.ok ? \\`memory-sync: synced \\${files.length} file(s)\\` : \\`memory-sync: failed (\\${res.statusText ?? res.status})\\`);\r\n`\r\n\r\n const claudeDir = join(workspaceDir, \".claude\")\r\n mkdirSync(claudeDir, { recursive: true })\r\n writeFileSync(join(claudeDir, \"memory-sync.mjs\"), script, { encoding: \"utf-8\", mode: 0o700 })\r\n}\r\n\r\n/**\r\n * Write .claude/identity-sync.mjs — uploads the agent's identity files\r\n * (SOUL.md, IDENTITY.md, USER.md, HEARTBEAT.md, optional goals.json with\r\n * {goals: string[]}) to Stride's identity endpoint and marks onboarding\r\n * complete. The agent runs this once, at the end of its first-boot interview.\r\n */\r\nexport function writeIdentitySyncScript(opts: HookWriterOptions): void {\r\n const { agentId, hookSecret, apiBaseUrl, workspaceDir } = opts\r\n const base = apiBaseUrl.replace(/\\/$/, \"\")\r\n const identityUrl = `${base}/api/internal/build/agents/${agentId}/identity`\r\n\r\n const script = `#!/usr/bin/env node\r\n// Auto-generated by stride-bridge. Do not edit.\r\n// Uploads identity files + goals to Stride and marks onboarding complete.\r\n\r\nimport { createHmac } from \"node:crypto\";\r\nimport { readFileSync, existsSync } from \"node:fs\";\r\nimport { join, dirname } from \"node:path\";\r\nimport { fileURLToPath } from \"node:url\";\r\n\r\nconst HOOK_SECRET = ${JSON.stringify(hookSecret)};\r\nconst IDENTITY_URL = ${JSON.stringify(identityUrl)};\r\nconst workspace = dirname(dirname(fileURLToPath(import.meta.url)));\r\n\r\nfunction readIf(name) {\r\n const p = join(workspace, name);\r\n return existsSync(p) ? readFileSync(p, \"utf-8\").slice(0, 20000) : undefined;\r\n}\r\n\r\nconst payload = {\r\n soulMd: readIf(\"SOUL.md\"),\r\n identityMd: readIf(\"IDENTITY.md\"),\r\n userMd: readIf(\"USER.md\"),\r\n heartbeatChecklist: readIf(\"HEARTBEAT.md\"),\r\n onboardingComplete: true,\r\n};\r\nconst goalsRaw = readIf(\"goals.json\");\r\nif (goalsRaw) {\r\n try {\r\n const parsed = JSON.parse(goalsRaw);\r\n if (Array.isArray(parsed.goals)) payload.goals = parsed.goals.slice(0, 5);\r\n } catch { /* ignore malformed goals.json */ }\r\n}\r\n\r\nconst body = JSON.stringify(payload);\r\nconst ts = Math.floor(Date.now() / 1000).toString();\r\nconst sig = createHmac(\"sha256\", HOOK_SECRET).update(ts + \"\\\\n\" + body).digest(\"hex\");\r\n\r\nconst res = await fetch(IDENTITY_URL, {\r\n method: \"POST\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n \"x-stride-hook-ts\": ts,\r\n \"x-stride-hook-sig\": sig,\r\n },\r\n body,\r\n}).catch((err) => ({ ok: false, statusText: String(err) }));\r\n\r\nconsole.log(res.ok ? \"identity-sync: onboarding recorded in Stride\" : \\`identity-sync: failed (\\${res.statusText ?? res.status})\\`);\r\n`\r\n\r\n const claudeDir = join(workspaceDir, \".claude\")\r\n mkdirSync(claudeDir, { recursive: true })\r\n writeFileSync(join(claudeDir, \"identity-sync.mjs\"), script, { encoding: \"utf-8\", mode: 0o700 })\r\n}\r\n\r\n/**\r\n * Write .claude/memory-search.mjs — semantic search over the agent's own\r\n * synced memory (Phase D). Usage: node .claude/memory-search.mjs \"query\"\r\n */\r\nexport function writeMemorySearchScript(opts: HookWriterOptions): void {\r\n const { agentId, hookSecret, apiBaseUrl, workspaceDir } = opts\r\n const base = apiBaseUrl.replace(/\\/$/, \"\")\r\n const searchUrl = `${base}/api/internal/build/agents/${agentId}/memory/search`\r\n\r\n const script = `#!/usr/bin/env node\r\n// Auto-generated by stride-bridge. Do not edit.\r\n// Semantically searches this agent's synced memory in Stride.\r\n\r\nimport { createHmac } from \"node:crypto\";\r\n\r\nconst HOOK_SECRET = ${JSON.stringify(hookSecret)};\r\nconst SEARCH_URL = ${JSON.stringify(searchUrl)};\r\n\r\nconst query = process.argv.slice(2).join(\" \").trim();\r\nif (!query) {\r\n console.log(\"usage: node memory-search.mjs <query>\");\r\n process.exit(0);\r\n}\r\n\r\nconst body = JSON.stringify({ query, limit: 5 });\r\nconst ts = Math.floor(Date.now() / 1000).toString();\r\nconst sig = createHmac(\"sha256\", HOOK_SECRET).update(ts + \"\\\\n\" + body).digest(\"hex\");\r\n\r\nconst res = await fetch(SEARCH_URL, {\r\n method: \"POST\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n \"x-stride-hook-ts\": ts,\r\n \"x-stride-hook-sig\": sig,\r\n },\r\n body,\r\n}).catch(() => null);\r\n\r\nif (!res || !res.ok) {\r\n console.log(\"memory-search: unavailable\");\r\n process.exit(0);\r\n}\r\nconst data = await res.json();\r\nconst results = data?.data?.results ?? [];\r\nif (results.length === 0) {\r\n console.log(\"memory-search: no matches\");\r\n} else {\r\n for (const r of results) {\r\n console.log(\"--- \" + (r.label ?? \"memory\") + \" ---\");\r\n console.log(String(r.content ?? \"\").slice(0, 600));\r\n }\r\n}\r\n`\r\n\r\n const claudeDir = join(workspaceDir, \".claude\")\r\n mkdirSync(claudeDir, { recursive: true })\r\n writeFileSync(join(claudeDir, \"memory-search.mjs\"), script, { encoding: \"utf-8\", mode: 0o700 })\r\n}\r\n\r\n/**\r\n * Write .claude/approval-request.mjs — a Node.js script the agent runs to POST\r\n * a plan/question/action approval request to the Stride approvals endpoint.\r\n * Node instead of the server's bash snippet because local agents run on Windows.\r\n *\r\n * Usage: node .claude/approval-request.mjs <title> <plan>\r\n * title — short description (max 200 chars)\r\n * plan — full plan / question / action text (max 8000 chars)\r\n *\r\n * On success the agent receives { approvalId, message } — it must END the run\r\n * after calling this and wait to be re-woken with the decision.\r\n */\r\nexport function writeApprovalRequestScript(opts: HookWriterOptions): void {\r\n const { agentId, hookSecret, apiBaseUrl, workspaceDir } = opts\r\n const base = apiBaseUrl.replace(/\\/$/, \"\")\r\n const approvalsUrl = `${base}/api/internal/build/agents/${agentId}/approvals`\r\n\r\n const script = `#!/usr/bin/env node\r\n// Auto-generated by stride-bridge. Do not edit.\r\n// Posts a plan/question/action approval request to Stride (HMAC-signed).\r\n// Usage: node .claude/approval-request.mjs <title> <plan>\r\n// After calling this, END your current run and wait to be re-woken.\r\n\r\nimport { createHmac } from \"node:crypto\";\r\n\r\nconst HOOK_SECRET = ${JSON.stringify(hookSecret)};\r\nconst APPROVALS_URL = ${JSON.stringify(approvalsUrl)};\r\n\r\nconst args = process.argv.slice(2);\r\nconst title = (args[0] ?? \"\").trim();\r\nconst plan = (args[1] ?? \"\").trim();\r\n\r\nif (!title) {\r\n console.error(\"approval-request: title is required\");\r\n console.error(\"usage: node .claude/approval-request.mjs <title> <plan>\");\r\n process.exit(1);\r\n}\r\n\r\nconst body = JSON.stringify({ type: \"plan\", title: title.slice(0, 200), body: plan.slice(0, 8000) });\r\nconst ts = Math.floor(Date.now() / 1000).toString();\r\nconst sig = createHmac(\"sha256\", HOOK_SECRET).update(ts + \"\\\\n\" + body).digest(\"hex\");\r\n\r\nconst res = await fetch(APPROVALS_URL, {\r\n method: \"POST\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n \"x-stride-hook-ts\": ts,\r\n \"x-stride-hook-sig\": sig,\r\n },\r\n body,\r\n}).catch((err) => ({ ok: false, statusText: String(err) }));\r\n\r\nif (!res.ok) {\r\n console.error(\\`approval-request: failed (\\${res.statusText ?? res.status})\\`);\r\n process.exit(1);\r\n}\r\n\r\nconst data = await res.json();\r\nconsole.log(\\`approval-request: submitted (approvalId=\\${data?.approvalId ?? \"?\"})\\`);\r\nconsole.log(data?.message ?? \"End your current run and wait to be re-woken.\");\r\n`\r\n\r\n const claudeDir = join(workspaceDir, \".claude\")\r\n mkdirSync(claudeDir, { recursive: true })\r\n writeFileSync(join(claudeDir, \"approval-request.mjs\"), script, { encoding: \"utf-8\", mode: 0o700 })\r\n}\r\n","/**\n * detect-runtimes.ts — CLI capability detection for the Bridge daemon.\n *\n * On startup and on each agent refresh, the daemon probes for installed AI\n * runtime CLIs (claude, codex, hermes). Each probe is a `--version` spawn\n * with a 3-second timeout; failures are swallowed (fail-soft per daemon\n * convention). Results are reported in heartbeat payloads so the dashboard\n * can display which runtimes are available on this bridge machine.\n *\n * Supported runtimes:\n * - claude-code: `claude --version`\n * - codex: `codex --version`\n * - hermes: `hermes --version`\n *\n * Design notes:\n * - Pure detection only — never installs, never fails the daemon.\n * - Cached for CACHE_TTL_MS to avoid excess spawning on every agent refresh.\n * - Each probe is capped at PROBE_TIMEOUT_MS (3 seconds).\n * - Version string is the first non-empty stdout line (trimmed).\n */\n\nimport { spawn } from \"node:child_process\"\nimport { logWarn } from \"./log.js\"\n\nexport interface RuntimeCapability {\n /** Runtime identifier matching the agent's agentRuntime field. */\n runtime: \"claude-code\" | \"codex\" | \"hermes\"\n /** Reported version string, e.g. \"1.2.3\". Empty string if undetectable. */\n version: string\n}\n\nconst PROBE_TIMEOUT_MS = 3_000\nconst CACHE_TTL_MS = 5 * 60 * 1000 // 5 minutes — same cadence as agent refresh\n\ninterface ProbeSpec {\n runtime: RuntimeCapability[\"runtime\"]\n /**\n * CLI command. On win32 we try both the .cmd shim path and the bare name\n * with shell:true as fallback inside probeRuntime.\n */\n cmd: string\n args: string[]\n}\n\nconst PROBES: ProbeSpec[] = [\n { runtime: \"claude-code\", cmd: \"claude\", args: [\"--version\"] },\n { runtime: \"codex\", cmd: \"codex\", args: [\"--version\"] },\n { runtime: \"hermes\", cmd: \"hermes\", args: [\"--version\"] },\n]\n\n/**\n * Spawn a single `<cmd> --version` and resolve with the first stdout line.\n * Resolves with an empty string if the process errors, exits non-zero, or\n * produces no output within PROBE_TIMEOUT_MS.\n */\nexport function probeRuntime(cmd: string, args: string[]): Promise<string> {\n return new Promise((resolve) => {\n let child: ReturnType<typeof spawn>\n let resolved = false\n\n const done = (value: string) => {\n if (!resolved) {\n resolved = true\n resolve(value)\n }\n }\n\n // On Windows, try the bare name with shell:true so npm .cmd shims resolve.\n const useShell = process.platform === \"win32\"\n\n try {\n child = spawn(cmd, args, {\n shell: useShell,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n env: process.env,\n })\n } catch {\n done(\"\"); return\n }\n\n let stdoutBuf = \"\"\n child.stdout?.on(\"data\", (chunk: Buffer) => {\n stdoutBuf += chunk.toString(\"utf-8\")\n })\n\n const timer = setTimeout(() => {\n try { child.kill(\"SIGTERM\") } catch { /* ignore */ }\n done(\"\")\n }, PROBE_TIMEOUT_MS)\n\n child.on(\"close\", () => {\n clearTimeout(timer)\n // Extract the first non-empty line from stdout as the version string.\n const firstLine = stdoutBuf\n .split(\"\\n\")\n .map((l) => l.trim())\n .find((l) => l.length > 0) ?? \"\"\n done(firstLine)\n })\n\n child.on(\"error\", () => {\n clearTimeout(timer)\n done(\"\")\n })\n })\n}\n\n/**\n * Extract a clean semver-like version from raw CLI version output.\n *\n * Handles common formats:\n * \"claude 1.2.3\" → \"1.2.3\"\n * \"Claude Code 1.2.3\" → \"1.2.3\"\n * \"hermes-agent 0.16.0\" → \"0.16.0\"\n * \"codex 0.1.0 (abc1234)\" → \"0.1.0\"\n * \"1.2.3\" → \"1.2.3\"\n * \"\" → \"\"\n */\nexport function extractVersion(raw: string): string {\n if (!raw.trim()) return \"\"\n // Match semver-like: digits.digits[.digits[...]]\n const match = raw.match(/\\d+\\.\\d+(?:\\.\\d+)*/)\n return match ? match[0] : raw.trim().split(/\\s+/).pop() ?? \"\"\n}\n\nlet cached: { capabilities: RuntimeCapability[]; at: number } | null = null\n\n/**\n * Detect all installed AI runtime CLIs. Results are cached for CACHE_TTL_MS.\n *\n * Returns a (possibly empty) array of RuntimeCapability objects for each\n * runtime that appears to be installed (probe returned a non-empty version).\n * Always returns the full probe list with empty-string versions for absent\n * runtimes so callers know what was checked.\n *\n * Uses the cached result when fresh enough; pass force=true to bypass.\n */\nexport async function detectRuntimes(force = false): Promise<RuntimeCapability[]> {\n if (!force && cached && Date.now() - cached.at < CACHE_TTL_MS) {\n return cached.capabilities\n }\n\n const results: RuntimeCapability[] = []\n\n for (const probe of PROBES) {\n try {\n const raw = await probeRuntime(probe.cmd, probe.args)\n results.push({ runtime: probe.runtime, version: extractVersion(raw) })\n } catch (err: unknown) {\n logWarn(\n `Runtime probe failed for \"${probe.runtime}\": ${err instanceof Error ? err.message : String(err)}`,\n )\n results.push({ runtime: probe.runtime, version: \"\" })\n }\n }\n\n cached = { capabilities: results, at: Date.now() }\n return results\n}\n\n/**\n * Invalidate the runtime detection cache. Called when agents are refreshed\n * so the dashboard always gets fresh data after a new runtime is installed.\n */\nexport function invalidateRuntimeCache(): void {\n cached = null\n}\n","/**\r\n * agents.ts — Fetch agent configs from Stride and provision local workspaces.\r\n *\r\n * At startup and every 5 minutes, fetches the list of agents assigned to this\r\n * bridge. For each agent, ensures:\r\n * ~/.stride-bridge/agents/<agentId>/workspace/\r\n * ~/.stride-bridge/agents/<agentId>/workspace/CLAUDE.md\r\n * ~/.stride-bridge/agents/<agentId>/workspace/.claude/settings.json\r\n * ~/.stride-bridge/agents/<agentId>/workspace/.claude/hook-runner.mjs\r\n */\r\n\r\nimport { join } from \"node:path\"\r\nimport { mkdirSync, writeFileSync, existsSync } from \"node:fs\"\r\nimport { get } from \"./api.js\"\r\nimport type { BridgeConfig } from \"./config.js\"\r\nimport { AGENTS_DIR } from \"./config.js\"\r\nimport {\r\n writeAgentHooks,\r\n writeMemorySyncScript,\r\n writeIdentitySyncScript,\r\n writeMemorySearchScript,\r\n writeApprovalRequestScript,\r\n} from \"./hooks-writer.js\"\r\nimport { invalidateRuntimeCache } from \"./detect-runtimes.js\"\r\nimport { log, logError } from \"./log.js\"\r\n\r\nexport interface BridgeAgent {\r\n id: string\r\n name: string\r\n status: string\r\n model: string\r\n systemPrompt: string\r\n soulMd?: string | null\r\n allowedTools: string[]\r\n maxBudgetUsd: number\r\n localSessionMode: string\r\n hookSecret: string\r\n // Phase 3 identity + memory layer (server-rendered templates)\r\n identityMd?: string | null\r\n userMd?: string | null\r\n heartbeatChecklist?: string | null\r\n memoryProtocolMd?: string | null\r\n defaultSoulMd?: string | null\r\n // Phase 4 first-boot onboarding\r\n onboardedAt?: string | null\r\n onboardingMd?: string | null\r\n // Phase 5 approval + experiment protocols (server already sends all four)\r\n requirePlanApproval?: boolean\r\n approvalProtocolMd?: string | null\r\n experimentProtocolMd?: string | null\r\n experimentSnippet?: string | null\r\n /**\r\n * WS1: Runtime for this agent. Optional — absent/unknown defaults to\r\n * \"claude-code\" in the runner (backward-compatible with old server versions).\r\n * Server-side field; if the server does not yet send this field the daemon\r\n * reads it as undefined and falls back to claude-code automatically.\r\n */\r\n agentRuntime?: string | null\r\n}\r\n\r\ninterface AgentsResponseData {\r\n agents: BridgeAgent[]\r\n}\r\n\r\n// In-memory cache of agent configs, refreshed periodically.\r\nlet cachedAgents: BridgeAgent[] = []\r\nconst REFRESH_INTERVAL_MS = 5 * 60 * 1000 // 5 minutes\r\nlet refreshTimer: ReturnType<typeof setInterval> | null = null\r\n\r\n/**\r\n * Fetch agent list from server and provision local workspaces.\r\n * Errors are caught and logged — a refresh failure must not crash the daemon.\r\n */\r\nexport async function refreshAgents(config: BridgeConfig): Promise<void> {\r\n try {\r\n const data = await get<AgentsResponseData>(config, \"/api/bridge/v1/agents\")\r\n cachedAgents = data.agents ?? []\r\n log(`Refreshed ${cachedAgents.length} agent(s)`)\r\n for (const agent of cachedAgents) {\r\n await ensureAgentWorkspace(config, agent)\r\n }\r\n // Invalidate cached runtime capabilities so the next heartbeat re-probes\r\n // for newly installed CLIs (user may have installed codex/hermes since last\r\n // refresh).\r\n invalidateRuntimeCache()\r\n } catch (err: unknown) {\r\n logError(\"Failed to refresh agents\", err)\r\n }\r\n}\r\n\r\n/**\r\n * Return the cached agent list (may be stale if refresh failed).\r\n */\r\nexport function getCachedAgents(): BridgeAgent[] {\r\n return cachedAgents\r\n}\r\n\r\n/**\r\n * Find a cached agent by ID.\r\n */\r\nexport function findAgent(agentId: string): BridgeAgent | undefined {\r\n return cachedAgents.find((a) => a.id === agentId)\r\n}\r\n\r\n/**\r\n * Ensure the local workspace directory exists for an agent, writing\r\n * CLAUDE.md and .claude/settings.json (with signed hooks).\r\n */\r\nasync function ensureAgentWorkspace(\r\n config: BridgeConfig,\r\n agent: BridgeAgent,\r\n): Promise<void> {\r\n const workspaceDir = agentWorkspaceDir(agent.id)\r\n mkdirSync(workspaceDir, { recursive: true })\r\n // Daily-journal directory (Layer 1 memory) — agent-written, never clobbered.\r\n mkdirSync(join(workspaceDir, \"memory\"), { recursive: true })\r\n\r\n // CLAUDE.md is fully generated — safe to overwrite on every refresh.\r\n const sections: string[] = []\r\n if (agent.systemPrompt) sections.push(agent.systemPrompt)\r\n sections.push(agent.soulMd ?? agent.defaultSoulMd ?? \"\")\r\n if (agent.memoryProtocolMd) sections.push(agent.memoryProtocolMd)\r\n sections.push(\r\n \"## Memory sync (local agent)\\n\\n\" +\r\n \"After updating MEMORY.md or today's daily journal, sync them to Stride by running:\\n\\n\" +\r\n \"```\\nnode .claude/memory-sync.mjs\\n```\\n\\n\" +\r\n \"Before re-researching something you may have learned before, search your \" +\r\n \"own past memory semantically:\\n\\n\" +\r\n '```\\nnode .claude/memory-search.mjs \"your question\"\\n```\\n',\r\n )\r\n // Approvals section — enables requirePlanApproval agents on Windows (no bash/openssl needed).\r\n if (agent.approvalProtocolMd) {\r\n sections.push(\r\n agent.approvalProtocolMd +\r\n \"\\n\\n### Approval Request (local agent)\\n\\n\" +\r\n \"Post a plan or question for human review using the Windows-safe Node script:\\n\\n\" +\r\n \"```\\nnode .claude/approval-request.mjs \\\"<title>\\\" \\\"<plan>\\\"\\n```\\n\\n\" +\r\n \"After posting, **end your current run immediately** and wait to be re-woken.\",\r\n )\r\n }\r\n // Experiments section\r\n if (agent.experimentProtocolMd) {\r\n sections.push(agent.experimentProtocolMd)\r\n if (agent.experimentSnippet) {\r\n sections.push(agent.experimentSnippet)\r\n }\r\n }\r\n if (!agent.onboardedAt && agent.onboardingMd) {\r\n sections.push(\r\n \"## FIRST BOOT — onboarding required\\n\\n\" +\r\n \"You have not been onboarded. Read ONBOARDING.md in this workspace and \" +\r\n \"complete the interview BEFORE regular work. To sync your identity after \" +\r\n \"the interview, run:\\n\\n```\\nnode .claude/identity-sync.mjs\\n```\\n\",\r\n )\r\n }\r\n const claudeMdContent = sections.filter(Boolean).join(\"\\n\\n\")\r\n writeFileSync(join(workspaceDir, \"CLAUDE.md\"), claudeMdContent, \"utf-8\")\r\n\r\n // AGENTS.md — identical content to CLAUDE.md so codex and hermes agents\r\n // get the same identity/soul/instructions. Both runtimes discover this file\r\n // natively (codex reads AGENTS.md from cwd; hermes reads AGENTS.md per\r\n // Addendum C.4 discovery order). We write it on every refresh alongside\r\n // CLAUDE.md so both always stay in sync.\r\n writeFileSync(join(workspaceDir, \"AGENTS.md\"), claudeMdContent, \"utf-8\")\r\n\r\n // ONBOARDING.md present only until the agent completes its interview.\r\n if (!agent.onboardedAt && agent.onboardingMd) {\r\n writeFileSync(join(workspaceDir, \"ONBOARDING.md\"), agent.onboardingMd, \"utf-8\")\r\n }\r\n\r\n // Identity files: server-rendered, overwrite on every refresh (dashboard is source of truth).\r\n // D5: write SOUL.md as a real file — makes identity-sync.mjs round-trip symmetric and\r\n // makes buildIdentityMd's \"see SOUL.md\" sentence true locally.\r\n const soulContent = agent.soulMd ?? agent.defaultSoulMd\r\n if (soulContent) writeFileSync(join(workspaceDir, \"SOUL.md\"), soulContent, \"utf-8\")\r\n if (agent.identityMd) writeFileSync(join(workspaceDir, \"IDENTITY.md\"), agent.identityMd, \"utf-8\")\r\n if (agent.userMd) writeFileSync(join(workspaceDir, \"USER.md\"), agent.userMd, \"utf-8\")\r\n if (agent.heartbeatChecklist) {\r\n writeFileSync(join(workspaceDir, \"HEARTBEAT.md\"), agent.heartbeatChecklist, \"utf-8\")\r\n }\r\n\r\n // MEMORY.md is AGENT-written (Layer 2) — scaffold once, never overwrite.\r\n const memoryMdPath = join(workspaceDir, \"MEMORY.md\")\r\n if (!existsSync(memoryMdPath)) {\r\n writeFileSync(\r\n memoryMdPath,\r\n \"# Long-term memory\\n\\nDurable learnings only — format: `## Topic — YYYY-MM-DD` followed by what you learned.\\n\",\r\n \"utf-8\",\r\n )\r\n }\r\n\r\n // .claude/settings.json with HMAC-signed PreToolUse hook\r\n writeAgentHooks({\r\n agentId: agent.id,\r\n hookSecret: agent.hookSecret,\r\n apiBaseUrl: config.apiBaseUrl,\r\n workspaceDir,\r\n })\r\n\r\n // .claude/memory-sync.mjs — signed memory uploader (node, Windows-safe)\r\n writeMemorySyncScript({\r\n agentId: agent.id,\r\n hookSecret: agent.hookSecret,\r\n apiBaseUrl: config.apiBaseUrl,\r\n workspaceDir,\r\n })\r\n\r\n // .claude/identity-sync.mjs — uploads identity files after onboarding\r\n writeIdentitySyncScript({\r\n agentId: agent.id,\r\n hookSecret: agent.hookSecret,\r\n apiBaseUrl: config.apiBaseUrl,\r\n workspaceDir,\r\n })\r\n\r\n // .claude/memory-search.mjs — semantic search over synced memory (Phase D)\r\n writeMemorySearchScript({\r\n agentId: agent.id,\r\n hookSecret: agent.hookSecret,\r\n apiBaseUrl: config.apiBaseUrl,\r\n workspaceDir,\r\n })\r\n\r\n // .claude/approval-request.mjs — Windows-safe approval request (Phase 5)\r\n // Resolves the ExitPlanMode dead-end on local agents without bash/openssl.\r\n writeApprovalRequestScript({\r\n agentId: agent.id,\r\n hookSecret: agent.hookSecret,\r\n apiBaseUrl: config.apiBaseUrl,\r\n workspaceDir,\r\n })\r\n\r\n log(`Provisioned workspace for agent \"${agent.name}\" (${agent.id})`)\r\n}\r\n\r\n/**\r\n * Return the workspace directory path for an agent.\r\n */\r\nexport function agentWorkspaceDir(agentId: string): string {\r\n return join(AGENTS_DIR, agentId, \"workspace\")\r\n}\r\n\r\n/**\r\n * Start the periodic agent refresh timer. Call once from the daemon loop.\r\n * Cleans up the timer when the process exits.\r\n */\r\nexport function startAgentRefreshTimer(config: BridgeConfig): void {\r\n if (refreshTimer !== null) return // already running\r\n\r\n refreshTimer = setInterval(() => {\r\n void refreshAgents(config)\r\n }, REFRESH_INTERVAL_MS)\r\n\r\n // Do not hold the event loop open if all other work is done.\r\n if (refreshTimer.unref) {\r\n refreshTimer.unref()\r\n }\r\n}\r\n\r\n/**\r\n * Stop the agent refresh timer.\r\n */\r\nexport function stopAgentRefreshTimer(): void {\r\n if (refreshTimer !== null) {\r\n clearInterval(refreshTimer)\r\n refreshTimer = null\r\n }\r\n}\r\n","/**\n * session.ts — Persistent-session state for local agents (Phase 2).\n *\n * Agents with localSessionMode === \"persistent\" carry conversation context\n * across work items via `claude -p --resume <sessionId>`. We track the\n * session per agent in agents/<id>/session.json and rotate (start fresh)\n * when the session gets old or has accumulated many runs — the headless\n * equivalent of cortex-os's 71-hour context rotation, defaulting lower\n * because -p turns are denser than interactive chat.\n */\n\nimport { join, dirname } from \"node:path\"\nimport { agentWorkspaceDir } from \"./agents.js\"\nimport { readJsonSafe, writeJsonAtomic } from \"./state.js\"\n\nexport interface AgentSessionState {\n sessionId: string | null\n sessionStartedAt: number | null\n runCount: number\n}\n\nexport interface RotationOptions {\n /** Max session age before rotation. Default 24h. */\n maxAgeMs?: number\n /** Max work items in one session before rotation. Default 40. */\n maxRuns?: number\n}\n\nconst EMPTY_STATE: AgentSessionState = {\n sessionId: null,\n sessionStartedAt: null,\n runCount: 0,\n}\n\n/**\n * Pure rotation decision: start a fresh session when there is no usable\n * session, the session is too old, or it has absorbed too many runs.\n */\nexport function shouldRotateSession(\n state: AgentSessionState,\n nowMs: number,\n opts: RotationOptions = {},\n): boolean {\n const { maxAgeMs = 24 * 60 * 60_000, maxRuns = 40 } = opts\n if (!state.sessionId || state.sessionStartedAt === null) return true\n if (nowMs - state.sessionStartedAt >= maxAgeMs) return true\n if (state.runCount >= maxRuns) return true\n return false\n}\n\nfunction sessionStatePath(agentId: string): string {\n // agents/<id>/session.json — sibling of the workspace dir\n return join(dirname(agentWorkspaceDir(agentId)), \"session.json\")\n}\n\nexport function loadSessionState(agentId: string): AgentSessionState {\n const parsed = readJsonSafe<Partial<AgentSessionState>>(sessionStatePath(agentId))\n if (!parsed) return { ...EMPTY_STATE }\n return {\n sessionId: typeof parsed.sessionId === \"string\" ? parsed.sessionId : null,\n sessionStartedAt:\n typeof parsed.sessionStartedAt === \"number\" ? parsed.sessionStartedAt : null,\n runCount: typeof parsed.runCount === \"number\" ? parsed.runCount : 0,\n }\n}\n\nexport function saveSessionState(agentId: string, state: AgentSessionState): void {\n writeJsonAtomic(sessionStatePath(agentId), state)\n}\n\n/**\n * Record a completed run's session id. Continuing an existing session bumps\n * runCount; a new session id resets the clock.\n */\nexport function recordRunSession(\n agentId: string,\n newSessionId: string | undefined,\n previous: AgentSessionState,\n nowMs: number,\n): AgentSessionState {\n if (!newSessionId) return previous\n const continued = previous.sessionId === newSessionId\n const next: AgentSessionState = continued\n ? { ...previous, runCount: previous.runCount + 1 }\n : { sessionId: newSessionId, sessionStartedAt: nowMs, runCount: 1 }\n saveSessionState(agentId, next)\n return next\n}\n","/**\n * prompt.ts — Pure prompt assembly for the Bridge runner.\n *\n * Responsible for:\n * 1. Gated soul injection — prepends \"Who you are\" + identity text ONLY\n * when cwd is NOT the agent workspace (the project-localFolder case where\n * the workspace CLAUDE.md / AGENTS.md is not auto-discovered by the runtime).\n * This gate applies uniformly to ALL runtimes (claude-code, codex, hermes).\n * 2. Session-rotation preamble — when a session was just rotated.\n * 3. The server-composed workPrompt verbatim (never reordered internally).\n *\n * Design invariants:\n * - Never throws — fail-soft per daemon convention. All errors are swallowed.\n * - Never reorders workPrompt internals — the inbox block must stay outermost\n * so its delivered→read lifecycle is tied to run completion.\n * - Soul injection doubles as identity injection (identityMd appended if present).\n * - Order when injected: identity/soul section → rotation preamble → workPrompt.\n */\n\nimport type { BridgeAgent } from \"./agents.js\"\n\nexport interface BuildPromptOpts {\n /** The server-composed prompt text (inbox + checklist + task). */\n workPrompt: string\n /**\n * The cached agent config. May be undefined when findAgent() returns nothing\n * (stale cache / refresh failure) — in that case, skip soul injection silently.\n */\n agent: Pick<BridgeAgent, \"soulMd\" | \"defaultSoulMd\" | \"identityMd\"> | undefined\n /** Actual working directory Claude Code will be launched in. */\n cwd: string\n /** Agent's own workspace directory (~/.stride-bridge/agents/<id>/workspace). */\n agentWorkspace: string\n /**\n * True when the persistent session was just rotated — prepends a reminder\n * to read HANDOFF.md.\n */\n rotated: boolean\n}\n\n/**\n * Assemble the full prompt text to be sent to the agent runtime via stdin.\n *\n * Soul injection is gated: only fires when `cwd !== agentWorkspace` AND the\n * agent has soul content. This covers project-localFolder runs where the\n * workspace CLAUDE.md / AGENTS.md (containing soul + instructions) is NOT\n * auto-loaded by the runtime.\n *\n * In the default case (cwd === agentWorkspace), soul is already in context:\n * - claude-code: auto-loads CLAUDE.md from cwd\n * - codex: discovers AGENTS.md from cwd natively\n * - hermes: discovers AGENTS.md per Addendum C.4 discovery order\n * Injecting again would double-include up to 20k chars per run and re-feed\n * it on every `--resume` / re-run work item.\n *\n * This gate applies uniformly to ALL runtimes — no runtime-specific override.\n */\nexport function buildPromptText(opts: BuildPromptOpts): string {\n try {\n const { workPrompt, agent, cwd, agentWorkspace, rotated } = opts\n\n const parts: string[] = []\n\n // 1. Soul/identity injection.\n //\n // Gated to project-cwd runs (cwd !== agentWorkspace) for ALL runtimes.\n // When cwd === agentWorkspace, the runtime auto-discovers CLAUDE.md or\n // AGENTS.md in that directory and soul is already in context — injecting\n // again causes double-inclusion.\n const soulText = agent?.soulMd ?? agent?.defaultSoulMd\n const shouldInjectSoul =\n cwd !== agentWorkspace &&\n soulText != null && soulText.trim().length > 0\n\n if (shouldInjectSoul) {\n // Identity: soul first, then identityMd if present.\n let identityBlock = `## Who you are\\n\\n${soulText}`\n if (agent?.identityMd && agent.identityMd.trim().length > 0) {\n identityBlock += `\\n\\n${agent.identityMd}`\n }\n parts.push(identityBlock)\n }\n\n // 2. Session-rotation preamble.\n if (rotated) {\n parts.push(\n \"## Session rotated\\n\" +\n \"Your previous session ended (context rotation). Read HANDOFF.md and \" +\n \"your recent memory/ journal entries before starting.\",\n )\n }\n\n // 3. Server-composed prompt verbatim (inbox + checklist + task).\n // Never reorder internals — inbox block lifecycle depends on ordering.\n parts.push(workPrompt)\n\n return parts.join(\"\\n\\n---\\n\\n\")\n } catch {\n // Fail-soft: if anything goes wrong in prompt assembly, return workPrompt\n // unchanged so the run still proceeds.\n return opts.workPrompt\n }\n}\n","/**\n * report-queue.ts — Pending and dead-letter report persistence for the Bridge.\n *\n * Handles two files on disk:\n * - pending-reports.json — transient failures, retried with backoff\n * - dead-reports.json — permanent failures (4xx non-retryable, or ≥20 attempts)\n *\n * Rules:\n * - ApiError with status >= 400 && < 500 (excluding 408 and 429) → dead-letter\n * immediately (permanent server rejection; retrying is pointless and, per the\n * spec, was causing an infinite retry loop on exitCode:null reports before WS1).\n * - 408 (Request Timeout) and 429 (Rate Limited) → retried normally.\n * - Network errors (status null) and 5xx → retried normally.\n * - After MAX_ATTEMPTS total attempts → dead-letter.\n *\n * Exported for testing; the runner delegates all queue I/O here.\n */\n\nimport { join } from \"node:path\"\nimport { BRIDGE_DIR, PENDING_REPORTS_PATH } from \"./config.js\"\nimport { readJsonSafe, writeJsonAtomic } from \"./state.js\"\nimport { ApiError } from \"./api.js\"\nimport { logError, logWarn } from \"./log.js\"\n\nexport const DEAD_REPORTS_PATH = join(BRIDGE_DIR, \"dead-reports.json\")\n\nconst MAX_ATTEMPTS = 20\n\nexport interface QueuedReport {\n runId: string\n report: RunReport\n attempts: number\n firstFailedAt: string\n}\n\n/**\n * Minimal shape of a RunReport — the queue only needs to persist and re-POST it.\n * Must stay compatible with runner.ts RunReport (same fields, no extras required).\n */\nexport interface RunReport {\n runId: string\n wakeupId: string\n failureKind?: string\n status: \"completed\" | \"failed\"\n stdoutExcerpt: string\n stderrExcerpt: string\n error?: string\n exitCode: number | null\n costUsd?: number\n tokensInput?: number\n tokensOutput?: number\n sessionId?: string\n}\n\n// ---------------------------------------------------------------------------\n// Retryability classification\n// ---------------------------------------------------------------------------\n\n/**\n * Returns true when an error is a permanent 4xx that should be dead-lettered\n * immediately rather than retried.\n *\n * Non-retryable: 400, 401, 403, 404, 409, 410, 422 (and any 4xx not in the\n * retryable set below).\n * Retryable 4xx exceptions: 408 (timeout), 429 (rate-limit).\n */\nexport function isPermanentClientError(err: unknown): boolean {\n if (!(err instanceof ApiError)) return false\n const { status } = err\n if (status === null) return false // network error → retry\n if (status < 400 || status >= 500) return false // 2xx/3xx/5xx → not a 4xx\n // Retryable 4xx exceptions\n if (status === 408 || status === 429) return false\n return true // all other 4xx → permanent\n}\n\n// ---------------------------------------------------------------------------\n// Queue I/O helpers (internal)\n// ---------------------------------------------------------------------------\n\n/**\n * Normalise a raw entry read from disk into a well-formed QueuedReport.\n *\n * Three shapes are handled:\n * 1. Canonical — {runId, report: object, attempts: number, firstFailedAt: string}\n * May have NaN/null attempts from a previous crash — healed with Number.isFinite.\n * 2. Legacy flat — {runId: string, status: string, …} with NO .report sub-object.\n * Written by pre-WS1 daemons that persisted RunReport[] directly. Wrapped as a\n * fresh QueuedReport with attempts=0 so the drain loop delivers it correctly.\n * 3. Unrecognised — missing runId or not a plain object → dropped with a warning.\n */\nexport function normalizeEntry(raw: unknown): QueuedReport | null {\n if (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) {\n logWarn(\"[report-queue] Dropping unrecognised queue entry (not an object)\")\n return null\n }\n const r = raw as Record<string, unknown>\n\n // Must have a runId string.\n if (typeof r[\"runId\"] !== \"string\" || !r[\"runId\"]) {\n logWarn(\"[report-queue] Dropping queue entry missing runId\")\n return null\n }\n const runId = r[\"runId\"]\n\n // Legacy flat shape: has a top-level `status` string but no `.report` sub-object.\n if (typeof r[\"status\"] === \"string\" && (r[\"report\"] === undefined || r[\"report\"] === null)) {\n logWarn(\n `[report-queue] Normalising legacy flat RunReport for run ${runId} (pre-WS1 daemon)`,\n )\n return {\n runId,\n report: r as unknown as RunReport,\n attempts: 0,\n firstFailedAt: new Date().toISOString(),\n }\n }\n\n // Canonical wrapped shape — must have a .report object.\n if (r[\"report\"] === null || typeof r[\"report\"] !== \"object\" || Array.isArray(r[\"report\"])) {\n logWarn(`[report-queue] Dropping queue entry for run ${runId}: invalid .report field`)\n return null\n }\n\n // Heal corrupted attempts (NaN / null / undefined from past crashes).\n const rawAttempts = r[\"attempts\"]\n const attempts = Number.isFinite(rawAttempts as number) ? (rawAttempts as number) : 0\n\n const firstFailedAt =\n typeof r[\"firstFailedAt\"] === \"string\" ? r[\"firstFailedAt\"] : new Date().toISOString()\n\n return {\n runId,\n report: r[\"report\"] as RunReport,\n attempts,\n firstFailedAt,\n }\n}\n\nfunction readQueue(path: string): QueuedReport[] {\n const raw = readJsonSafe<unknown[]>(path)\n if (!raw) return []\n const normalised: QueuedReport[] = []\n for (const entry of raw) {\n const item = normalizeEntry(entry)\n if (item !== null) normalised.push(item)\n }\n return normalised\n}\n\nfunction writeQueue(path: string, items: QueuedReport[]): void {\n writeJsonAtomic(path, items)\n}\n\nfunction removePendingById(runId: string, path: string): void {\n const items = readQueue(path)\n const filtered = items.filter((r) => r.runId !== runId)\n if (filtered.length !== items.length) {\n writeQueue(path, filtered)\n }\n}\n\nfunction updatePending(item: QueuedReport, path: string): void {\n const items = readQueue(path)\n const updated = items.map((r) => (r.runId === item.runId ? item : r))\n writeQueue(path, updated)\n}\n\nfunction deadLetter(item: QueuedReport, reason: string): void {\n logError(\n `[report-queue] Dead-lettering run ${item.runId} (${reason}, attempts=${item.attempts})`,\n )\n const existing = readQueue(DEAD_REPORTS_PATH)\n const deduped = existing.filter((r) => r.runId !== item.runId)\n deduped.push(item)\n writeQueue(DEAD_REPORTS_PATH, deduped)\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Append a QueuedReport to pending-reports.json (deduped by runId).\n */\nexport function enqueue(item: QueuedReport): void {\n const existing = readQueue(PENDING_REPORTS_PATH)\n const deduped = existing.filter((r) => r.runId !== item.runId)\n deduped.push(item)\n writeQueue(PENDING_REPORTS_PATH, deduped)\n}\n\n/**\n * Remove a successfully-sent report from pending-reports.json.\n * Called by runner.ts after a successful POST.\n */\nexport function removePendingReport(runId: string): void {\n removePendingById(runId, PENDING_REPORTS_PATH)\n}\n\n/**\n * Drain the pending-reports queue, calling `send` for each item.\n *\n * - On success: remove from queue.\n * - On permanent 4xx: dead-letter immediately (not retried).\n * - On transient error: increment attempts; dead-letter after MAX_ATTEMPTS.\n * - Order is preserved (FIFO).\n */\nexport async function drain(\n send: (item: QueuedReport) => Promise<void>,\n): Promise<void> {\n const items = readQueue(PENDING_REPORTS_PATH)\n if (items.length === 0) return\n\n for (const item of items) {\n try {\n await send(item)\n // Success — remove from pending.\n removePendingById(item.runId, PENDING_REPORTS_PATH)\n } catch (err: unknown) {\n if (isPermanentClientError(err)) {\n // Permanent 4xx — dead-letter immediately, remove from pending.\n removePendingById(item.runId, PENDING_REPORTS_PATH)\n deadLetter(item, `permanent ${(err as ApiError).status}`)\n } else {\n // Transient — increment attempts.\n const updated: QueuedReport = { ...item, attempts: item.attempts + 1 }\n if (updated.attempts >= MAX_ATTEMPTS) {\n // Too many attempts — dead-letter.\n removePendingById(item.runId, PENDING_REPORTS_PATH)\n deadLetter(updated, \"max_attempts_exceeded\")\n } else {\n // Update attempt counter in queue.\n updatePending(updated, PENDING_REPORTS_PATH)\n logWarn(\n `[report-queue] Transient failure for run ${item.runId} (attempt ${updated.attempts}/${MAX_ATTEMPTS})`,\n )\n }\n }\n }\n }\n}\n","/**\r\n * runner.ts — Execute a single work item via Claude Code CLI.\r\n *\r\n * Spawns `claude -p --output-format json` and writes the prompt via stdin.\r\n * stdin delivery matters because (1) the Windows .cmd shim needs shell:true\r\n * and an argv prompt would be an injection risk; (2) long prompts can exceed\r\n * Windows' command-line length limit.\r\n *\r\n * --settings always points at the agent workspace so the Stride PreToolUse\r\n * hook applies even when cwd is a project folder elsewhere on disk.\r\n *\r\n * Timeout: 15 minutes (SIGTERM then SIGKILL).\r\n */\r\n\r\nimport { spawn } from \"node:child_process\"\r\nimport { existsSync } from \"node:fs\"\r\nimport { join } from \"node:path\"\r\nimport { homedir } from \"node:os\"\r\nimport { post } from \"./api.js\"\r\nimport type { BridgeConfig } from \"./config.js\"\r\nimport { agentWorkspaceDir, findAgent } from \"./agents.js\"\r\nimport {\r\n loadSessionState,\r\n shouldRotateSession,\r\n recordRunSession,\r\n} from \"./session.js\"\r\nimport { buildPromptText } from \"./prompt.js\"\r\nimport {\r\n enqueue,\r\n drain,\r\n removePendingReport,\r\n type QueuedReport,\r\n type RunReport,\r\n} from \"./report-queue.js\"\r\nimport { log, logError, logWarn } from \"./log.js\"\r\n\r\nconst RUN_TIMEOUT_MS = 15 * 60 * 1000\r\nconst STDOUT_CAP = 10_000\r\nconst STDERR_CAP = 4_000\r\nconst REPORT_RETRY_COUNT = 3\r\nconst REPORT_RETRY_BASE_MS = 2_000\r\n\r\n/**\r\n * Resolve how to launch Claude Code.\r\n *\r\n * Windows landmine: npm installs a `claude` bash-script shim that EATS\r\n * BACKSLASHES from arguments. The native installer's claude.exe has no such\r\n * problem and can be spawned directly without a shell. Preference:\r\n * 1. ~/.local/bin/claude.exe (native installer) — shell:false\r\n * 2. `claude` via shell — last-resort fallback for npm-only installs\r\n */\r\nexport function resolveClaudeCommand(): { cmd: string; shell: boolean } {\r\n if (process.platform !== \"win32\") return { cmd: \"claude\", shell: false }\r\n const nativeExe = join(homedir(), \".local\", \"bin\", \"claude.exe\")\r\n if (existsSync(nativeExe)) return { cmd: nativeExe, shell: false }\r\n return { cmd: \"claude\", shell: true }\r\n}\r\n\r\n/**\r\n * Escape a list of arguments for shell:true spawns (cmd.exe on win32).\r\n *\r\n * Double-quotes each arg that contains shell metacharacters, using cmd.exe\r\n * quoting rules (double any embedded double-quote). Identical to the logic\r\n * that was previously inlined in the claude-code branch — extracted here so\r\n * all shell:true spawns use the same escaping and so it can be unit-tested.\r\n *\r\n * Safe on all platforms — on non-win32 this is never called because\r\n * buildCodexSpawnConfig/buildHermesSpawnConfig set shell:false there.\r\n */\r\nexport function shellEscapeArgs(args: string[]): string[] {\r\n return args.map((a) => (/[\\s\"^&|<>%]/.test(a) ? `\"${a.replace(/\"/g, '\"\"')}\"` : a))\r\n}\r\n\r\n/**\r\n * Validate a model slug against the allowed character set.\r\n *\r\n * Accepted: letters, digits, dots, underscores, colons, plus, slash, hyphen.\r\n * Rejects anything else — prevents shell metacharacter injection via the model\r\n * field when args are passed through shell:true or used as file names.\r\n *\r\n * Returns true when the slug is valid.\r\n */\r\nexport function isValidModelSlug(model: string): boolean {\r\n return /^[A-Za-z0-9._:+/-]+$/.test(model)\r\n}\r\n\r\n/**\r\n * Kind of work item. Absent/undefined ⇒ \"agent_run\" (backward compatible with\r\n * older servers that never send this field). The poller branches on this\r\n * BEFORE touching work.agent — exec / terminal_open items carry no `agent`.\r\n */\r\nexport type WorkItemKind = \"agent_run\" | \"exec\" | \"terminal_open\"\r\n\r\nexport interface WorkItem {\r\n wakeupId: string\r\n runId: string\r\n issueId?: string\r\n prompt: string\r\n workingDir?: string\r\n /**\r\n * Server Terminal/exec dispatch (additive). Absent ⇒ agent_run, where `agent`\r\n * + `prompt` are always present (existing contract). Present for the new\r\n * server-management work kinds, where `agent` is absent.\r\n */\r\n kind?: WorkItemKind\r\n /** exec kind: the command-log row id to report results back against. */\r\n execId?: string\r\n /** exec kind: the shell command to run verbatim (owner/admin-gated upstream). */\r\n command?: string\r\n /** exec kind: working directory for the command. */\r\n cwd?: string\r\n /** exec kind: optional per-command timeout (clamped daemon-side). */\r\n timeoutMs?: number\r\n /** terminal_open kind: the PTY session id (terminal_sessions.id). */\r\n sessionId?: string\r\n /** terminal_open kind: base relay WS URL to dial out to. */\r\n relayWsUrl?: string\r\n /** terminal_open kind: single-use join token (relay redeems it). */\r\n joinToken?: string\r\n /** terminal_open kind: initial PTY dimensions. */\r\n cols?: number\r\n rows?: number\r\n /** terminal_open kind: optional shell override. */\r\n shell?: string\r\n /**\r\n * Present for agent_run. Optional so exec/terminal_open items (no agent) type-\r\n * check; the poller guards on `work.agent` after the kind branch.\r\n */\r\n agent?: {\r\n id: string\r\n name: string\r\n model: string\r\n allowedTools: string[]\r\n maxBudgetUsd: number\r\n localSessionMode: string\r\n /**\r\n * WS1: Runtime for this agent. Optional — absent/undefined defaults to\r\n * \"claude-code\" for backward compatibility with older server versions\r\n * that do not yet send this field. The server-side field must be added\r\n * to /api/bridge/v1/work (FLAG: server-side work payload needs\r\n * agentRuntime field — see FLAG in runWorkItem below).\r\n */\r\n agentRuntime?: string | null\r\n }\r\n}\r\n\r\n// Backward-compatible re-export for callers that previously imported RunReport\r\n// directly from runner.ts.\r\nexport type { RunReport } from \"./report-queue.js\"\r\n\r\n/**\r\n * Parse the JSON output emitted by `claude -p --output-format json`.\r\n * Returns an empty object when the output has no recognisable JSON.\r\n */\r\nfunction parseClaudeOutput(raw: string): {\r\n costUsd?: number\r\n tokensInput?: number\r\n tokensOutput?: number\r\n sessionId?: string\r\n isError?: boolean\r\n resultText?: string\r\n apiErrorStatus?: number\r\n} {\r\n const trimmed = raw.trim()\r\n const lastBrace = trimmed.lastIndexOf(\"}\")\r\n if (lastBrace === -1) return {}\r\n let depth = 0\r\n let start = -1\r\n for (let i = lastBrace; i >= 0; i--) {\r\n if (trimmed[i] === \"}\") depth++\r\n else if (trimmed[i] === \"{\") {\r\n depth--\r\n if (depth === 0) { start = i; break }\r\n }\r\n }\r\n if (start === -1) return {}\r\n try {\r\n const p = JSON.parse(trimmed.slice(start, lastBrace + 1)) as Record<string, unknown>\r\n const r: ReturnType<typeof parseClaudeOutput> = {}\r\n if (typeof p[\"total_cost_usd\"] === \"number\") r.costUsd = p[\"total_cost_usd\"]\r\n if (typeof p[\"session_id\"] === \"string\") r.sessionId = p[\"session_id\"]\r\n if (typeof p[\"is_error\"] === \"boolean\") r.isError = p[\"is_error\"]\r\n if (typeof p[\"result\"] === \"string\") r.resultText = p[\"result\"]\r\n if (typeof p[\"api_error_status\"] === \"number\") r.apiErrorStatus = p[\"api_error_status\"]\r\n const u = p[\"usage\"]\r\n if (u && typeof u === \"object\") {\r\n const uo = u as Record<string, unknown>\r\n if (typeof uo[\"input_tokens\"] === \"number\") r.tokensInput = uo[\"input_tokens\"]\r\n if (typeof uo[\"output_tokens\"] === \"number\") r.tokensOutput = uo[\"output_tokens\"]\r\n }\r\n return r\r\n } catch { return {} }\r\n}\r\n\r\n/**\r\n * Classify a failed run for the cloud crash-loop breaker.\r\n * Rate-limited runs must NOT count toward the breaker (Anthropic is busy).\r\n * Pure — unit tested.\r\n */\r\nexport function classifyFailure(\r\n stderr: string,\r\n resultText: string | undefined,\r\n apiErrorStatus: number | undefined,\r\n): \"rate_limited\" | \"environment\" | \"error\" {\r\n const h = `${stderr}\\n${resultText ?? \"\"}`.toLowerCase()\r\n if (\r\n apiErrorStatus === 429 ||\r\n apiErrorStatus === 529 ||\r\n /rate.?limit|overloaded|too many requests|usage limit|quota|exhausted/.test(h)\r\n ) return \"rate_limited\"\r\n if (/enoent|not recognized|command not found|login|authenticate|credentials|api key/.test(h))\r\n return \"environment\"\r\n return \"error\"\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// WS1: Runtime resolution helpers\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Normalise the agentRuntime field to a canonical runtime string.\r\n * Unknown/missing values default to \"claude-code\" for backward compat.\r\n */\r\nexport function resolveRuntime(agentRuntime: string | null | undefined): \"claude-code\" | \"codex\" | \"hermes\" {\r\n switch (agentRuntime) {\r\n case \"codex\": return \"codex\"\r\n case \"hermes\": return \"hermes\"\r\n default: return \"claude-code\"\r\n }\r\n}\r\n\r\n/**\r\n * Parse the one-shot output emitted by `codex exec`.\r\n * Codex exec with --json flag returns a JSON object. We extract what we can;\r\n * per Cortex research (Addendum C) and plan WS1, codex v1 sessions are\r\n * fresh per run (no --resume equivalent for exec mode).\r\n *\r\n * Expected shape (varies by codex version):\r\n * { result?: string, cost?: number, usage?: {...} }\r\n */\r\nexport function parseCodexOutput(raw: string): {\r\n resultText?: string\r\n costUsd?: number\r\n isError?: boolean\r\n} {\r\n const trimmed = raw.trim()\r\n // Codex --json outputs one JSON object. Find it similarly to parseClaudeOutput.\r\n const lastBrace = trimmed.lastIndexOf(\"}\")\r\n if (lastBrace === -1) return {}\r\n let depth = 0\r\n let start = -1\r\n for (let i = lastBrace; i >= 0; i--) {\r\n if (trimmed[i] === \"}\") depth++\r\n else if (trimmed[i] === \"{\") {\r\n depth--\r\n if (depth === 0) { start = i; break }\r\n }\r\n }\r\n if (start === -1) return {}\r\n try {\r\n const p = JSON.parse(trimmed.slice(start, lastBrace + 1)) as Record<string, unknown>\r\n const r: ReturnType<typeof parseCodexOutput> = {}\r\n if (typeof p[\"result\"] === \"string\") r.resultText = p[\"result\"]\r\n if (typeof p[\"output\"] === \"string\") r.resultText = p[\"output\"]\r\n if (typeof p[\"cost\"] === \"number\") r.costUsd = p[\"cost\"]\r\n if (p[\"error\"] !== undefined) r.isError = true\r\n return r\r\n } catch { return {} }\r\n}\r\n\r\nconst HANDOFF_TIMEOUT_MS = 4 * 60 * 1000\r\n\r\n/** One short turn in the OLD session before rotation: write HANDOFF.md. */\r\nasync function runHandoffTurn(\r\n claude: { cmd: string; shell: boolean },\r\n agentWorkspace: string,\r\n settingsPath: string,\r\n model: string,\r\n oldSessionId: string,\r\n): Promise<void> {\r\n const rawArgs = [\"-p\", \"--output-format\", \"json\", \"--max-turns\", \"6\",\r\n \"--model\", model, \"--settings\", settingsPath, \"--resume\", oldSessionId]\r\n const args = claude.shell ? shellEscapeArgs(rawArgs) : rawArgs\r\n await new Promise<void>((resolve) => {\r\n let child: ReturnType<typeof spawn>\r\n try {\r\n child = spawn(claude.cmd, args, {\r\n cwd: agentWorkspace, env: { ...process.env },\r\n shell: claude.shell, stdio: [\"pipe\", \"ignore\", \"ignore\"],\r\n })\r\n child.stdin?.write(\r\n \"Your session is about to be rotated (context limit). Write or overwrite \" +\r\n \"HANDOFF.md in your workspace root RIGHT NOW: what you were working on, \" +\r\n \"current state, decisions in flight, and the immediate next step. \" +\r\n \"Max 60 lines. Do nothing else.\",\r\n )\r\n child.stdin?.end()\r\n } catch (err) {\r\n logWarn(`Handoff turn failed to spawn: ${err instanceof Error ? err.message : String(err)}`)\r\n resolve(); return\r\n }\r\n const timer = setTimeout(() => {\r\n logWarn(\"Handoff turn timed out — rotating without handoff doc\")\r\n try { child.kill(\"SIGTERM\") } catch { /* ignore */ }\r\n }, HANDOFF_TIMEOUT_MS)\r\n child.on(\"close\", () => { clearTimeout(timer); log(\"Handoff turn complete\"); resolve() })\r\n child.on(\"error\", () => { clearTimeout(timer); resolve() })\r\n })\r\n}\r\n\r\n/**\r\n * Spawn memory-sync.mjs post-run (best-effort local ingest trigger).\r\n * Only called on completed runs. All errors are swallowed.\r\n */\r\nasync function spawnMemorySync(agentWorkspace: string): Promise<void> {\r\n const scriptPath = join(agentWorkspace, \".claude\", \"memory-sync.mjs\")\r\n if (!existsSync(scriptPath)) return\r\n await new Promise<void>((resolve) => {\r\n let child: ReturnType<typeof spawn>\r\n try {\r\n child = spawn(process.execPath, [scriptPath], {\r\n cwd: agentWorkspace, env: { ...process.env },\r\n shell: false, stdio: [\"ignore\", \"ignore\", \"pipe\"],\r\n })\r\n } catch (err) {\r\n logWarn(`Memory sync spawn failed: ${err instanceof Error ? err.message : String(err)}`)\r\n resolve(); return\r\n }\r\n let stderrBuf = \"\"\r\n child.stderr?.on(\"data\", (c: Buffer) => { stderrBuf += c.toString(\"utf-8\") })\r\n const timer = setTimeout(() => {\r\n logWarn(\"Memory sync timed out after 60s — killing\")\r\n try { child.kill(\"SIGTERM\") } catch { /* ignore */ }\r\n }, 60_000)\r\n child.on(\"close\", (code) => {\r\n clearTimeout(timer)\r\n if (code !== 0) logWarn(`Memory sync exited ${String(code)}${stderrBuf ? `: ${stderrBuf.slice(-500)}` : \"\"}`)\r\n resolve()\r\n })\r\n child.on(\"error\", (err) => { clearTimeout(timer); logWarn(`Memory sync error: ${err.message}`); resolve() })\r\n })\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// WS1: Codex spawn\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Spawn config for runtime-aware execution.\r\n * Returns the command, args, whether to use shell, and how to deliver the\r\n * prompt (stdin vs embedded in args).\r\n */\r\ninterface SpawnConfig {\r\n cmd: string\r\n args: string[]\r\n shell: boolean\r\n /** When true, prompt is passed as the last positional arg, not via stdin. */\r\n promptAsArg: boolean\r\n}\r\n\r\n/**\r\n * Build spawn config for the codex runtime.\r\n *\r\n * Codex one-shot: `codex exec --json \"<prompt>\"` (v1 — fresh session per run;\r\n * persistent sessions via codex app-server JSON-RPC are deferred to v2 per\r\n * WS1 plan). --json requests machine-readable output.\r\n *\r\n * FLAG (server-side): /api/bridge/v1/work must include agentRuntime in the\r\n * work payload for the server to route codex agents to this branch. The\r\n * daemon reads the optional field and defaults to claude-code when absent,\r\n * so old servers continue working. New server-side work-dispatch logic needed\r\n * to populate agentRuntime from the agents table.\r\n *\r\n * FLAG (codex skills/~/.codex): codex discovers skills from ~/.codex/skills/.\r\n * Installing per-agent skills there is a host-wide operation that could affect\r\n * other codex users on the same machine. Deferred — would need a per-agent\r\n * skill directory strategy similar to hermes's HERMES_HOME profile isolation.\r\n */\r\nfunction buildCodexSpawnConfig(model: string, allowedTools: string[]): SpawnConfig {\r\n const useShell = process.platform === \"win32\"\r\n // codex exec --json [--model M] — prompt is passed via stdin (codex reads\r\n // from stdin when no positional prompt arg is given, matching the claude -p\r\n // pattern). If stdin is not supported in a future codex version, switch to\r\n // promptAsArg: true.\r\n const rawArgs = [\"exec\", \"--json\"]\r\n if (model && model.trim().length > 0) {\r\n rawArgs.push(\"--model\", model)\r\n }\r\n // codex does not have a --allowedTools flag; tool restriction is via its own\r\n // sandbox/approval policy (set to \"never\" for one-shot runs). Log a note.\r\n if (allowedTools.length > 0) {\r\n log(`codex runtime: --allowedTools [${allowedTools.join(\",\")}] not forwarded (no codex equivalent); use sandbox isolation for tool restriction`)\r\n }\r\n // Apply shell escaping when shell:true so cmd.exe metacharacters in the\r\n // model slug (or any future arg) cannot be injected.\r\n const args = useShell ? shellEscapeArgs(rawArgs) : rawArgs\r\n return { cmd: \"codex\", args, shell: useShell, promptAsArg: false }\r\n}\r\n\r\n/**\r\n * Build spawn config for the hermes runtime.\r\n *\r\n * Hermes one-shot: `hermes -z \"<prompt>\" [--model M] [--provider P]`\r\n * per Addendum C.2. -z = headless, stdout = final answer, exit 0/1/2.\r\n *\r\n * IMPORTANT: -z auto-sets HERMES_YOLO_MODE=1 + HERMES_ACCEPT_HOOKS=1.\r\n * Per Addendum C.3 and Q6 decision: v1 MUST be sandboxed/bridge-jailed.\r\n * The daemon itself does no sandboxing — that is the operator's\r\n * responsibility (documented in the CLI output and workspace).\r\n *\r\n * Per Addendum C.4: hermes reads AGENTS.md natively from cwd (discovery\r\n * order: .hermes.md/HERMES.md → AGENTS.md → CLAUDE.md). We now write\r\n * AGENTS.md alongside CLAUDE.md in agents.ts so hermes agents get identity.\r\n *\r\n * Model/provider injection: hermes -z supports --model and --provider.\r\n * We pass --model when set. Provider defaults to hermes's own config.\r\n *\r\n * FLAG (hermes quota): hermes -z produces no machine-readable token count.\r\n * Usage metering must be done at the provider key level (per-org API key).\r\n * Post-hoc SQLite scrape of ~/.hermes/state.db is possible but deferred.\r\n *\r\n * FLAG (hermes sessions): -z never emits a session_id so resume-from-one-shot\r\n * is not scriptable. Treat hermes one-shot runs as stateless (no --continue).\r\n */\r\nfunction buildHermesSpawnConfig(model: string, allowedTools: string[]): SpawnConfig {\r\n const useShell = process.platform === \"win32\"\r\n // Prompt is delivered via stdin (hermes -z reads from stdin when no\r\n // positional prompt arg is given, per Addendum C.2 / WS1 Phase 2 review).\r\n // This avoids cmd.exe injection — the full promptText MUST NOT appear in\r\n // argv because even with quoting a large multi-line prompt with shell\r\n // metacharacters is an injection and Windows command-line-length risk.\r\n // promptAsArg: false → runner writes prompt to child.stdin instead.\r\n const rawArgs = [\"-z\"]\r\n if (model && model.trim().length > 0) {\r\n rawArgs.push(\"--model\", model)\r\n }\r\n if (allowedTools.length > 0) {\r\n // hermes toolset restriction: comma-separated toolset names.\r\n // We map allowedTools to hermes toolsets on a best-effort basis —\r\n // if the list looks like hermes toolset names, pass them through.\r\n // Otherwise log a note (hermes toolsets differ from Claude tool names).\r\n const hermesToolsets = allowedTools.filter((t) =>\r\n /^(web|terminal|development|safe|memory|messaging|calendar|files|code|search)$/i.test(t),\r\n )\r\n if (hermesToolsets.length > 0) {\r\n rawArgs.push(\"--toolsets\", hermesToolsets.join(\",\"))\r\n } else {\r\n log(`hermes runtime: allowedTools [${allowedTools.join(\",\")}] not in hermes toolset format; skipping --toolsets`)\r\n }\r\n }\r\n // Apply shell escaping when shell:true so cmd.exe metacharacters in model\r\n // slug or toolset names cannot be injected.\r\n const args = useShell ? shellEscapeArgs(rawArgs) : rawArgs\r\n return { cmd: \"hermes\", args, shell: useShell, promptAsArg: false }\r\n}\r\n\r\n/**\r\n * Execute a work item. Returns when the run is complete (or timed out).\r\n * Reports results to the Stride API, with retry + local persistence on failure.\r\n *\r\n * WS1: Branches on work.agent.agentRuntime (or the cached agent's runtime)\r\n * to spawn the appropriate CLI. Defaults to claude-code when absent for\r\n * backward compat with older server versions.\r\n *\r\n * FLAG (server-side): /api/bridge/v1/work needs to include agentRuntime in\r\n * the work payload. The agent's runtime is stored in the agents table\r\n * (agentRuntime column). Until the server sends this field, all work items\r\n * will use claude-code (correct behavior for existing agents).\r\n */\r\nexport async function runWorkItem(config: BridgeConfig, work: WorkItem): Promise<void> {\r\n // Defensive guard: runWorkItem only handles the agent_run kind. The poller\r\n // branches on work.kind BEFORE calling this, so a missing agent here means a\r\n // malformed work item — fail the run cleanly rather than throwing on\r\n // work.agent.id (which previously crashed the single-flight loop).\r\n if (!work.agent) {\r\n logWarn(`Run ${work.runId} has no agent — not an agent_run work item; skipping`)\r\n await sendReport(config, {\r\n runId: work.runId,\r\n wakeupId: work.wakeupId,\r\n status: \"failed\",\r\n failureKind: \"config_error\",\r\n stdoutExcerpt: \"\",\r\n stderrExcerpt: \"\",\r\n error: \"Work item has no agent (wrong kind reached runWorkItem)\",\r\n exitCode: null,\r\n })\r\n return\r\n }\r\n const workAgent = work.agent\r\n const agent = findAgent(workAgent.id)\r\n const model = agent?.model ?? workAgent.model\r\n const agentWorkspace = agentWorkspaceDir(workAgent.id)\r\n\r\n // WS1: Resolve runtime — prefer work payload field (server-provided), then\r\n // fall back to cached agent config, then default to claude-code.\r\n const runtime = resolveRuntime(\r\n workAgent.agentRuntime ?? agent?.agentRuntime,\r\n )\r\n\r\n let cwd = agentWorkspace\r\n if (work.workingDir && existsSync(work.workingDir)) {\r\n cwd = work.workingDir\r\n } else if (work.workingDir) {\r\n logWarn(`workingDir \"${work.workingDir}\" does not exist; falling back to agent workspace`)\r\n }\r\n\r\n log(`Starting run ${work.runId} (agent \"${workAgent.name}\", runtime \"${runtime}\", model \"${model}\")`)\r\n log(` cwd: ${cwd}`)\r\n\r\n // TODO Phase 2: inject ANTHROPIC_API_KEY when authMode === \"org_api_key\".\r\n const env: NodeJS.ProcessEnv = { ...process.env }\r\n\r\n // WS1: For hermes, inject HERMES_HOME per-agent so each agent has isolated\r\n // state (sessions, memory, config). This avoids cross-agent contamination\r\n // when multiple hermes agents run on the same machine.\r\n if (runtime === \"hermes\") {\r\n env[\"HERMES_HOME\"] = join(agentWorkspace, \".hermes\")\r\n }\r\n\r\n // Build final prompt: soul injection gated by cwd for ALL runtimes.\r\n // When cwd === agentWorkspace, AGENTS.md / CLAUDE.md in the workspace is\r\n // auto-discovered by the runtime (codex reads AGENTS.md natively; hermes\r\n // follows AGENTS.md per Addendum C.4 discovery order) — no double-injection.\r\n // When cwd !== agentWorkspace (project-localFolder), soul is injected via\r\n // prompt for all runtimes (cwd !== agentWorkspace gate in prompt.ts).\r\n const promptText = buildPromptText({\r\n workPrompt: work.prompt,\r\n agent,\r\n cwd,\r\n agentWorkspace,\r\n rotated: false,\r\n })\r\n\r\n let stdoutBuf = \"\", stderrBuf = \"\"\r\n let exitCode: number | null = null\r\n let spawnError: string | undefined\r\n\r\n if (runtime === \"claude-code\") {\r\n // ---- Claude Code path (existing logic) --------------------------------\r\n const claude = resolveClaudeCommand()\r\n // Forward slashes survive every launch path (Windows APIs accept them;\r\n // bash-based npm shims EAT backslashes).\r\n const settingsPath = join(agentWorkspace, \".claude\", \"settings.json\").replace(/\\\\/g, \"/\")\r\n const rawArgs = [\"-p\", \"--output-format\", \"json\", \"--max-turns\", \"25\",\r\n \"--model\", model, \"--settings\", settingsPath]\r\n\r\n // --allowedTools: enforce when non-empty (cloud parity with run-operation.ts).\r\n if (Array.isArray(workAgent.allowedTools) && workAgent.allowedTools.length > 0) {\r\n rawArgs.push(\"--allowedTools\", workAgent.allowedTools.join(\",\"))\r\n }\r\n\r\n const persistent = workAgent.localSessionMode === \"persistent\"\r\n let sessionState = loadSessionState(workAgent.id)\r\n let rotated = false\r\n if (persistent) {\r\n if (shouldRotateSession(sessionState, Date.now())) {\r\n if (sessionState.sessionId) {\r\n log(`Rotating session for agent \"${workAgent.name}\" (age/run limit reached)`)\r\n await runHandoffTurn(claude, agentWorkspace, settingsPath, model, sessionState.sessionId)\r\n rotated = true\r\n }\r\n sessionState = { sessionId: null, sessionStartedAt: null, runCount: 0 }\r\n } else if (sessionState.sessionId) {\r\n rawArgs.push(\"--resume\", sessionState.sessionId)\r\n }\r\n }\r\n\r\n // Rebuild prompt with rotation context (only applicable to claude).\r\n const claudePromptText = buildPromptText({\r\n workPrompt: work.prompt, agent, cwd, agentWorkspace, rotated,\r\n })\r\n\r\n const args = claude.shell ? shellEscapeArgs(rawArgs) : rawArgs\r\n\r\n await new Promise<void>((resolve) => {\r\n let child: ReturnType<typeof spawn>\r\n try {\r\n child = spawn(claude.cmd, args, {\r\n cwd, env, shell: claude.shell,\r\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\r\n })\r\n child.stdin?.write(claudePromptText)\r\n child.stdin?.end()\r\n } catch (err: unknown) {\r\n spawnError = err instanceof Error ? err.message : String(err)\r\n resolve(); return\r\n }\r\n const timeoutHandle = setTimeout(() => {\r\n logWarn(`Run ${work.runId} exceeded timeout — sending SIGTERM`)\r\n try { child.kill(\"SIGTERM\") } catch { /* ignore */ }\r\n setTimeout(() => { try { child.kill(\"SIGKILL\") } catch { /* ignore */ } }, 5_000)\r\n }, RUN_TIMEOUT_MS)\r\n child.stdout?.on(\"data\", (c: Buffer) => { stdoutBuf += c.toString(\"utf-8\") })\r\n child.stderr?.on(\"data\", (c: Buffer) => { stderrBuf += c.toString(\"utf-8\") })\r\n child.on(\"close\", (code) => { clearTimeout(timeoutHandle); exitCode = code; resolve() })\r\n child.on(\"error\", (err) => { clearTimeout(timeoutHandle); spawnError = err.message; resolve() })\r\n })\r\n\r\n const stdoutExcerpt = stdoutBuf.length > STDOUT_CAP ? stdoutBuf.slice(-STDOUT_CAP) : stdoutBuf\r\n const stderrExcerpt = stderrBuf.length > STDERR_CAP ? stderrBuf.slice(-STDERR_CAP) : stderrBuf\r\n\r\n const parsed = parseClaudeOutput(stdoutBuf)\r\n const succeeded = spawnError === undefined && exitCode === 0 && parsed.isError !== true\r\n const errorMessage = succeeded ? undefined\r\n : spawnError\r\n ?? (parsed.isError ? parsed.resultText?.slice(0, 1000) : undefined)\r\n ?? (stderrExcerpt.trim() ? stderrExcerpt.trim().slice(-1000) : undefined)\r\n ?? `claude exited with code ${exitCode ?? \"unknown\"}`\r\n const failureKind = succeeded\r\n ? undefined\r\n : classifyFailure(stderrExcerpt, parsed.resultText, parsed.apiErrorStatus)\r\n\r\n const { isError: _ie, resultText: _rt, apiErrorStatus: _aes, ...reportFields } = parsed\r\n const report: RunReport = {\r\n runId: work.runId, wakeupId: work.wakeupId,\r\n status: succeeded ? \"completed\" : \"failed\",\r\n failureKind, stdoutExcerpt, stderrExcerpt,\r\n error: errorMessage, exitCode, ...reportFields,\r\n }\r\n\r\n log(`Run ${work.runId} ${report.status} (exit ${exitCode ?? \"n/a\"}${\r\n parsed.costUsd !== undefined ? `, cost $${parsed.costUsd.toFixed(4)}` : \"\"})`)\r\n\r\n if (persistent && report.status === \"completed\") {\r\n recordRunSession(workAgent.id, parsed.sessionId, sessionState, Date.now())\r\n }\r\n\r\n await sendReport(config, report)\r\n\r\n if (report.status === \"completed\") {\r\n await spawnMemorySync(agentWorkspace)\r\n }\r\n\r\n } else if (runtime === \"codex\") {\r\n // ---- Codex path -------------------------------------------------------\r\n\r\n // Belt: validate model slug before any spawn. An invalid slug (containing\r\n // shell metacharacters or path separators) would be an injection vector on\r\n // shell:true spawns and indicates a corrupted/malicious work payload.\r\n if (!isValidModelSlug(model)) {\r\n logWarn(`Run ${work.runId} aborted — model slug failed validation: \"${model}\"`)\r\n const report: RunReport = {\r\n runId: work.runId, wakeupId: work.wakeupId,\r\n status: \"failed\",\r\n failureKind: \"config_error\",\r\n stdoutExcerpt: \"\",\r\n stderrExcerpt: \"\",\r\n error: `Invalid model slug: \"${model}\" — must match ^[A-Za-z0-9._:+/-]+$`,\r\n exitCode: null,\r\n }\r\n await sendReport(config, report)\r\n return\r\n }\r\n\r\n const spawnCfg = buildCodexSpawnConfig(model, workAgent.allowedTools ?? [])\r\n // promptAsArg is always false for codex (stdin delivery); the arg-array\r\n // branch is kept for future flexibility but never taken currently.\r\n const args = spawnCfg.promptAsArg ? [...spawnCfg.args, promptText] : spawnCfg.args\r\n\r\n await new Promise<void>((resolve) => {\r\n let child: ReturnType<typeof spawn>\r\n try {\r\n child = spawn(spawnCfg.cmd, args, {\r\n cwd, env, shell: spawnCfg.shell,\r\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\r\n })\r\n if (!spawnCfg.promptAsArg) {\r\n child.stdin?.write(promptText)\r\n }\r\n child.stdin?.end()\r\n } catch (err: unknown) {\r\n spawnError = err instanceof Error ? err.message : String(err)\r\n resolve(); return\r\n }\r\n const timeoutHandle = setTimeout(() => {\r\n logWarn(`Run ${work.runId} exceeded timeout — sending SIGTERM`)\r\n try { child.kill(\"SIGTERM\") } catch { /* ignore */ }\r\n setTimeout(() => { try { child.kill(\"SIGKILL\") } catch { /* ignore */ } }, 5_000)\r\n }, RUN_TIMEOUT_MS)\r\n child.stdout?.on(\"data\", (c: Buffer) => { stdoutBuf += c.toString(\"utf-8\") })\r\n child.stderr?.on(\"data\", (c: Buffer) => { stderrBuf += c.toString(\"utf-8\") })\r\n child.on(\"close\", (code) => { clearTimeout(timeoutHandle); exitCode = code; resolve() })\r\n child.on(\"error\", (err) => { clearTimeout(timeoutHandle); spawnError = err.message; resolve() })\r\n })\r\n\r\n const stdoutExcerpt = stdoutBuf.length > STDOUT_CAP ? stdoutBuf.slice(-STDOUT_CAP) : stdoutBuf\r\n const stderrExcerpt = stderrBuf.length > STDERR_CAP ? stderrBuf.slice(-STDERR_CAP) : stderrBuf\r\n\r\n // Try JSON parse first; fall back to treating stdout as plain text answer.\r\n const parsed = parseCodexOutput(stdoutBuf)\r\n const succeeded = spawnError === undefined && exitCode === 0 && parsed.isError !== true\r\n const errorMessage = succeeded ? undefined\r\n : spawnError\r\n ?? (stderrExcerpt.trim() ? stderrExcerpt.trim().slice(-1000) : undefined)\r\n ?? `codex exited with code ${exitCode ?? \"unknown\"}`\r\n const failureKind = succeeded\r\n ? undefined\r\n : classifyFailure(stderrExcerpt, parsed.resultText ?? stdoutBuf.slice(0, 500), undefined)\r\n\r\n const report: RunReport = {\r\n runId: work.runId, wakeupId: work.wakeupId,\r\n status: succeeded ? \"completed\" : \"failed\",\r\n failureKind, stdoutExcerpt, stderrExcerpt,\r\n error: errorMessage, exitCode,\r\n costUsd: parsed.costUsd,\r\n }\r\n\r\n log(`Run ${work.runId} ${report.status} — codex (exit ${exitCode ?? \"n/a\"}${\r\n parsed.costUsd !== undefined ? `, cost $${parsed.costUsd.toFixed(4)}` : \"\"})`)\r\n\r\n await sendReport(config, report)\r\n\r\n if (report.status === \"completed\") {\r\n await spawnMemorySync(agentWorkspace)\r\n }\r\n\r\n } else {\r\n // ---- Hermes path (runtime === \"hermes\") --------------------------------\r\n // Per Addendum C.6 / Q6 decision: hermes -z is forced-YOLO. The operator\r\n // must ensure the agent runs in a sandboxed environment (bridge-jailed).\r\n // The daemon logs this clearly to surface the responsibility.\r\n log(`Hermes runtime: HERMES_YOLO_MODE is forced on by -z — ensure this bridge machine is sandboxed/isolated`)\r\n log(` HERMES_HOME: ${env[\"HERMES_HOME\"] ?? \"(default)\"}`)\r\n\r\n // Belt: validate model slug before any spawn.\r\n if (!isValidModelSlug(model)) {\r\n logWarn(`Run ${work.runId} aborted — model slug failed validation: \"${model}\"`)\r\n const report: RunReport = {\r\n runId: work.runId, wakeupId: work.wakeupId,\r\n status: \"failed\",\r\n failureKind: \"config_error\",\r\n stdoutExcerpt: \"\",\r\n stderrExcerpt: \"\",\r\n error: `Invalid model slug: \"${model}\" — must match ^[A-Za-z0-9._:+/-]+$`,\r\n exitCode: null,\r\n }\r\n await sendReport(config, report)\r\n return\r\n }\r\n\r\n const spawnCfg = buildHermesSpawnConfig(model, workAgent.allowedTools ?? [])\r\n // Prompt is delivered via stdin — promptAsArg is false (see buildHermesSpawnConfig).\r\n // This eliminates the cmd.exe metachar injection risk that existed when the\r\n // full promptText was pushed into argv as the last positional arg.\r\n const args = spawnCfg.args\r\n\r\n await new Promise<void>((resolve) => {\r\n let child: ReturnType<typeof spawn>\r\n try {\r\n child = spawn(spawnCfg.cmd, args, {\r\n cwd, env, shell: spawnCfg.shell,\r\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\r\n })\r\n child.stdin?.write(promptText)\r\n child.stdin?.end()\r\n } catch (err: unknown) {\r\n spawnError = err instanceof Error ? err.message : String(err)\r\n resolve(); return\r\n }\r\n const timeoutHandle = setTimeout(() => {\r\n logWarn(`Run ${work.runId} exceeded timeout — sending SIGTERM`)\r\n try { child.kill(\"SIGTERM\") } catch { /* ignore */ }\r\n setTimeout(() => { try { child.kill(\"SIGKILL\") } catch { /* ignore */ } }, 5_000)\r\n }, RUN_TIMEOUT_MS)\r\n child.stdout?.on(\"data\", (c: Buffer) => { stdoutBuf += c.toString(\"utf-8\") })\r\n child.stderr?.on(\"data\", (c: Buffer) => { stderrBuf += c.toString(\"utf-8\") })\r\n child.on(\"close\", (code) => { clearTimeout(timeoutHandle); exitCode = code; resolve() })\r\n child.on(\"error\", (err) => { clearTimeout(timeoutHandle); spawnError = err.message; resolve() })\r\n })\r\n\r\n const stdoutExcerpt = stdoutBuf.length > STDOUT_CAP ? stdoutBuf.slice(-STDOUT_CAP) : stdoutBuf\r\n const stderrExcerpt = stderrBuf.length > STDERR_CAP ? stderrBuf.slice(-STDERR_CAP) : stderrBuf\r\n\r\n // hermes -z: exit 0 = ok, 1 = agent failed/empty, 2 = usage error.\r\n // stdout is the plain text answer (no JSON from -z per Addendum C.3).\r\n // FLAG: hermes -z produces no token/cost data; metering at provider key level.\r\n const succeeded = spawnError === undefined && exitCode === 0\r\n const errorMessage = succeeded ? undefined\r\n : spawnError\r\n ?? (stderrExcerpt.trim() ? stderrExcerpt.trim().slice(-1000) : undefined)\r\n ?? `hermes exited with code ${exitCode ?? \"unknown\"}`\r\n\r\n // Hermes failureKind: exit 1 from -z can be quota/rate-limit (provider\r\n // error) or agent failure. Classify by stderr content.\r\n const failureKind = succeeded\r\n ? undefined\r\n : classifyFailure(stderrExcerpt, stdoutBuf.slice(0, 500), undefined)\r\n\r\n const report: RunReport = {\r\n runId: work.runId, wakeupId: work.wakeupId,\r\n status: succeeded ? \"completed\" : \"failed\",\r\n failureKind, stdoutExcerpt, stderrExcerpt,\r\n error: errorMessage, exitCode,\r\n // No costUsd / tokensInput / tokensOutput from hermes -z (FLAG above).\r\n }\r\n\r\n log(`Run ${work.runId} ${report.status} — hermes (exit ${exitCode ?? \"n/a\"})`)\r\n\r\n await sendReport(config, report)\r\n\r\n if (report.status === \"completed\") {\r\n await spawnMemorySync(agentWorkspace)\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * POST a run report with retry. Persists to pending-reports.json on exhaustion.\r\n */\r\nasync function sendReport(config: BridgeConfig, report: RunReport): Promise<void> {\r\n const path = `/api/bridge/v1/runs/${report.runId}`\r\n for (let attempt = 1; attempt <= REPORT_RETRY_COUNT; attempt++) {\r\n try {\r\n await post(config, path, report)\r\n log(`Reported run ${report.runId} (attempt ${attempt})`)\r\n removePendingReport(report.runId)\r\n return\r\n } catch (err: unknown) {\r\n logError(`Failed to report run ${report.runId} (attempt ${attempt})`, err)\r\n if (attempt < REPORT_RETRY_COUNT) await sleep(REPORT_RETRY_BASE_MS * Math.pow(2, attempt - 1))\r\n }\r\n }\r\n logWarn(`Persisting failed report for run ${report.runId} to pending-reports.json`)\r\n enqueue({ runId: report.runId, report, attempts: REPORT_RETRY_COUNT, firstFailedAt: new Date().toISOString() })\r\n}\r\n\r\n/**\r\n * Retry pending reports from previous failures (called each poll iteration).\r\n * Delegates dead-letter and attempt-cap logic to report-queue.drain.\r\n */\r\nexport async function retryPendingReports(config: BridgeConfig): Promise<void> {\r\n await drain(async (item: QueuedReport) => {\r\n const path = `/api/bridge/v1/runs/${item.report.runId}`\r\n await post(config, path, item.report)\r\n log(`Reported run ${item.report.runId} (from queue)`)\r\n })\r\n}\r\n\r\nfunction sleep(ms: number): Promise<void> {\r\n return new Promise((resolve) => setTimeout(resolve, ms))\r\n}\r\n","/**\n * exec.ts — Bounded one-shot shell command execution for the daemon exec path.\n *\n * Powers the `kind: 'exec'` work item (Processes/Services/Logs/Actions/Snippets\n * on daemon-backed servers). NOT used for agent runs — those go through\n * runner.ts. This is a deliberately small, self-contained spawner that mirrors\n * runner.ts's STDOUT_CAP / STDERR_CAP / SIGTERM→SIGKILL semantics so the exec\n * audit rows on the server look identical regardless of which path produced\n * them.\n *\n * Security notes:\n * - The command string comes from an owner/admin-gated Next API route and is\n * run verbatim through the host shell — this is the intended behaviour of a\n * server-management console (the operator IS the shell). The daemon does NOT\n * widen privileges: it runs as whatever user launched the bridge.\n * - Output is capped (tail-kept) so a runaway command cannot exhaust memory or\n * the report payload.\n * - We never log the command's stdout/stderr (it can contain secrets/PII).\n */\n\nimport { spawn } from \"node:child_process\"\n\n/** Output caps — identical to runner.ts so server-side audit rows match. */\nexport const STDOUT_CAP = 10_000\nexport const STDERR_CAP = 4_000\n\n/** Default and ceiling timeouts for a single exec (synchronous-feel, ≤30s). */\nexport const DEFAULT_EXEC_TIMEOUT_MS = 30_000\nexport const MAX_EXEC_TIMEOUT_MS = 60_000\n\n/** Grace period between SIGTERM and the SIGKILL escalation. */\nconst KILL_GRACE_MS = 5_000\n\nexport interface ExecOptions {\n /** Working directory. Falls back to the daemon's cwd when omitted/missing. */\n cwd?: string\n /** Wall-clock timeout in ms. Clamped to (0, MAX_EXEC_TIMEOUT_MS]. */\n timeoutMs?: number\n}\n\nexport type ExecStatus = \"completed\" | \"failed\" | \"timeout\"\n\nexport interface ExecResult {\n /** Process exit code; null on signal/timeout/spawn-error. */\n exitCode: number | null\n /** Tail-capped stdout (≤STDOUT_CAP chars). Never logged. */\n stdoutExcerpt: string\n /** Tail-capped stderr (≤STDERR_CAP chars). Never logged. */\n stderrExcerpt: string\n /** completed (exit 0) | failed (non-zero / spawn error) | timeout. */\n status: ExecStatus\n}\n\n/**\n * Clamp a requested timeout into the allowed range. Invalid / absent values\n * fall back to the default. Pure — unit tested.\n */\nexport function resolveExecTimeout(timeoutMs: number | undefined): number {\n if (typeof timeoutMs !== \"number\" || !Number.isFinite(timeoutMs) || timeoutMs <= 0) {\n return DEFAULT_EXEC_TIMEOUT_MS\n }\n return Math.min(timeoutMs, MAX_EXEC_TIMEOUT_MS)\n}\n\n/**\n * Tail-cap a buffer to at most `cap` characters (keep the most recent output,\n * which is where errors and prompts live). Pure — unit tested.\n */\nexport function capExcerpt(buf: string, cap: number): string {\n return buf.length > cap ? buf.slice(-cap) : buf\n}\n\n/**\n * Derive the final {exitCode, status} from a completed/failed/timed-out spawn.\n * Pure — unit tested. Precedence: timeout > spawn-error > exit-code.\n */\nexport function classifyExec(opts: {\n exitCode: number | null\n spawnError: string | undefined\n timedOut: boolean\n}): { exitCode: number | null; status: ExecStatus } {\n if (opts.timedOut) return { exitCode: opts.exitCode, status: \"timeout\" }\n if (opts.spawnError !== undefined) return { exitCode: opts.exitCode, status: \"failed\" }\n if (opts.exitCode === 0) return { exitCode: 0, status: \"completed\" }\n return { exitCode: opts.exitCode, status: \"failed\" }\n}\n\n/**\n * Resolve the shell + args used to run a command string verbatim.\n * cmd.exe on Windows, /bin/sh -c elsewhere. Pure — unit tested.\n */\nexport function resolveExecShell(command: string): { cmd: string; args: string[]; shell: boolean } {\n if (process.platform === \"win32\") {\n // cmd.exe /d (no AutoRun) /s /c \"<command>\" — /s + surrounding quotes keep\n // the whole command intact even when it contains its own quotes.\n return { cmd: process.env[\"ComSpec\"] ?? \"cmd.exe\", args: [\"/d\", \"/s\", \"/c\", command], shell: false }\n }\n const sh = process.env[\"SHELL\"] ?? \"/bin/sh\"\n return { cmd: sh, args: [\"-c\", command], shell: false }\n}\n\n/**\n * Run a shell command with a hard timeout and capped output.\n *\n * Resolves (never rejects) with an ExecResult so the caller's reporting logic\n * stays linear. A spawn failure (e.g. shell missing) → status \"failed\" with the\n * error text in stderrExcerpt. A timeout → SIGTERM, then SIGKILL after a grace\n * period → status \"timeout\".\n */\nexport async function execShellCommand(command: string, options: ExecOptions = {}): Promise<ExecResult> {\n const timeoutMs = resolveExecTimeout(options.timeoutMs)\n const { cmd, args, shell } = resolveExecShell(command)\n\n // cwd: only pass through when it exists; node throws synchronously on a\n // non-existent cwd, which we map to a clean \"failed\" result.\n const spawnCwd = options.cwd && options.cwd.length > 0 ? options.cwd : undefined\n\n let stdoutBuf = \"\"\n let stderrBuf = \"\"\n let exitCode: number | null = null\n let spawnError: string | undefined\n let timedOut = false\n\n await new Promise<void>((resolve) => {\n let child: ReturnType<typeof spawn>\n try {\n child = spawn(cmd, args, {\n cwd: spawnCwd,\n env: { ...process.env },\n shell,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n windowsHide: true,\n })\n } catch (err: unknown) {\n spawnError = err instanceof Error ? err.message : String(err)\n resolve()\n return\n }\n\n const timeoutHandle = setTimeout(() => {\n timedOut = true\n try {\n child.kill(\"SIGTERM\")\n } catch {\n /* ignore */\n }\n setTimeout(() => {\n try {\n child.kill(\"SIGKILL\")\n } catch {\n /* ignore */\n }\n }, KILL_GRACE_MS)\n }, timeoutMs)\n\n child.stdout?.on(\"data\", (c: Buffer) => {\n stdoutBuf += c.toString(\"utf-8\")\n })\n child.stderr?.on(\"data\", (c: Buffer) => {\n stderrBuf += c.toString(\"utf-8\")\n })\n child.on(\"close\", (code) => {\n clearTimeout(timeoutHandle)\n exitCode = code\n resolve()\n })\n child.on(\"error\", (err) => {\n clearTimeout(timeoutHandle)\n spawnError = err.message\n resolve()\n })\n })\n\n const stdoutExcerpt = capExcerpt(stdoutBuf, STDOUT_CAP)\n // On a spawn error there is no child stderr; surface the error text instead so\n // the operator sees why nothing ran.\n const stderrSource = spawnError !== undefined && stderrBuf.length === 0 ? spawnError : stderrBuf\n const stderrExcerpt = capExcerpt(stderrSource, STDERR_CAP)\n\n const { exitCode: finalExit, status } = classifyExec({ exitCode, spawnError, timedOut })\n\n return { exitCode: finalExit, stdoutExcerpt, stderrExcerpt, status }\n}\n","/**\n * terminal-pty.ts — Daemon-side interactive PTY session that DIALS OUT.\n *\n * Adapted from packages/agent-bridge/src/terminal-server.ts (the superseded\n * v0.1.2 daemon's localhost-bound, zero-auth PTY server). The WS frame protocol\n * is reused verbatim (input/output/resize/exit + ready/error/ping/pong), but the\n * transport is inverted: instead of the daemon LISTENING on a LAN port, it\n * CONNECTS OUT to the authenticated Fly relay\n * (`<relayWsUrl>/daemon?token=<joinToken>`). This works behind NAT and never\n * exposes a local port.\n *\n * The relay validates the joinToken (redeeming it against Next) before pairing\n * this socket with the waiting browser. The joinToken travels in the URL query\n * param; we ALSO send a first `{type:'auth', joinToken, sessionId}` frame so the\n * relay can locate the PARKED ROOM by sessionId and verify the token→sessionId\n * binding via redeem. Spec §2 amended (was browser-only): the relay's handleDaemon\n * parses THIS daemon-shaped frame explicitly (parseDaemonAuthFrame), consumes it,\n * and never forwards it to the browser. M1 and M2 are aligned on this exact frame.\n *\n * node-pty is loaded lazily via require() because it has native bindings that\n * may be absent on a freshly-installed daemon. If the load fails we send a\n * single `{type:'error'}` + a `{type:'output'}` notice explaining that only the\n * non-interactive exec path is available, then close — we never crash the\n * daemon.\n */\n\nimport os from \"node:os\"\nimport { existsSync } from \"node:fs\"\nimport type { WebSocket as WsWebSocket } from \"ws\"\nimport { log, logWarn } from \"./log.js\"\n\n/** Minimal structural type for the node-pty process we use (avoids a hard dep). */\ninterface PtyProcess {\n onData(cb: (data: string) => void): void\n onExit(cb: (e: { exitCode: number }) => void): void\n write(data: string): void\n resize(cols: number, rows: number): void\n kill(): void\n}\n\ninterface NodePtyModule {\n spawn(\n file: string,\n args: string[] | string,\n options: {\n name?: string\n cols?: number\n rows?: number\n cwd?: string\n env?: Record<string, string>\n },\n ): PtyProcess\n}\n\nexport interface OpenTerminalOptions {\n /** Base relay URL, e.g. wss://stride-terminal-relay.fly.dev */\n relayWsUrl: string\n /** Single-use join token minted by Next, redeemed by the relay. */\n joinToken: string\n /** The terminal session id (workforce_server_terminal_sessions.id). */\n sessionId: string\n cols?: number\n rows?: number\n /** Override shell; defaults to the platform interactive shell. */\n shell?: string\n /** Working directory; falls back to the user's home dir. */\n cwd?: string\n /**\n * Invoked exactly once when the session ends for ANY reason (shell exit, relay\n * socket close, ws error, or handle.close()). The poller uses this to drop the\n * session from its concurrency map — WITHOUT it, sessions that end on their own\n * (the normal case) leak a map slot forever and eventually wedge the cap.\n */\n onClosed?: (sessionId: string) => void\n}\n\nconst DEFAULT_COLS = 120\nconst DEFAULT_ROWS = 30\n\n/** Frames the daemon emits toward the relay (→ browser). Frozen contract §2. */\ntype OutFrame =\n | { type: \"ready\" }\n | { type: \"output\"; data: string }\n | { type: \"exit\"; code: number }\n | { type: \"error\"; message: string }\n | { type: \"pong\" }\n | { type: \"auth\"; joinToken: string; sessionId: string }\n\n/** Frames the daemon accepts from the relay (← browser). Frozen contract §2. */\ninterface InFrame {\n type: string\n data?: string\n cols?: number\n rows?: number\n}\n\n/**\n * Lazily load node-pty. Returns null when the native module is unavailable\n * (uninstalled, wrong ABI, build failure) — caller falls back to exec-only.\n */\nexport function loadNodePty(): NodePtyModule | null {\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n return require(\"node-pty\") as NodePtyModule\n } catch (err: unknown) {\n logWarn(`node-pty unavailable: ${err instanceof Error ? err.message : String(err)}`)\n return null\n }\n}\n\n/**\n * Resolve the interactive shell + args for the host platform. Pure (modulo\n * filesystem probe on Windows). Mirrors the agent-bridge selection: Git Bash →\n * PowerShell on Windows, $SHELL → /bin/bash elsewhere.\n */\nexport function resolveShell(override?: string): { shell: string; args: string[] } {\n if (override && override.length > 0) {\n return { shell: override, args: os.platform() === \"win32\" ? [] : [\"--login\"] }\n }\n if (os.platform() === \"win32\") {\n const gitBashPaths = [\n \"C:\\\\Program Files\\\\Git\\\\bin\\\\bash.exe\",\n \"C:\\\\Program Files (x86)\\\\Git\\\\bin\\\\bash.exe\",\n ]\n const bashPath = gitBashPaths.find((p) => existsSync(p))\n if (bashPath) return { shell: bashPath, args: [\"--login\", \"-i\"] }\n return { shell: \"powershell.exe\", args: [\"-NoLogo\"] }\n }\n return { shell: process.env[\"SHELL\"] ?? \"/bin/bash\", args: [\"--login\"] }\n}\n\n/**\n * Build the daemon-join WS URL. joinToken goes in the query param (relay reads\n * it there) AND is re-sent in the first frame (frozen contract: body too). Pure.\n */\nexport function buildDaemonJoinUrl(relayWsUrl: string, joinToken: string): string {\n const base = relayWsUrl.replace(/\\/+$/, \"\")\n return `${base}/daemon?token=${encodeURIComponent(joinToken)}`\n}\n\n/**\n * Handle to an open (or opening) terminal session so the poller can kill it on\n * shutdown. close() is idempotent.\n */\nexport interface TerminalSessionHandle {\n sessionId: string\n close(): void\n}\n\n/**\n * Open a daemon-side terminal session: dial the relay, spawn a PTY, and forward\n * frames in both directions. Resolves once the socket is established (or failed)\n * — the session itself runs detached until the PTY exits or the socket closes.\n *\n * The poller dispatches this DETACHED (not awaited in the single-flight loop)\n * and must NOT set activeRunAgentId for it.\n */\nexport async function openTerminalSession(\n opts: OpenTerminalOptions,\n): Promise<TerminalSessionHandle> {\n const { WebSocket } = await import(\"ws\")\n const url = buildDaemonJoinUrl(opts.relayWsUrl, opts.joinToken)\n const cols = opts.cols && opts.cols > 0 ? opts.cols : DEFAULT_COLS\n const rows = opts.rows && opts.rows > 0 ? opts.rows : DEFAULT_ROWS\n\n const ws: WsWebSocket = new WebSocket(url)\n let pty: PtyProcess | null = null\n let closed = false\n\n const send = (frame: OutFrame): void => {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify(frame))\n }\n }\n\n const cleanup = (reason: string): void => {\n if (closed) return\n closed = true\n if (pty) {\n try {\n pty.kill()\n } catch {\n /* ignore */\n }\n pty = null\n }\n try {\n ws.close()\n } catch {\n /* ignore */\n }\n log(`[terminal] session ${opts.sessionId} closed (${reason})`)\n // Notify the owner (poller) so it can drop its concurrency-map entry. This\n // is the ONLY removal path for self-terminating sessions (shell exit / relay\n // drop / network blip) — without it the cap leaks one slot per session.\n if (opts.onClosed) {\n try {\n opts.onClosed(opts.sessionId)\n } catch {\n /* ignore — teardown must never throw */\n }\n }\n }\n\n const handle: TerminalSessionHandle = {\n sessionId: opts.sessionId,\n close: () => cleanup(\"handle.close\"),\n }\n\n ws.on(\"open\", () => {\n // First frame: announce sessionId so the relay can locate the parked room +\n // verify the token→sessionId binding. Relay consumes this and does NOT\n // forward it to the browser (spec §2; relay parseDaemonAuthFrame).\n send({ type: \"auth\", joinToken: opts.joinToken, sessionId: opts.sessionId })\n\n const nodePty = loadNodePty()\n if (!nodePty) {\n send({\n type: \"output\",\n data:\n \"\\r\\n[stride-bridge] Interactive terminal unavailable on this machine: \" +\n \"node-pty is not installed. Non-interactive commands (Processes, \" +\n \"Services, Logs, Actions, Snippets) still work.\\r\\n\",\n })\n send({ type: \"error\", message: \"node-pty unavailable on daemon host\" })\n cleanup(\"node-pty unavailable\")\n return\n }\n\n const { shell, args } = resolveShell(opts.shell)\n try {\n pty = nodePty.spawn(shell, args, {\n name: \"xterm-256color\",\n cols,\n rows,\n cwd: opts.cwd && opts.cwd.length > 0 ? opts.cwd : os.homedir(),\n env: process.env as Record<string, string>,\n })\n } catch (err: unknown) {\n send({\n type: \"error\",\n message: `Failed to spawn shell: ${err instanceof Error ? err.message : String(err)}`,\n })\n cleanup(\"pty spawn failed\")\n return\n }\n\n pty.onData((data: string) => {\n send({ type: \"output\", data })\n })\n pty.onExit(({ exitCode }: { exitCode: number }) => {\n send({ type: \"exit\", code: exitCode })\n cleanup(`pty exit ${exitCode}`)\n })\n\n // PTY is attached and forwarding — tell the relay/browser we are live.\n send({ type: \"ready\" })\n log(`[terminal] session ${opts.sessionId} ready (${shell})`)\n })\n\n ws.on(\"message\", (raw: Buffer | ArrayBuffer | Buffer[]) => {\n const text = Buffer.isBuffer(raw)\n ? raw.toString(\"utf-8\")\n : Array.isArray(raw)\n ? Buffer.concat(raw).toString(\"utf-8\")\n : Buffer.from(raw).toString(\"utf-8\")\n let frame: InFrame\n try {\n frame = JSON.parse(text) as InFrame\n } catch {\n // Tolerate raw input (parity with agent-bridge) — treat as keystrokes.\n if (pty) pty.write(text)\n return\n }\n if (frame.type === \"input\" && typeof frame.data === \"string\") {\n if (pty) pty.write(frame.data)\n } else if (\n frame.type === \"resize\" &&\n typeof frame.cols === \"number\" &&\n typeof frame.rows === \"number\"\n ) {\n if (pty) {\n try {\n pty.resize(frame.cols, frame.rows)\n } catch {\n /* ignore invalid dimensions */\n }\n }\n } else if (frame.type === \"ping\") {\n send({ type: \"pong\" })\n }\n })\n\n ws.on(\"close\", () => cleanup(\"ws close\"))\n ws.on(\"error\", (err: Error) => {\n logWarn(`[terminal] session ${opts.sessionId} ws error: ${err.message}`)\n cleanup(\"ws error\")\n })\n\n return handle\n}\n","/**\n * quota.ts — Claude subscription quota snapshot (Phase 2).\n *\n * In claude_login mode the daemon runs on the customer's Claude Code OAuth\n * session, which is rate-limited in 5-hour and 7-day windows. We read the\n * OAuth token from ~/.claude/.credentials.json and query Anthropic's usage\n * endpoint, reporting \"% remaining\" in heartbeats so the dashboard can show\n * a capacity chip per bridge. Pattern ported from cortex-os dashboard\n * lib/quota.ts (MIT).\n *\n * Everything here is fail-soft: no credentials / API errors → null quota.\n */\n\nimport { join } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport { readJsonSafe } from \"./state.js\"\nimport { logWarn } from \"./log.js\"\n\nexport interface QuotaSnapshot {\n fiveHourRemainingPct: number | null\n sevenDayRemainingPct: number | null\n fetchedAt: string\n}\n\ninterface OauthUsageResponse {\n five_hour?: { utilization?: number }\n seven_day?: { utilization?: number }\n}\n\nconst USAGE_URL = \"https://api.anthropic.com/api/oauth/usage\"\nconst CACHE_TTL_MS = 60_000\nconst FETCH_TIMEOUT_MS = 5_000\n\n/**\n * Pure: utilization → whole-number percent remaining, clamped.\n * The OAuth usage API returns utilization as a PERCENT (e.g. 23.0 = 23% used),\n * verified against the live endpoint 2026-06-12 — treating it as a 0-1\n * fraction produced the \"0% Claude left\" bug.\n */\nexport function remainingPct(utilization: unknown): number | null {\n if (typeof utilization !== \"number\" || !Number.isFinite(utilization)) return null\n return Math.max(0, Math.min(100, Math.round(100 - utilization)))\n}\n\n/** Pure: map the usage API response to a snapshot. */\nexport function parseUsageResponse(body: OauthUsageResponse, nowIso: string): QuotaSnapshot {\n return {\n fiveHourRemainingPct: remainingPct(body.five_hour?.utilization),\n sevenDayRemainingPct: remainingPct(body.seven_day?.utilization),\n fetchedAt: nowIso,\n }\n}\n\nfunction readOauthToken(): string | null {\n if (process.env.CLAUDE_CODE_OAUTH_TOKEN) return process.env.CLAUDE_CODE_OAUTH_TOKEN\n const creds = readJsonSafe<{ claudeAiOauth?: { accessToken?: string } }>(\n join(homedir(), \".claude\", \".credentials.json\"),\n )\n return creds?.claudeAiOauth?.accessToken ?? null\n}\n\nlet cached: { snapshot: QuotaSnapshot; at: number } | null = null\nlet warnedNoToken = false\n\n/**\n * Fetch the current quota snapshot, cached for 60s. Returns null when no\n * OAuth token is available (org_api_key mode, or Claude not logged in).\n */\nexport async function getQuotaSnapshot(): Promise<QuotaSnapshot | null> {\n if (cached && Date.now() - cached.at < CACHE_TTL_MS) return cached.snapshot\n\n const token = readOauthToken()\n if (!token) {\n if (!warnedNoToken) {\n logWarn(\"No Claude OAuth token found — quota reporting disabled\")\n warnedNoToken = true\n }\n return null\n }\n\n try {\n const controller = new AbortController()\n const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS)\n const res = await fetch(USAGE_URL, {\n headers: { Authorization: `Bearer ${token}` },\n signal: controller.signal,\n })\n clearTimeout(timer)\n if (!res.ok) return cached?.snapshot ?? null\n\n const body = (await res.json()) as OauthUsageResponse\n const snapshot = parseUsageResponse(body, new Date().toISOString())\n cached = { snapshot, at: Date.now() }\n return snapshot\n } catch {\n // Stale-but-present beats nothing; otherwise null.\n return cached?.snapshot ?? null\n }\n}\n","/**\n * metrics.ts — Host metrics sampler for the daemon heartbeat.\n *\n * Collected once per heartbeat (60s) and sent as `hostMetrics` so the\n * dashboard's Servers page can chart CPU/memory/disk/network without any\n * inbound connection to the machine (PRPs/VpsFleetManagement.md Phase 1).\n *\n * Linux-first (VPSs): /proc/meminfo and /proc/net/dev when available, with\n * portable fallbacks (node:os, fs.statfs) for macOS/Windows bridges. Every\n * reading is best-effort — a missing source omits the field rather than\n * failing the heartbeat. CPU and network are deltas between heartbeats, so\n * the first sample after startup omits them.\n */\n\nimport { cpus, loadavg, totalmem, freemem, platform } from \"node:os\"\nimport { readFile, statfs } from \"node:fs/promises\"\n\nexport interface HostMetrics {\n /** Aggregate CPU busy % since the previous sample (0-100). */\n cpuPct?: number\n /** 1-minute load average (0 on Windows). */\n load1?: number\n memUsedMb?: number\n memTotalMb?: number\n diskUsedGb?: number\n diskTotalGb?: number\n /** Kilobytes/second received since the previous sample (all non-lo NICs). */\n netRxKbps?: number\n /** Kilobytes/second transmitted since the previous sample. */\n netTxKbps?: number\n}\n\n// ─── CPU (delta between samples) ─────────────────────────────────────────────\n\ninterface CpuTotals {\n idle: number\n total: number\n}\n\nexport function readCpuTotals(): CpuTotals {\n let idle = 0\n let total = 0\n for (const cpu of cpus()) {\n idle += cpu.times.idle\n total += cpu.times.user + cpu.times.nice + cpu.times.sys + cpu.times.idle + cpu.times.irq\n }\n return { idle, total }\n}\n\n/** Busy % between two cumulative samples; undefined when no time elapsed. */\nexport function computeCpuPct(prev: CpuTotals, curr: CpuTotals): number | undefined {\n const dTotal = curr.total - prev.total\n if (dTotal <= 0) return undefined\n const dIdle = curr.idle - prev.idle\n const pct = 100 * (1 - dIdle / dTotal)\n return Math.round(Math.min(100, Math.max(0, pct)) * 10) / 10\n}\n\n// ─── Memory ──────────────────────────────────────────────────────────────────\n\n/** Parses /proc/meminfo. MemAvailable is the honest \"free\" on Linux. */\nexport function parseMeminfo(content: string): { memUsedMb: number; memTotalMb: number } | undefined {\n const totalMatch = content.match(/MemTotal:\\s+(\\d+)\\s*kB/)\n const availMatch = content.match(/MemAvailable:\\s+(\\d+)\\s*kB/)\n if (!totalMatch || !availMatch) return undefined\n const totalMb = Math.round(Number(totalMatch[1]) / 1024)\n const availMb = Math.round(Number(availMatch[1]) / 1024)\n return { memUsedMb: totalMb - availMb, memTotalMb: totalMb }\n}\n\n// ─── Network (delta between samples) ─────────────────────────────────────────\n\ninterface NetTotals {\n rxBytes: number\n txBytes: number\n at: number\n}\n\n/** Sums rx/tx bytes across all non-loopback interfaces in /proc/net/dev. */\nexport function parseNetDev(content: string): { rxBytes: number; txBytes: number } {\n let rxBytes = 0\n let txBytes = 0\n for (const line of content.split(\"\\n\")) {\n const match = line.match(/^\\s*([^:\\s]+):\\s*(\\d+)(?:\\s+\\d+){7}\\s+(\\d+)/)\n if (!match || match[1] === \"lo\") continue\n rxBytes += Number(match[2])\n txBytes += Number(match[3])\n }\n return { rxBytes, txBytes }\n}\n\nexport function computeNetKbps(\n prev: NetTotals,\n curr: NetTotals,\n): { netRxKbps: number; netTxKbps: number } | undefined {\n const seconds = (curr.at - prev.at) / 1000\n if (seconds <= 0) return undefined\n const rx = (curr.rxBytes - prev.rxBytes) / 1024 / seconds\n const tx = (curr.txBytes - prev.txBytes) / 1024 / seconds\n if (rx < 0 || tx < 0) return undefined // counters reset (reboot/overflow)\n return { netRxKbps: Math.round(rx * 10) / 10, netTxKbps: Math.round(tx * 10) / 10 }\n}\n\n// ─── Collector ───────────────────────────────────────────────────────────────\n\nlet prevCpu: CpuTotals | null = null\nlet prevNet: NetTotals | null = null\n\n/** Resets delta state (tests only). */\nexport function resetMetricsState(): void {\n prevCpu = null\n prevNet = null\n}\n\nexport async function collectHostMetrics(): Promise<HostMetrics> {\n const metrics: HostMetrics = {}\n\n // CPU\n try {\n const curr = readCpuTotals()\n if (prevCpu) {\n const pct = computeCpuPct(prevCpu, curr)\n if (pct !== undefined) metrics.cpuPct = pct\n }\n prevCpu = curr\n } catch {\n // omit\n }\n\n // Load\n try {\n const load = loadavg()[0]\n if (Number.isFinite(load)) metrics.load1 = Math.round(load * 100) / 100\n } catch {\n // omit\n }\n\n // Memory — /proc/meminfo when available, node:os fallback elsewhere.\n try {\n const meminfo = parseMeminfo(await readFile(\"/proc/meminfo\", \"utf8\"))\n if (meminfo) Object.assign(metrics, meminfo)\n } catch {\n const totalMb = Math.round(totalmem() / 1024 / 1024)\n metrics.memTotalMb = totalMb\n metrics.memUsedMb = totalMb - Math.round(freemem() / 1024 / 1024)\n }\n\n // Disk (root volume)\n try {\n const root = platform() === \"win32\" ? \"C:\\\\\" : \"/\"\n const stats = await statfs(root)\n const totalGb = (stats.blocks * stats.bsize) / 1024 ** 3\n const freeGb = (stats.bfree * stats.bsize) / 1024 ** 3\n metrics.diskTotalGb = Math.round(totalGb * 10) / 10\n metrics.diskUsedGb = Math.round((totalGb - freeGb) * 10) / 10\n } catch {\n // omit\n }\n\n // Network — Linux only.\n try {\n const parsed = parseNetDev(await readFile(\"/proc/net/dev\", \"utf8\"))\n const curr: NetTotals = { ...parsed, at: Date.now() }\n if (prevNet) {\n const kbps = computeNetKbps(prevNet, curr)\n if (kbps) Object.assign(metrics, kbps)\n }\n prevNet = curr\n } catch {\n // omit\n }\n\n return metrics\n}\n","/**\r\n * poller.ts — Main daemon loop for `stride-bridge start`.\r\n *\r\n * Polls /api/bridge/v1/work every 2.5 seconds.\r\n * Handles one work item at a time (single-flight Phase 1).\r\n * Sends heartbeat every 60 seconds independently.\r\n * Exponential backoff on fetch errors: 2.5s → 5 → 10 → 30s cap.\r\n * Posts daemon_started on startup and daemon_stopping on SIGINT/SIGTERM.\r\n */\r\n\r\nimport { platform, release } from \"node:os\"\r\nimport { post, postBestEffort } from \"./api.js\"\r\nimport type { BridgeConfig } from \"./config.js\"\r\nimport {\r\n refreshAgents,\r\n startAgentRefreshTimer,\r\n stopAgentRefreshTimer,\r\n getCachedAgents,\r\n} from \"./agents.js\"\r\nimport { runWorkItem, retryPendingReports } from \"./runner.js\"\r\nimport type { WorkItem, WorkItemKind } from \"./runner.js\"\r\nimport { execShellCommand } from \"./exec.js\"\r\nimport { openTerminalSession } from \"./terminal-pty.js\"\r\nimport type { TerminalSessionHandle } from \"./terminal-pty.js\"\r\nimport { getQuotaSnapshot } from \"./quota.js\"\r\nimport type { QuotaSnapshot } from \"./quota.js\"\r\nimport { detectRuntimes } from \"./detect-runtimes.js\"\r\nimport type { RuntimeCapability } from \"./detect-runtimes.js\"\r\nimport { collectHostMetrics } from \"./metrics.js\"\r\nimport type { HostMetrics } from \"./metrics.js\"\r\nimport { VERSION } from \"./version.js\"\r\nimport { log, logError, logWarn } from \"./log.js\"\r\n\r\nconst POLL_INTERVAL_MS = 2_500\r\nconst HEARTBEAT_INTERVAL_MS = 60_000\r\nconst BACKOFF_STEPS_MS = [2_500, 5_000, 10_000, 30_000]\r\n\r\ninterface WorkResponse {\r\n work: WorkItem | null\r\n}\r\n\r\n/** Per-agent session entry sent to the heartbeat endpoint. */\r\nexport interface AgentSession {\r\n agentId: string\r\n status: \"idle\" | \"running\"\r\n currentTask?: string\r\n}\r\n\r\n/** The event payload shape accepted by /api/bridge/v1/events. */\r\nexport interface EventPayload {\r\n kind: string\r\n message: string\r\n agentId?: string\r\n details?: Record<string, unknown>\r\n}\r\n\r\n/** The heartbeat payload shape accepted by /api/bridge/v1/heartbeat. */\r\nexport interface HeartbeatPayload {\r\n daemonVersion: string\r\n osInfo: { platform: string; release: string }\r\n agents: AgentSession[]\r\n quota?: QuotaSnapshot\r\n /**\r\n * WS1: Detected CLI capabilities on this bridge machine.\r\n * Optional for backward compat — old server versions ignore the field.\r\n * Only runtimes with a non-empty version string are included in the array\r\n * that is sent; the full probe list (including absent runtimes) is\r\n * available from detectRuntimes() if callers need it.\r\n *\r\n * NOTE: the server's HeartbeatPayloadSchema names this field `capabilities`\r\n * (stored in machineInfo.capabilities). It was previously sent as\r\n * `runtimes`, which Zod silently stripped — so detection never reached the\r\n * dashboard. Field renamed to match the server (fixed with VPS P1).\r\n */\r\n capabilities?: RuntimeCapability[]\r\n /**\r\n * Host metrics sample (CPU/mem/disk/net) for the Servers page. Optional —\r\n * old server versions strip it; collection failures omit fields.\r\n */\r\n hostMetrics?: HostMetrics\r\n}\r\n\r\n/**\r\n * Module-level state tracking the agent currently executing a run.\r\n * Single-flight loop means at most one agent is running at any time.\r\n */\r\nlet activeRunAgentId: string | null = null\r\nlet activeRunTask: string | undefined = undefined\r\n\r\n/**\r\n * Live terminal PTY sessions, keyed by sessionId. Dispatched DETACHED from the\r\n * single-flight poll loop (interactive sessions are long-lived and must not\r\n * block agent work). Killed on shutdown. A small concurrency cap protects the\r\n * host from runaway session counts.\r\n */\r\nconst activeTerminalSessions = new Map<string, TerminalSessionHandle>()\r\nconst MAX_CONCURRENT_TERMINALS = 8\r\n\r\n/** Test-only accessors for the concurrency map (no production caller). */\r\nexport function getActiveTerminalSessionCount(): number {\r\n return activeTerminalSessions.size\r\n}\r\n/** Test-only: close a reserved/active session via its tracked handle. */\r\nexport function closeActiveTerminalSessionForTest(sessionId: string): void {\r\n activeTerminalSessions.get(sessionId)?.close()\r\n}\r\n/** Test-only: clear the map between tests. */\r\nexport function resetActiveTerminalSessionsForTest(): void {\r\n activeTerminalSessions.clear()\r\n}\r\n\r\n/** Result payload reported to /api/bridge/v1/exec/{execId} (frozen contract). */\r\nexport interface ExecReportPayload {\r\n execId: string\r\n status: \"completed\" | \"failed\" | \"timeout\"\r\n exitCode: number | null\r\n stdoutExcerpt: string\r\n stderrExcerpt: string\r\n}\r\n\r\n/**\r\n * Determine the work item kind. Absent/unknown ⇒ \"agent_run\" for backward\r\n * compatibility with older servers that never send a `kind`. Pure — unit tested.\r\n */\r\nexport function classifyWorkItem(work: WorkItem): WorkItemKind {\r\n switch (work.kind) {\r\n case \"exec\":\r\n return \"exec\"\r\n case \"terminal_open\":\r\n return \"terminal_open\"\r\n default:\r\n return \"agent_run\"\r\n }\r\n}\r\n\r\n/**\r\n * Run an exec work item: spawn the command, then report the bounded result to\r\n * /api/bridge/v1/exec/{execId}. Never throws — reporting failures are logged\r\n * (the server's bounded poll will time the row out). Does NOT set\r\n * activeRunAgentId (exec is not an agent run).\r\n */\r\nexport async function handleExecWork(config: BridgeConfig, work: WorkItem): Promise<void> {\r\n if (!work.execId || typeof work.command !== \"string\") {\r\n logWarn(`exec work item missing execId/command (run ${work.runId}); ignoring`)\r\n return\r\n }\r\n const execId = work.execId\r\n log(`Running exec ${execId}`)\r\n const result = await execShellCommand(work.command, {\r\n cwd: work.cwd,\r\n timeoutMs: work.timeoutMs,\r\n })\r\n const payload: ExecReportPayload = {\r\n execId,\r\n status: result.status,\r\n exitCode: result.exitCode,\r\n stdoutExcerpt: result.stdoutExcerpt,\r\n stderrExcerpt: result.stderrExcerpt,\r\n }\r\n try {\r\n await post(config, `/api/bridge/v1/exec/${execId}`, payload)\r\n log(`Reported exec ${execId} (${result.status})`)\r\n } catch (err: unknown) {\r\n logError(`Failed to report exec ${execId}`, err)\r\n }\r\n}\r\n\r\n/**\r\n * Dispatch a terminal_open work item DETACHED (fire-and-forget). The session\r\n * runs until the PTY exits or the relay socket closes; the handle is tracked so\r\n * shutdown can kill it. Enforces a concurrency cap. Never throws.\r\n */\r\nexport function dispatchTerminalWork(work: WorkItem): void {\r\n if (!work.sessionId || !work.relayWsUrl || !work.joinToken) {\r\n logWarn(`terminal_open work item missing sessionId/relayWsUrl/joinToken (run ${work.runId}); ignoring`)\r\n return\r\n }\r\n const sessionId = work.sessionId\r\n // Atomic slot reservation (fixes the TOCTOU race + the self-terminating-session\r\n // leak): the cap check AND the map insert happen in the SAME synchronous tick,\r\n // before the async dial, so several queued terminal_open items returned in quick\r\n // succession can never each pass the check and over-spawn. A placeholder handle\r\n // reserves the slot; the real handle replaces it once the dial resolves.\r\n if (activeTerminalSessions.has(sessionId)) {\r\n // Already reserved/active (duplicate dispatch) — ignore.\r\n return\r\n }\r\n if (activeTerminalSessions.size >= MAX_CONCURRENT_TERMINALS) {\r\n logWarn(\r\n `terminal_open ignored — concurrency cap reached (${MAX_CONCURRENT_TERMINALS} active sessions)`,\r\n )\r\n return\r\n }\r\n\r\n const relayWsUrl = work.relayWsUrl\r\n const joinToken = work.joinToken\r\n\r\n // The single removal path for ALL teardown reasons (shell exit, relay drop, ws\r\n // error, handle.close). Idempotent — the map delete is safe to call repeatedly.\r\n const onClosed = (id: string): void => {\r\n activeTerminalSessions.delete(id)\r\n }\r\n\r\n // Reserve the slot synchronously with a placeholder. close() is wired to the\r\n // real handle once openTerminalSession resolves; until then it just frees the\r\n // reservation (and onClosed will also have fired if the dial failed fast).\r\n let realHandle: TerminalSessionHandle | null = null\r\n activeTerminalSessions.set(sessionId, {\r\n sessionId,\r\n close: () => {\r\n if (realHandle) realHandle.close()\r\n activeTerminalSessions.delete(sessionId)\r\n },\r\n })\r\n\r\n log(`Opening terminal session ${sessionId} (detached)`)\r\n void openTerminalSession({\r\n relayWsUrl,\r\n joinToken,\r\n sessionId,\r\n cols: work.cols,\r\n rows: work.rows,\r\n shell: work.shell,\r\n cwd: work.cwd,\r\n onClosed,\r\n })\r\n .then((handle) => {\r\n realHandle = handle\r\n // If the session already tore down before the dial resolved, onClosed has\r\n // removed the reservation — make sure the now-known handle is also closed.\r\n if (!activeTerminalSessions.has(sessionId)) {\r\n handle.close()\r\n }\r\n })\r\n .catch((err: unknown) => {\r\n // openTerminalSession is designed not to reject, but guard anyway: drop the\r\n // reservation so a failed dial never permanently consumes a slot.\r\n logError(`Failed to open terminal session ${sessionId}`, err)\r\n activeTerminalSessions.delete(sessionId)\r\n })\r\n}\r\n\r\n/** Kill all live terminal sessions (shutdown path). */\r\nfunction closeAllTerminalSessions(): void {\r\n if (activeTerminalSessions.size === 0) return\r\n log(`Closing ${activeTerminalSessions.size} terminal session(s)`)\r\n for (const handle of activeTerminalSessions.values()) {\r\n try {\r\n handle.close()\r\n } catch {\r\n /* ignore */\r\n }\r\n }\r\n activeTerminalSessions.clear()\r\n}\r\n\r\n/**\r\n * Build the event payload for daemon lifecycle/incident events.\r\n *\r\n * daemonVersion and osInfo are nested inside `details` because the server\r\n * EventPayloadSchema only accepts {kind, agentId, message, details} and\r\n * zod-strips top-level extras — nesting is the backward-compatible direction.\r\n */\r\nexport function buildEventPayload(opts: {\r\n kind: string\r\n message: string\r\n agentId?: string\r\n daemonVersion: string\r\n osInfo?: { platform: string; release: string }\r\n extra?: Record<string, unknown>\r\n}): EventPayload {\r\n const details: Record<string, unknown> = {\r\n daemonVersion: opts.daemonVersion,\r\n ...(opts.osInfo ? { osInfo: opts.osInfo } : {}),\r\n ...(opts.extra ?? {}),\r\n }\r\n const payload: EventPayload = {\r\n kind: opts.kind,\r\n message: opts.message,\r\n details,\r\n }\r\n if (opts.agentId !== undefined) payload.agentId = opts.agentId\r\n return payload\r\n}\r\n\r\n/**\r\n * Build the heartbeat payload.\r\n *\r\n * agentSessions is a map of agentId → { hasSession: boolean } combined with\r\n * the current active-run state. Any agent with a known session is \"idle\" unless\r\n * it is the currently-active run. Agents with no session are also \"idle\" (no\r\n * entry omitted — server stores whatever we send, and the spec says send all\r\n * known agents).\r\n */\r\nexport function buildHeartbeatPayload(opts: {\r\n daemonVersion: string\r\n osInfo: { platform: string; release: string }\r\n agentIds: string[]\r\n activeAgentId: string | null\r\n activeTask: string | undefined\r\n quota?: QuotaSnapshot\r\n /** WS1: detected runtime capabilities to include in the heartbeat. */\r\n runtimes?: RuntimeCapability[]\r\n /** Host metrics sample for the Servers page. */\r\n hostMetrics?: HostMetrics\r\n}): HeartbeatPayload {\r\n const agents: AgentSession[] = opts.agentIds.map((agentId) => {\r\n if (agentId === opts.activeAgentId) {\r\n const entry: AgentSession = { agentId, status: \"running\" }\r\n if (opts.activeTask) entry.currentTask = opts.activeTask\r\n return entry\r\n }\r\n return { agentId, status: \"idle\" }\r\n })\r\n\r\n const payload: HeartbeatPayload = {\r\n daemonVersion: opts.daemonVersion,\r\n osInfo: opts.osInfo,\r\n agents,\r\n }\r\n if (opts.quota !== undefined) payload.quota = opts.quota\r\n if (opts.runtimes !== undefined) payload.capabilities = opts.runtimes\r\n if (opts.hostMetrics !== undefined && Object.keys(opts.hostMetrics).length > 0) {\r\n payload.hostMetrics = opts.hostMetrics\r\n }\r\n return payload\r\n}\r\n\r\nlet running = false\r\n\r\n/**\r\n * Start the daemon loop. Blocks until SIGINT/SIGTERM.\r\n */\r\nexport async function startDaemon(config: BridgeConfig): Promise<void> {\r\n running = true\r\n\r\n // Register signal handlers first so they fire even if startup work fails.\r\n const shutdown = async (signal: string) => {\r\n if (!running) return\r\n running = false\r\n log(`Received ${signal} — shutting down gracefully`)\r\n stopAgentRefreshTimer()\r\n // Kill any live PTYs + close their relay sockets before announcing stop.\r\n closeAllTerminalSessions()\r\n await postBestEffort(\r\n config,\r\n \"/api/bridge/v1/events\",\r\n buildEventPayload({\r\n kind: \"daemon_stopping\",\r\n message: `Daemon stopping (${signal})`,\r\n daemonVersion: VERSION,\r\n }),\r\n )\r\n process.exit(0)\r\n }\r\n\r\n process.on(\"SIGINT\", () => void shutdown(\"SIGINT\"))\r\n process.on(\"SIGTERM\", () => void shutdown(\"SIGTERM\"))\r\n\r\n // Announce startup — daemonVersion + osInfo nested in details (server strips top-level extras).\r\n await postBestEffort(\r\n config,\r\n \"/api/bridge/v1/events\",\r\n buildEventPayload({\r\n kind: \"daemon_started\",\r\n message: \"Daemon started\",\r\n daemonVersion: VERSION,\r\n osInfo: { platform: platform(), release: release() },\r\n }),\r\n )\r\n\r\n log(`Daemon started (v${VERSION}, bridge ${config.bridgeId})`)\r\n\r\n // Fetch agents on startup\r\n await refreshAgents(config)\r\n startAgentRefreshTimer(config)\r\n\r\n // Heartbeat timer — runs independently of the poll loop\r\n const sendHeartbeat = async () => {\r\n const cachedAgents = getCachedAgents()\r\n const agentIds = cachedAgents.map((a) => a.id)\r\n const quota = await getQuotaSnapshot()\r\n // WS1: detect installed runtimes (cached for 5 min — same interval as\r\n // agent refresh, which also invalidates the cache when agents are\r\n // re-fetched). Only send runtimes that were actually found (non-empty\r\n // version string) so the server payload stays compact.\r\n let runtimes: RuntimeCapability[] | undefined\r\n try {\r\n const all = await detectRuntimes()\r\n const present = all.filter((r) => r.version.length > 0)\r\n runtimes = present.length > 0 ? present : undefined\r\n } catch {\r\n // Non-fatal — skip runtimes this heartbeat.\r\n }\r\n // Host metrics for the Servers page — best-effort, never blocks the beat.\r\n let hostMetrics: HostMetrics | undefined\r\n try {\r\n hostMetrics = await collectHostMetrics()\r\n } catch {\r\n // Non-fatal — skip metrics this heartbeat.\r\n }\r\n const payload = buildHeartbeatPayload({\r\n daemonVersion: VERSION,\r\n osInfo: { platform: platform(), release: release() },\r\n agentIds,\r\n activeAgentId: activeRunAgentId,\r\n activeTask: activeRunTask,\r\n quota: quota ?? undefined,\r\n runtimes,\r\n hostMetrics,\r\n })\r\n try {\r\n await post(config, \"/api/bridge/v1/heartbeat\", payload)\r\n } catch (err: unknown) {\r\n logWarn(`Heartbeat failed: ${err instanceof Error ? err.message : String(err)}`)\r\n }\r\n }\r\n\r\n // First heartbeat immediately so the dashboard flips to connected fast.\r\n void sendHeartbeat()\r\n const heartbeatTimer = setInterval(() => void sendHeartbeat(), HEARTBEAT_INTERVAL_MS)\r\n\r\n if (heartbeatTimer.unref) heartbeatTimer.unref()\r\n\r\n // Main poll loop\r\n let backoffIndex = 0\r\n\r\n while (running) {\r\n // Retry any persisted failed reports before fetching new work\r\n try {\r\n await retryPendingReports(config)\r\n } catch {\r\n // Non-fatal\r\n }\r\n\r\n try {\r\n const data = await post<WorkResponse>(config, \"/api/bridge/v1/work\", {})\r\n backoffIndex = 0 // reset backoff on success\r\n\r\n if (data.work) {\r\n const work = data.work\r\n const kind = classifyWorkItem(work)\r\n log(`Received work item: run ${work.runId} (kind ${kind})`)\r\n\r\n // Kind branch — MUST run before touching work.agent (exec/terminal_open\r\n // items carry no agent and would crash on work.agent.id otherwise).\r\n if (kind === \"terminal_open\") {\r\n // Detached: interactive sessions are long-lived. Do NOT await (would\r\n // block the single-flight loop) and do NOT set activeRunAgentId.\r\n dispatchTerminalWork(work)\r\n // Poll again immediately — there may be more work queued.\r\n continue\r\n }\r\n\r\n if (kind === \"exec\") {\r\n // Bounded (≤60s) — safe to await inline. Does not set activeRunAgentId.\r\n try {\r\n await handleExecWork(config, work)\r\n } catch (err: unknown) {\r\n logError(`Unhandled error in handleExecWork for run ${work.runId}`, err)\r\n }\r\n continue\r\n }\r\n\r\n // agent_run (default) — existing behaviour, unchanged.\r\n // Track active run for heartbeat telemetry.\r\n activeRunAgentId = work.agent?.id ?? null\r\n activeRunTask = work.prompt.slice(0, 200)\r\n // Single-flight: await the run before polling again\r\n try {\r\n await runWorkItem(config, work)\r\n } catch (err: unknown) {\r\n logError(`Unhandled error in runWorkItem for run ${work.runId}`, err)\r\n } finally {\r\n activeRunAgentId = null\r\n activeRunTask = undefined\r\n }\r\n // Poll immediately after completing a run (don't wait full interval)\r\n continue\r\n }\r\n } catch (err: unknown) {\r\n const delay = BACKOFF_STEPS_MS[Math.min(backoffIndex, BACKOFF_STEPS_MS.length - 1)]\r\n logError(\r\n `Poll error (backoff ${delay}ms)`,\r\n err,\r\n )\r\n backoffIndex = Math.min(backoffIndex + 1, BACKOFF_STEPS_MS.length - 1)\r\n await sleep(delay)\r\n continue\r\n }\r\n\r\n await sleep(POLL_INTERVAL_MS)\r\n }\r\n\r\n clearInterval(heartbeatTimer)\r\n}\r\n\r\nfunction sleep(ms: number): Promise<void> {\r\n return new Promise((resolve) => setTimeout(resolve, ms))\r\n}\r\n","/**\n * cli.ts — Stride Bridge CLI entry point.\n *\n * Commands:\n * connect <pairingCode> [--api-url <url>] — Pair this machine with StrideOps\n * start — Start the daemon loop (foreground)\n * status — Print config + connectivity info\n * doctor — Run prerequisite checks\n */\n\nimport { Command } from \"commander\"\nimport { VERSION } from \"./version.js\"\nimport { runPair } from \"./pair.js\"\nimport { startDaemon } from \"./poller.js\"\nimport { readConfig, requireConfig, CONFIG_PATH, isConfigured } from \"./config.js\"\nimport { log } from \"./log.js\"\nimport { execSync } from \"node:child_process\"\nimport { existsSync, accessSync, constants, mkdirSync } from \"node:fs\"\nimport { join } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport { post } from \"./api.js\"\n\nconst DEFAULT_API_URL = \"https://app.strideops.ai\"\n\nconst program = new Command()\n\nprogram\n .name(\"stride-bridge\")\n .description(\"Stride Bridge daemon — run StrideOps Build agents locally\")\n .version(VERSION)\n\n// ---------------------------------------------------------------------------\n// connect\n// ---------------------------------------------------------------------------\n\nprogram\n .command(\"connect <pairingCode>\")\n .description(\"Pair this machine with StrideOps using a one-time pairing code\")\n .option(\n \"--api-url <url>\",\n \"StrideOps API base URL\",\n DEFAULT_API_URL,\n )\n .action(async (pairingCode: string, opts: { apiUrl: string }) => {\n await runPair(pairingCode, opts.apiUrl)\n })\n\n// ---------------------------------------------------------------------------\n// start\n// ---------------------------------------------------------------------------\n\nprogram\n .command(\"start\")\n .description(\"Start the daemon (foreground; press Ctrl+C to stop)\")\n .action(async () => {\n const config = requireConfig()\n log(`Starting daemon with bridge \"${config.bridgeName}\" (${config.bridgeId})`)\n await startDaemon(config)\n })\n\n// ---------------------------------------------------------------------------\n// status\n// ---------------------------------------------------------------------------\n\nprogram\n .command(\"status\")\n .description(\"Print current configuration and server connectivity\")\n .action(async () => {\n const config = readConfig()\n\n console.log(\"=== Stride Bridge Status ===\")\n console.log()\n\n if (!config) {\n console.log(\"Status : NOT CONNECTED\")\n console.log(`Config path : ${CONFIG_PATH}`)\n console.log()\n console.log(\"Run `stride-bridge connect <PAIRING_CODE>` to get started.\")\n return\n }\n\n console.log(`Status : CONNECTED`)\n console.log(`Bridge name : ${config.bridgeName}`)\n console.log(`Bridge ID : ${config.bridgeId}`)\n console.log(`Org ID : ${config.orgId}`)\n console.log(`API URL : ${config.apiBaseUrl}`)\n console.log(`Auth mode : ${config.authMode}`)\n console.log(`Config path : ${CONFIG_PATH}`)\n console.log()\n\n // Check server reachability\n process.stdout.write(\"Server : checking... \")\n try {\n await post(config, \"/api/bridge/v1/heartbeat\", {\n daemonVersion: VERSION,\n osInfo: {},\n agents: [],\n })\n console.log(\"REACHABLE\")\n } catch (err: unknown) {\n console.log(\n `UNREACHABLE (${err instanceof Error ? err.message : String(err)})`,\n )\n }\n console.log()\n })\n\n// ---------------------------------------------------------------------------\n// autostart\n// ---------------------------------------------------------------------------\n\nprogram\n .command(\"autostart <action>\")\n .description(\"Manage start-at-logon: install | remove | status (Windows Task Scheduler)\")\n .action(async (action: string) => {\n const { autostartInstall, autostartRemove, autostartStatus } = await import(\"./autostart.js\")\n if (action === \"install\") autostartInstall()\n else if (action === \"remove\") autostartRemove()\n else if (action === \"status\") autostartStatus()\n else {\n console.error(`Unknown action \"${action}\" — use install, remove, or status`)\n process.exitCode = 1\n }\n })\n\n// ---------------------------------------------------------------------------\n// doctor\n// ---------------------------------------------------------------------------\n\nprogram\n .command(\"doctor\")\n .description(\"Check all prerequisites for running the bridge daemon\")\n .action(async () => {\n console.log(\"=== Stride Bridge Doctor ===\")\n console.log()\n\n let allGood = true\n\n // 1. Node version\n const nodeVersion = process.versions.node\n const [major] = nodeVersion.split(\".\").map(Number)\n const nodeOk = major >= 20\n printCheck(\n \"Node.js >= 20\",\n nodeOk,\n `Found v${nodeVersion}`,\n `Found v${nodeVersion} — upgrade to Node.js 20+`,\n )\n if (!nodeOk) allGood = false\n\n // 2. claude CLI on PATH\n let claudeVersion = \"\"\n let claudeOnPath = false\n try {\n claudeVersion = execSync(\"claude --version\", {\n encoding: \"utf-8\",\n timeout: 5_000,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }).trim()\n claudeOnPath = true\n } catch {\n claudeOnPath = false\n }\n printCheck(\n \"claude CLI on PATH\",\n claudeOnPath,\n claudeVersion || \"found\",\n \"claude not found — install Claude Code CLI from https://docs.anthropic.com/claude-code\",\n )\n if (!claudeOnPath) allGood = false\n\n // 3. Claude authenticated (config presence heuristic)\n let claudeAuthed = false\n let claudeAuthNote = \"\"\n if (claudeOnPath) {\n // Claude Code stores its config under ~/.claude/ or %APPDATA%/claude/\n const possiblePaths = [\n join(homedir(), \".claude\", \"settings.json\"),\n join(homedir(), \".config\", \"claude\", \"settings.json\"),\n join(\n process.env[\"APPDATA\"] ?? join(homedir(), \"AppData\", \"Roaming\"),\n \"Claude\",\n \"settings.json\",\n ),\n ]\n claudeAuthed = possiblePaths.some(existsSync)\n claudeAuthNote = claudeAuthed\n ? \"config found\"\n : \"no config found — run `claude` to authenticate\"\n } else {\n claudeAuthNote = \"skipped (claude not on PATH)\"\n }\n printCheck(\n \"Claude authenticated\",\n claudeAuthed,\n claudeAuthNote,\n claudeAuthNote,\n )\n if (!claudeAuthed && claudeOnPath) allGood = false\n\n // 4. Config file valid\n const configured = isConfigured()\n const configData = readConfig()\n const configValid = configured && configData !== null\n printCheck(\n \"Bridge config\",\n configValid,\n configValid\n ? `${CONFIG_PATH} (bridge: ${configData?.bridgeName})`\n : configured\n ? `${CONFIG_PATH} exists but could not be parsed`\n : \"not found — run `stride-bridge connect <CODE>`\",\n configured\n ? `${CONFIG_PATH} could not be parsed — re-run connect`\n : \"not found — run `stride-bridge connect <CODE>`\",\n )\n if (!configValid) allGood = false\n\n // 5. Server reachable\n if (configData) {\n process.stdout.write(\"[ ] StrideOps server reachable ... \")\n try {\n await post(configData, \"/api/bridge/v1/heartbeat\", {\n daemonVersion: VERSION,\n osInfo: {},\n agents: [],\n })\n clearLine()\n printCheck(\"StrideOps server reachable\", true, configData.apiBaseUrl, \"\")\n } catch (err: unknown) {\n clearLine()\n printCheck(\n \"StrideOps server reachable\",\n false,\n \"\",\n `${configData.apiBaseUrl} — ${err instanceof Error ? err.message : String(err)}`,\n )\n allGood = false\n }\n } else {\n printCheck(\n \"StrideOps server reachable\",\n false,\n \"\",\n \"skipped (not configured)\",\n )\n }\n\n // 6. Workspace dir writable\n const bridgeDir = join(homedir(), \".stride-bridge\")\n try {\n mkdirSync(bridgeDir, { recursive: true })\n accessSync(bridgeDir, constants.W_OK)\n printCheck(\"Bridge workspace writable\", true, bridgeDir, \"\")\n } catch {\n printCheck(\n \"Bridge workspace writable\",\n false,\n \"\",\n `${bridgeDir} is not writable`,\n )\n allGood = false\n }\n\n console.log()\n if (allGood) {\n console.log(\"All checks passed. Run `stride-bridge start` to launch the daemon.\")\n } else {\n console.log(\n \"Some checks failed. Fix the issues above, then re-run `stride-bridge doctor`.\",\n )\n process.exit(1)\n }\n })\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction printCheck(\n label: string,\n ok: boolean,\n successNote: string,\n failureNote: string,\n): void {\n const icon = ok ? \"[ok]\" : \"[!!]\"\n const note = ok ? successNote : failureNote\n console.log(`${icon} ${label}${note ? \" — \" + note : \"\"}`)\n}\n\nfunction clearLine(): void {\n // Move cursor up one line and clear it (for the \"checking...\" line)\n process.stdout.write(\"\\r\\x1b[K\")\n}\n\n// ---------------------------------------------------------------------------\n// Parse\n// ---------------------------------------------------------------------------\n\nprogram.parseAsync(process.argv).catch((err: unknown) => {\n console.error(\n `[stride-bridge] Fatal: ${err instanceof Error ? err.message : String(err)}`,\n )\n process.exit(1)\n})\n"]}
|