@routecraft/cli 0.5.0-canary.44 → 0.5.0-canary.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,17 +1,17 @@
1
1
  # @routecraft/cli
2
2
 
3
- Run Routecraft capabilities from the terminal.
3
+ Run Routecraft capabilities from the terminal. **Bun-only runtime** (>= 1.1.0); see the [Runtime reference](https://routecraft.dev/docs/reference/runtime) for the rationale and the Node embedding alternative.
4
4
 
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
- npm install -g @routecraft/cli
9
- ```
10
-
11
- or
8
+ # Bun (recommended)
9
+ bun add -g @routecraft/cli
12
10
 
13
- ```bash
11
+ # npm / pnpm / yarn (still requires Bun on the host at runtime)
12
+ npm install -g @routecraft/cli
14
13
  pnpm add -g @routecraft/cli
14
+ yarn global add @routecraft/cli
15
15
  ```
16
16
 
17
17
  ## Usage
@@ -22,7 +22,9 @@ craft run my-capability.ts
22
22
 
23
23
  The CLI loads your capability file, starts all registered capabilities, and keeps the process running. It handles graceful shutdown on `SIGINT`/`SIGTERM` and automatically loads a `.env` file from the current directory if present.
24
24
 
25
- TypeScript files are supported directly -- no build step required.
25
+ TypeScript files are supported directly -- Bun strips types natively, no build step required.
26
+
27
+ If Bun is missing, the CLI fails fast with a `[routecraft]` error pointing at the install instructions. Node users should embed `@routecraft/routecraft` programmatically rather than going through the CLI -- see [Programmatic Invocation](https://routecraft.dev/docs/advanced/programmatic-invocation).
26
28
 
27
29
  ## Options
28
30
 
@@ -1,4 +1,4 @@
1
- function u(s){return s.replace(/[%_\\]/g,"\\$&")}var g=class s{db;stmtCache=new Map;constructor(t){this.db=t;}stmt(t,e){let n=this.stmtCache.get(t);return n||(n=this.db.prepare(e),this.stmtCache.set(t,n)),n}static async open(t){let e;try{let r=await import('better-sqlite3');e="default"in r&&typeof r.default=="function"?r.default:r;}catch{throw new Error("better-sqlite3 is not installed. Install it with: pnpm add better-sqlite3")}let n=new e(t,{readonly:true});try{n.pragma("journal_mode = WAL");}catch{}{let r=new e(t);try{r.prepare("CREATE INDEX IF NOT EXISTS idx_exchanges_started_at ON exchanges(started_at)").run(),r.prepare("CREATE INDEX IF NOT EXISTS idx_exchanges_route_started ON exchanges(route_id, started_at)").run(),r.prepare("CREATE INDEX IF NOT EXISTS idx_exchanges_correlation_id ON exchanges(correlation_id)").run(),r.prepare("PRAGMA table_info(events)").all().some(o=>o.name==="exchange_id")||(r.prepare("ALTER TABLE events ADD COLUMN exchange_id TEXT").run(),r.prepare("ALTER TABLE events ADD COLUMN correlation_id TEXT").run()),r.prepare("CREATE INDEX IF NOT EXISTS idx_events_exchange_id ON events(exchange_id)").run(),r.prepare("CREATE INDEX IF NOT EXISTS idx_events_correlation_id ON events(correlation_id)").run(),r.prepare(`CREATE TABLE IF NOT EXISTS exchange_snapshots (
1
+ function u(s){return s.replace(/[%_\\]/g,"\\$&")}var g=class s{db;stmtCache=new Map;constructor(t){this.db=t;}stmt(t,e){let n=this.stmtCache.get(t);return n||(n=this.db.prepare(e),this.stmtCache.set(t,n)),n}static async open(t){let e;try{let r=await import('better-sqlite3');e="default"in r&&typeof r.default=="function"?r.default:r;}catch{throw new Error("better-sqlite3 is not installed. Install it with: bun add better-sqlite3")}let n=new e(t,{readonly:true});try{n.pragma("journal_mode = WAL");}catch{}{let r=new e(t);try{r.prepare("CREATE INDEX IF NOT EXISTS idx_exchanges_started_at ON exchanges(started_at)").run(),r.prepare("CREATE INDEX IF NOT EXISTS idx_exchanges_route_started ON exchanges(route_id, started_at)").run(),r.prepare("CREATE INDEX IF NOT EXISTS idx_exchanges_correlation_id ON exchanges(correlation_id)").run(),r.prepare("PRAGMA table_info(events)").all().some(o=>o.name==="exchange_id")||(r.prepare("ALTER TABLE events ADD COLUMN exchange_id TEXT").run(),r.prepare("ALTER TABLE events ADD COLUMN correlation_id TEXT").run()),r.prepare("CREATE INDEX IF NOT EXISTS idx_events_exchange_id ON events(exchange_id)").run(),r.prepare("CREATE INDEX IF NOT EXISTS idx_events_correlation_id ON events(correlation_id)").run(),r.prepare(`CREATE TABLE IF NOT EXISTS exchange_snapshots (
2
2
  exchange_id TEXT NOT NULL,
3
3
  context_id TEXT NOT NULL,
4
4
  headers TEXT NOT NULL,
@@ -136,5 +136,5 @@ function u(s){return s.replace(/[%_\\]/g,"\\$&")}var g=class s{db;stmtCache=new
136
136
  AND CAST(strftime('%s', started_at) AS INTEGER) >= ?`).get(t,o),m=new Array(e).fill(0);for(let d of c)d.bucket>=0&&d.bucket<e&&(m[d.bucket]=d.cnt);return {throughput:m,recentErrors:S?.cnt??0}}getMaxEventId(){return this.db.prepare("SELECT COALESCE(MAX(id), 0) AS maxId FROM events").get().maxId}getExchangeSnapshot(t){try{let n=this.stmt("exchangeSnapshot",`SELECT headers, body, truncated
137
137
  FROM exchange_snapshots
138
138
  WHERE exchange_id = ?
139
- LIMIT 1`).get(t);return n?{headers:n.headers,body:n.body,truncated:n.truncated!==0}:null}catch{return null}}close(){this.db.close();}};function l(s,t){if(s.length===0)return null;let e=t*(s.length-1),n=Math.floor(e),r=Math.ceil(e);return n===r?s[n]:s[n]+(s[r]-s[n])*(e-n)}export{g as a};//# sourceMappingURL=chunk-DPJWCR2V.js.map
140
- //# sourceMappingURL=chunk-DPJWCR2V.js.map
139
+ LIMIT 1`).get(t);return n?{headers:n.headers,body:n.body,truncated:n.truncated!==0}:null}catch{return null}}close(){this.db.close();}};function l(s,t){if(s.length===0)return null;let e=t*(s.length-1),n=Math.floor(e),r=Math.ceil(e);return n===r?s[n]:s[n]+(s[r]-s[n])*(e-n)}export{g as a};//# sourceMappingURL=chunk-3CIF67XJ.js.map
140
+ //# sourceMappingURL=chunk-3CIF67XJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/tui/db.ts"],"names":["escapeLike","TelemetryDb","_TelemetryDb","db","key","sql","s","dbPath","Database","mod","wdb","c","routeId","limit","exchangeId","correlationId","searchId","info","col","options","sinceId","params","escaped","row","durations","r","percentile","bucketCount","bucketWidthSec","nowSec","snapped","windowStart","rows","result","tRows","eRow","throughput","sorted","p","idx","lo","hi"],"mappings":"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","file":"chunk-3CIF67XJ.js","sourcesContent":["import type { TelemetryEvent } from \"@routecraft/routecraft\";\n\n/** Exchange row shape from the telemetry SQLite database. */\ninterface TelemetryExchange {\n id: string;\n routeId: string;\n contextId: string;\n correlationId: string;\n status: string;\n startedAt: string;\n completedAt: string | null;\n durationMs: number | null;\n error: string | null;\n}\n\n/**\n * Minimal type for the better-sqlite3 database to avoid hard dependency.\n */\ninterface Database {\n prepare(sql: string): Statement;\n close(): void;\n pragma(pragma: string): unknown;\n}\n\ninterface Statement {\n all(...params: unknown[]): unknown[];\n get(...params: unknown[]): unknown;\n run(...params: unknown[]): unknown;\n}\n\ntype DatabaseConstructor = new (\n filename: string,\n options?: { readonly?: boolean },\n) => Database;\n\n/**\n * Read-only accessor for the telemetry SQLite database.\n * Used by the TUI to query historical data without affecting the running engine.\n *\n * Use the static `open()` factory instead of the constructor directly.\n */\n/** Escape LIKE metacharacters so they match literally. */\nfunction escapeLike(s: string): string {\n return s.replace(/[%_\\\\]/g, \"\\\\$&\");\n}\n\nexport class TelemetryDb {\n private db: Database;\n private stmtCache = new Map<string, Statement>();\n\n private constructor(db: Database) {\n this.db = db;\n }\n\n /** Prepare and cache a statement by key. Avoids re-parsing on every call. */\n private stmt(key: string, sql: string): Statement {\n let s = this.stmtCache.get(key);\n if (!s) {\n s = this.db.prepare(sql);\n this.stmtCache.set(key, s);\n }\n return s;\n }\n\n /**\n * Open a telemetry database in read-only mode.\n *\n * Uses dynamic `import()` so the module resolves correctly under Bun's\n * isolated linker (CJS `require()` from an ESM bundle does not follow\n * the package's own dependency graph).\n */\n static async open(dbPath: string): Promise<TelemetryDb> {\n let Database: DatabaseConstructor;\n try {\n const mod = await import(\"better-sqlite3\");\n Database = (\n \"default\" in mod && typeof mod.default === \"function\"\n ? mod.default\n : mod\n ) as DatabaseConstructor;\n } catch {\n throw new Error(\n \"better-sqlite3 is not installed. Install it with: bun add better-sqlite3\",\n );\n }\n\n const db = new Database(dbPath, { readonly: true });\n try {\n db.pragma(\"journal_mode = WAL\");\n } catch {\n // Read-only connection cannot change journal mode; safe to ignore\n }\n\n // Ensure indexes exist for TUI query performance.\n // If the DB was created before indexes were added, create them now\n // using a separate writable connection.\n {\n const wdb = new Database(dbPath);\n try {\n wdb\n .prepare(\n \"CREATE INDEX IF NOT EXISTS idx_exchanges_started_at ON exchanges(started_at)\",\n )\n .run();\n wdb\n .prepare(\n \"CREATE INDEX IF NOT EXISTS idx_exchanges_route_started ON exchanges(route_id, started_at)\",\n )\n .run();\n wdb\n .prepare(\n \"CREATE INDEX IF NOT EXISTS idx_exchanges_correlation_id ON exchanges(correlation_id)\",\n )\n .run();\n // Add exchange_id/correlation_id columns to events table if missing\n const cols = wdb.prepare(\"PRAGMA table_info(events)\").all() as Array<{\n name: string;\n }>;\n if (!cols.some((c) => c.name === \"exchange_id\")) {\n wdb.prepare(\"ALTER TABLE events ADD COLUMN exchange_id TEXT\").run();\n wdb\n .prepare(\"ALTER TABLE events ADD COLUMN correlation_id TEXT\")\n .run();\n }\n wdb\n .prepare(\n \"CREATE INDEX IF NOT EXISTS idx_events_exchange_id ON events(exchange_id)\",\n )\n .run();\n wdb\n .prepare(\n \"CREATE INDEX IF NOT EXISTS idx_events_correlation_id ON events(correlation_id)\",\n )\n .run();\n // Ensure exchange_snapshots table exists for older databases\n wdb\n .prepare(\n `CREATE TABLE IF NOT EXISTS exchange_snapshots (\n exchange_id TEXT NOT NULL,\n context_id TEXT NOT NULL,\n headers TEXT NOT NULL,\n body TEXT,\n truncated INTEGER NOT NULL DEFAULT 0,\n captured_at TEXT NOT NULL DEFAULT (datetime('now')),\n PRIMARY KEY (exchange_id, context_id)\n )`,\n )\n .run();\n } catch {\n // Best-effort; the writer will create them on next restart\n } finally {\n wdb.close();\n }\n }\n\n return new TelemetryDb(db);\n }\n\n /**\n * Get a summary of all routes with aggregated metrics.\n * Routes are grouped by ID across all context runs so that restarting\n * the same application does not create duplicate rows.\n */\n getRouteSummary(): Array<{\n id: string;\n status: string;\n totalExchanges: number;\n completedExchanges: number;\n failedExchanges: number;\n droppedExchanges: number;\n avgDurationMs: number | null;\n }> {\n const s = this.stmt(\n \"routeSummary\",\n `WITH unique_routes AS (\n SELECT\n id,\n MAX(registered_at) AS registered_at,\n (SELECT r2.status FROM routes r2\n WHERE r2.id = r.id\n ORDER BY r2.registered_at DESC LIMIT 1) AS status\n FROM routes r\n GROUP BY id\n ),\n exchange_counts AS (\n SELECT\n route_id,\n COUNT(*) AS total,\n SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) AS completed,\n SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) AS failed,\n SUM(CASE WHEN status = 'dropped' THEN 1 ELSE 0 END) AS dropped\n FROM exchanges\n GROUP BY route_id\n ),\n recent_avg AS (\n SELECT route_id, AVG(duration_ms) AS avgDur\n FROM exchanges\n WHERE started_at >= datetime('now', '-5 minutes')\n GROUP BY route_id\n )\n SELECT\n ur.id,\n ur.status,\n COALESCE(ec.total, 0) AS totalExchanges,\n COALESCE(ec.completed, 0) AS completedExchanges,\n COALESCE(ec.failed, 0) AS failedExchanges,\n COALESCE(ec.dropped, 0) AS droppedExchanges,\n ra.avgDur AS avgDurationMs\n FROM unique_routes ur\n LEFT JOIN exchange_counts ec ON ur.id = ec.route_id\n LEFT JOIN recent_avg ra ON ur.id = ra.route_id\n ORDER BY ur.registered_at DESC`,\n );\n return s.all() as Array<{\n id: string;\n status: string;\n totalExchanges: number;\n completedExchanges: number;\n failedExchanges: number;\n droppedExchanges: number;\n avgDurationMs: number | null;\n }>;\n }\n\n /**\n * Get exchanges for a specific route, ordered by most recent first.\n */\n getExchangesByRoute(routeId: string, limit = -1): TelemetryExchange[] {\n const s = this.stmt(\n \"exchangesByRoute\",\n `SELECT\n id,\n route_id AS routeId,\n context_id AS contextId,\n correlation_id AS correlationId,\n status,\n started_at AS startedAt,\n completed_at AS completedAt,\n duration_ms AS durationMs,\n error\n FROM exchanges\n WHERE route_id = ?\n ORDER BY started_at DESC\n LIMIT ?`,\n );\n return s.all(routeId, limit) as TelemetryExchange[];\n }\n\n /**\n * Get all exchanges across all routes, ordered by most recent first.\n */\n getAllExchanges(limit = -1): TelemetryExchange[] {\n const s = this.stmt(\n \"allExchanges\",\n `SELECT\n id,\n route_id AS routeId,\n context_id AS contextId,\n correlation_id AS correlationId,\n status,\n started_at AS startedAt,\n completed_at AS completedAt,\n duration_ms AS durationMs,\n error\n FROM exchanges\n ORDER BY started_at DESC\n LIMIT ?`,\n );\n return s.all(limit) as TelemetryExchange[];\n }\n\n /**\n * Get all failed exchanges across all routes, ordered by most recent first.\n * Shows every failed exchange including child exchanges from split/multicast,\n * without deduplication by correlation chain.\n */\n getFailedExchanges(limit = -1): TelemetryExchange[] {\n const s = this.stmt(\n \"failedExchanges\",\n `SELECT\n id,\n route_id AS routeId,\n context_id AS contextId,\n correlation_id AS correlationId,\n status,\n started_at AS startedAt,\n completed_at AS completedAt,\n duration_ms AS durationMs,\n error\n FROM exchanges\n WHERE status = 'failed'\n ORDER BY started_at DESC\n LIMIT ?`,\n );\n return s.all(limit) as TelemetryExchange[];\n }\n\n /**\n * Get events for an exchange and all related exchanges sharing the\n * same correlation ID. Uses indexed exchange_id/correlation_id columns\n * with a fallback to details LIKE for databases created before the\n * column migration.\n */\n getEventsByExchange(\n exchangeId: string,\n correlationId: string,\n ): TelemetryEvent[] {\n const searchId = correlationId || exchangeId;\n\n // Try indexed column lookup first (fast path)\n const hasColumns = this.hasEventIdColumns();\n if (hasColumns) {\n const s = this.stmt(\n \"eventsByExchangeIndexed\",\n `SELECT\n id,\n timestamp,\n context_id AS contextId,\n event_name AS eventName,\n details\n FROM events\n WHERE exchange_id = ? OR correlation_id = ?\n ORDER BY id ASC`,\n );\n return s.all(searchId, searchId) as TelemetryEvent[];\n }\n\n // Fallback: full-text LIKE scan for older databases\n const s = this.stmt(\n \"eventsByExchangeFallback\",\n `SELECT\n id,\n timestamp,\n context_id AS contextId,\n event_name AS eventName,\n details\n FROM events\n WHERE details LIKE '%' || ? || '%' ESCAPE '\\\\'\n ORDER BY id ASC`,\n );\n return s.all(escapeLike(searchId)) as TelemetryEvent[];\n }\n\n /** Check whether the events table has the exchange_id column. */\n private hasEventIdColumns(): boolean {\n if (this._hasEventIdColumns !== undefined) return this._hasEventIdColumns;\n try {\n const info = this.db.prepare(\"PRAGMA table_info(events)\").all() as Array<{\n name: string;\n }>;\n this._hasEventIdColumns = info.some((col) => col.name === \"exchange_id\");\n } catch {\n this._hasEventIdColumns = false;\n }\n return this._hasEventIdColumns;\n }\n private _hasEventIdColumns: boolean | undefined;\n\n /**\n * Get recent events, optionally filtered by event name pattern or route ID.\n */\n getRecentEvents(options?: {\n limit?: number;\n eventNameFilter?: string;\n routeIdFilter?: string;\n sinceId?: number;\n }): TelemetryEvent[] {\n const limit = options?.limit ?? 100;\n const sinceId = options?.sinceId ?? 0;\n\n let sql = `\n SELECT\n id,\n timestamp,\n context_id AS contextId,\n event_name AS eventName,\n details\n FROM events\n WHERE id > ?\n `;\n const params: unknown[] = [sinceId];\n\n if (options?.eventNameFilter) {\n sql += \" AND event_name LIKE ? ESCAPE '\\\\'\";\n params.push(`%${escapeLike(options.eventNameFilter)}%`);\n }\n\n if (options?.routeIdFilter) {\n sql +=\n \" AND (event_name LIKE ? ESCAPE '\\\\' OR details LIKE ? ESCAPE '\\\\')\";\n const escaped = escapeLike(options.routeIdFilter);\n params.push(`%${escaped}%`, `%${escaped}%`);\n }\n\n sql += \" ORDER BY id DESC LIMIT ?\";\n params.push(limit);\n\n const stmt = this.db.prepare(sql);\n return stmt.all(...params) as TelemetryEvent[];\n }\n\n /**\n * Get aggregated metrics for the dashboard, including duration percentiles.\n * Percentiles are computed over exchanges from the last 5 minutes.\n */\n getMetrics(): import(\"./types.js\").Metrics {\n const s = this.stmt(\n \"metrics\",\n `SELECT\n (SELECT COUNT(DISTINCT id) FROM routes) AS totalRoutes,\n (SELECT COUNT(*) FROM exchanges) AS totalExchanges,\n (SELECT COUNT(*) FROM exchanges WHERE status = 'completed') AS completedExchanges,\n (SELECT COUNT(*) FROM exchanges WHERE status = 'failed') AS failedExchanges,\n (SELECT COUNT(*) FROM exchanges WHERE status = 'dropped') AS droppedExchanges,\n (SELECT AVG(duration_ms) FROM exchanges\n WHERE started_at >= datetime('now', '-5 minutes')) AS avgDurationMs`,\n );\n const row = s.get() as {\n totalRoutes: number;\n totalExchanges: number;\n completedExchanges: number;\n failedExchanges: number;\n droppedExchanges: number;\n avgDurationMs: number | null;\n };\n\n // Compute percentiles from recent exchanges with non-null durations\n const pctStmt = this.stmt(\n \"percentiles\",\n `SELECT duration_ms\n FROM exchanges\n WHERE duration_ms IS NOT NULL\n AND started_at >= datetime('now', '-5 minutes')\n ORDER BY duration_ms ASC`,\n );\n const durations = (pctStmt.all() as Array<{ duration_ms: number }>).map(\n (r) => r.duration_ms,\n );\n\n return {\n ...row,\n errorRate:\n row.totalExchanges > 0 ? row.failedExchanges / row.totalExchanges : 0,\n p90DurationMs: percentile(durations, 0.9),\n p95DurationMs: percentile(durations, 0.95),\n p99DurationMs: percentile(durations, 0.99),\n };\n }\n\n /**\n * Get exchange counts for a rolling window using fine-grained buckets.\n * Default: 60 buckets of 5 seconds = 5-minute rolling window.\n * Returns values oldest-first for sparkline rendering.\n */\n getLiveTrafficBuckets(bucketCount = 60, bucketWidthSec = 5): number[] {\n const nowSec = Math.floor(Date.now() / 1000);\n const snapped = Math.floor(nowSec / bucketWidthSec) * bucketWidthSec;\n const windowStart = snapped - (bucketCount - 1) * bucketWidthSec;\n\n const s = this.stmt(\n \"liveTraffic\",\n `SELECT\n CAST((CAST(strftime('%s', started_at) AS INTEGER) - ?) / ? AS INTEGER) AS bucket,\n COUNT(*) AS cnt\n FROM exchanges\n WHERE CAST(strftime('%s', started_at) AS INTEGER) >= ?\n AND CAST(strftime('%s', started_at) AS INTEGER) <= ?\n GROUP BY bucket`,\n );\n const rows = s.all(\n windowStart,\n bucketWidthSec,\n windowStart,\n snapped + bucketWidthSec,\n ) as Array<{ bucket: number; cnt: number }>;\n\n const result = new Array(bucketCount).fill(0) as number[];\n for (const row of rows) {\n if (row.bucket >= 0 && row.bucket < bucketCount) {\n result[row.bucket] += row.cnt;\n }\n }\n return result;\n }\n\n /**\n * Get activity data for a single route: throughput sparkline + recent error count.\n */\n getSingleRouteActivity(\n routeId: string,\n bucketCount = 12,\n bucketWidthSec = 5,\n ): { throughput: number[]; recentErrors: number } {\n const nowSec = Math.floor(Date.now() / 1000);\n const snapped = Math.floor(nowSec / bucketWidthSec) * bucketWidthSec;\n const windowStart = snapped - (bucketCount - 1) * bucketWidthSec;\n\n const tStmt = this.stmt(\n \"singleRouteActivity\",\n `SELECT\n CAST((CAST(strftime('%s', started_at) AS INTEGER) - ?) / ? AS INTEGER) AS bucket,\n COUNT(*) AS cnt\n FROM exchanges\n WHERE route_id = ?\n AND CAST(strftime('%s', started_at) AS INTEGER) >= ?\n GROUP BY bucket`,\n );\n const tRows = tStmt.all(\n windowStart,\n bucketWidthSec,\n routeId,\n windowStart,\n ) as Array<{ bucket: number; cnt: number }>;\n\n const eStmt = this.stmt(\n \"singleRouteErrors\",\n `SELECT COUNT(*) AS cnt\n FROM exchanges\n WHERE route_id = ?\n AND status = 'failed'\n AND CAST(strftime('%s', started_at) AS INTEGER) >= ?`,\n );\n const eRow = eStmt.get(routeId, windowStart) as { cnt: number } | undefined;\n\n const throughput = new Array(bucketCount).fill(0) as number[];\n for (const row of tRows) {\n if (row.bucket >= 0 && row.bucket < bucketCount) {\n throughput[row.bucket] = row.cnt;\n }\n }\n\n return { throughput, recentErrors: eRow?.cnt ?? 0 };\n }\n\n /**\n * Get the maximum event ID (for tailing/polling).\n */\n getMaxEventId(): number {\n const stmt = this.db.prepare(\n \"SELECT COALESCE(MAX(id), 0) AS maxId FROM events\",\n );\n const row = stmt.get() as { maxId: number };\n return row.maxId;\n }\n\n /**\n * Get the exchange snapshot (headers and body) for a given exchange.\n * Returns null if no snapshot was captured.\n */\n getExchangeSnapshot(\n exchangeId: string,\n ): import(\"./types.js\").ExchangeSnapshot | null {\n try {\n const s = this.stmt(\n \"exchangeSnapshot\",\n `SELECT headers, body, truncated\n FROM exchange_snapshots\n WHERE exchange_id = ?\n LIMIT 1`,\n );\n const row = s.get(exchangeId) as\n | { headers: string; body: string | null; truncated: number }\n | undefined;\n if (!row) return null;\n return {\n headers: row.headers,\n body: row.body,\n truncated: row.truncated !== 0,\n };\n } catch {\n // Table may not exist in very old databases\n return null;\n }\n }\n\n /**\n * Close the database connection.\n */\n close(): void {\n this.db.close();\n }\n}\n\n/**\n * Compute a percentile from a sorted array of numbers using linear interpolation.\n * Returns null if the array is empty.\n */\nfunction percentile(sorted: number[], p: number): number | null {\n if (sorted.length === 0) return null;\n const idx = p * (sorted.length - 1);\n const lo = Math.floor(idx);\n const hi = Math.ceil(idx);\n if (lo === hi) return sorted[lo]!;\n return sorted[lo]! + (sorted[hi]! - sorted[lo]!) * (idx - lo);\n}\n"]}
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env bun
2
- var n={major:1,minor:1,patch:0},l="https://bun.com/docs/installation",g="https://routecraft.dev/docs/advanced/programmatic-invocation";function f(e=process.versions.bun??null){let o=e;if(!o)return {ok:false,message:`[routecraft] The craft CLI requires Bun. Install Bun from ${l}, or embed @routecraft/routecraft programmatically (see ${g}).`};let s=o.split(/[-+]/)[0]??"",[t,a,u]=s.split("."),r=Number(t),c=Number(a),m=Number(u??"0");return !Number.isFinite(r)||!Number.isFinite(c)||!Number.isFinite(m)?{ok:false,message:`[routecraft] Could not parse Bun version "${o}". Routecraft requires Bun ${p(n)} or later. Upgrade Bun: ${l}.`}:r>n.major||r===n.major&&(c>n.minor||c===n.minor&&m>=n.patch)?{ok:true}:{ok:false,message:`[routecraft] Bun ${o} is not supported. Routecraft requires Bun ${p(n)} or later. Upgrade Bun: ${l}.`}}function p(e){return `${e.major}.${e.minor}.${e.patch}`}var d=f();d.ok||(console.error(d.message),process.exit(1));var{Command:h}=await import('commander'),i=new h;i.name("craft").description("A modern routing framework for TypeScript").version("0.5.0-canary.44").enablePositionalOptions().option("--log-level <level>","Log level (e.g. info, warn, error, silent to disable)").option("--log-file <path>","Write logs to a file instead of stdout").showSuggestionAfterError().showHelpAfterError().exitOverride(e=>{e.code==="commander.unknownCommand"&&process.exit(0);});process.argv.length<=2&&i.help({error:false});i.command("run").description("Run routes from a single TypeScript/JavaScript file").argument("<file>","Path to a file containing routes").argument("[args...]","CLI command and flags to pass through to CLI adapter routes").option("--env <path>","Load environment variables from a .env file (default: .env)").passThroughOptions().action(async(e,o,s)=>{let t=i.opts();t.logLevel!==void 0&&(process.env.LOG_LEVEL=t.logLevel,process.env.CRAFT_LOG_LEVEL=t.logLevel),t.logFile!==void 0&&(process.env.LOG_FILE=t.logFile,process.env.CRAFT_LOG_FILE=t.logFile);let{loadEnvFile:a}=await import('./util-GX4G3K5I.js');s.env!==void 0?a(s.env):a();let{runCommand:u}=await import('./run-3Y3G7OTJ.js'),r=await u(e,o);if(!r.success){r.message&&console.error(r.message);let c=r.code??1;setImmediate(()=>process.exit(c));return}});i.command("tui").description("Launch the Terminal UI to monitor Routecraft execution history").option("--db <path>","Path to the telemetry SQLite database",".routecraft/telemetry.db").action(async e=>{let{resolve:o,isAbsolute:s}=await import('path'),t=s(e.db)?e.db:o(process.cwd(),e.db),{renderTui:a}=await import('./tui/app.js');await a(t);});i.parse();//# sourceMappingURL=index.js.map
2
+ var n={major:1,minor:1,patch:0},l="https://bun.com/docs/installation",g="https://routecraft.dev/docs/advanced/programmatic-invocation";function f(e=process.versions.bun??null){let o=e;if(!o)return {ok:false,message:`[routecraft] The craft CLI requires Bun. Install Bun from ${l}, or embed @routecraft/routecraft programmatically (see ${g}).`};let s=o.split(/[-+]/)[0]??"",[t,a,u]=s.split("."),r=Number(t),c=Number(a),m=Number(u??"0");return !Number.isFinite(r)||!Number.isFinite(c)||!Number.isFinite(m)?{ok:false,message:`[routecraft] Could not parse Bun version "${o}". Routecraft requires Bun ${p(n)} or later. Upgrade Bun: ${l}.`}:r>n.major||r===n.major&&(c>n.minor||c===n.minor&&m>=n.patch)?{ok:true}:{ok:false,message:`[routecraft] Bun ${o} is not supported. Routecraft requires Bun ${p(n)} or later. Upgrade Bun: ${l}.`}}function p(e){return `${e.major}.${e.minor}.${e.patch}`}var d=f();d.ok||(console.error(d.message),process.exit(1));var{Command:h}=await import('commander'),i=new h;i.name("craft").description("A modern routing framework for TypeScript").version("0.5.0-canary.45").enablePositionalOptions().option("--log-level <level>","Log level (e.g. info, warn, error, silent to disable)").option("--log-file <path>","Write logs to a file instead of stdout").showSuggestionAfterError().showHelpAfterError().exitOverride(e=>{e.code==="commander.unknownCommand"&&process.exit(0);});process.argv.length<=2&&i.help({error:false});i.command("run").description("Run routes from a single TypeScript/JavaScript file").argument("<file>","Path to a file containing routes").argument("[args...]","CLI command and flags to pass through to CLI adapter routes").option("--env <path>","Load environment variables from a .env file (default: .env)").passThroughOptions().action(async(e,o,s)=>{let t=i.opts();t.logLevel!==void 0&&(process.env.LOG_LEVEL=t.logLevel,process.env.CRAFT_LOG_LEVEL=t.logLevel),t.logFile!==void 0&&(process.env.LOG_FILE=t.logFile,process.env.CRAFT_LOG_FILE=t.logFile);let{loadEnvFile:a}=await import('./util-GX4G3K5I.js');s.env!==void 0?a(s.env):a();let{runCommand:u}=await import('./run-3Y3G7OTJ.js'),r=await u(e,o);if(!r.success){r.message&&console.error(r.message);let c=r.code??1;setImmediate(()=>process.exit(c));return}});i.command("tui").description("Launch the Terminal UI to monitor Routecraft execution history").option("--db <path>","Path to the telemetry SQLite database",".routecraft/telemetry.db").action(async e=>{let{resolve:o,isAbsolute:s}=await import('path'),t=s(e.db)?e.db:o(process.cwd(),e.db),{renderTui:a}=await import('./tui/app.js');await a(t);});i.parse();//# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/runtime-gate.ts","../src/index.ts"],"names":["MIN_BUN_VERSION","INSTALL_URL","EMBEDDING_DOC_URL","checkBunRuntime","bunVersion","version","stripped","majorStr","minorStr","patchStr","major","minor","patch","formatVersion","v","gate","Command","program","err","filePath","args","options","globalOpts","loadEnvFile","runCommand","result","code","resolve","isAbsolute","dbPath","renderTui"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Runtime gate for the craft CLI.\n *\n * The CLI is Bun-only. Users on Node embed @routecraft/routecraft\n * programmatically instead of going through the CLI.\n *\n * Exposed as a pure function so unit tests can pass arbitrary version strings\n * without spawning real bun processes.\n */\n\nconst MIN_BUN_VERSION = { major: 1, minor: 1, patch: 0 } as const;\n\nconst INSTALL_URL = \"https://bun.com/docs/installation\";\nconst EMBEDDING_DOC_URL =\n \"https://routecraft.dev/docs/advanced/programmatic-invocation\";\n\nexport type RuntimeGateResult = { ok: true } | { ok: false; message: string };\n\n// Accept `null` (not `undefined`) to express \"not running on Bun\" so tests can\n// reliably exercise the missing-bun path. JS default-parameter semantics\n// re-apply the default for explicit `undefined`, which would otherwise let\n// `process.versions.bun` leak in when the suite runs under Bun.\nexport function checkBunRuntime(\n bunVersion: string | null = process.versions[\"bun\"] ?? null,\n): RuntimeGateResult {\n const version = bunVersion;\n\n if (!version) {\n return {\n ok: false,\n message:\n `[routecraft] The craft CLI requires Bun. ` +\n `Install Bun from ${INSTALL_URL}, ` +\n `or embed @routecraft/routecraft programmatically (see ${EMBEDDING_DOC_URL}).`,\n };\n }\n\n // Strip both prerelease (`-`) and build metadata (`+`) per SemVer.\n const stripped = version.split(/[-+]/)[0] ?? \"\";\n const [majorStr, minorStr, patchStr] = stripped.split(\".\");\n const major = Number(majorStr);\n const minor = Number(minorStr);\n const patch = Number(patchStr ?? \"0\");\n\n if (\n !Number.isFinite(major) ||\n !Number.isFinite(minor) ||\n !Number.isFinite(patch)\n ) {\n return {\n ok: false,\n message:\n `[routecraft] Could not parse Bun version \"${version}\". ` +\n `Routecraft requires Bun ${formatVersion(MIN_BUN_VERSION)} or later. ` +\n `Upgrade Bun: ${INSTALL_URL}.`,\n };\n }\n\n const meetsFloor =\n major > MIN_BUN_VERSION.major ||\n (major === MIN_BUN_VERSION.major &&\n (minor > MIN_BUN_VERSION.minor ||\n (minor === MIN_BUN_VERSION.minor && patch >= MIN_BUN_VERSION.patch)));\n\n if (!meetsFloor) {\n return {\n ok: false,\n message:\n `[routecraft] Bun ${version} is not supported. ` +\n `Routecraft requires Bun ${formatVersion(MIN_BUN_VERSION)} or later. ` +\n `Upgrade Bun: ${INSTALL_URL}.`,\n };\n }\n\n return { ok: true };\n}\n\nfunction formatVersion(v: typeof MIN_BUN_VERSION): string {\n return `${v.major}.${v.minor}.${v.patch}`;\n}\n","#!/usr/bin/env bun\n\n/**\n * Routecraft CLI: single entry point.\n *\n * The CLI runs on Bun. For Node-based usage, embed @routecraft/routecraft\n * programmatically (see https://routecraft.dev/docs/advanced/programmatic-invocation).\n *\n * 1. Bun runtime gate (presence + version floor)\n * 2. Define program and parse; log options are global and applied before\n * lazy-loading run/util (which load the logger)\n */\n\nimport { checkBunRuntime } from \"./runtime-gate.js\";\n\n// ── 1. Bun runtime gate ─────────────────────────────────────────────\nconst gate = checkBunRuntime();\nif (!gate.ok) {\n // eslint-disable-next-line no-console\n console.error(gate.message);\n process.exit(1);\n}\n\n// ── 2. CLI definition (only Commander; run/util are lazy-loaded so logger sees env) ─\nconst { Command } = await import(\"commander\");\nconst program = new Command();\n\nprogram\n .name(\"craft\")\n .description(\"A modern routing framework for TypeScript\")\n .version(\"0.5.0-canary.44\")\n .enablePositionalOptions()\n .option(\n \"--log-level <level>\",\n \"Log level (e.g. info, warn, error, silent to disable)\",\n )\n .option(\"--log-file <path>\", \"Write logs to a file instead of stdout\")\n .showSuggestionAfterError()\n .showHelpAfterError()\n .exitOverride((err) => {\n if (err.code === \"commander.unknownCommand\") {\n process.exit(0);\n }\n });\n\n// Show help by default if no arguments provided\nif (process.argv.length <= 2) {\n program.help({ error: false });\n}\n\n/**\n * The 'run' command executes routes from a single file.\n *\n * Example:\n * craft run ./my-routes.ts\n * craft run ./my-cli.ts greet --name World\n */\nprogram\n .command(\"run\")\n .description(\"Run routes from a single TypeScript/JavaScript file\")\n .argument(\"<file>\", \"Path to a file containing routes\")\n .argument(\n \"[args...]\",\n \"CLI command and flags to pass through to CLI adapter routes\",\n )\n .option(\n \"--env <path>\",\n \"Load environment variables from a .env file (default: .env)\",\n )\n .passThroughOptions()\n .action(async (filePath, args: string[], options) => {\n // Apply global log options to env before any import that creates the logger\n const globalOpts = program.opts();\n if (globalOpts[\"logLevel\"] !== undefined) {\n process.env[\"LOG_LEVEL\"] = globalOpts[\"logLevel\"];\n process.env[\"CRAFT_LOG_LEVEL\"] = globalOpts[\"logLevel\"];\n }\n if (globalOpts[\"logFile\"] !== undefined) {\n process.env[\"LOG_FILE\"] = globalOpts[\"logFile\"];\n process.env[\"CRAFT_LOG_FILE\"] = globalOpts[\"logFile\"];\n }\n\n const { loadEnvFile } = await import(\"./util.js\");\n if (options.env !== undefined) {\n loadEnvFile(options.env);\n } else {\n loadEnvFile();\n }\n\n const { runCommand } = await import(\"./run.js\");\n const result = await runCommand(filePath, args);\n if (!result.success) {\n if (result.message) {\n // eslint-disable-next-line no-console\n console.error(result.message);\n }\n // Defer exit so pino/sonic-boom can finish initializing and avoid \"sonic boom is not ready yet\"\n const code = result.code ?? 1;\n setImmediate(() => process.exit(code));\n return;\n }\n // Don't call process.exit(); let the event loop drain naturally.\n // process.exit() triggers C++ static destructors that race with ONNX\n // Runtime cleanup (onnxruntime#25038: \"mutex lock failed\").\n });\n\n/**\n * The 'tui' command launches the Terminal UI for monitoring Routecraft execution.\n *\n * Example:\n * craft tui\n * craft tui --db .routecraft/telemetry.db\n */\nprogram\n .command(\"tui\")\n .description(\"Launch the Terminal UI to monitor Routecraft execution history\")\n .option(\n \"--db <path>\",\n \"Path to the telemetry SQLite database\",\n \".routecraft/telemetry.db\",\n )\n .action(async (options) => {\n const { resolve, isAbsolute } = await import(\"node:path\");\n const dbPath = isAbsolute(options.db)\n ? options.db\n : resolve(process.cwd(), options.db);\n\n const { renderTui } = await import(\"./tui/app.js\");\n await renderTui(dbPath);\n });\n\n// Parse the command line arguments and execute the appropriate command\nprogram.parse();\n"]}
1
+ {"version":3,"sources":["../src/runtime-gate.ts","../src/index.ts"],"names":["MIN_BUN_VERSION","INSTALL_URL","EMBEDDING_DOC_URL","checkBunRuntime","bunVersion","version","stripped","majorStr","minorStr","patchStr","major","minor","patch","formatVersion","v","gate","Command","program","err","filePath","args","options","globalOpts","loadEnvFile","runCommand","result","code","resolve","isAbsolute","dbPath","renderTui"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Runtime gate for the craft CLI.\n *\n * The CLI is Bun-only. Users on Node embed @routecraft/routecraft\n * programmatically instead of going through the CLI.\n *\n * Exposed as a pure function so unit tests can pass arbitrary version strings\n * without spawning real bun processes.\n */\n\nconst MIN_BUN_VERSION = { major: 1, minor: 1, patch: 0 } as const;\n\nconst INSTALL_URL = \"https://bun.com/docs/installation\";\nconst EMBEDDING_DOC_URL =\n \"https://routecraft.dev/docs/advanced/programmatic-invocation\";\n\nexport type RuntimeGateResult = { ok: true } | { ok: false; message: string };\n\n// Accept `null` (not `undefined`) to express \"not running on Bun\" so tests can\n// reliably exercise the missing-bun path. JS default-parameter semantics\n// re-apply the default for explicit `undefined`, which would otherwise let\n// `process.versions.bun` leak in when the suite runs under Bun.\nexport function checkBunRuntime(\n bunVersion: string | null = process.versions[\"bun\"] ?? null,\n): RuntimeGateResult {\n const version = bunVersion;\n\n if (!version) {\n return {\n ok: false,\n message:\n `[routecraft] The craft CLI requires Bun. ` +\n `Install Bun from ${INSTALL_URL}, ` +\n `or embed @routecraft/routecraft programmatically (see ${EMBEDDING_DOC_URL}).`,\n };\n }\n\n // Strip both prerelease (`-`) and build metadata (`+`) per SemVer.\n const stripped = version.split(/[-+]/)[0] ?? \"\";\n const [majorStr, minorStr, patchStr] = stripped.split(\".\");\n const major = Number(majorStr);\n const minor = Number(minorStr);\n const patch = Number(patchStr ?? \"0\");\n\n if (\n !Number.isFinite(major) ||\n !Number.isFinite(minor) ||\n !Number.isFinite(patch)\n ) {\n return {\n ok: false,\n message:\n `[routecraft] Could not parse Bun version \"${version}\". ` +\n `Routecraft requires Bun ${formatVersion(MIN_BUN_VERSION)} or later. ` +\n `Upgrade Bun: ${INSTALL_URL}.`,\n };\n }\n\n const meetsFloor =\n major > MIN_BUN_VERSION.major ||\n (major === MIN_BUN_VERSION.major &&\n (minor > MIN_BUN_VERSION.minor ||\n (minor === MIN_BUN_VERSION.minor && patch >= MIN_BUN_VERSION.patch)));\n\n if (!meetsFloor) {\n return {\n ok: false,\n message:\n `[routecraft] Bun ${version} is not supported. ` +\n `Routecraft requires Bun ${formatVersion(MIN_BUN_VERSION)} or later. ` +\n `Upgrade Bun: ${INSTALL_URL}.`,\n };\n }\n\n return { ok: true };\n}\n\nfunction formatVersion(v: typeof MIN_BUN_VERSION): string {\n return `${v.major}.${v.minor}.${v.patch}`;\n}\n","#!/usr/bin/env bun\n\n/**\n * Routecraft CLI: single entry point.\n *\n * The CLI runs on Bun. For Node-based usage, embed @routecraft/routecraft\n * programmatically (see https://routecraft.dev/docs/advanced/programmatic-invocation).\n *\n * 1. Bun runtime gate (presence + version floor)\n * 2. Define program and parse; log options are global and applied before\n * lazy-loading run/util (which load the logger)\n */\n\nimport { checkBunRuntime } from \"./runtime-gate.js\";\n\n// ── 1. Bun runtime gate ─────────────────────────────────────────────\nconst gate = checkBunRuntime();\nif (!gate.ok) {\n // eslint-disable-next-line no-console\n console.error(gate.message);\n process.exit(1);\n}\n\n// ── 2. CLI definition (only Commander; run/util are lazy-loaded so logger sees env) ─\nconst { Command } = await import(\"commander\");\nconst program = new Command();\n\nprogram\n .name(\"craft\")\n .description(\"A modern routing framework for TypeScript\")\n .version(\"0.5.0-canary.45\")\n .enablePositionalOptions()\n .option(\n \"--log-level <level>\",\n \"Log level (e.g. info, warn, error, silent to disable)\",\n )\n .option(\"--log-file <path>\", \"Write logs to a file instead of stdout\")\n .showSuggestionAfterError()\n .showHelpAfterError()\n .exitOverride((err) => {\n if (err.code === \"commander.unknownCommand\") {\n process.exit(0);\n }\n });\n\n// Show help by default if no arguments provided\nif (process.argv.length <= 2) {\n program.help({ error: false });\n}\n\n/**\n * The 'run' command executes routes from a single file.\n *\n * Example:\n * craft run ./my-routes.ts\n * craft run ./my-cli.ts greet --name World\n */\nprogram\n .command(\"run\")\n .description(\"Run routes from a single TypeScript/JavaScript file\")\n .argument(\"<file>\", \"Path to a file containing routes\")\n .argument(\n \"[args...]\",\n \"CLI command and flags to pass through to CLI adapter routes\",\n )\n .option(\n \"--env <path>\",\n \"Load environment variables from a .env file (default: .env)\",\n )\n .passThroughOptions()\n .action(async (filePath, args: string[], options) => {\n // Apply global log options to env before any import that creates the logger\n const globalOpts = program.opts();\n if (globalOpts[\"logLevel\"] !== undefined) {\n process.env[\"LOG_LEVEL\"] = globalOpts[\"logLevel\"];\n process.env[\"CRAFT_LOG_LEVEL\"] = globalOpts[\"logLevel\"];\n }\n if (globalOpts[\"logFile\"] !== undefined) {\n process.env[\"LOG_FILE\"] = globalOpts[\"logFile\"];\n process.env[\"CRAFT_LOG_FILE\"] = globalOpts[\"logFile\"];\n }\n\n const { loadEnvFile } = await import(\"./util.js\");\n if (options.env !== undefined) {\n loadEnvFile(options.env);\n } else {\n loadEnvFile();\n }\n\n const { runCommand } = await import(\"./run.js\");\n const result = await runCommand(filePath, args);\n if (!result.success) {\n if (result.message) {\n // eslint-disable-next-line no-console\n console.error(result.message);\n }\n // Defer exit so pino/sonic-boom can finish initializing and avoid \"sonic boom is not ready yet\"\n const code = result.code ?? 1;\n setImmediate(() => process.exit(code));\n return;\n }\n // Don't call process.exit(); let the event loop drain naturally.\n // process.exit() triggers C++ static destructors that race with ONNX\n // Runtime cleanup (onnxruntime#25038: \"mutex lock failed\").\n });\n\n/**\n * The 'tui' command launches the Terminal UI for monitoring Routecraft execution.\n *\n * Example:\n * craft tui\n * craft tui --db .routecraft/telemetry.db\n */\nprogram\n .command(\"tui\")\n .description(\"Launch the Terminal UI to monitor Routecraft execution history\")\n .option(\n \"--db <path>\",\n \"Path to the telemetry SQLite database\",\n \".routecraft/telemetry.db\",\n )\n .action(async (options) => {\n const { resolve, isAbsolute } = await import(\"node:path\");\n const dbPath = isAbsolute(options.db)\n ? options.db\n : resolve(process.cwd(), options.db);\n\n const { renderTui } = await import(\"./tui/app.js\");\n await renderTui(dbPath);\n });\n\n// Parse the command line arguments and execute the appropriate command\nprogram.parse();\n"]}
package/dist/tui/app.js CHANGED
@@ -1,6 +1,6 @@
1
- import {a}from'../chunk-DPJWCR2V.js';import {useState,useCallback,useEffect,Fragment as Fragment$1}from'react';import {render,useApp,useStdout,useInput,Box,Text}from'ink';import {jsx,jsxs,Fragment}from'react/jsx-runtime';var st=[{items:[{key:"capabilities",label:"Capabilities",shortcut:"1"}]},{items:[{key:"exchanges",label:"Exchanges",shortcut:"2"},{key:"errors",label:"Errors",shortcut:"3"},{key:"events",label:"Events",shortcut:"4"}]}],Ct=st.flatMap(e=>e.items);function ge(e,t){return t<=0?"":e.length>t?e.slice(0,t-1)+"\u2026":e}function _(e){return e==null||!Number.isFinite(e)||e<0?"-":e===0?"<1ms":e<1e3?`${Math.round(e)}ms`:`${(e/1e3).toFixed(1)}s`}function oe(e){switch(e){case "completed":case "started":return "green";case "failed":return "red";case "stopped":case "dropped":return "yellow";default:return "white"}}function N(e,t){return t===void 0?e:t<=0?"":e.length>t?e.slice(0,t-1)+"\u2026":e.padEnd(t)}function Ut(e){try{let t=JSON.parse(e),o="exchangeId"in t?`${String(t.exchangeId).slice(0,8)}`:"",s="duration"in t?_(t.duration):"";if("operation"in t&&"routeId"in t){let r="adapter"in t?`(${t.adapter})`:"adapterId"in t?`(${t.adapterId})`:"",n="";if("metadata"in t&&typeof t.metadata=="object"&&t.metadata!==null){let u=t.metadata,l=Object.keys(u).slice(0,2);l.length>0&&(n=l.map(m=>`${m}=${u[m]}`).join(" "));}return {step:String(t.operation),adapter:r,exchange:o,duration:s,meta:n}}if("routeId"in t&&"exchangeId"in t){let r="error"in t?"(err)":"reason"in t?`(${String(t.reason).slice(0,8)})`:"";return {step:String(t.routeId),adapter:r,exchange:o,duration:s,meta:""}}if("route"in t&&typeof t.route=="object"&&t.route!==null){let r=t.route;return {step:r.routeId??r.definition?.id??"?",adapter:"",exchange:"",duration:"",meta:""}}if("pluginId"in t)return {step:`plugin=${t.pluginId}`,adapter:"",exchange:"",duration:"",meta:""};if("error"in t){let r=t.error;return {step:typeof r=="object"&&r!==null&&"message"in r?String(r.message):String(r),adapter:"",exchange:"",duration:"",meta:""}}return null}catch{return null}}function Dt(e,t){let o=Ut(t);return o||{step:t,adapter:"",exchange:"",duration:"",meta:""}}function q(e){return e.toLocaleString("en-US")}function at(e,t,o){return o<=0?t:e<t?e:e>=t+o?e-o+1:t}function Ce(e=0){let[t,o]=useState(e),[s,r]=useState(0),n=useCallback((m,d,g)=>{let p=Math.max(0,Math.min(m,d-1));o(p),r(f=>at(p,f,g));},[]),u=useCallback((m,d,g)=>{o(p=>{let f=Math.max(0,Math.min(p+m,d-1));return r(i=>at(f,i,g)),f});},[]),l=useCallback(()=>{o(0),r(0);},[]);return {selectedIndex:t,scrollOffset:s,moveBy:u,moveTo:n,reset:l}}function S({title:e,subtitle:t,color:o="gray",width:s,flexGrow:r,paddingX:n=1,children:u}){let l=s?s-2-n*2:20;return jsxs(Box,{flexDirection:"column",borderStyle:"round",borderColor:o,paddingX:n,width:s,flexGrow:r,children:[e&&jsxs(Fragment,{children:[jsxs(Text,{bold:true,children:[e,t&&jsxs(Fragment,{children:[" ",t]})]}),jsx(Text,{dimColor:true,children:"\u2500".repeat(Math.max(l,1))})]}),u]})}var Kt=[192,36,18,9],qt=10240,De=[{max:0,color:"gray"},{max:10,color:"green"},{max:20,color:"green"},{max:30,color:"yellow"},{max:40,color:"yellow"},{max:50,color:"red"}];function He({values:e,columns:t,steps:o=De,label:s}){let r=o.length-1,n=e.length>=t?e.slice(e.length-t):[...new Array(t-e.length).fill(0),...e],u=n.map(d=>{if(d<=0)return 0;for(let g=1;g<o.length;g++)if(d<o[g].max)return g;return r}),l=Math.ceil(r/4),m=[];for(let d=l-1;d>=0;d--){let g=d*4,p=[];for(let f=0;f<n.length;f++){let i=u[f],y=0,k="";for(let W=0;W<4;W++){let E=g+W+1;if(E>r)break;(i>=E||i===0&&E===1)&&(y|=Kt[W],k=i===0?o[0].color:o[E].color);}let L=String.fromCharCode(qt+y),K=p[p.length-1];K&&K.color===k?K.text+=L:p.push({text:L,color:k});}m.push(jsx(Text,{children:p.map((f,i)=>f.color?jsx(Text,{color:f.color,children:f.text},i):jsx(Text,{children:f.text},i))},d));}return jsxs(Fragment,{children:[m,s&&jsx(Text,{dimColor:true,children:s})]})}function Nt({route:e}){return jsxs(Fragment,{children:[jsxs(Text,{children:["Capability:"," ",jsx(Text,{bold:true,color:"cyan",children:e.id})]}),jsxs(Text,{children:["Status:"," ",jsx(Text,{bold:true,color:oe(e.status),children:e.status})," ","Exchanges: ",jsx(Text,{bold:true,children:q(e.totalExchanges)})," ","Errors:"," ",jsx(Text,{bold:true,...e.failedExchanges>0?{color:"red"}:{},children:q(e.failedExchanges)})," ","Dropped:"," ",jsx(Text,{bold:true,...e.droppedExchanges>0?{color:"yellow"}:{},children:q(e.droppedExchanges)})," ","Avg: ",jsx(Text,{bold:true,children:_(e.avgDurationMs)})]})]})}function Ee({columns:e,data:t,rowKey:o,selectedIndex:s,scrollOffset:r,visibleRows:n,gap:u=2,emptyMessage:l="No data",renderFullRow:m}){let d=" ".repeat(u),g=jsx(Box,{children:e.map((i,y)=>{let L=y===e.length-1?"":d;if(i.width==="flex")return jsxs(Fragment$1,{children:[jsx(Box,{flexGrow:1,children:jsx(Text,{bold:true,dimColor:true,children:i.header})}),L&&jsx(Text,{children:L})]},y);let K=i.align==="right"?i.header.padStart(i.width):N(i.header,i.width);return jsxs(Fragment$1,{children:[jsx(Text,{bold:true,dimColor:true,children:K}),L&&jsx(Text,{children:L})]},y)})});if(t.length===0)return jsxs(Fragment,{children:[g,jsx(Text,{dimColor:true,children:l})]});let p=t.slice(r,r+n),f=t.length-r-n;return jsxs(Fragment,{children:[g,p.map((i,y)=>{let k=r+y,L=k===s,K=m?.(i,k);return K!==void 0?jsx(Box,{children:K},o(i,k)):jsx(Box,{children:e.map((W,E)=>{let O=E===e.length-1?"":d,T=W.width==="flex"?void 0:W.width,w=W.render(i,L,T);return W.width==="flex"?jsxs(Fragment$1,{children:[jsx(Box,{flexGrow:1,children:jsx(Text,{wrap:"truncate",children:w})}),O&&jsx(Text,{children:O})]},E):jsxs(Fragment$1,{children:[w,O&&jsx(Text,{children:O})]},E)})},o(i,k))}),jsx(Text,{dimColor:true,children:f>0?"\u2193 more":" "})]})}function Je(e){let t=new WeakMap;function o(s){let r=e(s);if(!r)return;let n=t.get(r);return n||(n=Dt(r.eventName,r.details),t.set(r,n)),n}return [{header:"Step",width:10,render:(s,r,n)=>{let u=o(s);return u?jsx(Text,{children:N(u.step,n)}):jsx(Text,{children:N("",n)})}},{header:"Adapter",width:10,render:(s,r,n)=>{let u=o(s);return u?jsx(Text,{children:N(u.adapter,n)}):jsx(Text,{children:N("",n)})}},{header:"Exchange",width:12,render:(s,r,n)=>{let u=o(s);return u?jsx(Text,{children:N(u.exchange,n)}):jsx(Text,{children:N("",n)})}},{header:"Duration",width:8,align:"right",render:s=>{let r=o(s);return r?jsx(Text,{children:r.duration.padStart(8)}):jsx(Text,{children:""})}}]}function Te(){return {header:"",width:2,render:(e,t)=>jsx(Text,{...t?{color:"cyan"}:{},bold:t,children:t?"> ":" "})}}var er=[Te(),{header:"ID",width:"flex",render:(e,t)=>jsx(Text,{...t?{color:"cyan"}:{},bold:t,children:e.id})},{header:"Status",width:9,render:(e,t,o)=>jsx(Text,{color:oe(e.status),children:N(e.status,o)})},{header:"Duration",width:8,align:"right",render:e=>jsx(Text,{children:_(e.durationMs).padStart(8)})},{header:"Time",width:8,render:(e,t,o)=>jsx(Text,{dimColor:true,children:N(e.startedAt.replace("T"," ").slice(11,19),o)})}];function Ve({capabilityId:e,route:t,exchanges:o,selectedIndex:s,scrollOffset:r,width:n,height:u,color:l="gray",activity:m}){let d=Math.ceil((De.length-1)/4),g=t?2+d+2:0,p=Math.max(u-6-g,3),f=t?"EXCHANGES":`EXCHANGES: ${e}`;return jsxs(Box,{flexDirection:"column",width:n,flexGrow:1,children:[t&&jsxs(S,{width:n,children:[jsx(Nt,{route:t}),jsx(Text,{children:" "}),jsx(He,{values:m?m.throughput:[],columns:n-4,label:"Exchanges per 5s bucket"})]}),jsx(S,{title:f,width:n,flexGrow:1,color:l,children:jsx(Ee,{columns:er,data:o,rowKey:i=>i.id+i.contextId,selectedIndex:s,scrollOffset:r,visibleRows:p,emptyMessage:"No exchanges"})})]})}function tr(e){let t=[],o=/("(?:[^"\\]|\\.)*")\s*:|("(?:[^"\\]|\\.)*")|(-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)|(\btrue\b|\bfalse\b)|(\bnull\b)|([{}[\],:])/g,s=0,r;for(;(r=o.exec(e))!==null;)r.index>s&&t.push({text:e.slice(s,r.index),type:"brace"}),r[1]!==void 0?(t.push({text:r[1],type:"key"}),t.push({text:":",type:"brace"})):r[2]!==void 0?t.push({text:r[2],type:"string"}):r[3]!==void 0?t.push({text:r[3],type:"number"}):r[4]!==void 0?t.push({text:r[4],type:"boolean"}):r[5]!==void 0?t.push({text:r[5],type:"null"}):r[6]!==void 0&&t.push({text:r[6],type:"brace"}),s=r.index+r[0].length;return s<e.length&&t.push({text:e.slice(s),type:"brace"}),t}var rr={key:"cyan",string:"green",number:"yellow",boolean:"yellow",null:"red",brace:"gray"};function Ae(e,t){try{let o=JSON.parse(e);return JSON.stringify(o,null,2).split(`
1
+ import {a}from'../chunk-3CIF67XJ.js';import {useState,useCallback,useEffect,Fragment as Fragment$1}from'react';import {render,useApp,useStdout,useInput,Box,Text}from'ink';import {jsx,jsxs,Fragment}from'react/jsx-runtime';var st=[{items:[{key:"capabilities",label:"Capabilities",shortcut:"1"}]},{items:[{key:"exchanges",label:"Exchanges",shortcut:"2"},{key:"errors",label:"Errors",shortcut:"3"},{key:"events",label:"Events",shortcut:"4"}]}],Ct=st.flatMap(e=>e.items);function ge(e,t){return t<=0?"":e.length>t?e.slice(0,t-1)+"\u2026":e}function _(e){return e==null||!Number.isFinite(e)||e<0?"-":e===0?"<1ms":e<1e3?`${Math.round(e)}ms`:`${(e/1e3).toFixed(1)}s`}function oe(e){switch(e){case "completed":case "started":return "green";case "failed":return "red";case "stopped":case "dropped":return "yellow";default:return "white"}}function N(e,t){return t===void 0?e:t<=0?"":e.length>t?e.slice(0,t-1)+"\u2026":e.padEnd(t)}function Ut(e){try{let t=JSON.parse(e),o="exchangeId"in t?`${String(t.exchangeId).slice(0,8)}`:"",s="duration"in t?_(t.duration):"";if("operation"in t&&"routeId"in t){let r="adapter"in t?`(${t.adapter})`:"adapterId"in t?`(${t.adapterId})`:"",n="";if("metadata"in t&&typeof t.metadata=="object"&&t.metadata!==null){let u=t.metadata,l=Object.keys(u).slice(0,2);l.length>0&&(n=l.map(m=>`${m}=${u[m]}`).join(" "));}return {step:String(t.operation),adapter:r,exchange:o,duration:s,meta:n}}if("routeId"in t&&"exchangeId"in t){let r="error"in t?"(err)":"reason"in t?`(${String(t.reason).slice(0,8)})`:"";return {step:String(t.routeId),adapter:r,exchange:o,duration:s,meta:""}}if("route"in t&&typeof t.route=="object"&&t.route!==null){let r=t.route;return {step:r.routeId??r.definition?.id??"?",adapter:"",exchange:"",duration:"",meta:""}}if("pluginId"in t)return {step:`plugin=${t.pluginId}`,adapter:"",exchange:"",duration:"",meta:""};if("error"in t){let r=t.error;return {step:typeof r=="object"&&r!==null&&"message"in r?String(r.message):String(r),adapter:"",exchange:"",duration:"",meta:""}}return null}catch{return null}}function Dt(e,t){let o=Ut(t);return o||{step:t,adapter:"",exchange:"",duration:"",meta:""}}function q(e){return e.toLocaleString("en-US")}function at(e,t,o){return o<=0?t:e<t?e:e>=t+o?e-o+1:t}function Ce(e=0){let[t,o]=useState(e),[s,r]=useState(0),n=useCallback((m,d,g)=>{let p=Math.max(0,Math.min(m,d-1));o(p),r(f=>at(p,f,g));},[]),u=useCallback((m,d,g)=>{o(p=>{let f=Math.max(0,Math.min(p+m,d-1));return r(i=>at(f,i,g)),f});},[]),l=useCallback(()=>{o(0),r(0);},[]);return {selectedIndex:t,scrollOffset:s,moveBy:u,moveTo:n,reset:l}}function S({title:e,subtitle:t,color:o="gray",width:s,flexGrow:r,paddingX:n=1,children:u}){let l=s?s-2-n*2:20;return jsxs(Box,{flexDirection:"column",borderStyle:"round",borderColor:o,paddingX:n,width:s,flexGrow:r,children:[e&&jsxs(Fragment,{children:[jsxs(Text,{bold:true,children:[e,t&&jsxs(Fragment,{children:[" ",t]})]}),jsx(Text,{dimColor:true,children:"\u2500".repeat(Math.max(l,1))})]}),u]})}var Kt=[192,36,18,9],qt=10240,De=[{max:0,color:"gray"},{max:10,color:"green"},{max:20,color:"green"},{max:30,color:"yellow"},{max:40,color:"yellow"},{max:50,color:"red"}];function He({values:e,columns:t,steps:o=De,label:s}){let r=o.length-1,n=e.length>=t?e.slice(e.length-t):[...new Array(t-e.length).fill(0),...e],u=n.map(d=>{if(d<=0)return 0;for(let g=1;g<o.length;g++)if(d<o[g].max)return g;return r}),l=Math.ceil(r/4),m=[];for(let d=l-1;d>=0;d--){let g=d*4,p=[];for(let f=0;f<n.length;f++){let i=u[f],y=0,k="";for(let X=0;X<4;X++){let E=g+X+1;if(E>r)break;(i>=E||i===0&&E===1)&&(y|=Kt[X],k=i===0?o[0].color:o[E].color);}let L=String.fromCharCode(qt+y),K=p[p.length-1];K&&K.color===k?K.text+=L:p.push({text:L,color:k});}m.push(jsx(Text,{children:p.map((f,i)=>f.color?jsx(Text,{color:f.color,children:f.text},i):jsx(Text,{children:f.text},i))},d));}return jsxs(Fragment,{children:[m,s&&jsx(Text,{dimColor:true,children:s})]})}function Nt({route:e}){return jsxs(Fragment,{children:[jsxs(Text,{children:["Capability:"," ",jsx(Text,{bold:true,color:"cyan",children:e.id})]}),jsxs(Text,{children:["Status:"," ",jsx(Text,{bold:true,color:oe(e.status),children:e.status})," ","Exchanges: ",jsx(Text,{bold:true,children:q(e.totalExchanges)})," ","Errors:"," ",jsx(Text,{bold:true,...e.failedExchanges>0?{color:"red"}:{},children:q(e.failedExchanges)})," ","Dropped:"," ",jsx(Text,{bold:true,...e.droppedExchanges>0?{color:"yellow"}:{},children:q(e.droppedExchanges)})," ","Avg: ",jsx(Text,{bold:true,children:_(e.avgDurationMs)})]})]})}function Ee({columns:e,data:t,rowKey:o,selectedIndex:s,scrollOffset:r,visibleRows:n,gap:u=2,emptyMessage:l="No data",renderFullRow:m}){let d=" ".repeat(u),g=jsx(Box,{children:e.map((i,y)=>{let L=y===e.length-1?"":d;if(i.width==="flex")return jsxs(Fragment$1,{children:[jsx(Box,{flexGrow:1,children:jsx(Text,{bold:true,dimColor:true,children:i.header})}),L&&jsx(Text,{children:L})]},y);let K=i.align==="right"?i.header.padStart(i.width):N(i.header,i.width);return jsxs(Fragment$1,{children:[jsx(Text,{bold:true,dimColor:true,children:K}),L&&jsx(Text,{children:L})]},y)})});if(t.length===0)return jsxs(Fragment,{children:[g,jsx(Text,{dimColor:true,children:l})]});let p=t.slice(r,r+n),f=t.length-r-n;return jsxs(Fragment,{children:[g,p.map((i,y)=>{let k=r+y,L=k===s,K=m?.(i,k);return K!==void 0?jsx(Box,{children:K},o(i,k)):jsx(Box,{children:e.map((X,E)=>{let O=E===e.length-1?"":d,T=X.width==="flex"?void 0:X.width,w=X.render(i,L,T);return X.width==="flex"?jsxs(Fragment$1,{children:[jsx(Box,{flexGrow:1,children:jsx(Text,{wrap:"truncate",children:w})}),O&&jsx(Text,{children:O})]},E):jsxs(Fragment$1,{children:[w,O&&jsx(Text,{children:O})]},E)})},o(i,k))}),jsx(Text,{dimColor:true,children:f>0?"\u2193 more":" "})]})}function Je(e){let t=new WeakMap;function o(s){let r=e(s);if(!r)return;let n=t.get(r);return n||(n=Dt(r.eventName,r.details),t.set(r,n)),n}return [{header:"Step",width:10,render:(s,r,n)=>{let u=o(s);return u?jsx(Text,{children:N(u.step,n)}):jsx(Text,{children:N("",n)})}},{header:"Adapter",width:10,render:(s,r,n)=>{let u=o(s);return u?jsx(Text,{children:N(u.adapter,n)}):jsx(Text,{children:N("",n)})}},{header:"Exchange",width:12,render:(s,r,n)=>{let u=o(s);return u?jsx(Text,{children:N(u.exchange,n)}):jsx(Text,{children:N("",n)})}},{header:"Duration",width:8,align:"right",render:s=>{let r=o(s);return r?jsx(Text,{children:r.duration.padStart(8)}):jsx(Text,{children:""})}}]}function Te(){return {header:"",width:2,render:(e,t)=>jsx(Text,{...t?{color:"cyan"}:{},bold:t,children:t?"> ":" "})}}var er=[Te(),{header:"ID",width:"flex",render:(e,t)=>jsx(Text,{...t?{color:"cyan"}:{},bold:t,children:e.id})},{header:"Status",width:9,render:(e,t,o)=>jsx(Text,{color:oe(e.status),children:N(e.status,o)})},{header:"Duration",width:8,align:"right",render:e=>jsx(Text,{children:_(e.durationMs).padStart(8)})},{header:"Time",width:8,render:(e,t,o)=>jsx(Text,{dimColor:true,children:N(e.startedAt.replace("T"," ").slice(11,19),o)})}];function Ve({capabilityId:e,route:t,exchanges:o,selectedIndex:s,scrollOffset:r,width:n,height:u,color:l="gray",activity:m}){let d=Math.ceil((De.length-1)/4),g=t?2+d+2:0,p=Math.max(u-6-g,3),f=t?"EXCHANGES":`EXCHANGES: ${e}`;return jsxs(Box,{flexDirection:"column",width:n,flexGrow:1,children:[t&&jsxs(S,{width:n,children:[jsx(Nt,{route:t}),jsx(Text,{children:" "}),jsx(He,{values:m?m.throughput:[],columns:n-4,label:"Exchanges per 5s bucket"})]}),jsx(S,{title:f,width:n,flexGrow:1,color:l,children:jsx(Ee,{columns:er,data:o,rowKey:i=>i.id+i.contextId,selectedIndex:s,scrollOffset:r,visibleRows:p,emptyMessage:"No exchanges"})})]})}function tr(e){let t=[],o=/("(?:[^"\\]|\\.)*")\s*:|("(?:[^"\\]|\\.)*")|(-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)|(\btrue\b|\bfalse\b)|(\bnull\b)|([{}[\],:])/g,s=0,r;for(;(r=o.exec(e))!==null;)r.index>s&&t.push({text:e.slice(s,r.index),type:"brace"}),r[1]!==void 0?(t.push({text:r[1],type:"key"}),t.push({text:":",type:"brace"})):r[2]!==void 0?t.push({text:r[2],type:"string"}):r[3]!==void 0?t.push({text:r[3],type:"number"}):r[4]!==void 0?t.push({text:r[4],type:"boolean"}):r[5]!==void 0?t.push({text:r[5],type:"null"}):r[6]!==void 0&&t.push({text:r[6],type:"brace"}),s=r.index+r[0].length;return s<e.length&&t.push({text:e.slice(s),type:"brace"}),t}var rr={key:"cyan",string:"green",number:"yellow",boolean:"yellow",null:"red",brace:"gray"};function Ae(e,t){try{let o=JSON.parse(e);return JSON.stringify(o,null,2).split(`
2
2
  `).map(r=>{let n=Math.max(1,t);return r.length>n?r.slice(0,Math.max(0,n-1))+"\u2026":r})}catch{let o=Math.max(1,t);return e.split(`
3
- `).map(s=>s.length>o?s.slice(0,Math.max(0,o-1))+"\u2026":s)}}function Ue({line:e}){let t=tr(e);return t.length===0?jsx(Text,{children:e}):jsx(Text,{children:t.map((o,s)=>jsx(Text,{color:rr[o.type],children:o.text},s))})}function We(e){try{let t=JSON.parse(e);return typeof t!="object"||t===null||Array.isArray(t)?null:t}catch{return null}}function or(e,t){let o=new Map,s=0;o.set(t,{exchangeId:t,label:"parent",events:[]});for(let r of e){let n=We(r.details),u=n?String(n.exchangeId??""):"",l=!u||u===t?t:u;o.has(l)||(s++,o.set(l,{exchangeId:l,label:`child ${s}`,events:[]})),o.get(l).events.push(r);}return Array.from(o.values())}var sr=[Te(),{header:"Time",width:8,render:(e,t,o)=>{if(!e.event)return jsx(Text,{children:N("",o)});let s=" ".repeat(e.indent);return jsxs(Text,{dimColor:true,children:[s,e.event.timestamp.replace("T"," ").slice(11,19)]})}},{header:"Event",width:"flex",render:e=>e.event?jsx(Text,{color:"cyan",children:e.event.eventName}):jsx(Text,{})},...Je(e=>e.event)];function Xe({exchange:e,events:t,width:o,height:s,scrollOffset:r,selectedIndex:n=-1,color:u="gray"}){let l=e.error?2:0,m=Math.max(s-9-l,3),d=or(t,e.id),g=d.length>1,p=[];for(let i of d){g&&p.push({type:"header",text:`${i.label} (${i.exchangeId.slice(0,8)}) - ${i.events.length} events`,indent:0});for(let y of i.events)p.push({type:"event",event:y,indent:g?2:0});}let f=g?`EXCHANGE FLOW (${d.length} exchanges, ${t.length} events)`:`RELATED EVENTS (${t.length})`;return jsxs(Box,{flexDirection:"column",width:o,flexGrow:1,children:[jsxs(S,{width:o,children:[jsxs(Text,{children:["Capability:"," ",jsx(Text,{bold:true,color:"cyan",children:e.routeId})]}),jsxs(Text,{children:["Exchange:"," ",jsx(Text,{bold:true,color:"cyan",children:ge(e.id,o-14)})]}),jsxs(Text,{children:["Status:"," ",jsx(Text,{bold:true,color:oe(e.status),children:e.status}),e.durationMs!==null&&jsxs(Text,{children:[" ","Duration:"," ",jsx(Text,{bold:true,children:_(e.durationMs)})]})," ","Started: ",jsx(Text,{bold:true,children:e.startedAt}),e.completedAt&&jsxs(Text,{children:[" ","Completed: ",jsx(Text,{bold:true,children:e.completedAt})]})]}),e.error&&e.status==="failed"&&jsxs(Fragment,{children:[jsx(Text,{children:" "}),jsxs(Text,{color:"red",children:["Error: ",e.error]})]}),e.error&&e.status==="dropped"&&jsxs(Fragment,{children:[jsx(Text,{children:" "}),jsxs(Text,{color:"yellow",children:["Reason: ",e.error]})]})]}),jsx(S,{title:f,width:o,flexGrow:1,color:u,children:jsx(Ee,{columns:sr,data:p,rowKey:(i,y)=>i.type==="header"?`h-${y}`:`${i.event?.id??i.event?.timestamp}-${y}`,selectedIndex:n,scrollOffset:r,visibleRows:m,emptyMessage:"No related events found",renderFullRow:i=>i.type==="header"?jsx(Text,{bold:true,color:"yellow",children:i.text}):void 0})})]})}var ar=[Te(),{header:"Time",width:19,render:(e,t,o)=>jsx(Text,{...t?{color:"cyan"}:{},bold:t,children:N(e.timestamp.replace("T"," ").slice(0,19),o)})},{header:"Event",width:"flex",render:e=>jsx(Text,{color:"cyan",children:e.eventName})},...Je(e=>e)];function Ot({events:e,selectedIndex:t,scrollOffset:o,width:s,height:r,color:n="gray"}){let u=Math.max(r-6,5);return jsx(S,{title:"EVENTS",subtitle:jsxs(Text,{dimColor:true,children:["(",e.length," total)"]}),width:s,flexGrow:1,color:n,children:jsx(Ee,{columns:ar,data:e,rowKey:(l,m)=>l.id!==void 0?String(l.id):`${l.timestamp}-${m}`,selectedIndex:t,scrollOffset:o,visibleRows:u,emptyMessage:"No events recorded yet."})})}function Ne({event:e,width:t,height:o,scrollOffset:s,color:r="cyan"}){let n=We(e.details),u=n&&typeof n.routeId=="string"?n.routeId:void 0,l=n&&typeof n.exchangeId=="string"?n.exchangeId:void 0,d=2+(1+(u?1:0)+(l?1:0)+2),g=5,p=Math.max(t-6,20),f=Ae(e.details,p),i=Math.max(o-d-g,3),y=f.slice(s,s+i);return jsxs(Box,{flexDirection:"column",width:t,flexGrow:1,children:[jsxs(S,{width:t,children:[jsxs(Text,{children:["Context:"," ",jsx(Text,{bold:true,color:"cyan",children:e.contextId})]}),u&&jsxs(Text,{children:["Capability:"," ",jsx(Text,{bold:true,color:"cyan",children:u})]}),l&&jsxs(Text,{children:["Exchange:"," ",jsx(Text,{bold:true,color:"cyan",children:l})]}),jsxs(Text,{children:["Event:"," ",jsx(Text,{bold:true,color:"cyan",children:e.eventName})]}),jsxs(Text,{children:["Time: ",jsx(Text,{bold:true,children:e.timestamp.replace("T"," ")})]})]}),jsxs(S,{title:"DETAILS",subtitle:jsxs(Text,{dimColor:true,children:["(",s+1,"-",Math.min(s+i,f.length),"/",f.length," lines)"]}),width:t,flexGrow:1,color:r,children:[y.map((k,L)=>jsx(Ue,{line:k},s+L)),y.length<i&&Array.from({length:i-y.length}).map((k,L)=>jsx(Text,{children:" "},`pad-${L}`))]})]})}function dr(e,t){let o=[];return o.push("HEADERS"),o.push(...Ae(e.headers,t)),o.push(""),o.push("BODY"),e.body!==null?(o.push(...Ae(e.body,t)),e.truncated&&(o.push(""),o.push("[Body truncated to configured limit]"))):o.push("[null]"),o}function qe({exchange:e,snapshot:t,width:o,height:s,scrollOffset:r,color:n="cyan"}){let m=Math.max(o-6,20),d=Math.max(s-5-5,3),p=t!==null?dr(t,m):["[Snapshots not captured]","","Enable with:"," telemetry({ sqlite: { captureSnapshots: true } })"],f=p.slice(r,r+d);return jsxs(Box,{flexDirection:"column",width:o,flexGrow:1,children:[jsxs(S,{width:o,children:[jsxs(Text,{children:["Capability:"," ",jsx(Text,{bold:true,color:"cyan",children:e.routeId})]}),jsxs(Text,{children:["Exchange:"," ",jsx(Text,{bold:true,color:"cyan",children:ge(e.id,o-14)})]}),jsxs(Text,{children:["Status:"," ",jsx(Text,{bold:true,color:oe(e.status),children:e.status}),e.durationMs!==null&&jsxs(Text,{children:[" ","Duration:"," ",jsx(Text,{bold:true,children:_(e.durationMs)})]})]})]}),jsxs(S,{title:"EXCHANGE SNAPSHOT",subtitle:jsxs(Text,{dimColor:true,children:["(",r+1,"-",Math.min(r+d,p.length),"/",p.length," lines)"]}),width:o,flexGrow:1,color:n,children:[f.map((i,y)=>i==="HEADERS"||i==="BODY"?jsx(Text,{bold:true,color:"yellow",children:i},r+y):i.startsWith("[")?jsx(Text,{dimColor:true,children:i},r+y):jsx(Ue,{line:i},r+y)),f.length<d&&Array.from({length:d-f.length}).map((i,y)=>jsx(Text,{children:" "},`pad-${y}`))]})]})}function ur(e){return e.failedExchanges>0?"red":e.totalExchanges>0?"green":"yellow"}function _t({routes:e,selectedIndex:t,listOffset:o,visibleRows:s,width:r}){let n=o;return jsxs(Fragment,{children:[jsx(Text,{children:" "}),jsx(Text,{bold:true,dimColor:true,children:"\u2500".repeat(r+2)}),e.length===0?jsx(Text,{dimColor:true,children:"No capabilities"}):e.slice(n,n+s).map((u,l)=>{let m=n+l;return jsxs(Text,{wrap:"truncate",children:[jsx(Text,{...m===t?{color:"cyan"}:{},bold:m===t,children:m===t?"> ":" "}),jsx(Text,{color:ur(u),children:"\u25CF "}),jsx(Text,{...m===t?{color:"cyan"}:{},bold:m===t,children:ge(u.id,r-2)})]},u.id)}),e.length>s&&jsxs(Text,{dimColor:true,children:[t+1,"/",e.length]})]})}function yr({db:e}){let{exit:t}=useApp(),{stdout:o}=useStdout(),s=o?.columns??80,r=o?.rows??24,[n,u]=useState("capabilities"),[l,m]=useState("nav"),[d,g]=useState(false),[p,f]=useState([]),[i,y]=useState({totalRoutes:0,totalExchanges:0,completedExchanges:0,failedExchanges:0,droppedExchanges:0,errorRate:0,avgDurationMs:null,p90DurationMs:null,p95DurationMs:null,p99DurationMs:null}),[k,L]=useState([]),[K,W]=useState(void 0),E=Ce(),[X,O]=useState([]),T=Ce(),[w,ht]=useState(void 0),[he,ft]=useState([]),[Be,gt]=useState([]),te=Ce(),F=Ce(),[re,bt]=useState(void 0),[G,ce]=useState(false),[Le,ne]=useState(0),[H,Ye]=useState(false),[ze,ke]=useState(0),[Qe,Pt]=useState(null),fe=50,de=10,Oe=Math.max(Math.min(Math.floor(s*.18),26),16),ue=Math.max(Math.min(Math.floor(s*.22),30),20),A=Math.max(s-Oe-ue,30),R=Math.max(r-5,10),Ze=Math.max(R-10,3),et=useCallback(()=>{try{let c=e.getRouteSummary();f(c),y(e.getMetrics());let a=ue-4;L(e.getLiveTrafficBuckets(a,5));let I=A-4,b=c[E.selectedIndex];if(b&&W(e.getSingleRouteActivity(b.id,I,5)),l==="center")return;if(n==="capabilities"){let h=c[E.selectedIndex];h&&O(e.getExchangesByRoute(h.id,fe));}else n==="exchanges"?O(e.getAllExchanges(fe)):n==="errors"?O(e.getFailedExchanges(fe)):n==="events"&&gt(e.getRecentEvents({limit:200}));}catch{}},[e,n,E.selectedIndex,ue,A,l]);useEffect(()=>{et();let c=setInterval(et,2e3);return ()=>{clearInterval(c);}},[et]);let yt=useCallback(c=>{E.moveTo(c,p.length,Ze),T.reset();let a=p[c];a&&O(e.getExchangesByRoute(a.id,fe));},[e,p,E,T,Ze]),jt=useCallback(c=>{u(c),g(false),ce(false),Ye(false),m("nav"),T.reset(),c==="exchanges"?O(e.getAllExchanges(fe)):c==="errors"?O(e.getFailedExchanges(fe)):c==="events"&&(te.reset(),gt(e.getRecentEvents({limit:200})));},[e,T,te]),tt=p[E.selectedIndex],Gt=Math.ceil((De.length-1)/4),Ft=tt?2+Gt+2:0,_e=Math.max(R-6-Ft,3),Et=Math.max(R-6,5);useInput((c,a)=>{if(c==="q"){e.close(),t();return}let I=Ct.find(b=>b.shortcut===c);if(I){jt(I.key);return}if(n==="events"){if(G){let b=a.ctrl?de:1;c==="j"||a.downArrow?ne(h=>h+b):c==="k"||a.upArrow?ne(h=>Math.max(h-b,0)):(a.escape||a.backspace||a.delete)&&(ce(false),ne(0));return}if(l==="nav")a.return&&m("center");else {let b=a.ctrl?de:1;if(c==="j"||a.downArrow)te.moveBy(b,Be.length,Et);else if(c==="k"||a.upArrow)te.moveBy(-b,Be.length,Et);else if(a.return){let h=Be[te.selectedIndex];h&&(bt(h),ne(0),ce(true));}else (a.escape||a.backspace||a.delete)&&(m("nav"),te.reset());}return}if(H){let b=a.ctrl?de:1;c==="j"||a.downArrow?ke(h=>h+b):c==="k"||a.upArrow?ke(h=>Math.max(h-b,0)):(a.escape||a.backspace||a.delete)&&(Ye(false),ke(0));return}if(d&&!G){let b=w?.error?2:0,h=Math.max(R-9-b,3),$t=new Set(he.map(me=>{try{let Re=JSON.parse(me.details);return String(Re.exchangeId??"")}catch{return ""}})),vt=Math.max($t.size,1),Jt=vt>1?vt:0,wt=he.length+Jt,Rt=a.ctrl?de:1;if(c==="j"||a.downArrow)F.moveBy(Rt,wt,h);else if(c==="k"||a.upArrow)F.moveBy(-Rt,wt,h);else if(a.return){let me=0,Re,Pe=w?.id??"",xe=new Map;xe.set(Pe,[]);for(let Se of he)try{let rt=JSON.parse(Se.details),nt=String(rt.exchangeId??""),ot=!nt||nt===Pe?Pe:nt;xe.has(ot)||xe.set(ot,[]),xe.get(ot).push(Se);}catch{xe.get(Pe).push(Se);}let Vt=xe.size>1;for(let[,Se]of xe){Vt&&me++;for(let rt of Se)me===F.selectedIndex&&(Re=rt),me++;}Re&&(bt(Re),ne(0),ce(true));}else if(c==="e"&&w){let me=e.getExchangeSnapshot(w.id);Pt(me),ke(0),Ye(true);}else (a.escape||a.backspace||a.delete)&&(F.reset(),g(false));return}if(d&&G){let b=a.ctrl?de:1;c==="j"||a.downArrow?ne(h=>h+b):c==="k"||a.upArrow?ne(h=>Math.max(h-b,0)):(a.escape||a.backspace||a.delete)&&(ce(false),ne(0));return}if(n==="capabilities"&&l==="nav"){if(c==="j"||a.downArrow)yt(Math.min(E.selectedIndex+1,p.length-1));else if(c==="k"||a.upArrow)yt(Math.max(E.selectedIndex-1,0));else if(a.return){m("center");let b=p[E.selectedIndex];b&&O(e.getExchangesByRoute(b.id));}return}if(n==="capabilities"&&l==="center"){let b=a.ctrl?de:1;if(c==="j"||a.downArrow)T.moveBy(b,X.length,_e);else if(c==="k"||a.upArrow)T.moveBy(-b,X.length,_e);else if(a.return){let h=X[T.selectedIndex];h&&(ht(h),ft(e.getEventsByExchange(h.id,h.correlationId)),F.reset(),ce(false),g(true));}else (a.escape||a.backspace||a.delete)&&(m("nav"),T.reset());return}if(n==="exchanges"||n==="errors"){if(l==="nav")a.return&&(m("center"),O(n==="exchanges"?e.getAllExchanges():e.getFailedExchanges()));else {let b=a.ctrl?de:1;if(c==="j"||a.downArrow)T.moveBy(b,X.length,_e);else if(c==="k"||a.upArrow)T.moveBy(-b,X.length,_e);else if(a.return){let h=X[T.selectedIndex];h&&(ht(h),ft(e.getEventsByExchange(h.id,h.correlationId)),F.reset(),ce(false),g(true));}else (a.escape||a.backspace||a.delete)&&(m("nav"),T.reset());}return}});let Tt=n==="capabilities"&&l==="nav"&&!d,Ht=!Tt,D=[];return H?(D.push({key:"j/k",action:"Scroll"}),D.push({key:"Ctrl+j/k",action:"Jump 10"}),D.push({key:"Esc",action:"Back"})):l==="center"&&(D.push({key:"j/k",action:"Navigate"}),D.push({key:"Ctrl+j/k",action:"Jump 10"})),H||(l==="nav"?n==="capabilities"?(D.push({key:"j/k",action:"Navigate"}),D.push({key:"Enter",action:"Exchanges"})):D.push({key:"Enter",action:"Browse"}):!d&&!G?(D.push({key:"Enter",action:"Detail"}),D.push({key:"Esc",action:"Back"})):d&&!G?(D.push({key:"Enter",action:"Event detail"}),D.push({key:"e",action:"Snapshot"}),D.push({key:"Esc",action:"Back"})):D.push({key:"Esc",action:"Back"})),D.push({key:"1..4",action:"Switch view"}),D.push({key:"q",action:"Quit"}),jsxs(Box,{flexDirection:"column",width:s,height:r,children:[jsxs(Box,{borderStyle:"round",borderColor:"cyan",paddingX:1,width:s,children:[jsx(Text,{bold:true,color:"cyan",children:"ROUTECRAFT TUI"}),jsx(Text,{children:" "}),jsx(Text,{dimColor:true,children:"v0.4.0"})]}),jsxs(Box,{flexDirection:"row",width:s,flexGrow:1,children:[jsx(Box,{flexDirection:"column",width:Oe,children:jsxs(S,{title:"NAVIGATION",color:Tt?"cyan":"gray",width:Oe,flexGrow:1,children:[st.map((c,a)=>jsxs(Box,{flexDirection:"column",children:[a>0&&jsx(Text,{children:" "}),c.label&&jsx(Text,{dimColor:true,bold:true,children:c.label}),c.items.map(I=>jsxs(Text,{children:[jsxs(Text,{bold:n===I.key,...n===I.key?{color:"cyan"}:{},children:[n===I.key?"> ":" ",I.label]}),jsxs(Text,{dimColor:true,children:[" (",I.shortcut,")"]})]},I.key))]},c.label??a)),n==="capabilities"&&jsx(_t,{routes:p,selectedIndex:E.selectedIndex,listOffset:E.scrollOffset,visibleRows:Ze,width:Oe-6})]})}),n==="capabilities"&&!d&&jsx(Ve,{capabilityId:tt?.id??"",route:tt,exchanges:X,selectedIndex:l==="center"?T.selectedIndex:-1,scrollOffset:l==="center"?T.scrollOffset:0,width:A,height:R,color:Ht?"cyan":"gray",activity:K}),n==="capabilities"&&H&&w&&jsx(qe,{exchange:w,snapshot:Qe,width:A,height:R,scrollOffset:ze,color:"cyan"}),n==="capabilities"&&d&&w&&!G&&!H&&jsx(Xe,{exchange:w,events:he,width:A,height:R,selectedIndex:F.selectedIndex,scrollOffset:F.scrollOffset,color:"cyan"}),n==="capabilities"&&d&&G&&!H&&re&&jsx(Ne,{event:re,width:A,height:R,scrollOffset:Le,color:"cyan"}),n==="exchanges"&&!d&&jsx(Ve,{capabilityId:"All Capabilities",exchanges:X,selectedIndex:l==="center"?T.selectedIndex:-1,scrollOffset:l==="center"?T.scrollOffset:0,width:A,height:R,color:l==="center"?"cyan":"gray"}),n==="exchanges"&&H&&w&&jsx(qe,{exchange:w,snapshot:Qe,width:A,height:R,scrollOffset:ze,color:"cyan"}),n==="exchanges"&&d&&w&&!G&&!H&&jsx(Xe,{exchange:w,events:he,width:A,height:R,selectedIndex:F.selectedIndex,scrollOffset:F.scrollOffset,color:"cyan"}),n==="exchanges"&&d&&G&&!H&&re&&jsx(Ne,{event:re,width:A,height:R,scrollOffset:Le,color:"cyan"}),n==="errors"&&!d&&jsx(Ve,{capabilityId:"Failed Exchanges",exchanges:X,selectedIndex:l==="center"?T.selectedIndex:-1,scrollOffset:l==="center"?T.scrollOffset:0,width:A,height:R,color:l==="center"?"cyan":"gray"}),n==="errors"&&H&&w&&jsx(qe,{exchange:w,snapshot:Qe,width:A,height:R,scrollOffset:ze,color:"cyan"}),n==="errors"&&d&&w&&!G&&!H&&jsx(Xe,{exchange:w,events:he,width:A,height:R,selectedIndex:F.selectedIndex,scrollOffset:F.scrollOffset,color:"cyan"}),n==="errors"&&d&&G&&!H&&re&&jsx(Ne,{event:re,width:A,height:R,scrollOffset:Le,color:"cyan"}),n==="events"&&!G&&jsx(Ot,{events:Be,selectedIndex:l==="center"?te.selectedIndex:-1,scrollOffset:l==="center"?te.scrollOffset:0,width:A,height:R,color:l==="center"?"cyan":"gray"}),n==="events"&&G&&re&&jsx(Ne,{event:re,width:A,height:R,scrollOffset:Le,color:"cyan"}),jsxs(Box,{flexDirection:"column",width:ue,children:[jsxs(S,{title:"METRICS",width:ue,flexGrow:1,children:[jsx(He,{values:k,columns:ue-4,steps:[{max:0,color:"gray"},...Array.from({length:7},(c,a)=>({max:(a+1)*5,color:"green"})),...Array.from({length:7},(c,a)=>({max:35+(a+1)*10,color:"yellow"})),...Array.from({length:6},(c,a)=>({max:105+(a+1)*25,color:"red"}))],label:"Exchanges per 5s bucket"}),jsx(Text,{children:" "}),jsx(Text,{bold:true,dimColor:true,children:"THROUGHPUT"}),[["Exchanges",q(i.totalExchanges),"cyan"],["Completed",q(i.completedExchanges),"green"],["Errors",q(i.failedExchanges),i.failedExchanges>0?"red":"green"],["Dropped",q(i.droppedExchanges),i.droppedExchanges>0?"yellow":"green"],["Error Rate",`${(i.errorRate*100).toFixed(1)}%`,i.errorRate>.1?"red":"green"],["Capabilities",q(i.totalRoutes),""]].map(([c,a,I])=>jsxs(Box,{children:[jsxs(Text,{children:[c,":"]}),jsx(Box,{flexGrow:1,justifyContent:"flex-end",children:jsx(Text,{bold:true,...I?{color:I}:{},children:a})})]},c)),jsx(Text,{children:" "}),jsx(Text,{bold:true,dimColor:true,children:"LATENCY (5m)"}),[["Avg",_(i.avgDurationMs),""],["p90",_(i.p90DurationMs),""],["p95",_(i.p95DurationMs),""],["p99",_(i.p99DurationMs),""]].map(([c,a,I])=>jsxs(Box,{children:[jsxs(Text,{children:[c,":"]}),jsx(Box,{flexGrow:1,justifyContent:"flex-end",children:jsx(Text,{bold:true,...I?{color:I}:{},children:a})})]},c))]}),jsx(S,{title:"KEYMAP",width:ue,children:D.map(c=>jsxs(Box,{children:[jsx(Text,{children:c.action}),jsx(Box,{flexGrow:1,justifyContent:"flex-end",children:jsxs(Text,{color:"yellow",children:["[",c.key,"]"]})})]},c.key))})]})]})]})}async function Zn(e){let t;try{t=await a.open(e);}catch(s){let r=s instanceof Error?s.message:String(s);process.stderr.write(`Failed to open telemetry database: ${r}
3
+ `).map(s=>s.length>o?s.slice(0,Math.max(0,o-1))+"\u2026":s)}}function Ue({line:e}){let t=tr(e);return t.length===0?jsx(Text,{children:e}):jsx(Text,{children:t.map((o,s)=>jsx(Text,{color:rr[o.type],children:o.text},s))})}function Xe(e){try{let t=JSON.parse(e);return typeof t!="object"||t===null||Array.isArray(t)?null:t}catch{return null}}function or(e,t){let o=new Map,s=0;o.set(t,{exchangeId:t,label:"parent",events:[]});for(let r of e){let n=Xe(r.details),u=n?String(n.exchangeId??""):"",l=!u||u===t?t:u;o.has(l)||(s++,o.set(l,{exchangeId:l,label:`child ${s}`,events:[]})),o.get(l).events.push(r);}return Array.from(o.values())}var sr=[Te(),{header:"Time",width:8,render:(e,t,o)=>{if(!e.event)return jsx(Text,{children:N("",o)});let s=" ".repeat(e.indent);return jsxs(Text,{dimColor:true,children:[s,e.event.timestamp.replace("T"," ").slice(11,19)]})}},{header:"Event",width:"flex",render:e=>e.event?jsx(Text,{color:"cyan",children:e.event.eventName}):jsx(Text,{})},...Je(e=>e.event)];function We({exchange:e,events:t,width:o,height:s,scrollOffset:r,selectedIndex:n=-1,color:u="gray"}){let l=e.error?2:0,m=Math.max(s-9-l,3),d=or(t,e.id),g=d.length>1,p=[];for(let i of d){g&&p.push({type:"header",text:`${i.label} (${i.exchangeId.slice(0,8)}) - ${i.events.length} events`,indent:0});for(let y of i.events)p.push({type:"event",event:y,indent:g?2:0});}let f=g?`EXCHANGE FLOW (${d.length} exchanges, ${t.length} events)`:`RELATED EVENTS (${t.length})`;return jsxs(Box,{flexDirection:"column",width:o,flexGrow:1,children:[jsxs(S,{width:o,children:[jsxs(Text,{children:["Capability:"," ",jsx(Text,{bold:true,color:"cyan",children:e.routeId})]}),jsxs(Text,{children:["Exchange:"," ",jsx(Text,{bold:true,color:"cyan",children:ge(e.id,o-14)})]}),jsxs(Text,{children:["Status:"," ",jsx(Text,{bold:true,color:oe(e.status),children:e.status}),e.durationMs!==null&&jsxs(Text,{children:[" ","Duration:"," ",jsx(Text,{bold:true,children:_(e.durationMs)})]})," ","Started: ",jsx(Text,{bold:true,children:e.startedAt}),e.completedAt&&jsxs(Text,{children:[" ","Completed: ",jsx(Text,{bold:true,children:e.completedAt})]})]}),e.error&&e.status==="failed"&&jsxs(Fragment,{children:[jsx(Text,{children:" "}),jsxs(Text,{color:"red",children:["Error: ",e.error]})]}),e.error&&e.status==="dropped"&&jsxs(Fragment,{children:[jsx(Text,{children:" "}),jsxs(Text,{color:"yellow",children:["Reason: ",e.error]})]})]}),jsx(S,{title:f,width:o,flexGrow:1,color:u,children:jsx(Ee,{columns:sr,data:p,rowKey:(i,y)=>i.type==="header"?`h-${y}`:`${i.event?.id??i.event?.timestamp}-${y}`,selectedIndex:n,scrollOffset:r,visibleRows:m,emptyMessage:"No related events found",renderFullRow:i=>i.type==="header"?jsx(Text,{bold:true,color:"yellow",children:i.text}):void 0})})]})}var ar=[Te(),{header:"Time",width:19,render:(e,t,o)=>jsx(Text,{...t?{color:"cyan"}:{},bold:t,children:N(e.timestamp.replace("T"," ").slice(0,19),o)})},{header:"Event",width:"flex",render:e=>jsx(Text,{color:"cyan",children:e.eventName})},...Je(e=>e)];function Ot({events:e,selectedIndex:t,scrollOffset:o,width:s,height:r,color:n="gray"}){let u=Math.max(r-6,5);return jsx(S,{title:"EVENTS",subtitle:jsxs(Text,{dimColor:true,children:["(",e.length," total)"]}),width:s,flexGrow:1,color:n,children:jsx(Ee,{columns:ar,data:e,rowKey:(l,m)=>l.id!==void 0?String(l.id):`${l.timestamp}-${m}`,selectedIndex:t,scrollOffset:o,visibleRows:u,emptyMessage:"No events recorded yet."})})}function Ne({event:e,width:t,height:o,scrollOffset:s,color:r="cyan"}){let n=Xe(e.details),u=n&&typeof n.routeId=="string"?n.routeId:void 0,l=n&&typeof n.exchangeId=="string"?n.exchangeId:void 0,d=2+(1+(u?1:0)+(l?1:0)+2),g=5,p=Math.max(t-6,20),f=Ae(e.details,p),i=Math.max(o-d-g,3),y=f.slice(s,s+i);return jsxs(Box,{flexDirection:"column",width:t,flexGrow:1,children:[jsxs(S,{width:t,children:[jsxs(Text,{children:["Context:"," ",jsx(Text,{bold:true,color:"cyan",children:e.contextId})]}),u&&jsxs(Text,{children:["Capability:"," ",jsx(Text,{bold:true,color:"cyan",children:u})]}),l&&jsxs(Text,{children:["Exchange:"," ",jsx(Text,{bold:true,color:"cyan",children:l})]}),jsxs(Text,{children:["Event:"," ",jsx(Text,{bold:true,color:"cyan",children:e.eventName})]}),jsxs(Text,{children:["Time: ",jsx(Text,{bold:true,children:e.timestamp.replace("T"," ")})]})]}),jsxs(S,{title:"DETAILS",subtitle:jsxs(Text,{dimColor:true,children:["(",s+1,"-",Math.min(s+i,f.length),"/",f.length," lines)"]}),width:t,flexGrow:1,color:r,children:[y.map((k,L)=>jsx(Ue,{line:k},s+L)),y.length<i&&Array.from({length:i-y.length}).map((k,L)=>jsx(Text,{children:" "},`pad-${L}`))]})]})}function dr(e,t){let o=[];return o.push("HEADERS"),o.push(...Ae(e.headers,t)),o.push(""),o.push("BODY"),e.body!==null?(o.push(...Ae(e.body,t)),e.truncated&&(o.push(""),o.push("[Body truncated to configured limit]"))):o.push("[null]"),o}function qe({exchange:e,snapshot:t,width:o,height:s,scrollOffset:r,color:n="cyan"}){let m=Math.max(o-6,20),d=Math.max(s-5-5,3),p=t!==null?dr(t,m):["[Snapshots not captured]","","Enable with:"," telemetry({ sqlite: { captureSnapshots: true } })"],f=p.slice(r,r+d);return jsxs(Box,{flexDirection:"column",width:o,flexGrow:1,children:[jsxs(S,{width:o,children:[jsxs(Text,{children:["Capability:"," ",jsx(Text,{bold:true,color:"cyan",children:e.routeId})]}),jsxs(Text,{children:["Exchange:"," ",jsx(Text,{bold:true,color:"cyan",children:ge(e.id,o-14)})]}),jsxs(Text,{children:["Status:"," ",jsx(Text,{bold:true,color:oe(e.status),children:e.status}),e.durationMs!==null&&jsxs(Text,{children:[" ","Duration:"," ",jsx(Text,{bold:true,children:_(e.durationMs)})]})]})]}),jsxs(S,{title:"EXCHANGE SNAPSHOT",subtitle:jsxs(Text,{dimColor:true,children:["(",r+1,"-",Math.min(r+d,p.length),"/",p.length," lines)"]}),width:o,flexGrow:1,color:n,children:[f.map((i,y)=>i==="HEADERS"||i==="BODY"?jsx(Text,{bold:true,color:"yellow",children:i},r+y):i.startsWith("[")?jsx(Text,{dimColor:true,children:i},r+y):jsx(Ue,{line:i},r+y)),f.length<d&&Array.from({length:d-f.length}).map((i,y)=>jsx(Text,{children:" "},`pad-${y}`))]})]})}function ur(e){return e.failedExchanges>0?"red":e.totalExchanges>0?"green":"yellow"}function _t({routes:e,selectedIndex:t,listOffset:o,visibleRows:s,width:r}){let n=o;return jsxs(Fragment,{children:[jsx(Text,{children:" "}),jsx(Text,{bold:true,dimColor:true,children:"\u2500".repeat(r+2)}),e.length===0?jsx(Text,{dimColor:true,children:"No capabilities"}):e.slice(n,n+s).map((u,l)=>{let m=n+l;return jsxs(Text,{wrap:"truncate",children:[jsx(Text,{...m===t?{color:"cyan"}:{},bold:m===t,children:m===t?"> ":" "}),jsx(Text,{color:ur(u),children:"\u25CF "}),jsx(Text,{...m===t?{color:"cyan"}:{},bold:m===t,children:ge(u.id,r-2)})]},u.id)}),e.length>s&&jsxs(Text,{dimColor:true,children:[t+1,"/",e.length]})]})}function yr({db:e}){let{exit:t}=useApp(),{stdout:o}=useStdout(),s=o?.columns??80,r=o?.rows??24,[n,u]=useState("capabilities"),[l,m]=useState("nav"),[d,g]=useState(false),[p,f]=useState([]),[i,y]=useState({totalRoutes:0,totalExchanges:0,completedExchanges:0,failedExchanges:0,droppedExchanges:0,errorRate:0,avgDurationMs:null,p90DurationMs:null,p95DurationMs:null,p99DurationMs:null}),[k,L]=useState([]),[K,X]=useState(void 0),E=Ce(),[W,O]=useState([]),T=Ce(),[w,ht]=useState(void 0),[he,ft]=useState([]),[Be,gt]=useState([]),te=Ce(),F=Ce(),[re,bt]=useState(void 0),[G,ce]=useState(false),[Le,ne]=useState(0),[H,Ye]=useState(false),[ze,ke]=useState(0),[Qe,Pt]=useState(null),fe=50,de=10,Oe=Math.max(Math.min(Math.floor(s*.18),26),16),ue=Math.max(Math.min(Math.floor(s*.22),30),20),A=Math.max(s-Oe-ue,30),R=Math.max(r-5,10),Ze=Math.max(R-10,3),et=useCallback(()=>{try{let c=e.getRouteSummary();f(c),y(e.getMetrics());let a=ue-4;L(e.getLiveTrafficBuckets(a,5));let I=A-4,b=c[E.selectedIndex];if(b&&X(e.getSingleRouteActivity(b.id,I,5)),l==="center")return;if(n==="capabilities"){let h=c[E.selectedIndex];h&&O(e.getExchangesByRoute(h.id,fe));}else n==="exchanges"?O(e.getAllExchanges(fe)):n==="errors"?O(e.getFailedExchanges(fe)):n==="events"&&gt(e.getRecentEvents({limit:200}));}catch{}},[e,n,E.selectedIndex,ue,A,l]);useEffect(()=>{et();let c=setInterval(et,2e3);return ()=>{clearInterval(c);}},[et]);let yt=useCallback(c=>{E.moveTo(c,p.length,Ze),T.reset();let a=p[c];a&&O(e.getExchangesByRoute(a.id,fe));},[e,p,E,T,Ze]),jt=useCallback(c=>{u(c),g(false),ce(false),Ye(false),m("nav"),T.reset(),c==="exchanges"?O(e.getAllExchanges(fe)):c==="errors"?O(e.getFailedExchanges(fe)):c==="events"&&(te.reset(),gt(e.getRecentEvents({limit:200})));},[e,T,te]),tt=p[E.selectedIndex],Gt=Math.ceil((De.length-1)/4),Ft=tt?2+Gt+2:0,_e=Math.max(R-6-Ft,3),Et=Math.max(R-6,5);useInput((c,a)=>{if(c==="q"){e.close(),t();return}let I=Ct.find(b=>b.shortcut===c);if(I){jt(I.key);return}if(n==="events"){if(G){let b=a.ctrl?de:1;c==="j"||a.downArrow?ne(h=>h+b):c==="k"||a.upArrow?ne(h=>Math.max(h-b,0)):(a.escape||a.backspace||a.delete)&&(ce(false),ne(0));return}if(l==="nav")a.return&&m("center");else {let b=a.ctrl?de:1;if(c==="j"||a.downArrow)te.moveBy(b,Be.length,Et);else if(c==="k"||a.upArrow)te.moveBy(-b,Be.length,Et);else if(a.return){let h=Be[te.selectedIndex];h&&(bt(h),ne(0),ce(true));}else (a.escape||a.backspace||a.delete)&&(m("nav"),te.reset());}return}if(H){let b=a.ctrl?de:1;c==="j"||a.downArrow?ke(h=>h+b):c==="k"||a.upArrow?ke(h=>Math.max(h-b,0)):(a.escape||a.backspace||a.delete)&&(Ye(false),ke(0));return}if(d&&!G){let b=w?.error?2:0,h=Math.max(R-9-b,3),$t=new Set(he.map(me=>{try{let Re=JSON.parse(me.details);return String(Re.exchangeId??"")}catch{return ""}})),vt=Math.max($t.size,1),Jt=vt>1?vt:0,wt=he.length+Jt,Rt=a.ctrl?de:1;if(c==="j"||a.downArrow)F.moveBy(Rt,wt,h);else if(c==="k"||a.upArrow)F.moveBy(-Rt,wt,h);else if(a.return){let me=0,Re,Pe=w?.id??"",xe=new Map;xe.set(Pe,[]);for(let Se of he)try{let rt=JSON.parse(Se.details),nt=String(rt.exchangeId??""),ot=!nt||nt===Pe?Pe:nt;xe.has(ot)||xe.set(ot,[]),xe.get(ot).push(Se);}catch{xe.get(Pe).push(Se);}let Vt=xe.size>1;for(let[,Se]of xe){Vt&&me++;for(let rt of Se)me===F.selectedIndex&&(Re=rt),me++;}Re&&(bt(Re),ne(0),ce(true));}else if(c==="e"&&w){let me=e.getExchangeSnapshot(w.id);Pt(me),ke(0),Ye(true);}else (a.escape||a.backspace||a.delete)&&(F.reset(),g(false));return}if(d&&G){let b=a.ctrl?de:1;c==="j"||a.downArrow?ne(h=>h+b):c==="k"||a.upArrow?ne(h=>Math.max(h-b,0)):(a.escape||a.backspace||a.delete)&&(ce(false),ne(0));return}if(n==="capabilities"&&l==="nav"){if(c==="j"||a.downArrow)yt(Math.min(E.selectedIndex+1,p.length-1));else if(c==="k"||a.upArrow)yt(Math.max(E.selectedIndex-1,0));else if(a.return){m("center");let b=p[E.selectedIndex];b&&O(e.getExchangesByRoute(b.id));}return}if(n==="capabilities"&&l==="center"){let b=a.ctrl?de:1;if(c==="j"||a.downArrow)T.moveBy(b,W.length,_e);else if(c==="k"||a.upArrow)T.moveBy(-b,W.length,_e);else if(a.return){let h=W[T.selectedIndex];h&&(ht(h),ft(e.getEventsByExchange(h.id,h.correlationId)),F.reset(),ce(false),g(true));}else (a.escape||a.backspace||a.delete)&&(m("nav"),T.reset());return}if(n==="exchanges"||n==="errors"){if(l==="nav")a.return&&(m("center"),O(n==="exchanges"?e.getAllExchanges():e.getFailedExchanges()));else {let b=a.ctrl?de:1;if(c==="j"||a.downArrow)T.moveBy(b,W.length,_e);else if(c==="k"||a.upArrow)T.moveBy(-b,W.length,_e);else if(a.return){let h=W[T.selectedIndex];h&&(ht(h),ft(e.getEventsByExchange(h.id,h.correlationId)),F.reset(),ce(false),g(true));}else (a.escape||a.backspace||a.delete)&&(m("nav"),T.reset());}return}});let Tt=n==="capabilities"&&l==="nav"&&!d,Ht=!Tt,D=[];return H?(D.push({key:"j/k",action:"Scroll"}),D.push({key:"Ctrl+j/k",action:"Jump 10"}),D.push({key:"Esc",action:"Back"})):l==="center"&&(D.push({key:"j/k",action:"Navigate"}),D.push({key:"Ctrl+j/k",action:"Jump 10"})),H||(l==="nav"?n==="capabilities"?(D.push({key:"j/k",action:"Navigate"}),D.push({key:"Enter",action:"Exchanges"})):D.push({key:"Enter",action:"Browse"}):!d&&!G?(D.push({key:"Enter",action:"Detail"}),D.push({key:"Esc",action:"Back"})):d&&!G?(D.push({key:"Enter",action:"Event detail"}),D.push({key:"e",action:"Snapshot"}),D.push({key:"Esc",action:"Back"})):D.push({key:"Esc",action:"Back"})),D.push({key:"1..4",action:"Switch view"}),D.push({key:"q",action:"Quit"}),jsxs(Box,{flexDirection:"column",width:s,height:r,children:[jsxs(Box,{borderStyle:"round",borderColor:"cyan",paddingX:1,width:s,children:[jsx(Text,{bold:true,color:"cyan",children:"ROUTECRAFT TUI"}),jsx(Text,{children:" "}),jsx(Text,{dimColor:true,children:"v0.4.0"})]}),jsxs(Box,{flexDirection:"row",width:s,flexGrow:1,children:[jsx(Box,{flexDirection:"column",width:Oe,children:jsxs(S,{title:"NAVIGATION",color:Tt?"cyan":"gray",width:Oe,flexGrow:1,children:[st.map((c,a)=>jsxs(Box,{flexDirection:"column",children:[a>0&&jsx(Text,{children:" "}),c.label&&jsx(Text,{dimColor:true,bold:true,children:c.label}),c.items.map(I=>jsxs(Text,{children:[jsxs(Text,{bold:n===I.key,...n===I.key?{color:"cyan"}:{},children:[n===I.key?"> ":" ",I.label]}),jsxs(Text,{dimColor:true,children:[" (",I.shortcut,")"]})]},I.key))]},c.label??a)),n==="capabilities"&&jsx(_t,{routes:p,selectedIndex:E.selectedIndex,listOffset:E.scrollOffset,visibleRows:Ze,width:Oe-6})]})}),n==="capabilities"&&!d&&jsx(Ve,{capabilityId:tt?.id??"",route:tt,exchanges:W,selectedIndex:l==="center"?T.selectedIndex:-1,scrollOffset:l==="center"?T.scrollOffset:0,width:A,height:R,color:Ht?"cyan":"gray",activity:K}),n==="capabilities"&&H&&w&&jsx(qe,{exchange:w,snapshot:Qe,width:A,height:R,scrollOffset:ze,color:"cyan"}),n==="capabilities"&&d&&w&&!G&&!H&&jsx(We,{exchange:w,events:he,width:A,height:R,selectedIndex:F.selectedIndex,scrollOffset:F.scrollOffset,color:"cyan"}),n==="capabilities"&&d&&G&&!H&&re&&jsx(Ne,{event:re,width:A,height:R,scrollOffset:Le,color:"cyan"}),n==="exchanges"&&!d&&jsx(Ve,{capabilityId:"All Capabilities",exchanges:W,selectedIndex:l==="center"?T.selectedIndex:-1,scrollOffset:l==="center"?T.scrollOffset:0,width:A,height:R,color:l==="center"?"cyan":"gray"}),n==="exchanges"&&H&&w&&jsx(qe,{exchange:w,snapshot:Qe,width:A,height:R,scrollOffset:ze,color:"cyan"}),n==="exchanges"&&d&&w&&!G&&!H&&jsx(We,{exchange:w,events:he,width:A,height:R,selectedIndex:F.selectedIndex,scrollOffset:F.scrollOffset,color:"cyan"}),n==="exchanges"&&d&&G&&!H&&re&&jsx(Ne,{event:re,width:A,height:R,scrollOffset:Le,color:"cyan"}),n==="errors"&&!d&&jsx(Ve,{capabilityId:"Failed Exchanges",exchanges:W,selectedIndex:l==="center"?T.selectedIndex:-1,scrollOffset:l==="center"?T.scrollOffset:0,width:A,height:R,color:l==="center"?"cyan":"gray"}),n==="errors"&&H&&w&&jsx(qe,{exchange:w,snapshot:Qe,width:A,height:R,scrollOffset:ze,color:"cyan"}),n==="errors"&&d&&w&&!G&&!H&&jsx(We,{exchange:w,events:he,width:A,height:R,selectedIndex:F.selectedIndex,scrollOffset:F.scrollOffset,color:"cyan"}),n==="errors"&&d&&G&&!H&&re&&jsx(Ne,{event:re,width:A,height:R,scrollOffset:Le,color:"cyan"}),n==="events"&&!G&&jsx(Ot,{events:Be,selectedIndex:l==="center"?te.selectedIndex:-1,scrollOffset:l==="center"?te.scrollOffset:0,width:A,height:R,color:l==="center"?"cyan":"gray"}),n==="events"&&G&&re&&jsx(Ne,{event:re,width:A,height:R,scrollOffset:Le,color:"cyan"}),jsxs(Box,{flexDirection:"column",width:ue,children:[jsxs(S,{title:"METRICS",width:ue,flexGrow:1,children:[jsx(He,{values:k,columns:ue-4,steps:[{max:0,color:"gray"},...Array.from({length:7},(c,a)=>({max:(a+1)*5,color:"green"})),...Array.from({length:7},(c,a)=>({max:35+(a+1)*10,color:"yellow"})),...Array.from({length:6},(c,a)=>({max:105+(a+1)*25,color:"red"}))],label:"Exchanges per 5s bucket"}),jsx(Text,{children:" "}),jsx(Text,{bold:true,dimColor:true,children:"THROUGHPUT"}),[["Exchanges",q(i.totalExchanges),"cyan"],["Completed",q(i.completedExchanges),"green"],["Errors",q(i.failedExchanges),i.failedExchanges>0?"red":"green"],["Dropped",q(i.droppedExchanges),i.droppedExchanges>0?"yellow":"green"],["Error Rate",`${(i.errorRate*100).toFixed(1)}%`,i.errorRate>.1?"red":"green"],["Capabilities",q(i.totalRoutes),""]].map(([c,a,I])=>jsxs(Box,{children:[jsxs(Text,{children:[c,":"]}),jsx(Box,{flexGrow:1,justifyContent:"flex-end",children:jsx(Text,{bold:true,...I?{color:I}:{},children:a})})]},c)),jsx(Text,{children:" "}),jsx(Text,{bold:true,dimColor:true,children:"LATENCY (5m)"}),[["Avg",_(i.avgDurationMs),""],["p90",_(i.p90DurationMs),""],["p95",_(i.p95DurationMs),""],["p99",_(i.p99DurationMs),""]].map(([c,a,I])=>jsxs(Box,{children:[jsxs(Text,{children:[c,":"]}),jsx(Box,{flexGrow:1,justifyContent:"flex-end",children:jsx(Text,{bold:true,...I?{color:I}:{},children:a})})]},c))]}),jsx(S,{title:"KEYMAP",width:ue,children:D.map(c=>jsxs(Box,{children:[jsx(Text,{children:c.action}),jsx(Box,{flexGrow:1,justifyContent:"flex-end",children:jsxs(Text,{color:"yellow",children:["[",c.key,"]"]})})]},c.key))})]})]})]})}async function Zn(e){let t;try{t=await a.open(e);}catch(s){let r=s instanceof Error?s.message:String(s);process.stderr.write(`Failed to open telemetry database: ${r}
4
4
  `),process.stderr.write(`Path: ${e}
5
5
  `),process.stderr.write(`Make sure you have a running Routecraft context with telemetry() enabled.
6
6
  `),process.exit(1);}await render(jsx(yr,{db:t})).waitUntilExit();}export{Zn as renderTui};//# sourceMappingURL=app.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/tui/types.ts","../../src/tui/utils.ts","../../src/tui/hooks/use-scroll-list.ts","../../src/tui/components/panel.tsx","../../src/tui/components/dot-graph.tsx","../../src/tui/components/route-header.tsx","../../src/tui/components/table.tsx","../../src/tui/components/event-columns.tsx","../../src/tui/components/center-exchange-list.tsx","../../src/tui/components/json-format.tsx","../../src/tui/components/center-exchange-detail.tsx","../../src/tui/components/events-view.tsx","../../src/tui/components/event-detail.tsx","../../src/tui/components/exchange-deep-view.tsx","../../src/tui/components/capability-list.tsx","../../src/tui/app.tsx"],"names":["NAV_SECTIONS","ALL_NAV_ITEMS","s","truncate","str","maxLen","formatDuration","ms","statusColor","status","col","len","parseEventDetail","raw","d","exchange","duration","adapter","meta","m","keys","k","qualifier","route","err","formatDetailColumns","_eventName","parsed","fmtNum","n","adjustScrollOffset","selected","currentOffset","visibleRows","useScrollList","initialIndex","selectedIndex","setSelectedIndex","useState","scrollOffset","setScrollOffset","moveTo","useCallback","index","listLength","clamped","off","moveBy","delta","prev","next","reset","Panel","title","subtitle","color","width","flexGrow","paddingX","children","innerWidth","jsxs","Box","Fragment","Text","jsx","BRAILLE_DOTS","BRAILLE_BASE","DEFAULT_STEPS","DotGraph","values","columns","steps","label","dotHeight","data","heights","v","i","termRows","rows","tr","baseStep","segments","ci","h","bits","sr","stepLevel","char","last","RouteHeader","Table","rowKey","gap","emptyMessage","renderFullRow","gapStr","header","c","after","text","visible","remaining","row","vi","dataIndex","fullRow","resolved","cell","eventDetailColumns","accessor","cache","getColumns","ev","cols","_sel","w","selectorColumn","_row","exchangeColumns","CenterExchangeList","capabilityId","exchanges","height","activity","graphTermRows","headerRows","tableRows","ex","tokenizeLine","line","tokens","re","lastIndex","match","TOKEN_COLORS","formatJson","maxWidth","clampedMax","ColoredJsonLine","token","parseDetails","groupEventsByExchange","events","parentExchangeId","groups","childIndex","exId","key","detailColumns","indent","CenterExchangeDetail","hasExtra","eventRows","hasChildren","displayRows","group","eventsTitle","eventColumns","EventsView","EventDetail","event","routeId","exchangeId","headerHeight","jsonChrome","jsonWidth","jsonLines","_","buildSnapshotLines","snapshot","lines","ExchangeDeepView","dotColor","CapabilityList","routes","listOffset","offset","App","db","exit","useApp","stdout","useStdout","activeNav","setActiveNav","focus","setFocus","showDetail","setShowDetail","setRoutes","metrics","setMetrics","liveTraffic","setLiveTraffic","selectedRouteActivity","setSelectedRouteActivity","routeScroll","setExchanges","exchangeScroll","selectedExchange","setSelectedExchange","exchangeEvents","setExchangeEvents","setEvents","eventScroll","detailScroll","selectedEvent","setSelectedEvent","showEventDetail","setShowEventDetail","eventDetailScroll","setEventDetailScroll","showDeepView","setShowDeepView","deepViewScroll","setDeepViewScroll","exchangeSnapshot","setExchangeSnapshot","PAGE_SIZE","JUMP","leftWidth","rightWidth","centerWidth","bodyHeight","navListHeight","refresh","routeSummary","liveCols","routeCols","curRoute","useEffect","timer","selectRoute","switchNav","nav","selectedRoute","exchangeHeaderRows","exchangeTableRows","eventsTableRows","useInput","input","navByShortcut","step","detailEventRows","uniqueExchangeIds","groupCount","totalDisplayRows","rowIndex","targetEvent","parentId","gKey","groupEvents","navActive","centerActive","keymapItems","section","si","item","value","renderTui","dbPath","TelemetryDb","msg","render"],"mappings":"6NAOO,IAAMA,EAAAA,CAA6B,CACxC,CACE,KAAA,CAAO,CAAC,CAAE,GAAA,CAAK,eAAgB,KAAA,CAAO,cAAA,CAAgB,QAAA,CAAU,GAAI,CAAC,CACvE,CAAA,CACA,CACE,KAAA,CAAO,CACL,CAAE,GAAA,CAAK,WAAA,CAAa,KAAA,CAAO,WAAA,CAAa,QAAA,CAAU,GAAI,CAAA,CACtD,CAAE,GAAA,CAAK,QAAA,CAAU,KAAA,CAAO,QAAA,CAAU,QAAA,CAAU,GAAI,CAAA,CAChD,CAAE,GAAA,CAAK,QAAA,CAAU,KAAA,CAAO,QAAA,CAAU,QAAA,CAAU,GAAI,CAClD,CACF,CACF,CAAA,CAEaC,EAAAA,CAAgBD,EAAAA,CAAa,OAAA,CAASE,CAAAA,EAAMA,CAAAA,CAAE,KAAK,CAAA,CCpBzD,SAASC,EAAAA,CAASC,CAAAA,CAAaC,CAAAA,CAAwB,CAC5D,OAAIA,GAAU,CAAA,CAAU,EAAA,CACjBD,CAAAA,CAAI,MAAA,CAASC,CAAAA,CAASD,CAAAA,CAAI,KAAA,CAAM,CAAA,CAAGC,CAAAA,CAAS,CAAC,CAAA,CAAI,QAAA,CAAWD,CACrE,CAEO,SAASE,CAAAA,CAAeC,EAA2B,CAExD,OADIA,CAAAA,EAAO,IAAA,EACP,CAAC,MAAA,CAAO,QAAA,CAASA,CAAE,CAAA,EAAKA,CAAAA,CAAK,CAAA,CAAU,GAAA,CACvCA,CAAAA,GAAO,CAAA,CAAU,MAAA,CACjBA,CAAAA,CAAK,IAAa,CAAA,EAAG,IAAA,CAAK,KAAA,CAAMA,CAAE,CAAC,CAAA,EAAA,CAAA,CAChC,CAAA,EAAA,CAAIA,CAAAA,CAAK,GAAA,EAAM,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,CAClC,CAEO,SAASC,EAAAA,CAAYC,EAAwB,CAClD,OAAQA,CAAAA,EACN,KAAK,WAAA,CACL,KAAK,SAAA,CACH,OAAO,OAAA,CACT,KAAK,QAAA,CACH,OAAO,KAAA,CACT,KAAK,SAAA,CACL,KAAK,SAAA,CACH,OAAO,QAAA,CACT,QACE,OAAO,OACX,CACF,CAEO,SAASC,CAAAA,CAAIN,CAAAA,CAAaO,CAAAA,CAAiC,CAChE,OAAIA,CAAAA,GAAQ,MAAA,CAAkBP,EAC1BO,CAAAA,EAAO,CAAA,CAAU,EAAA,CACjBP,CAAAA,CAAI,MAAA,CAASO,CAAAA,CAAYP,CAAAA,CAAI,KAAA,CAAM,CAAA,CAAGO,CAAAA,CAAM,CAAC,CAAA,CAAI,QAAA,CAC9CP,CAAAA,CAAI,MAAA,CAAOO,CAAG,CACvB,CA0BA,SAASC,EAAAA,CAAiBC,CAAAA,CAAmC,CAC3D,GAAI,CACF,IAAMC,CAAAA,CAAI,IAAA,CAAK,KAAA,CAAMD,CAAG,CAAA,CAElBE,CAAAA,CACJ,YAAA,GAAgBD,CAAAA,CAAI,GAAG,MAAA,CAAOA,CAAAA,CAAE,UAAa,CAAA,CAAE,KAAA,CAAM,CAAA,CAAG,CAAC,CAAC,CAAA,CAAA,CAAK,EAAA,CAC3DE,CAAAA,CACJ,UAAA,GAAcF,CAAAA,CAAIR,CAAAA,CAAeQ,CAAAA,CAAE,QAAqB,EAAI,EAAA,CAG9D,GAAI,WAAA,GAAeA,CAAAA,EAAK,SAAA,GAAaA,CAAAA,CAAG,CACtC,IAAMG,CAAAA,CACJ,SAAA,GAAaH,CAAAA,CACT,CAAA,CAAA,EAAIA,CAAAA,CAAE,OAAU,CAAA,CAAA,CAAA,CAChB,WAAA,GAAeA,EACb,CAAA,CAAA,EAAIA,CAAAA,CAAE,SAAY,CAAA,CAAA,CAAA,CAClB,EAAA,CACJI,CAAAA,CAAO,EAAA,CACX,GACE,UAAA,GAAcJ,CAAAA,EACd,OAAOA,CAAAA,CAAE,QAAA,EAAgB,QAAA,EACzBA,CAAAA,CAAE,QAAA,GAAgB,KAClB,CACA,IAAMK,CAAAA,CAAIL,CAAAA,CAAE,QAAA,CACNM,CAAAA,CAAO,MAAA,CAAO,IAAA,CAAKD,CAAC,CAAA,CAAE,KAAA,CAAM,CAAA,CAAG,CAAC,CAAA,CAClCC,CAAAA,CAAK,MAAA,CAAS,IAAGF,CAAAA,CAAOE,CAAAA,CAAK,GAAA,CAAKC,CAAAA,EAAM,CAAA,EAAGA,CAAC,CAAA,CAAA,EAAIF,CAAAA,CAAEE,CAAC,CAAC,CAAA,CAAE,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA,EACtE,CACA,OAAO,CACL,IAAA,CAAM,MAAA,CAAOP,CAAAA,CAAE,SAAY,CAAA,CAC3B,OAAA,CAAAG,CAAAA,CACA,QAAA,CAAAF,CAAAA,CACA,QAAA,CAAAC,CAAAA,CACA,IAAA,CAAAE,CACF,CACF,CAGA,GAAI,SAAA,GAAaJ,CAAAA,EAAK,YAAA,GAAgBA,CAAAA,CAAG,CACvC,IAAMQ,CAAAA,CACJ,OAAA,GAAWR,CAAAA,CACP,OAAA,CACA,QAAA,GAAYA,CAAAA,CACV,CAAA,CAAA,EAAI,MAAA,CAAOA,CAAAA,CAAE,MAAS,EAAE,KAAA,CAAM,CAAA,CAAG,CAAC,CAAC,CAAA,CAAA,CAAA,CACnC,EAAA,CACR,OAAO,CACL,IAAA,CAAM,MAAA,CAAOA,CAAAA,CAAE,OAAU,CAAA,CACzB,OAAA,CAASQ,CAAAA,CACT,QAAA,CAAAP,EACA,QAAA,CAAAC,CAAAA,CACA,IAAA,CAAM,EACR,CACF,CAGA,GAAI,OAAA,GAAWF,CAAAA,EAAK,OAAOA,CAAAA,CAAE,KAAA,EAAa,QAAA,EAAYA,CAAAA,CAAE,KAAA,GAAa,IAAA,CAAM,CACzE,IAAMS,CAAAA,CAAQT,CAAAA,CAAE,KAAA,CAIhB,OAAO,CACL,IAAA,CAAMS,CAAAA,CAAM,OAAA,EAAWA,CAAAA,CAAM,UAAA,EAAY,EAAA,EAAM,GAAA,CAC/C,OAAA,CAAS,EAAA,CACT,QAAA,CAAU,GACV,QAAA,CAAU,EAAA,CACV,IAAA,CAAM,EACR,CACF,CAGA,GAAI,UAAA,GAAcT,CAAAA,CAChB,OAAO,CACL,IAAA,CAAM,CAAA,OAAA,EAAUA,CAAAA,CAAE,QAAW,CAAA,CAAA,CAC7B,QAAS,EAAA,CACT,QAAA,CAAU,EAAA,CACV,QAAA,CAAU,EAAA,CACV,IAAA,CAAM,EACR,CAAA,CAIF,GAAI,OAAA,GAAWA,CAAAA,CAAG,CAChB,IAAMU,CAAAA,CAAMV,CAAAA,CAAE,KAAA,CAKd,OAAO,CACL,IAAA,CAJA,OAAOU,CAAAA,EAAQ,QAAA,EAAYA,CAAAA,GAAQ,IAAA,EAAQ,SAAA,GAAaA,CAAAA,CACpD,MAAA,CAAQA,CAAAA,CAA4B,OAAO,CAAA,CAC3C,MAAA,CAAOA,CAAG,CAAA,CAGd,QAAS,EAAA,CACT,QAAA,CAAU,EAAA,CACV,QAAA,CAAU,EAAA,CACV,IAAA,CAAM,EACR,CACF,CAEA,OAAO,IACT,CAAA,KAAQ,CACN,OAAO,IACT,CACF,CA4BO,SAASC,EAAAA,CACdC,CAAAA,CACAb,CAAAA,CACe,CACf,IAAMc,CAAAA,CAASf,EAAAA,CAAiBC,CAAG,CAAA,CACnC,OAAKc,CAAAA,EACI,CAAE,IAAA,CAAMd,CAAAA,CAAK,OAAA,CAAS,GAAI,QAAA,CAAU,EAAA,CAAI,QAAA,CAAU,EAAA,CAAI,IAAA,CAAM,EAAG,CAG1E,CA6BO,SAASe,CAAAA,CAAOC,CAAAA,CAAmB,CACxC,OAAOA,CAAAA,CAAE,cAAA,CAAe,OAAO,CACjC,CAYO,SAASC,EAAAA,CACdC,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CACQ,CACR,OAAIA,CAAAA,EAAe,CAAA,CAAUD,CAAAA,CACzBD,CAAAA,CAAWC,CAAAA,CAAsBD,CAAAA,CACjCA,CAAAA,EAAYC,CAAAA,CAAgBC,EACvBF,CAAAA,CAAWE,CAAAA,CAAc,CAAA,CAC3BD,CACT,CCnOO,SAASE,EAAAA,CAAcC,CAAAA,CAAe,CAAA,CAAoB,CAC/D,GAAM,CAACC,CAAAA,CAAeC,CAAgB,CAAA,CAAIC,QAAAA,CAASH,CAAY,CAAA,CACzD,CAACI,CAAAA,CAAcC,CAAe,CAAA,CAAIF,QAAAA,CAAS,CAAC,CAAA,CAE5CG,CAAAA,CAASC,WAAAA,CACb,CAACC,CAAAA,CAAeC,CAAAA,CAAoBX,CAAAA,GAAwB,CAC1D,IAAMY,CAAAA,CAAU,IAAA,CAAK,GAAA,CAAI,CAAA,CAAG,IAAA,CAAK,GAAA,CAAIF,CAAAA,CAAOC,CAAAA,CAAa,CAAC,CAAC,CAAA,CAC3DP,EAAiBQ,CAAO,CAAA,CACxBL,CAAAA,CAAiBM,CAAAA,EAAQhB,EAAAA,CAAmBe,CAAAA,CAASC,CAAAA,CAAKb,CAAW,CAAC,EACxE,CAAA,CACA,EACF,CAAA,CAEMc,CAAAA,CAASL,WAAAA,CACb,CAACM,CAAAA,CAAeJ,CAAAA,CAAoBX,CAAAA,GAAwB,CAC1DI,CAAAA,CAAkBY,CAAAA,EAAS,CACzB,IAAMC,CAAAA,CAAO,IAAA,CAAK,GAAA,CAAI,CAAA,CAAG,IAAA,CAAK,GAAA,CAAID,CAAAA,CAAOD,CAAAA,CAAOJ,EAAa,CAAC,CAAC,CAAA,CAC/D,OAAAJ,CAAAA,CAAiBM,CAAAA,EAAQhB,EAAAA,CAAmBoB,CAAAA,CAAMJ,CAAAA,CAAKb,CAAW,CAAC,CAAA,CAC5DiB,CACT,CAAC,EACH,CAAA,CACA,EACF,CAAA,CAEMC,CAAAA,CAAQT,WAAAA,CAAY,IAAM,CAC9BL,CAAAA,CAAiB,CAAC,CAAA,CAClBG,CAAAA,CAAgB,CAAC,EACnB,CAAA,CAAG,EAAE,CAAA,CAEL,OAAO,CAAE,aAAA,CAAAJ,CAAAA,CAAe,YAAA,CAAAG,CAAAA,CAAc,MAAA,CAAAQ,CAAAA,CAAQ,MAAA,CAAAN,CAAAA,CAAQ,KAAA,CAAAU,CAAM,CAC9D,CChDO,SAASC,CAAAA,CAAM,CACpB,KAAA,CAAAC,CAAAA,CACA,QAAA,CAAAC,CAAAA,CACA,MAAAC,CAAAA,CAAQ,MAAA,CACR,KAAA,CAAAC,CAAAA,CACA,QAAA,CAAAC,CAAAA,CACA,QAAA,CAAAC,CAAAA,CAAW,CAAA,CACX,QAAA,CAAAC,CACF,CAAA,CAQG,CAED,IAAMC,CAAAA,CAAaJ,CAAAA,CAAQA,EAAQ,CAAA,CAAIE,CAAAA,CAAW,CAAA,CAAI,EAAA,CAEtD,OACEG,IAAAA,CAACC,GAAAA,CAAA,CACC,aAAA,CAAc,QAAA,CACd,WAAA,CAAY,OAAA,CACZ,WAAA,CAAaP,CAAAA,CACb,QAAA,CAAUG,CAAAA,CACV,MAAOF,CAAAA,CACP,QAAA,CAAUC,CAAAA,CAET,QAAA,CAAA,CAAAJ,CAAAA,EACCQ,IAAAA,CAAAE,QAAAA,CAAA,CACE,QAAA,CAAA,CAAAF,IAAAA,CAACG,IAAAA,CAAA,CAAK,IAAA,CAAI,IAAA,CACP,QAAA,CAAA,CAAAX,CAAAA,CACAC,GAAYO,IAAAA,CAAAE,QAAAA,CAAA,CAAE,QAAA,CAAA,CAAA,GAAA,CAAET,CAAAA,CAAAA,CAAS,CAAA,CAAA,CAC5B,CAAA,CACAW,GAAAA,CAACD,IAAAA,CAAA,CAAK,QAAA,CAAQ,IAAA,CAAE,QAAA,CAAA,QAAA,CAAS,MAAA,CAAO,IAAA,CAAK,GAAA,CAAIJ,EAAY,CAAC,CAAC,CAAA,CAAE,CAAA,CAAA,CAC3D,CAAA,CAEDD,CAAAA,CAAAA,CACH,CAEJ,CC7BA,IAAMO,EAAAA,CAAe,CACnB,GAAA,CACA,EAAA,CACA,EAAA,CACA,CACF,CAAA,CACMC,EAAAA,CAAe,KAAA,CAQRC,EAAAA,CAA2B,CACtC,CAAE,IAAK,CAAA,CAAG,KAAA,CAAO,MAAO,CAAA,CACxB,CAAE,GAAA,CAAK,EAAA,CAAI,KAAA,CAAO,OAAQ,CAAA,CAC1B,CAAE,GAAA,CAAK,EAAA,CAAI,KAAA,CAAO,OAAQ,CAAA,CAC1B,CAAE,GAAA,CAAK,EAAA,CAAI,KAAA,CAAO,QAAS,CAAA,CAC3B,CAAE,GAAA,CAAK,EAAA,CAAI,KAAA,CAAO,QAAS,CAAA,CAC3B,CAAE,GAAA,CAAK,EAAA,CAAI,KAAA,CAAO,KAAM,CAC1B,CAAA,CAcO,SAASC,EAAAA,CAAS,CACvB,MAAA,CAAAC,CAAAA,CACA,OAAA,CAAAC,CAAAA,CACA,KAAA,CAAAC,CAAAA,CAAQJ,EAAAA,CACR,KAAA,CAAAK,CACF,CAAA,CAKG,CACD,IAAMC,EAAYF,CAAAA,CAAM,MAAA,CAAS,CAAA,CAG3BG,CAAAA,CACJL,CAAAA,CAAO,MAAA,EAAUC,CAAAA,CACbD,CAAAA,CAAO,KAAA,CAAMA,CAAAA,CAAO,MAAA,CAASC,CAAO,CAAA,CACpC,CACE,GAAI,IAAI,MAAMA,CAAAA,CAAUD,CAAAA,CAAO,MAAM,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,CAC7C,GAAGA,CACL,CAAA,CAGAM,CAAAA,CAAUD,CAAAA,CAAK,GAAA,CAAKE,CAAAA,EAAM,CAC9B,GAAIA,GAAK,CAAA,CAAG,OAAO,CAAA,CACnB,IAAA,IAASC,CAAAA,CAAI,CAAA,CAAGA,CAAAA,CAAIN,CAAAA,CAAM,MAAA,CAAQM,CAAAA,EAAAA,CAChC,GAAID,CAAAA,CAAIL,CAAAA,CAAMM,CAAC,CAAA,CAAG,GAAA,CAAK,OAAOA,CAAAA,CAEhC,OAAOJ,CACT,CAAC,CAAA,CAEKK,CAAAA,CAAW,IAAA,CAAK,IAAA,CAAKL,CAAAA,CAAY,CAAC,CAAA,CAGlCM,CAAAA,CAAsB,EAAC,CAC7B,IAAA,IAASC,CAAAA,CAAKF,EAAW,CAAA,CAAGE,CAAAA,EAAM,CAAA,CAAGA,CAAAA,EAAAA,CAAM,CACzC,IAAMC,CAAAA,CAAWD,CAAAA,CAAK,CAAA,CAGhBE,CAAAA,CAA8C,EAAC,CAErD,IAAA,IAASC,CAAAA,CAAK,CAAA,CAAGA,CAAAA,CAAKT,EAAK,MAAA,CAAQS,CAAAA,EAAAA,CAAM,CACvC,IAAMC,CAAAA,CAAIT,CAAAA,CAAQQ,CAAE,CAAA,CAChBE,CAAAA,CAAO,CAAA,CACP/B,CAAAA,CAAQ,EAAA,CAEZ,IAAA,IAASgC,CAAAA,CAAK,CAAA,CAAGA,CAAAA,CAAK,EAAGA,CAAAA,EAAAA,CAAM,CAC7B,IAAMC,CAAAA,CAAYN,CAAAA,CAAWK,CAAAA,CAAK,CAAA,CAClC,GAAIC,CAAAA,CAAYd,CAAAA,CAAW,MAAA,CAGhBW,CAAAA,EAAKG,CAAAA,EAAcH,CAAAA,GAAM,CAAA,EAAKG,CAAAA,GAAc,KAErDF,CAAAA,EAAQpB,EAAAA,CAAaqB,CAAE,CAAA,CAEvBhC,CAAAA,CAAQ8B,CAAAA,GAAM,CAAA,CAAIb,CAAAA,CAAM,CAAC,CAAA,CAAG,KAAA,CAAQA,CAAAA,CAAMgB,CAAS,CAAA,CAAG,KAAA,EAE1D,CAEA,IAAMC,CAAAA,CAAO,MAAA,CAAO,YAAA,CAAatB,EAAAA,CAAemB,CAAI,CAAA,CAC9CI,CAAAA,CAAOP,CAAAA,CAASA,CAAAA,CAAS,MAAA,CAAS,CAAC,CAAA,CACrCO,CAAAA,EAAQA,CAAAA,CAAK,KAAA,GAAUnC,CAAAA,CACzBmC,EAAK,IAAA,EAAQD,CAAAA,CAEbN,CAAAA,CAAS,IAAA,CAAK,CAAE,IAAA,CAAMM,CAAAA,CAAM,KAAA,CAAAlC,CAAM,CAAC,EAEvC,CAEAyB,CAAAA,CAAK,IAAA,CACHf,GAAAA,CAACD,IAAAA,CAAA,CACE,QAAA,CAAAmB,CAAAA,CAAS,GAAA,CAAI,CAACjF,CAAAA,CAAG,CAAA,GAChBA,CAAAA,CAAE,KAAA,CACA+D,GAAAA,CAACD,IAAAA,CAAA,CAAa,KAAA,CAAO9D,CAAAA,CAAE,KAAA,CACpB,QAAA,CAAAA,CAAAA,CAAE,MADM,CAEX,CAAA,CAEA+D,GAAAA,CAACD,IAAAA,CAAA,CAAc,QAAA,CAAA9D,CAAAA,CAAE,IAAA,CAAA,CAAN,CAAW,CAE1B,CAAA,CAAA,CATS+E,CAUX,CACF,EACF,CAEA,OACEpB,KAAAE,QAAAA,CAAA,CACG,QAAA,CAAA,CAAAiB,CAAAA,CACAP,CAAAA,EAASR,GAAAA,CAACD,IAAAA,CAAA,CAAK,QAAA,CAAQ,IAAA,CAAE,QAAA,CAAAS,CAAAA,CAAM,CAAA,CAAA,CAClC,CAEJ,CCvIO,SAASkB,GAAY,CAAE,KAAA,CAAApE,CAAM,CAAA,CAA4B,CAC9D,OACEsC,IAAAA,CAAAE,QAAAA,CAAA,CACE,QAAA,CAAA,CAAAF,IAAAA,CAACG,IAAAA,CAAA,CAAK,QAAA,CAAA,CAAA,aAAA,CACQ,GAAA,CACZC,GAAAA,CAACD,KAAA,CAAK,IAAA,CAAI,IAAA,CAAC,KAAA,CAAM,MAAA,CACd,QAAA,CAAAzC,CAAAA,CAAM,EAAA,CACT,CAAA,CAAA,CACF,CAAA,CACAsC,IAAAA,CAACG,IAAAA,CAAA,CAAK,QAAA,CAAA,CAAA,SAAA,CACI,GAAA,CACRC,GAAAA,CAACD,KAAA,CAAK,IAAA,CAAI,IAAA,CAAC,KAAA,CAAOxD,EAAAA,CAAYe,CAAAA,CAAM,MAAM,CAAA,CACvC,QAAA,CAAAA,CAAAA,CAAM,MAAA,CACT,CAAA,CACC,IAAA,CAAK,aAAA,CAAW0C,GAAAA,CAACD,IAAAA,CAAA,CAAK,IAAA,CAAI,IAAA,CAAE,QAAA,CAAApC,CAAAA,CAAOL,CAAAA,CAAM,cAAc,CAAA,CAAE,CAAA,CACzD,IAAA,CAAK,SAAA,CAAQ,GAAA,CACd0C,GAAAA,CAACD,IAAAA,CAAA,CACC,IAAA,CAAI,IAAA,CACH,GAAIzC,CAAAA,CAAM,eAAA,CAAkB,CAAA,CAAI,CAAE,KAAA,CAAO,KAAe,CAAA,CAAI,EAAC,CAE7D,QAAA,CAAAK,CAAAA,CAAOL,CAAAA,CAAM,eAAe,CAAA,CAC/B,CAAA,CACC,IAAA,CAAK,WAAS,GAAA,CACf0C,GAAAA,CAACD,IAAAA,CAAA,CACC,IAAA,CAAI,IAAA,CACH,GAAIzC,CAAAA,CAAM,gBAAA,CAAmB,CAAA,CAAI,CAAE,KAAA,CAAO,QAAkB,CAAA,CAAI,EAAC,CAEjE,SAAAK,CAAAA,CAAOL,CAAAA,CAAM,gBAAgB,CAAA,CAChC,CAAA,CACC,IAAA,CAAK,OAAA,CAAK0C,GAAAA,CAACD,IAAAA,CAAA,CAAK,IAAA,CAAI,IAAA,CAAE,QAAA,CAAA1D,CAAAA,CAAeiB,CAAAA,CAAM,aAAa,EAAE,CAAA,CAAA,CAC7D,CAAA,CAAA,CACF,CAEJ,CCIO,SAASqE,EAAAA,CAAS,CACvB,OAAA,CAAArB,CAAAA,CACA,IAAA,CAAAI,CAAAA,CACA,MAAA,CAAAkB,CAAAA,CACA,aAAA,CAAAzD,CAAAA,CACA,aAAAG,CAAAA,CACA,WAAA,CAAAN,CAAAA,CACA,GAAA,CAAA6D,CAAAA,CAAM,CAAA,CACN,YAAA,CAAAC,CAAAA,CAAe,SAAA,CACf,aAAA,CAAAC,CACF,CAAA,CAAkB,CAChB,IAAMC,CAAAA,CAAS,GAAA,CAAI,OAAOH,CAAG,CAAA,CAGvBI,CAAAA,CACJjC,GAAAA,CAACH,GAAAA,CAAA,CACE,QAAA,CAAAS,CAAAA,CAAQ,GAAA,CAAI,CAAC4B,CAAAA,CAAGf,CAAAA,GAAO,CAEtB,IAAMgB,CAAAA,CADShB,CAAAA,GAAOb,EAAQ,MAAA,CAAS,CAAA,CAChB,EAAA,CAAK0B,CAAAA,CAE5B,GAAIE,CAAAA,CAAE,KAAA,GAAU,MAAA,CACd,OACEtC,IAAAA,CAACE,UAAAA,CAAA,CACC,QAAA,CAAA,CAAAE,GAAAA,CAACH,GAAAA,CAAA,CAAI,SAAU,CAAA,CACb,QAAA,CAAAG,GAAAA,CAACD,IAAAA,CAAA,CAAK,IAAA,CAAI,IAAA,CAAC,QAAA,CAAQ,IAAA,CAChB,QAAA,CAAAmC,CAAAA,CAAE,MAAA,CACL,CAAA,CACF,CAAA,CACCC,CAAAA,EAASnC,GAAAA,CAACD,KAAA,CAAM,QAAA,CAAAoC,CAAAA,CAAM,CAAA,CAAA,CAAA,CANVhB,CAOf,CAAA,CAIJ,IAAMiB,CAAAA,CACJF,CAAAA,CAAE,KAAA,GAAU,OAAA,CACRA,CAAAA,CAAE,MAAA,CAAO,QAAA,CAASA,CAAAA,CAAE,KAAK,EACzBzF,CAAAA,CAAIyF,CAAAA,CAAE,MAAA,CAAQA,CAAAA,CAAE,KAAK,CAAA,CAE3B,OACEtC,IAAAA,CAACE,UAAAA,CAAA,CACC,QAAA,CAAA,CAAAE,GAAAA,CAACD,IAAAA,CAAA,CAAK,IAAA,CAAI,IAAA,CAAC,SAAQ,IAAA,CAChB,QAAA,CAAAqC,CAAAA,CACH,CAAA,CACCD,CAAAA,EAASnC,GAAAA,CAACD,IAAAA,CAAA,CAAM,QAAA,CAAAoC,CAAAA,CAAM,CAAA,CAAA,CAAA,CAJVhB,CAKf,CAEJ,CAAC,CAAA,CACH,CAAA,CAGF,GAAIT,CAAAA,CAAK,MAAA,GAAW,CAAA,CAClB,OACEd,IAAAA,CAAAE,QAAAA,CAAA,CACG,QAAA,CAAA,CAAAmC,CAAAA,CACDjC,GAAAA,CAACD,IAAAA,CAAA,CAAK,QAAA,CAAQ,IAAA,CAAE,QAAA,CAAA+B,CAAAA,CAAa,GAC/B,CAAA,CAIJ,IAAMO,CAAAA,CAAU3B,CAAAA,CAAK,KAAA,CAAMpC,CAAAA,CAAcA,CAAAA,CAAeN,CAAW,CAAA,CAC7DsE,CAAAA,CAAY5B,CAAAA,CAAK,MAAA,CAASpC,CAAAA,CAAeN,CAAAA,CAE/C,OACE4B,IAAAA,CAAAE,SAAA,CACG,QAAA,CAAA,CAAAmC,CAAAA,CACAI,CAAAA,CAAQ,GAAA,CAAI,CAACE,CAAAA,CAAKC,CAAAA,GAAO,CACxB,IAAMC,CAAAA,CAAYnE,CAAAA,CAAekE,CAAAA,CAC3B1E,CAAAA,CAAW2E,CAAAA,GAActE,CAAAA,CAGzBuE,EAAUX,CAAAA,GAAgBQ,CAAAA,CAAKE,CAAS,CAAA,CAC9C,OAAIC,CAAAA,GAAY,MAAA,CACP1C,GAAAA,CAACH,GAAAA,CAAA,CAAkC,QAAA,CAAA6C,CAAAA,CAAAA,CAAzBd,CAAAA,CAAOW,CAAAA,CAAKE,CAAS,CAAY,EAIlDzC,GAAAA,CAACH,GAAAA,CAAA,CACE,QAAA,CAAAS,CAAAA,CAAQ,GAAA,CAAI,CAAC4B,CAAAA,CAAGf,CAAAA,GAAO,CAEtB,IAAMgB,CAAAA,CADShB,CAAAA,GAAOb,CAAAA,CAAQ,MAAA,CAAS,CAAA,CAChB,GAAK0B,CAAAA,CACtBW,CAAAA,CAAWT,CAAAA,CAAE,KAAA,GAAU,MAAA,CAAS,MAAA,CAAYA,CAAAA,CAAE,KAAA,CAC9CU,CAAAA,CAAOV,CAAAA,CAAE,MAAA,CAAOK,CAAAA,CAAKzE,CAAAA,CAAU6E,CAAQ,CAAA,CAE7C,OAAIT,EAAE,KAAA,GAAU,MAAA,CAEZtC,IAAAA,CAACE,UAAAA,CAAA,CACC,QAAA,CAAA,CAAAE,GAAAA,CAACH,GAAAA,CAAA,CAAI,QAAA,CAAU,CAAA,CACb,QAAA,CAAAG,GAAAA,CAACD,IAAAA,CAAA,CAAK,IAAA,CAAK,WAAY,QAAA,CAAA6C,CAAAA,CAAK,CAAA,CAC9B,CAAA,CACCT,CAAAA,EAASnC,GAAAA,CAACD,IAAAA,CAAA,CAAM,QAAA,CAAAoC,CAAAA,CAAM,CAAA,CAAA,CAAA,CAJVhB,CAKf,CAAA,CAKFvB,IAAAA,CAACE,UAAAA,CAAA,CACE,UAAA8C,CAAAA,CACAT,CAAAA,EAASnC,GAAAA,CAACD,IAAAA,CAAA,CAAM,QAAA,CAAAoC,CAAAA,CAAM,CAAA,CAAA,CAAA,CAFVhB,CAGf,CAEJ,CAAC,CAAA,CAAA,CAxBOS,CAAAA,CAAOW,CAAAA,CAAKE,CAAS,CAyB/B,CAEJ,CAAC,CAAA,CACDzC,GAAAA,CAACD,IAAAA,CAAA,CAAK,QAAA,CAAQ,IAAA,CAAE,QAAA,CAAAuC,CAAAA,CAAY,CAAA,CAAI,aAAA,CAAgB,GAAA,CAAI,CAAA,CAAA,CACtD,CAEJ,CCvIO,SAASO,EAAAA,CACdC,CAAAA,CACgB,CAChB,IAAMC,CAAAA,CAAQ,IAAI,OAAA,CAElB,SAASC,CAAAA,CAAWT,CAAAA,CAAmC,CACrD,IAAMU,CAAAA,CAAKH,CAAAA,CAASP,CAAG,CAAA,CACvB,GAAI,CAACU,CAAAA,CAAI,OACT,IAAIC,CAAAA,CAAOH,CAAAA,CAAM,GAAA,CAAIE,CAAE,CAAA,CACvB,OAAKC,IACHA,CAAAA,CAAO1F,EAAAA,CAAoByF,CAAAA,CAAG,SAAA,CAAWA,CAAAA,CAAG,OAAO,CAAA,CACnDF,CAAAA,CAAM,GAAA,CAAIE,CAAAA,CAAIC,CAAI,CAAA,CAAA,CAEbA,CACT,CAEA,OAAO,CACL,CACE,MAAA,CAAQ,MAAA,CACR,KAAA,CAAO,EAAA,CACP,MAAA,CAAQ,CAACX,CAAAA,CAAKY,CAAAA,CAAMC,CAAAA,GAAM,CACxB,IAAMF,CAAAA,CAAOF,CAAAA,CAAWT,CAAG,CAAA,CAC3B,OAAKW,EACElD,GAAAA,CAACD,IAAAA,CAAA,CAAM,QAAA,CAAAtD,CAAAA,CAAIyG,CAAAA,CAAK,IAAA,CAAME,CAAC,CAAA,CAAE,CAAA,CADdpD,GAAAA,CAACD,IAAAA,CAAA,CAAM,QAAA,CAAAtD,CAAAA,CAAI,EAAA,CAAI2G,CAAC,CAAA,CAAE,CAEtC,CACF,CAAA,CACA,CACE,MAAA,CAAQ,SAAA,CACR,KAAA,CAAO,EAAA,CACP,MAAA,CAAQ,CAACb,CAAAA,CAAKY,CAAAA,CAAMC,CAAAA,GAAM,CACxB,IAAMF,EAAOF,CAAAA,CAAWT,CAAG,CAAA,CAC3B,OAAKW,CAAAA,CACElD,GAAAA,CAACD,IAAAA,CAAA,CAAM,QAAA,CAAAtD,CAAAA,CAAIyG,CAAAA,CAAK,OAAA,CAASE,CAAC,CAAA,CAAE,CAAA,CADjBpD,GAAAA,CAACD,KAAA,CAAM,QAAA,CAAAtD,CAAAA,CAAI,EAAA,CAAI2G,CAAC,CAAA,CAAE,CAEtC,CACF,CAAA,CACA,CACE,MAAA,CAAQ,UAAA,CACR,KAAA,CAAO,EAAA,CACP,MAAA,CAAQ,CAACb,EAAKY,CAAAA,CAAMC,CAAAA,GAAM,CACxB,IAAMF,CAAAA,CAAOF,CAAAA,CAAWT,CAAG,CAAA,CAC3B,OAAKW,CAAAA,CACElD,GAAAA,CAACD,IAAAA,CAAA,CAAM,QAAA,CAAAtD,CAAAA,CAAIyG,CAAAA,CAAK,SAAUE,CAAC,CAAA,CAAE,CAAA,CADlBpD,GAAAA,CAACD,IAAAA,CAAA,CAAM,QAAA,CAAAtD,CAAAA,CAAI,EAAA,CAAI2G,CAAC,CAAA,CAAE,CAEtC,CACF,CAAA,CACA,CACE,MAAA,CAAQ,WACR,KAAA,CAAO,CAAA,CACP,KAAA,CAAO,OAAA,CACP,MAAA,CAASb,CAAAA,EAAQ,CACf,IAAMW,CAAAA,CAAOF,CAAAA,CAAWT,CAAG,CAAA,CAC3B,OAAKW,CAAAA,CACElD,GAAAA,CAACD,IAAAA,CAAA,CAAM,QAAA,CAAAmD,CAAAA,CAAK,QAAA,CAAS,QAAA,CAAS,CAAC,CAAA,CAAE,CAAA,CADtBlD,GAAAA,CAACD,IAAAA,CAAA,CAAM,QAAA,CAAA,EAAA,CAAG,CAE9B,CACF,CACF,CACF,CAKO,SAASsD,EAAAA,EAAkC,CAChD,OAAO,CACL,MAAA,CAAQ,EAAA,CACR,KAAA,CAAO,CAAA,CACP,MAAA,CAAQ,CAACC,CAAAA,CAAMxF,CAAAA,GACbkC,GAAAA,CAACD,IAAAA,CAAA,CAAM,GAAIjC,EAAW,CAAE,KAAA,CAAO,MAAgB,CAAA,CAAI,EAAC,CAAI,IAAA,CAAMA,CAAAA,CAC3D,QAAA,CAAAA,CAAAA,CAAW,IAAA,CAAO,IAAA,CACrB,CAEJ,CACF,CCzEA,IAAMyF,EAAAA,CAA+C,CACnDF,EAAAA,EAA+B,CAC/B,CACE,MAAA,CAAQ,IAAA,CACR,KAAA,CAAO,MAAA,CACP,MAAA,CAAQ,CAACd,CAAAA,CAAKzE,IACZkC,GAAAA,CAACD,IAAAA,CAAA,CAAM,GAAIjC,CAAAA,CAAW,CAAE,KAAA,CAAO,MAAgB,CAAA,CAAI,EAAC,CAAI,IAAA,CAAMA,CAAAA,CAC3D,QAAA,CAAAyE,CAAAA,CAAI,EAAA,CACP,CAEJ,CAAA,CACA,CACE,MAAA,CAAQ,QAAA,CACR,KAAA,CAAO,CAAA,CACP,MAAA,CAAQ,CAACA,CAAAA,CAAKY,CAAAA,CAAMC,CAAAA,GAClBpD,GAAAA,CAACD,IAAAA,CAAA,CAAK,KAAA,CAAOxD,EAAAA,CAAYgG,EAAI,MAAM,CAAA,CAAI,QAAA,CAAA9F,CAAAA,CAAI8F,CAAAA,CAAI,MAAA,CAAQa,CAAC,CAAA,CAAE,CAE9D,CAAA,CACA,CACE,MAAA,CAAQ,UAAA,CACR,KAAA,CAAO,CAAA,CACP,KAAA,CAAO,QACP,MAAA,CAASb,CAAAA,EAAQvC,GAAAA,CAACD,IAAAA,CAAA,CAAM,QAAA,CAAA1D,CAAAA,CAAekG,CAAAA,CAAI,UAAU,CAAA,CAAE,QAAA,CAAS,CAAC,CAAA,CAAE,CACrE,CAAA,CACA,CACE,OAAQ,MAAA,CACR,KAAA,CAAO,CAAA,CACP,MAAA,CAAQ,CAACA,CAAAA,CAAKY,CAAAA,CAAMC,CAAAA,GAClBpD,GAAAA,CAACD,IAAAA,CAAA,CAAK,QAAA,CAAQ,IAAA,CACX,QAAA,CAAAtD,CAAAA,CAAI8F,CAAAA,CAAI,UAAU,OAAA,CAAQ,GAAA,CAAK,GAAG,CAAA,CAAE,KAAA,CAAM,EAAA,CAAI,EAAE,CAAA,CAAGa,CAAC,CAAA,CACvD,CAEJ,CACF,CAAA,CAEO,SAASI,EAAAA,CAAmB,CACjC,aAAAC,CAAAA,CACA,KAAA,CAAAnG,CAAAA,CACA,SAAA,CAAAoG,CAAAA,CACA,aAAA,CAAAvF,CAAAA,CACA,YAAA,CAAAG,CAAAA,CACA,KAAA,CAAAiB,CAAAA,CACA,MAAA,CAAAoE,CAAAA,CACA,KAAA,CAAArE,CAAAA,CAAQ,MAAA,CACR,SAAAsE,CACF,CAAA,CAUG,CACD,IAAMC,CAAAA,CAAgB,IAAA,CAAK,IAAA,CAAA,CAAM1D,EAAAA,CAAc,MAAA,CAAS,CAAA,EAAK,CAAC,CAAA,CACxD2D,CAAAA,CAAaxG,CAAAA,CAAQ,CAAA,CAAIuG,CAAAA,CAAgB,EAAI,CAAA,CAC7CE,CAAAA,CAAY,IAAA,CAAK,GAAA,CAAIJ,CAAAA,CAAS,CAAA,CAAqBG,CAAAA,CAAY,CAAC,CAAA,CAEhE1E,CAAAA,CAAQ9B,CAAAA,CAAQ,WAAA,CAAc,CAAA,WAAA,EAAcmG,CAAY,CAAA,CAAA,CAE9D,OACE7D,KAACC,GAAAA,CAAA,CAAI,aAAA,CAAc,QAAA,CAAS,KAAA,CAAON,CAAAA,CAAO,QAAA,CAAU,CAAA,CACjD,QAAA,CAAA,CAAAjC,CAAAA,EACCsC,IAAAA,CAACT,CAAAA,CAAA,CAAM,KAAA,CAAOI,CAAAA,CACZ,QAAA,CAAA,CAAAS,IAAC0B,EAAAA,CAAA,CAAY,KAAA,CAAOpE,CAAAA,CAAO,CAAA,CAC3B0C,GAAAA,CAACD,IAAAA,CAAA,CAAK,QAAA,CAAA,GAAA,CAAC,CAAA,CACPC,GAAAA,CAACI,EAAAA,CAAA,CACC,MAAA,CAAQwD,CAAAA,CAAWA,CAAAA,CAAS,WAAa,EAAC,CAC1C,OAAA,CAASrE,CAAAA,CAAQ,CAAA,CACjB,KAAA,CAAM,yBAAA,CACR,CAAA,CAAA,CACF,CAAA,CAEFS,GAAAA,CAACb,CAAAA,CAAA,CAAM,KAAA,CAAOC,CAAAA,CAAO,KAAA,CAAOG,CAAAA,CAAO,SAAU,CAAA,CAAG,KAAA,CAAOD,CAAAA,CACrD,QAAA,CAAAU,GAAAA,CAAC2B,EAAAA,CAAA,CACC,OAAA,CAAS4B,EAAAA,CACT,IAAA,CAAMG,CAAAA,CACN,MAAA,CAASM,CAAAA,EAAOA,CAAAA,CAAG,EAAA,CAAKA,CAAAA,CAAG,UAC3B,aAAA,CAAe7F,CAAAA,CACf,YAAA,CAAcG,CAAAA,CACd,WAAA,CAAayF,CAAAA,CACb,YAAA,CAAa,cAAA,CACf,CAAA,CACF,CAAA,CAAA,CACF,CAEJ,CC9EO,SAASE,EAAAA,CAAaC,CAAAA,CAA2B,CACtD,IAAMC,CAAAA,CAAsB,EAAC,CACvBC,EACJ,6HAAA,CACEC,CAAAA,CAAY,CAAA,CACZC,CAAAA,CAEJ,KAAA,CAAQA,CAAAA,CAAQF,CAAAA,CAAG,IAAA,CAAKF,CAAI,CAAA,IAAO,IAAA,EAE7BI,CAAAA,CAAM,KAAA,CAAQD,CAAAA,EAChBF,CAAAA,CAAO,IAAA,CAAK,CAAE,IAAA,CAAMD,CAAAA,CAAK,KAAA,CAAMG,CAAAA,CAAWC,CAAAA,CAAM,KAAK,CAAA,CAAG,IAAA,CAAM,OAAQ,CAAC,CAAA,CAGrEA,CAAAA,CAAM,CAAC,CAAA,GAAM,MAAA,EAEfH,CAAAA,CAAO,KAAK,CAAE,IAAA,CAAMG,CAAAA,CAAM,CAAC,CAAA,CAAG,IAAA,CAAM,KAAM,CAAC,CAAA,CAC3CH,CAAAA,CAAO,IAAA,CAAK,CAAE,IAAA,CAAM,GAAA,CAAK,IAAA,CAAM,OAAQ,CAAC,CAAA,EAC/BG,CAAAA,CAAM,CAAC,CAAA,GAAM,MAAA,CACtBH,CAAAA,CAAO,IAAA,CAAK,CAAE,IAAA,CAAMG,CAAAA,CAAM,CAAC,CAAA,CAAG,IAAA,CAAM,QAAS,CAAC,CAAA,CACrCA,EAAM,CAAC,CAAA,GAAM,MAAA,CACtBH,CAAAA,CAAO,IAAA,CAAK,CAAE,IAAA,CAAMG,CAAAA,CAAM,CAAC,CAAA,CAAG,IAAA,CAAM,QAAS,CAAC,CAAA,CACrCA,CAAAA,CAAM,CAAC,IAAM,MAAA,CACtBH,CAAAA,CAAO,IAAA,CAAK,CAAE,IAAA,CAAMG,CAAAA,CAAM,CAAC,CAAA,CAAG,IAAA,CAAM,SAAU,CAAC,CAAA,CACtCA,CAAAA,CAAM,CAAC,CAAA,GAAM,MAAA,CACtBH,EAAO,IAAA,CAAK,CAAE,IAAA,CAAMG,CAAAA,CAAM,CAAC,CAAA,CAAG,IAAA,CAAM,MAAO,CAAC,CAAA,CACnCA,CAAAA,CAAM,CAAC,CAAA,GAAM,MAAA,EACtBH,CAAAA,CAAO,IAAA,CAAK,CAAE,IAAA,CAAMG,CAAAA,CAAM,CAAC,CAAA,CAAG,IAAA,CAAM,OAAQ,CAAC,CAAA,CAG/CD,CAAAA,CAAYC,CAAAA,CAAM,KAAA,CAAQA,CAAAA,CAAM,CAAC,CAAA,CAAE,MAAA,CAIrC,OAAID,EAAYH,CAAAA,CAAK,MAAA,EACnBC,CAAAA,CAAO,IAAA,CAAK,CAAE,IAAA,CAAMD,CAAAA,CAAK,KAAA,CAAMG,CAAS,CAAA,CAAG,IAAA,CAAM,OAAQ,CAAC,CAAA,CAGrDF,CACT,CAEO,IAAMI,EAAAA,CAA0C,CACrD,GAAA,CAAK,MAAA,CACL,MAAA,CAAQ,OAAA,CACR,MAAA,CAAQ,QAAA,CACR,OAAA,CAAS,QAAA,CACT,IAAA,CAAM,KAAA,CACN,KAAA,CAAO,MACT,CAAA,CAKO,SAASC,GAAW5H,CAAAA,CAAa6H,CAAAA,CAA4B,CAClE,GAAI,CACF,IAAM/G,CAAAA,CAAS,IAAA,CAAK,MAAMd,CAAG,CAAA,CAE7B,OADe,IAAA,CAAK,SAAA,CAAUc,CAAAA,CAAQ,IAAA,CAAM,CAAC,EAC/B,KAAA,CAAM;AAAA,CAAI,EAAE,GAAA,CAAKwG,CAAAA,EAAS,CACtC,IAAMQ,CAAAA,CAAa,KAAK,GAAA,CAAI,CAAA,CAAGD,CAAQ,CAAA,CACvC,OAAOP,CAAAA,CAAK,MAAA,CAASQ,EACjBR,CAAAA,CAAK,KAAA,CAAM,EAAG,IAAA,CAAK,GAAA,CAAI,CAAA,CAAGQ,CAAAA,CAAa,CAAC,CAAC,CAAA,CAAI,SAC7CR,CACN,CAAC,CACH,CAAA,KAAQ,CACN,IAAMQ,CAAAA,CAAa,KAAK,GAAA,CAAI,CAAA,CAAGD,CAAQ,CAAA,CACvC,OAAO7H,EACJ,KAAA,CAAM;AAAA,CAAI,CAAA,CACV,GAAA,CAAKsH,CAAAA,EACJA,CAAAA,CAAK,MAAA,CAASQ,CAAAA,CACVR,CAAAA,CAAK,KAAA,CAAM,CAAA,CAAG,IAAA,CAAK,GAAA,CAAI,CAAA,CAAGQ,CAAAA,CAAa,CAAC,CAAC,CAAA,CAAI,QAAA,CAC7CR,CACN,CACJ,CACF,CAKO,SAASS,EAAAA,CAAgB,CAAE,IAAA,CAAAT,CAAK,CAAA,CAAqB,CAC1D,IAAMC,CAAAA,CAASF,EAAAA,CAAaC,CAAI,CAAA,CAChC,OAAIC,CAAAA,CAAO,MAAA,GAAW,CAAA,CAAUnE,GAAAA,CAACD,IAAAA,CAAA,CAAM,QAAA,CAAAmE,CAAAA,CAAK,CAAA,CAE1ClE,GAAAA,CAACD,IAAAA,CAAA,CACE,QAAA,CAAAoE,CAAAA,CAAO,GAAA,CAAI,CAACS,CAAAA,CAAO/D,CAAAA,GAClBb,GAAAA,CAACD,IAAAA,CAAA,CAAa,KAAA,CAAOwE,EAAAA,CAAaK,CAAAA,CAAM,IAAI,EACzC,QAAA,CAAAA,CAAAA,CAAM,IAAA,CAAA,CADE/D,CAEX,CACD,CAAA,CACH,CAEJ,CAKO,SAASgE,EAAAA,CAAajI,CAAAA,CAA6C,CACxE,GAAI,CACF,IAAMc,CAAAA,CAAkB,IAAA,CAAK,KAAA,CAAMd,CAAG,CAAA,CACtC,OACE,OAAOc,CAAAA,EAAW,QAAA,EAClBA,CAAAA,GAAW,IAAA,EACX,KAAA,CAAM,OAAA,CAAQA,CAAM,EAEb,IAAA,CAEFA,CACT,CAAA,KAAQ,CACN,OAAO,IACT,CACF,CC7GA,SAASoH,EAAAA,CACPC,CAAAA,CACAC,CAAAA,CACgE,CAChE,IAAMC,CAAAA,CAAS,IAAI,GAAA,CAIfC,CAAAA,CAAa,CAAA,CAEjBD,CAAAA,CAAO,GAAA,CAAID,CAAAA,CAAkB,CAC3B,UAAA,CAAYA,CAAAA,CACZ,KAAA,CAAO,QAAA,CACP,MAAA,CAAQ,EACV,CAAC,CAAA,CAED,IAAA,IAAW/B,CAAAA,IAAM8B,CAAAA,CAAQ,CACvB,IAAMlI,EAAIgI,EAAAA,CAAa5B,CAAAA,CAAG,OAAO,CAAA,CAC3BkC,CAAAA,CAAOtI,CAAAA,CAAI,MAAA,CAAOA,CAAAA,CAAE,UAAA,EAAiB,EAAE,CAAA,CAAI,EAAA,CAC3CuI,CAAAA,CAAM,CAACD,GAAQA,CAAAA,GAASH,CAAAA,CAAmBA,CAAAA,CAAmBG,CAAAA,CAE/DF,CAAAA,CAAO,GAAA,CAAIG,CAAG,CAAA,GACjBF,CAAAA,EAAAA,CACAD,CAAAA,CAAO,GAAA,CAAIG,CAAAA,CAAK,CACd,UAAA,CAAYA,CAAAA,CACZ,KAAA,CAAO,CAAA,MAAA,EAASF,CAAU,CAAA,CAAA,CAC1B,MAAA,CAAQ,EACV,CAAC,CAAA,CAAA,CAEHD,CAAAA,CAAO,GAAA,CAAIG,CAAG,CAAA,CAAG,MAAA,CAAO,IAAA,CAAKnC,CAAE,EACjC,CAEA,OAAO,KAAA,CAAM,IAAA,CAAKgC,CAAAA,CAAO,MAAA,EAAQ,CACnC,CAEA,IAAMI,EAAAA,CAAyC,CAC7ChC,EAAAA,EAA2B,CAC3B,CACE,MAAA,CAAQ,MAAA,CACR,KAAA,CAAO,CAAA,CACP,MAAA,CAAQ,CAACd,CAAAA,CAAKY,CAAAA,CAAMC,CAAAA,GAAM,CACxB,GAAI,CAACb,CAAAA,CAAI,KAAA,CAAO,OAAOvC,GAAAA,CAACD,IAAAA,CAAA,CAAM,QAAA,CAAAtD,CAAAA,CAAI,EAAA,CAAI2G,CAAC,CAAA,CAAE,CAAA,CACzC,IAAMkC,CAAAA,CAAS,GAAA,CAAI,MAAA,CAAO/C,CAAAA,CAAI,MAAM,CAAA,CACpC,OACE3C,IAAAA,CAACG,IAAAA,CAAA,CAAK,QAAA,CAAQ,IAAA,CACX,QAAA,CAAA,CAAAuF,CAAAA,CACA/C,CAAAA,CAAI,KAAA,CAAM,SAAA,CAAU,OAAA,CAAQ,GAAA,CAAK,GAAG,EAAE,KAAA,CAAM,EAAA,CAAI,EAAE,CAAA,CAAA,CACrD,CAEJ,CACF,CAAA,CACA,CACE,MAAA,CAAQ,OAAA,CACR,KAAA,CAAO,MAAA,CACP,MAAA,CAASA,CAAAA,EACFA,EAAI,KAAA,CACFvC,GAAAA,CAACD,IAAAA,CAAA,CAAK,KAAA,CAAM,MAAA,CAAQ,QAAA,CAAAwC,CAAAA,CAAI,KAAA,CAAM,SAAA,CAAU,CAAA,CADxBvC,GAAAA,CAACD,IAAAA,CAAA,EAAK,CAGjC,CAAA,CACA,GAAG8C,EAAAA,CAAgCN,CAAAA,EAAQA,CAAAA,CAAI,KAAK,CACtD,CAAA,CAEO,SAASgD,EAAAA,CAAqB,CACnC,QAAA,CAAAzI,CAAAA,CACA,MAAA,CAAAiI,CAAAA,CACA,KAAA,CAAAxF,CAAAA,CACA,MAAA,CAAAoE,CAAAA,CACA,YAAA,CAAArF,CAAAA,CACA,aAAA,CAAAH,CAAAA,CAAgB,EAAA,CAChB,KAAA,CAAAmB,CAAAA,CAAQ,MACV,CAAA,CAQG,CACD,IAAMkG,EAAW1I,CAAAA,CAAS,KAAA,CAAQ,CAAA,CAAI,CAAA,CAChC2I,CAAAA,CAAY,IAAA,CAAK,GAAA,CAAI9B,CAAAA,CAAS,CAAA,CAAqB6B,CAAAA,CAAU,CAAC,CAAA,CAE9DP,CAAAA,CAASH,EAAAA,CAAsBC,EAAQjI,CAAAA,CAAS,EAAE,CAAA,CAClD4I,CAAAA,CAAcT,CAAAA,CAAO,MAAA,CAAS,CAAA,CAE9BU,CAAAA,CAA4B,EAAC,CACnC,IAAA,IAAWC,CAAAA,IAASX,CAAAA,CAAQ,CACtBS,GACFC,CAAAA,CAAY,IAAA,CAAK,CACf,IAAA,CAAM,QAAA,CACN,IAAA,CAAM,CAAA,EAAGC,CAAAA,CAAM,KAAK,CAAA,EAAA,EAAKA,CAAAA,CAAM,UAAA,CAAW,KAAA,CAAM,CAAA,CAAG,CAAC,CAAC,CAAA,IAAA,EAAOA,CAAAA,CAAM,MAAA,CAAO,MAAM,CAAA,OAAA,CAAA,CAC/E,MAAA,CAAQ,CACV,CAAC,CAAA,CAEH,IAAA,IAAW3C,CAAAA,IAAM2C,CAAAA,CAAM,MAAA,CACrBD,CAAAA,CAAY,KAAK,CACf,IAAA,CAAM,OAAA,CACN,KAAA,CAAO1C,CAAAA,CACP,MAAA,CAAQyC,CAAAA,CAAc,CAAA,CAAI,CAC5B,CAAC,EAEL,CAEA,IAAMG,CAAAA,CAAcH,EAChB,CAAA,eAAA,EAAkBT,CAAAA,CAAO,MAAM,CAAA,YAAA,EAAeF,CAAAA,CAAO,MAAM,CAAA,QAAA,CAAA,CAC3D,CAAA,gBAAA,EAAmBA,CAAAA,CAAO,MAAM,CAAA,CAAA,CAAA,CAEpC,OACEnF,IAAAA,CAACC,GAAAA,CAAA,CAAI,aAAA,CAAc,QAAA,CAAS,KAAA,CAAON,CAAAA,CAAO,QAAA,CAAU,CAAA,CAClD,QAAA,CAAA,CAAAK,IAAAA,CAACT,CAAAA,CAAA,CAAM,KAAA,CAAOI,CAAAA,CACZ,QAAA,CAAA,CAAAK,IAAAA,CAACG,IAAAA,CAAA,CAAK,QAAA,CAAA,CAAA,aAAA,CACQ,GAAA,CACZC,GAAAA,CAACD,IAAAA,CAAA,CAAK,IAAA,CAAI,IAAA,CAAC,KAAA,CAAM,MAAA,CACd,QAAA,CAAAjD,CAAAA,CAAS,OAAA,CACZ,CAAA,CAAA,CACF,CAAA,CACA8C,KAACG,IAAAA,CAAA,CAAK,QAAA,CAAA,CAAA,WAAA,CACM,GAAA,CACVC,GAAAA,CAACD,IAAAA,CAAA,CAAK,IAAA,CAAI,IAAA,CAAC,KAAA,CAAM,MAAA,CACd,QAAA,CAAA7D,EAAAA,CAASY,CAAAA,CAAS,EAAA,CAAIyC,CAAAA,CAAQ,EAAE,CAAA,CACnC,CAAA,CAAA,CACF,CAAA,CACAK,IAAAA,CAACG,IAAAA,CAAA,CAAK,QAAA,CAAA,CAAA,SAAA,CACI,GAAA,CACRC,GAAAA,CAACD,IAAAA,CAAA,CAAK,IAAA,CAAI,IAAA,CAAC,MAAOxD,EAAAA,CAAYO,CAAAA,CAAS,MAAM,CAAA,CAC1C,QAAA,CAAAA,CAAAA,CAAS,MAAA,CACZ,CAAA,CACCA,CAAAA,CAAS,UAAA,GAAe,IAAA,EACvB8C,IAAAA,CAACG,IAAAA,CAAA,CACE,QAAA,CAAA,CAAA,IAAA,CAAK,WAAA,CAAU,GAAA,CAChBC,GAAAA,CAACD,IAAAA,CAAA,CAAK,IAAA,CAAI,IAAA,CAAE,QAAA,CAAA1D,CAAAA,CAAeS,CAAAA,CAAS,UAAU,CAAA,CAAE,CAAA,CAAA,CAClD,CAAA,CAED,IAAA,CAAK,YAASkD,GAAAA,CAACD,IAAAA,CAAA,CAAK,IAAA,CAAI,IAAA,CAAE,QAAA,CAAAjD,CAAAA,CAAS,SAAA,CAAU,CAAA,CAC7CA,CAAAA,CAAS,WAAA,EACR8C,IAAAA,CAACG,IAAAA,CAAA,CACE,eAAK,aAAA,CAAWC,GAAAA,CAACD,IAAAA,CAAA,CAAK,IAAA,CAAI,IAAA,CAAE,QAAA,CAAAjD,CAAAA,CAAS,WAAA,CAAY,CAAA,CAAA,CACpD,CAAA,CAAA,CAEJ,CAAA,CACCA,CAAAA,CAAS,KAAA,EAASA,EAAS,MAAA,GAAW,QAAA,EACrC8C,IAAAA,CAAAE,QAAAA,CAAA,CACE,QAAA,CAAA,CAAAE,GAAAA,CAACD,IAAAA,CAAA,CAAK,QAAA,CAAA,GAAA,CAAC,CAAA,CACPH,IAAAA,CAACG,IAAAA,CAAA,CAAK,KAAA,CAAM,KAAA,CAAM,QAAA,CAAA,CAAA,SAAA,CAAQjD,CAAAA,CAAS,KAAA,CAAA,CAAM,CAAA,CAAA,CAC3C,CAAA,CAEDA,CAAAA,CAAS,KAAA,EAASA,CAAAA,CAAS,MAAA,GAAW,SAAA,EACrC8C,IAAAA,CAAAE,QAAAA,CAAA,CACE,QAAA,CAAA,CAAAE,IAACD,IAAAA,CAAA,CAAK,QAAA,CAAA,GAAA,CAAC,CAAA,CACPH,IAAAA,CAACG,IAAAA,CAAA,CAAK,KAAA,CAAM,QAAA,CAAS,QAAA,CAAA,CAAA,UAAA,CAASjD,CAAAA,CAAS,KAAA,CAAA,CAAM,CAAA,CAAA,CAC/C,CAAA,CAAA,CAEJ,EAEAkD,GAAAA,CAACb,CAAAA,CAAA,CAAM,KAAA,CAAO0G,CAAAA,CAAa,KAAA,CAAOtG,CAAAA,CAAO,QAAA,CAAU,CAAA,CAAG,KAAA,CAAOD,CAAAA,CAC3D,QAAA,CAAAU,GAAAA,CAAC2B,EAAAA,CAAA,CACC,OAAA,CAAS0D,EAAAA,CACT,IAAA,CAAMM,CAAAA,CACN,MAAA,CAAQ,CAACpD,CAAAA,CAAK1B,CAAAA,GACZ0B,CAAAA,CAAI,IAAA,GAAS,QAAA,CACT,CAAA,EAAA,EAAK1B,CAAC,CAAA,CAAA,CACN,CAAA,EAAG0B,CAAAA,CAAI,KAAA,EAAO,EAAA,EAAMA,CAAAA,CAAI,KAAA,EAAO,SAAS,CAAA,CAAA,EAAI1B,CAAC,CAAA,CAAA,CAEnD,aAAA,CAAe1C,CAAAA,CACf,YAAA,CAAcG,CAAAA,CACd,WAAA,CAAamH,CAAAA,CACb,aAAa,yBAAA,CACb,aAAA,CAAgBlD,CAAAA,EACdA,CAAAA,CAAI,IAAA,GAAS,QAAA,CACXvC,GAAAA,CAACD,IAAAA,CAAA,CAAK,IAAA,CAAI,IAAA,CAAC,KAAA,CAAM,QAAA,CACd,QAAA,CAAAwC,EAAI,IAAA,CACP,CAAA,CACE,MAAA,CAER,CAAA,CACF,CAAA,CAAA,CACF,CAEJ,CC7LA,IAAMuD,EAAAA,CAAyC,CAC7CzC,EAAAA,EAA4B,CAC5B,CACE,MAAA,CAAQ,MAAA,CACR,KAAA,CAAO,EAAA,CACP,MAAA,CAAQ,CAACd,CAAAA,CAAKzE,CAAAA,CAAUsF,CAAAA,GACtBpD,GAAAA,CAACD,IAAAA,CAAA,CAAM,GAAIjC,CAAAA,CAAW,CAAE,KAAA,CAAO,MAAgB,CAAA,CAAI,EAAC,CAAI,IAAA,CAAMA,CAAAA,CAC3D,QAAA,CAAArB,EAAI8F,CAAAA,CAAI,SAAA,CAAU,OAAA,CAAQ,GAAA,CAAK,GAAG,CAAA,CAAE,KAAA,CAAM,CAAA,CAAG,EAAE,CAAA,CAAGa,CAAC,CAAA,CACtD,CAEJ,CAAA,CACA,CACE,MAAA,CAAQ,OAAA,CACR,KAAA,CAAO,MAAA,CACP,MAAA,CAASb,CAAAA,EAAQvC,GAAAA,CAACD,IAAAA,CAAA,CAAK,KAAA,CAAM,MAAA,CAAQ,QAAA,CAAAwC,CAAAA,CAAI,SAAA,CAAU,CACrD,EACA,GAAGM,EAAAA,CAAiCN,CAAAA,EAAQA,CAAG,CACjD,CAAA,CAEO,SAASwD,EAAAA,CAAW,CACzB,MAAA,CAAAhB,CAAAA,CACA,aAAA,CAAA5G,CAAAA,CACA,YAAA,CAAAG,CAAAA,CACA,KAAA,CAAAiB,CAAAA,CACA,MAAA,CAAAoE,CAAAA,CACA,KAAA,CAAArE,CAAAA,CAAQ,MACV,CAAA,CAOG,CACD,IAAMyE,CAAAA,CAAY,IAAA,CAAK,GAAA,CAAIJ,CAAAA,CAAS,CAAA,CAAoB,CAAC,CAAA,CAEzD,OACE3D,GAAAA,CAACb,CAAAA,CAAA,CACC,KAAA,CAAM,QAAA,CACN,QAAA,CAAUS,IAAAA,CAACG,IAAAA,CAAA,CAAK,QAAA,CAAQ,IAAA,CAAC,QAAA,CAAA,CAAA,GAAA,CAAEgF,EAAO,MAAA,CAAO,SAAA,CAAA,CAAO,CAAA,CAChD,KAAA,CAAOxF,CAAAA,CACP,QAAA,CAAU,CAAA,CACV,KAAA,CAAOD,CAAAA,CAEP,QAAA,CAAAU,GAAAA,CAAC2B,EAAAA,CAAA,CACC,OAAA,CAASmE,GACT,IAAA,CAAMf,CAAAA,CACN,MAAA,CAAQ,CAAC9B,CAAAA,CAAIpC,CAAAA,GACXoC,CAAAA,CAAG,EAAA,GAAO,MAAA,CAAY,MAAA,CAAOA,CAAAA,CAAG,EAAE,CAAA,CAAI,CAAA,EAAGA,CAAAA,CAAG,SAAS,CAAA,CAAA,EAAIpC,CAAC,CAAA,CAAA,CAE5D,aAAA,CAAe1C,CAAAA,CACf,YAAA,CAAcG,CAAAA,CACd,WAAA,CAAayF,CAAAA,CACb,YAAA,CAAa,yBAAA,CACf,CAAA,CACF,CAEJ,CC5DO,SAASiC,EAAAA,CAAY,CAC1B,KAAA,CAAAC,CAAAA,CACA,KAAA,CAAA1G,CAAAA,CACA,MAAA,CAAAoE,CAAAA,CACA,YAAA,CAAArF,CAAAA,CACA,KAAA,CAAAgB,CAAAA,CAAQ,MACV,CAAA,CAMG,CACD,IAAMzC,CAAAA,CAAIgI,EAAAA,CAAaoB,EAAM,OAAO,CAAA,CAC9BC,CAAAA,CACJrJ,CAAAA,EAAK,OAAOA,CAAAA,CAAE,OAAA,EAAe,QAAA,CAAWA,CAAAA,CAAE,OAAA,CAAa,MAAA,CACnDsJ,CAAAA,CACJtJ,CAAAA,EAAK,OAAOA,CAAAA,CAAE,UAAA,EAAkB,QAAA,CAAWA,CAAAA,CAAE,UAAA,CAAgB,MAAA,CAKzDuJ,CAAAA,CAAe,CAAA,EAFD,CAAA,EAAKF,CAAAA,CAAU,CAAA,CAAI,CAAA,CAAA,EAAMC,CAAAA,CAAa,CAAA,CAAI,CAAA,CAAA,CAAK,CAAA,CAAA,CAI7DE,EAAa,CAAA,CACbC,CAAAA,CAAY,IAAA,CAAK,GAAA,CAAI/G,CAAAA,CAAQ,CAAA,CAAG,EAAE,CAAA,CAClCgH,CAAAA,CAAY/B,EAAAA,CAAWyB,CAAAA,CAAM,OAAA,CAASK,CAAS,CAAA,CAC/CtI,EAAc,IAAA,CAAK,GAAA,CAAI2F,CAAAA,CAASyC,CAAAA,CAAeC,CAAAA,CAAY,CAAC,CAAA,CAC5DhE,CAAAA,CAAUkE,CAAAA,CAAU,KAAA,CAAMjI,CAAAA,CAAcA,CAAAA,CAAeN,CAAW,CAAA,CAExE,OACE4B,IAAAA,CAACC,GAAAA,CAAA,CAAI,aAAA,CAAc,QAAA,CAAS,KAAA,CAAON,CAAAA,CAAO,QAAA,CAAU,CAAA,CAClD,QAAA,CAAA,CAAAK,IAAAA,CAACT,CAAAA,CAAA,CAAM,KAAA,CAAOI,CAAAA,CACZ,QAAA,CAAA,CAAAK,IAAAA,CAACG,IAAAA,CAAA,CAAK,QAAA,CAAA,CAAA,UAAA,CACK,GAAA,CACTC,GAAAA,CAACD,IAAAA,CAAA,CAAK,IAAA,CAAI,IAAA,CAAC,KAAA,CAAM,MAAA,CACd,QAAA,CAAAkG,CAAAA,CAAM,UACT,CAAA,CAAA,CACF,CAAA,CACCC,CAAAA,EACCtG,IAAAA,CAACG,IAAAA,CAAA,CAAK,QAAA,CAAA,CAAA,aAAA,CACQ,GAAA,CACZC,GAAAA,CAACD,IAAAA,CAAA,CAAK,IAAA,CAAI,IAAA,CAAC,KAAA,CAAM,MAAA,CACd,QAAA,CAAAmG,CAAAA,CACH,CAAA,CAAA,CACF,CAAA,CAEDC,CAAAA,EACCvG,IAAAA,CAACG,IAAAA,CAAA,CAAK,QAAA,CAAA,CAAA,WAAA,CACM,GAAA,CACVC,GAAAA,CAACD,IAAAA,CAAA,CAAK,IAAA,CAAI,IAAA,CAAC,MAAM,MAAA,CACd,QAAA,CAAAoG,CAAAA,CACH,CAAA,CAAA,CACF,CAAA,CAEFvG,IAAAA,CAACG,IAAAA,CAAA,CAAK,QAAA,CAAA,CAAA,QAAA,CACG,GAAA,CACPC,GAAAA,CAACD,IAAAA,CAAA,CAAK,IAAA,CAAI,IAAA,CAAC,KAAA,CAAM,MAAA,CACd,QAAA,CAAAkG,CAAAA,CAAM,SAAA,CACT,CAAA,CAAA,CACF,CAAA,CACArG,IAAAA,CAACG,IAAAA,CAAA,CAAK,QAAA,CAAA,CAAA,QAAA,CACEC,GAAAA,CAACD,IAAAA,CAAA,CAAK,IAAA,CAAI,KAAE,QAAA,CAAAkG,CAAAA,CAAM,SAAA,CAAU,OAAA,CAAQ,GAAA,CAAK,GAAG,CAAA,CAAE,CAAA,CAAA,CACtD,CAAA,CAAA,CACF,CAAA,CAEArG,IAAAA,CAACT,CAAAA,CAAA,CACC,KAAA,CAAM,UACN,QAAA,CACES,IAAAA,CAACG,IAAAA,CAAA,CAAK,QAAA,CAAQ,IAAA,CAAC,QAAA,CAAA,CAAA,GAAA,CACXzB,CAAAA,CAAe,CAAA,CAAE,GAAA,CAClB,IAAA,CAAK,GAAA,CAAIA,CAAAA,CAAeN,CAAAA,CAAauI,EAAU,MAAM,CAAA,CAAE,GAAA,CACvDA,CAAAA,CAAU,MAAA,CAAO,SAAA,CAAA,CACpB,CAAA,CAEF,KAAA,CAAOhH,CAAAA,CACP,QAAA,CAAU,CAAA,CACV,KAAA,CAAOD,CAAAA,CAEN,QAAA,CAAA,CAAA+C,CAAAA,CAAQ,GAAA,CAAI,CAAC6B,CAAAA,CAAMrD,CAAAA,GAClBb,GAAAA,CAAC2E,EAAAA,CAAA,CAAuC,IAAA,CAAMT,CAAAA,CAAAA,CAAxB5F,CAAAA,CAAeuC,CAAe,CACrD,CAAA,CACAwB,CAAAA,CAAQ,MAAA,CAASrE,GAChB,KAAA,CAAM,IAAA,CAAK,CAAE,MAAA,CAAQA,CAAAA,CAAcqE,CAAAA,CAAQ,MAAO,CAAC,CAAA,CAAE,GAAA,CAAI,CAACmE,CAAAA,CAAG3F,CAAAA,GAC3Db,GAAAA,CAACD,KAAA,CAAsB,QAAA,CAAA,GAAA,CAAA,CAAZ,CAAA,IAAA,EAAOc,CAAC,CAAA,CAAK,CACzB,CAAA,CAAA,CACL,CAAA,CAAA,CACF,CAEJ,CCrFA,SAAS4F,EAAAA,CACPC,CAAAA,CACAjC,CAAAA,CACU,CACV,IAAMkC,CAAAA,CAAkB,EAAC,CAEzB,OAAAA,CAAAA,CAAM,IAAA,CAAK,SAAS,CAAA,CACpBA,CAAAA,CAAM,IAAA,CAAK,GAAGnC,EAAAA,CAAWkC,CAAAA,CAAS,OAAA,CAASjC,CAAQ,CAAC,CAAA,CACpDkC,EAAM,IAAA,CAAK,EAAE,CAAA,CACbA,CAAAA,CAAM,IAAA,CAAK,MAAM,CAAA,CACbD,CAAAA,CAAS,IAAA,GAAS,IAAA,EACpBC,CAAAA,CAAM,IAAA,CAAK,GAAGnC,EAAAA,CAAWkC,EAAS,IAAA,CAAMjC,CAAQ,CAAC,CAAA,CAC7CiC,CAAAA,CAAS,SAAA,GACXC,CAAAA,CAAM,IAAA,CAAK,EAAE,CAAA,CACbA,CAAAA,CAAM,IAAA,CAAK,sCAAsC,CAAA,CAAA,EAGnDA,EAAM,IAAA,CAAK,QAAQ,CAAA,CAGdA,CACT,CAEO,SAASC,EAAAA,CAAiB,CAC/B,QAAA,CAAA9J,CAAAA,CACA,QAAA,CAAA4J,CAAAA,CACA,KAAA,CAAAnH,CAAAA,CACA,MAAA,CAAAoE,CAAAA,CACA,YAAA,CAAArF,CAAAA,CACA,KAAA,CAAAgB,CAAAA,CAAQ,MACV,CAAA,CAOG,CAKD,IAAMgH,CAAAA,CAAY,IAAA,CAAK,GAAA,CAAI/G,CAAAA,CAAQ,CAAA,CAAG,EAAE,EAClCvB,CAAAA,CAAc,IAAA,CAAK,GAAA,CAAI2F,CAAAA,CAAS,CAAA,CAAe,CAAA,CAAY,CAAC,CAAA,CAG5D4C,CAAAA,CADcG,CAAAA,GAAa,IAAA,CAE7BD,EAAAA,CAAmBC,CAAAA,CAAUJ,CAAS,CAAA,CACtC,CACE,0BAAA,CACA,EAAA,CACA,cAAA,CACA,qDACF,CAAA,CAEEjE,CAAAA,CAAUkE,CAAAA,CAAU,KAAA,CAAMjI,CAAAA,CAAcA,CAAAA,CAAeN,CAAW,CAAA,CAExE,OACE4B,IAAAA,CAACC,IAAA,CAAI,aAAA,CAAc,QAAA,CAAS,KAAA,CAAON,CAAAA,CAAO,QAAA,CAAU,CAAA,CAClD,QAAA,CAAA,CAAAK,IAAAA,CAACT,CAAAA,CAAA,CAAM,KAAA,CAAOI,CAAAA,CACZ,QAAA,CAAA,CAAAK,IAAAA,CAACG,IAAAA,CAAA,CAAK,QAAA,CAAA,CAAA,aAAA,CACQ,GAAA,CACZC,GAAAA,CAACD,IAAAA,CAAA,CAAK,IAAA,CAAI,IAAA,CAAC,KAAA,CAAM,MAAA,CACd,QAAA,CAAAjD,CAAAA,CAAS,OAAA,CACZ,CAAA,CAAA,CACF,EACA8C,IAAAA,CAACG,IAAAA,CAAA,CAAK,QAAA,CAAA,CAAA,WAAA,CACM,GAAA,CACVC,GAAAA,CAACD,IAAAA,CAAA,CAAK,IAAA,CAAI,IAAA,CAAC,KAAA,CAAM,MAAA,CACd,QAAA,CAAA7D,EAAAA,CAASY,EAAS,EAAA,CAAIyC,CAAAA,CAAQ,EAAE,CAAA,CACnC,CAAA,CAAA,CACF,CAAA,CACAK,IAAAA,CAACG,IAAAA,CAAA,CAAK,QAAA,CAAA,CAAA,SAAA,CACI,GAAA,CACRC,GAAAA,CAACD,IAAAA,CAAA,CAAK,KAAI,IAAA,CAAC,KAAA,CAAOxD,EAAAA,CAAYO,CAAAA,CAAS,MAAM,CAAA,CAC1C,QAAA,CAAAA,CAAAA,CAAS,MAAA,CACZ,CAAA,CACCA,CAAAA,CAAS,UAAA,GAAe,IAAA,EACvB8C,IAAAA,CAACG,IAAAA,CAAA,CACE,QAAA,CAAA,CAAA,IAAA,CAAK,WAAA,CAAU,GAAA,CAChBC,GAAAA,CAACD,IAAAA,CAAA,CAAK,IAAA,CAAI,IAAA,CAAE,QAAA,CAAA1D,CAAAA,CAAeS,CAAAA,CAAS,UAAU,CAAA,CAAE,CAAA,CAAA,CAClD,GAEJ,CAAA,CAAA,CACF,CAAA,CAEA8C,IAAAA,CAACT,CAAAA,CAAA,CACC,KAAA,CAAM,mBAAA,CACN,QAAA,CACES,IAAAA,CAACG,IAAAA,CAAA,CAAK,QAAA,CAAQ,IAAA,CAAC,QAAA,CAAA,CAAA,GAAA,CACXzB,EAAe,CAAA,CAAE,GAAA,CAClB,IAAA,CAAK,GAAA,CAAIA,CAAAA,CAAeN,CAAAA,CAAauI,CAAAA,CAAU,MAAM,CAAA,CAAE,GAAA,CACvDA,CAAAA,CAAU,MAAA,CAAO,SAAA,CAAA,CACpB,CAAA,CAEF,MAAOhH,CAAAA,CACP,QAAA,CAAU,CAAA,CACV,KAAA,CAAOD,CAAAA,CAEN,QAAA,CAAA,CAAA+C,CAAAA,CAAQ,GAAA,CAAI,CAAC6B,CAAAA,CAAMrD,CAAAA,GACdqD,CAAAA,GAAS,SAAA,EAAaA,CAAAA,GAAS,MAAA,CAE/BlE,GAAAA,CAACD,IAAAA,CAAA,CAA4B,IAAA,CAAI,IAAA,CAAC,KAAA,CAAM,QAAA,CACrC,QAAA,CAAAmE,CAAAA,CAAAA,CADQ5F,CAAAA,CAAeuC,CAE1B,CAAA,CAGAqD,CAAAA,CAAK,UAAA,CAAW,GAAG,EAEnBlE,GAAAA,CAACD,IAAAA,CAAA,CAA4B,QAAA,CAAQ,IAAA,CAClC,QAAA,CAAAmE,CAAAA,CAAAA,CADQ5F,CAAAA,CAAeuC,CAE1B,CAAA,CAGGb,GAAAA,CAAC2E,EAAAA,CAAA,CAAuC,IAAA,CAAMT,GAAxB5F,CAAAA,CAAeuC,CAAe,CAC5D,CAAA,CACAwB,CAAAA,CAAQ,MAAA,CAASrE,CAAAA,EAChB,KAAA,CAAM,IAAA,CAAK,CAAE,MAAA,CAAQA,CAAAA,CAAcqE,CAAAA,CAAQ,MAAO,CAAC,CAAA,CAAE,GAAA,CAAI,CAACmE,CAAAA,CAAG3F,CAAAA,GAC3Db,GAAAA,CAACD,IAAAA,CAAA,CAAsB,QAAA,CAAA,GAAA,CAAA,CAAZ,CAAA,IAAA,EAAOc,CAAC,CAAA,CAAK,CACzB,CAAA,CAAA,CACL,CAAA,CAAA,CACF,CAEJ,CChIA,SAASgG,EAAAA,CAASvJ,EAA6B,CAC7C,OAAIA,CAAAA,CAAM,eAAA,CAAkB,CAAA,CAAU,KAAA,CAClCA,CAAAA,CAAM,cAAA,CAAiB,CAAA,CAAU,OAAA,CAC9B,QACT,CAEO,SAASwJ,EAAAA,CAAe,CAC7B,MAAA,CAAAC,CAAAA,CACA,aAAA,CAAA5I,CAAAA,CACA,UAAA,CAAA6I,CAAAA,CACA,WAAA,CAAAhJ,CAAAA,CACA,KAAA,CAAAuB,CACF,CAAA,CAMG,CACD,IAAM0H,CAAAA,CAASD,CAAAA,CAEf,OACEpH,IAAAA,CAAAE,QAAAA,CAAA,CACE,QAAA,CAAA,CAAAE,GAAAA,CAACD,IAAAA,CAAA,CAAK,QAAA,CAAA,GAAA,CAAC,CAAA,CACPC,GAAAA,CAACD,IAAAA,CAAA,CAAK,IAAA,CAAI,IAAA,CAAC,QAAA,CAAQ,IAAA,CAChB,QAAA,CAAA,QAAA,CAAS,MAAA,CAAOR,CAAAA,CAAQ,CAAC,CAAA,CAC5B,CAAA,CACCwH,CAAAA,CAAO,MAAA,GAAW,CAAA,CACjB/G,GAAAA,CAACD,IAAAA,CAAA,CAAK,QAAA,CAAQ,IAAA,CAAC,2BAAe,CAAA,CAE9BgH,CAAAA,CAAO,KAAA,CAAME,CAAAA,CAAQA,CAAAA,CAASjJ,CAAW,CAAA,CAAE,GAAA,CAAI,CAACV,CAAAA,CAAOkF,CAAAA,GAAO,CAC5D,IAAM3B,CAAAA,CAAIoG,EAASzE,CAAAA,CACnB,OACE5C,IAAAA,CAACG,IAAAA,CAAA,CAAoB,IAAA,CAAK,UAAA,CACxB,QAAA,CAAA,CAAAC,GAAAA,CAACD,IAAAA,CAAA,CACE,GAAIc,CAAAA,GAAM1C,CAAAA,CAAgB,CAAE,KAAA,CAAO,MAAgB,CAAA,CAAI,EAAC,CACzD,IAAA,CAAM0C,CAAAA,GAAM1C,CAAAA,CAEX,QAAA,CAAA0C,CAAAA,GAAM1C,CAAAA,CAAgB,IAAA,CAAO,IAAA,CAChC,CAAA,CACA6B,GAAAA,CAACD,IAAAA,CAAA,CAAK,KAAA,CAAO8G,EAAAA,CAASvJ,CAAK,CAAA,CAAI,QAAA,CAAA,SAAA,CAAU,CAAA,CACzC0C,GAAAA,CAACD,IAAAA,CAAA,CACE,GAAIc,CAAAA,GAAM1C,CAAAA,CAAgB,CAAE,MAAO,MAAgB,CAAA,CAAI,EAAC,CACzD,IAAA,CAAM0C,CAAAA,GAAM1C,CAAAA,CAEX,QAAA,CAAAjC,EAAAA,CAASoB,CAAAA,CAAM,EAAA,CAAIiC,CAAAA,CAAQ,CAAC,CAAA,CAC/B,IAbSjC,CAAAA,CAAM,EAcjB,CAEJ,CAAC,CAAA,CAEFyJ,CAAAA,CAAO,MAAA,CAAS/I,CAAAA,EACf4B,IAAAA,CAACG,IAAAA,CAAA,CAAK,QAAA,CAAQ,IAAA,CACX,QAAA,CAAA,CAAA5B,EAAgB,CAAA,CAAE,GAAA,CAAE4I,CAAAA,CAAO,MAAA,CAAA,CAC9B,CAAA,CAAA,CAEJ,CAEJ,CC9BA,SAASG,EAAAA,CAAI,CAAE,EAAA,CAAAC,CAAG,CAAA,CAAwB,CACxC,GAAM,CAAE,IAAA,CAAAC,CAAK,CAAA,CAAIC,MAAAA,EAAO,CAClB,CAAE,MAAA,CAAAC,CAAO,EAAIC,SAAAA,EAAU,CACvBhI,CAAAA,CAAQ+H,CAAAA,EAAQ,OAAA,EAAW,EAAA,CAC3B3D,CAAAA,CAAS2D,CAAAA,EAAQ,IAAA,EAAQ,EAAA,CAEzB,CAACE,CAAAA,CAAWC,CAAY,CAAA,CAAIpJ,SAAkB,cAAc,CAAA,CAC5D,CAACqJ,CAAAA,CAAOC,CAAQ,CAAA,CAAItJ,QAAAA,CAAgB,KAAK,CAAA,CACzC,CAACuJ,CAAAA,CAAYC,CAAa,CAAA,CAAIxJ,QAAAA,CAAS,KAAK,CAAA,CAE5C,CAAC0I,CAAAA,CAAQe,CAAS,CAAA,CAAIzJ,QAAAA,CAAyB,EAAE,CAAA,CACjD,CAAC0J,CAAAA,CAASC,CAAU,CAAA,CAAI3J,QAAAA,CAAkB,CAC9C,WAAA,CAAa,CAAA,CACb,cAAA,CAAgB,CAAA,CAChB,kBAAA,CAAoB,CAAA,CACpB,eAAA,CAAiB,CAAA,CACjB,gBAAA,CAAkB,CAAA,CAClB,SAAA,CAAW,CAAA,CACX,aAAA,CAAe,IAAA,CACf,aAAA,CAAe,KACf,aAAA,CAAe,IAAA,CACf,aAAA,CAAe,IACjB,CAAC,CAAA,CACK,CAAC4J,CAAAA,CAAaC,CAAc,CAAA,CAAI7J,QAAAA,CAAmB,EAAE,CAAA,CACrD,CAAC8J,CAAAA,CAAuBC,CAAwB,CAAA,CAAI/J,QAAAA,CAExD,MAAS,CAAA,CACLgK,CAAAA,CAAcpK,EAAAA,EAAc,CAC5B,CAACyF,CAAAA,CAAW4E,CAAY,CAAA,CAAIjK,QAAAA,CAA2B,EAAE,CAAA,CACzDkK,CAAAA,CAAiBtK,EAAAA,EAAc,CAC/B,CAACuK,CAAAA,CAAkBC,EAAmB,CAAA,CAAIpK,QAAAA,CAE9C,MAAS,CAAA,CACL,CAACqK,EAAAA,CAAgBC,EAAiB,CAAA,CAAItK,QAAAA,CAAwB,EAAE,CAAA,CAChE,CAAC0G,EAAAA,CAAQ6D,EAAS,CAAA,CAAIvK,QAAAA,CAAwB,EAAE,CAAA,CAChDwK,EAAAA,CAAc5K,EAAAA,EAAc,CAC5B6K,EAAe7K,EAAAA,EAAc,CAC7B,CAAC8K,EAAAA,CAAeC,EAAgB,CAAA,CAAI3K,QAAAA,CACxC,MACF,CAAA,CACM,CAAC4K,CAAAA,CAAiBC,EAAkB,CAAA,CAAI7K,QAAAA,CAAS,KAAK,CAAA,CACtD,CAAC8K,EAAAA,CAAmBC,EAAoB,CAAA,CAAI/K,QAAAA,CAAS,CAAC,CAAA,CACtD,CAACgL,CAAAA,CAAcC,EAAe,CAAA,CAAIjL,QAAAA,CAAS,KAAK,EAChD,CAACkL,EAAAA,CAAgBC,EAAiB,CAAA,CAAInL,QAAAA,CAAS,CAAC,CAAA,CAChD,CAACoL,EAAAA,CAAkBC,EAAmB,CAAA,CAC1CrL,QAAAA,CAAkC,IAAI,CAAA,CAClCsL,EAAAA,CAAY,EAAA,CACZC,EAAAA,CAAO,EAAA,CAGPC,EAAAA,CAAY,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,KAAA,CAAMtK,CAAAA,CAAQ,GAAI,CAAA,CAAG,EAAE,CAAA,CAAG,EAAE,CAAA,CAC/DuK,EAAAA,CAAa,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,KAAA,CAAMvK,CAAAA,CAAQ,GAAI,CAAA,CAAG,EAAE,CAAA,CAAG,EAAE,CAAA,CAChEwK,CAAAA,CAAc,IAAA,CAAK,GAAA,CAAIxK,CAAAA,CAAQsK,EAAAA,CAAYC,EAAAA,CAAY,EAAE,CAAA,CACzDE,CAAAA,CAAa,IAAA,CAAK,GAAA,CAAIrG,CAAAA,CAAS,CAAA,CAAG,EAAE,CAAA,CAEpCsG,GAAgB,IAAA,CAAK,GAAA,CAAID,CAAAA,CADT,EAAA,CACqC,CAAC,CAAA,CAEtDE,EAAAA,CAAUzL,WAAAA,CAAY,IAAM,CAChC,GAAI,CAEF,IAAM0L,CAAAA,CAAehD,CAAAA,CAAG,eAAA,EAAgB,CACxCW,CAAAA,CAAUqC,CAAY,CAAA,CACtBnC,CAAAA,CAAWb,CAAAA,CAAG,UAAA,EAAY,CAAA,CAC1B,IAAMiD,CAAAA,CAAWN,EAAAA,CAAa,CAAA,CAC9B5B,CAAAA,CAAef,EAAG,qBAAA,CAAsBiD,CAAAA,CAAU,CAAC,CAAC,CAAA,CAGpD,IAAMC,CAAAA,CAAYN,CAAAA,CAAc,CAAA,CAC1BO,CAAAA,CAAWH,CAAAA,CAAa9B,CAAAA,CAAY,aAAa,CAAA,CAQvD,GAPIiC,CAAAA,EACFlC,CAAAA,CACEjB,CAAAA,CAAG,sBAAA,CAAuBmD,CAAAA,CAAS,EAAA,CAAID,CAAAA,CAAW,CAAC,CACrD,CAAA,CAIE3C,CAAAA,GAAU,QAAA,CAAU,OAExB,GAAIF,IAAc,cAAA,CAAgB,CAChC,IAAMlK,CAAAA,CAAQ6M,CAAAA,CAAa9B,CAAAA,CAAY,aAAa,CAAA,CAChD/K,CAAAA,EACFgL,CAAAA,CAAanB,CAAAA,CAAG,mBAAA,CAAoB7J,CAAAA,CAAM,EAAA,CAAIqM,EAAS,CAAC,EAE5D,CAAA,KAAWnC,CAAAA,GAAc,WAAA,CACvBc,CAAAA,CAAanB,CAAAA,CAAG,eAAA,CAAgBwC,EAAS,CAAC,CAAA,CACjCnC,CAAAA,GAAc,QAAA,CACvBc,CAAAA,CAAanB,CAAAA,CAAG,mBAAmBwC,EAAS,CAAC,CAAA,CACpCnC,CAAAA,GAAc,QAAA,EACvBoB,EAAAA,CAAUzB,CAAAA,CAAG,eAAA,CAAgB,CAAE,KAAA,CAAO,GAAI,CAAC,CAAC,EAEhD,CAAA,KAAQ,CAER,CACF,CAAA,CAAG,CACDA,CAAAA,CACAK,CAAAA,CACAa,CAAAA,CAAY,aAAA,CACZyB,EAAAA,CACAC,CAAAA,CACArC,CACF,CAAC,CAAA,CAED6C,SAAAA,CAAU,IAAM,CACdL,EAAAA,EAAQ,CACR,IAAMM,CAAAA,CAAQ,WAAA,CAAYN,EAAAA,CAAS,GAAI,CAAA,CACvC,OAAO,IAAM,CACX,aAAA,CAAcM,CAAK,EACrB,CACF,CAAA,CAAG,CAACN,EAAO,CAAC,CAAA,CAEZ,IAAMO,EAAAA,CAAchM,WAAAA,CACjBC,CAAAA,EAAkB,CACjB2J,CAAAA,CAAY,MAAA,CAAO3J,CAAAA,CAAOqI,CAAAA,CAAO,MAAA,CAAQkD,EAAa,CAAA,CACtD1B,CAAAA,CAAe,KAAA,EAAM,CACrB,IAAMjL,CAAAA,CAAQyJ,CAAAA,CAAOrI,CAAK,CAAA,CACtBpB,CAAAA,EACFgL,CAAAA,CAAanB,CAAAA,CAAG,mBAAA,CAAoB7J,CAAAA,CAAM,GAAIqM,EAAS,CAAC,EAE5D,CAAA,CACA,CAACxC,CAAAA,CAAIJ,CAAAA,CAAQsB,CAAAA,CAAaE,CAAAA,CAAgB0B,EAAa,CACzD,CAAA,CAEMS,EAAAA,CAAYjM,WAAAA,CACfkM,GAAiB,CAChBlD,CAAAA,CAAakD,CAAG,CAAA,CAChB9C,CAAAA,CAAc,KAAK,CAAA,CACnBqB,EAAAA,CAAmB,KAAK,CAAA,CACxBI,EAAAA,CAAgB,KAAK,CAAA,CACrB3B,CAAAA,CAAS,KAAK,CAAA,CACdY,CAAAA,CAAe,KAAA,EAAM,CACjBoC,CAAAA,GAAQ,WAAA,CACVrC,CAAAA,CAAanB,CAAAA,CAAG,eAAA,CAAgBwC,EAAS,CAAC,CAAA,CACjCgB,CAAAA,GAAQ,QAAA,CACjBrC,CAAAA,CAAanB,EAAG,kBAAA,CAAmBwC,EAAS,CAAC,CAAA,CACpCgB,CAAAA,GAAQ,QAAA,GACjB9B,EAAAA,CAAY,KAAA,EAAM,CAClBD,EAAAA,CAAUzB,CAAAA,CAAG,eAAA,CAAgB,CAAE,KAAA,CAAO,GAAI,CAAC,CAAC,CAAA,EAEhD,CAAA,CACA,CAACA,CAAAA,CAAIoB,CAAAA,CAAgBM,EAAW,CAClC,CAAA,CAEM+B,EAAAA,CAAgB7D,CAAAA,CAAOsB,CAAAA,CAAY,aAAa,EAIhDxE,EAAAA,CAAgB,IAAA,CAAK,IAAA,CAAA,CAAM1D,EAAAA,CAAc,MAAA,CAAS,CAAA,EAAK,CAAC,CAAA,CACxD0K,EAAAA,CAAqBD,EAAAA,CAAgB,CAAA,CAAI/G,EAAAA,CAAgB,CAAA,CAAI,CAAA,CAC7DiH,EAAAA,CAAoB,IAAA,CAAK,GAAA,CAC7Bd,CAAAA,CAAa,CAAA,CAAqBa,EAAAA,CAClC,CACF,CAAA,CACME,EAAAA,CAAkB,IAAA,CAAK,GAAA,CAAIf,CAAAA,CAAa,CAAA,CAAoB,CAAC,CAAA,CAEnEgB,QAAAA,CAAS,CAACC,CAAAA,CAAO7F,CAAAA,GAAQ,CACvB,GAAI6F,CAAAA,GAAU,GAAA,CAAK,CACjB9D,CAAAA,CAAG,KAAA,EAAM,CACTC,CAAAA,EAAK,CACL,MACF,CAGA,IAAM8D,CAAAA,CAAgBlP,EAAAA,CAAc,IAAA,CAAM4B,CAAAA,EAAMA,CAAAA,CAAE,QAAA,GAAaqN,CAAK,CAAA,CACpE,GAAIC,CAAAA,CAAe,CACjBR,EAAAA,CAAUQ,CAAAA,CAAc,GAAG,EAC3B,MACF,CAGA,GAAI1D,CAAAA,GAAc,QAAA,CAAU,CAC1B,GAAIyB,CAAAA,CAAiB,CAEnB,IAAMkC,CAAAA,CAAO/F,CAAAA,CAAI,IAAA,CAAOwE,EAAAA,CAAO,CAAA,CAC3BqB,CAAAA,GAAU,GAAA,EAAO7F,CAAAA,CAAI,SAAA,CACvBgE,EAAAA,CAAsBvI,CAAAA,EAAMA,CAAAA,CAAIsK,CAAI,CAAA,CAC3BF,CAAAA,GAAU,GAAA,EAAO7F,CAAAA,CAAI,OAAA,CAC9BgE,EAAAA,CAAsBvI,CAAAA,EAAM,KAAK,GAAA,CAAIA,CAAAA,CAAIsK,CAAAA,CAAM,CAAC,CAAC,CAAA,CAAA,CACxC/F,CAAAA,CAAI,MAAA,EAAUA,CAAAA,CAAI,SAAA,EAAaA,CAAAA,CAAI,MAAA,IAC5C8D,EAAAA,CAAmB,KAAK,CAAA,CACxBE,EAAAA,CAAqB,CAAC,CAAA,CAAA,CAExB,MACF,CACA,GAAI1B,CAAAA,GAAU,KAAA,CACRtC,CAAAA,CAAI,MAAA,EACNuC,CAAAA,CAAS,QAAQ,CAAA,CAAA,KAEd,CACL,IAAMwD,EAAO/F,CAAAA,CAAI,IAAA,CAAOwE,EAAAA,CAAO,CAAA,CAC/B,GAAIqB,CAAAA,GAAU,GAAA,EAAO7F,CAAAA,CAAI,SAAA,CACvByD,EAAAA,CAAY,MAAA,CAAOsC,CAAAA,CAAMpG,EAAAA,CAAO,MAAA,CAAQgG,EAAe,CAAA,CAAA,KAAA,GAC9CE,CAAAA,GAAU,GAAA,EAAO7F,CAAAA,CAAI,OAAA,CAC9ByD,EAAAA,CAAY,MAAA,CAAO,CAACsC,CAAAA,CAAMpG,EAAAA,CAAO,MAAA,CAAQgG,EAAe,CAAA,CAAA,KAAA,GAC/C3F,CAAAA,CAAI,MAAA,CAAQ,CACrB,IAAMnC,CAAAA,CAAK8B,EAAAA,CAAO8D,EAAAA,CAAY,aAAa,CAAA,CACvC5F,CAAAA,GACF+F,EAAAA,CAAiB/F,CAAE,CAAA,CACnBmG,EAAAA,CAAqB,CAAC,CAAA,CACtBF,EAAAA,CAAmB,IAAI,CAAA,EAE3B,CAAA,KAAA,CAAW9D,CAAAA,CAAI,MAAA,EAAUA,CAAAA,CAAI,SAAA,EAAaA,CAAAA,CAAI,MAAA,IAC5CuC,CAAAA,CAAS,KAAK,CAAA,CACdkB,EAAAA,CAAY,KAAA,EAAM,EAEtB,CACA,MACF,CAGA,GAAIQ,CAAAA,CAAc,CAChB,IAAM8B,CAAAA,CAAO/F,CAAAA,CAAI,IAAA,CAAOwE,EAAAA,CAAO,CAAA,CAC3BqB,CAAAA,GAAU,GAAA,EAAO7F,CAAAA,CAAI,SAAA,CACvBoE,EAAAA,CAAmB3I,CAAAA,EAAMA,CAAAA,CAAIsK,CAAI,CAAA,CACxBF,CAAAA,GAAU,GAAA,EAAO7F,CAAAA,CAAI,OAAA,CAC9BoE,EAAAA,CAAmB3I,CAAAA,EAAM,IAAA,CAAK,GAAA,CAAIA,CAAAA,CAAIsK,CAAAA,CAAM,CAAC,CAAC,CAAA,CAAA,CACrC/F,CAAAA,CAAI,MAAA,EAAUA,CAAAA,CAAI,SAAA,EAAaA,CAAAA,CAAI,MAAA,IAC5CkE,EAAAA,CAAgB,KAAK,CAAA,CACrBE,EAAAA,CAAkB,CAAC,CAAA,CAAA,CAErB,MACF,CAGA,GAAI5B,CAAAA,EAAc,CAACqB,CAAAA,CAAiB,CAClC,IAAMzD,CAAAA,CAAWgD,CAAAA,EAAkB,KAAA,CAAQ,CAAA,CAAI,CAAA,CACzC4C,CAAAA,CAAkB,IAAA,CAAK,IAC3BpB,CAAAA,CAAa,CAAA,CAAqBxE,CAAAA,CAClC,CACF,CAAA,CAEM6F,EAAAA,CAAoB,IAAI,GAAA,CAC5B3C,EAAAA,CAAe,GAAA,CAAKzF,EAAAA,EAAO,CACzB,GAAI,CACF,IAAMpG,EAAAA,CAAI,IAAA,CAAK,KAAA,CAAMoG,EAAAA,CAAG,OAAO,CAAA,CAC/B,OAAO,MAAA,CAAOpG,EAAAA,CAAE,UAAA,EAAiB,EAAE,CACrC,CAAA,KAAQ,CACN,OAAO,EACT,CACF,CAAC,CACH,CAAA,CACMyO,EAAAA,CAAa,IAAA,CAAK,GAAA,CAAID,EAAAA,CAAkB,IAAA,CAAM,CAAC,CAAA,CAC/CvH,EAAAA,CAAawH,EAAAA,CAAa,CAAA,CAAIA,GAAa,CAAA,CAC3CC,EAAAA,CAAmB7C,EAAAA,CAAe,MAAA,CAAS5E,EAAAA,CAC3CqH,EAAAA,CAAO/F,CAAAA,CAAI,IAAA,CAAOwE,EAAAA,CAAO,CAAA,CAC/B,GAAIqB,CAAAA,GAAU,GAAA,EAAO7F,CAAAA,CAAI,UACvB0D,CAAAA,CAAa,MAAA,CAAOqC,EAAAA,CAAMI,EAAAA,CAAkBH,CAAe,CAAA,CAAA,KAAA,GAClDH,CAAAA,GAAU,GAAA,EAAO7F,CAAAA,CAAI,OAAA,CAC9B0D,CAAAA,CAAa,MAAA,CAAO,CAACqC,EAAAA,CAAMI,EAAAA,CAAkBH,CAAe,CAAA,CAAA,KAAA,GACnDhG,CAAAA,CAAI,MAAA,CAAQ,CAGrB,IAAIoG,EAAAA,CAAW,CAAA,CACXC,EAAAA,CACEC,EAAAA,CAAWlD,CAAAA,EAAkB,EAAA,EAAM,EAAA,CACnCvD,EAAAA,CAAS,IAAI,IACnBA,EAAAA,CAAO,GAAA,CAAIyG,EAAAA,CAAU,EAAE,CAAA,CACvB,IAAA,IAAWzI,EAAAA,IAAMyF,EAAAA,CACf,GAAI,CACF,IAAM7L,EAAAA,CAAI,IAAA,CAAK,KAAA,CAAMoG,EAAAA,CAAG,OAAO,CAAA,CACzBkC,EAAAA,CAAO,MAAA,CAAOtI,EAAAA,CAAE,UAAA,EAAiB,EAAE,CAAA,CACnC8O,EAAAA,CAAO,CAACxG,EAAAA,EAAQA,EAAAA,GAASuG,EAAAA,CAAWA,EAAAA,CAAWvG,GAChDF,EAAAA,CAAO,GAAA,CAAI0G,EAAI,CAAA,EAAG1G,EAAAA,CAAO,GAAA,CAAI0G,EAAAA,CAAM,EAAE,CAAA,CAC1C1G,EAAAA,CAAO,GAAA,CAAI0G,EAAI,CAAA,CAAG,IAAA,CAAK1I,EAAE,EAC3B,CAAA,KAAQ,CACNgC,EAAAA,CAAO,GAAA,CAAIyG,EAAQ,CAAA,CAAG,IAAA,CAAKzI,EAAE,EAC/B,CAEF,IAAMyC,EAAAA,CAAcT,EAAAA,CAAO,KAAO,CAAA,CAClC,IAAA,GAAW,EAAG2G,EAAW,CAAA,GAAK3G,EAAAA,CAAQ,CAChCS,EAAAA,EAAa8F,EAAAA,EAAAA,CACjB,IAAA,IAAWvI,EAAAA,IAAM2I,EAAAA,CACXJ,EAAAA,GAAa1C,EAAa,aAAA,GAC5B2C,EAAAA,CAAcxI,EAAAA,CAAAA,CAEhBuI,EAAAA,GAEJ,CACIC,EAAAA,GACFzC,EAAAA,CAAiByC,EAAW,CAAA,CAC5BrC,EAAAA,CAAqB,CAAC,CAAA,CACtBF,EAAAA,CAAmB,IAAI,GAE3B,CAAA,KAAA,GAAW+B,CAAAA,GAAU,GAAA,EAAOzC,CAAAA,CAAkB,CAC5C,IAAM9B,EAAAA,CAAWS,CAAAA,CAAG,mBAAA,CAAoBqB,CAAAA,CAAiB,EAAE,CAAA,CAC3DkB,EAAAA,CAAoBhD,EAAQ,CAAA,CAC5B8C,EAAAA,CAAkB,CAAC,CAAA,CACnBF,EAAAA,CAAgB,IAAI,EACtB,CAAA,KAAA,CAAWlE,CAAAA,CAAI,MAAA,EAAUA,CAAAA,CAAI,SAAA,EAAaA,CAAAA,CAAI,MAAA,IAC5C0D,CAAAA,CAAa,KAAA,GACbjB,CAAAA,CAAc,KAAK,CAAA,CAAA,CAErB,MACF,CAGA,GAAID,CAAAA,EAAcqB,CAAAA,CAAiB,CACjC,IAAMkC,CAAAA,CAAO/F,CAAAA,CAAI,IAAA,CAAOwE,EAAAA,CAAO,EAC3BqB,CAAAA,GAAU,GAAA,EAAO7F,CAAAA,CAAI,SAAA,CACvBgE,EAAAA,CAAsBvI,CAAAA,EAAMA,CAAAA,CAAIsK,CAAI,CAAA,CAC3BF,CAAAA,GAAU,GAAA,EAAO7F,CAAAA,CAAI,OAAA,CAC9BgE,EAAAA,CAAsBvI,GAAM,IAAA,CAAK,GAAA,CAAIA,CAAAA,CAAIsK,CAAAA,CAAM,CAAC,CAAC,CAAA,CAAA,CACxC/F,CAAAA,CAAI,MAAA,EAAUA,CAAAA,CAAI,SAAA,EAAaA,CAAAA,CAAI,MAAA,IAC5C8D,EAAAA,CAAmB,KAAK,CAAA,CACxBE,EAAAA,CAAqB,CAAC,CAAA,CAAA,CAExB,MACF,CAGA,GAAI5B,CAAAA,GAAc,cAAA,EAAkBE,CAAAA,GAAU,KAAA,CAAO,CACnD,GAAIuD,CAAAA,GAAU,GAAA,EAAO7F,EAAI,SAAA,CACvBqF,EAAAA,CAAY,IAAA,CAAK,GAAA,CAAIpC,CAAAA,CAAY,aAAA,CAAgB,CAAA,CAAGtB,CAAAA,CAAO,MAAA,CAAS,CAAC,CAAC,CAAA,CAAA,KAAA,GAC7DkE,CAAAA,GAAU,GAAA,EAAO7F,EAAI,OAAA,CAC9BqF,EAAAA,CAAY,IAAA,CAAK,GAAA,CAAIpC,CAAAA,CAAY,aAAA,CAAgB,CAAA,CAAG,CAAC,CAAC,CAAA,CAAA,KAAA,GAC7CjD,CAAAA,CAAI,MAAA,CAAQ,CACrBuC,CAAAA,CAAS,QAAQ,CAAA,CAEjB,IAAMrK,CAAAA,CAAQyJ,CAAAA,CAAOsB,CAAAA,CAAY,aAAa,CAAA,CAC1C/K,CAAAA,EACFgL,CAAAA,CAAanB,CAAAA,CAAG,mBAAA,CAAoB7J,CAAAA,CAAM,EAAE,CAAC,EAEjD,CACA,MACF,CAGA,GAAIkK,CAAAA,GAAc,cAAA,EAAkBE,CAAAA,GAAU,QAAA,CAAU,CACtD,IAAMyD,CAAAA,CAAO/F,CAAAA,CAAI,IAAA,CAAOwE,EAAAA,CAAO,CAAA,CAC/B,GAAIqB,CAAAA,GAAU,GAAA,EAAO7F,CAAAA,CAAI,SAAA,CACvBmD,CAAAA,CAAe,MAAA,CAAO4C,CAAAA,CAAMzH,CAAAA,CAAU,MAAA,CAAQoH,EAAiB,CAAA,CAAA,KAAA,GACtDG,CAAAA,GAAU,GAAA,EAAO7F,CAAAA,CAAI,OAAA,CAC9BmD,CAAAA,CAAe,MAAA,CAAO,CAAC4C,CAAAA,CAAMzH,CAAAA,CAAU,MAAA,CAAQoH,EAAiB,CAAA,CAAA,KAAA,GACvD1F,CAAAA,CAAI,MAAA,CAAQ,CACrB,IAAMpB,CAAAA,CAAKN,CAAAA,CAAU6E,CAAAA,CAAe,aAAa,CAAA,CAC7CvE,CAAAA,GACFyE,EAAAA,CAAoBzE,CAAE,CAAA,CACtB2E,EAAAA,CAAkBxB,CAAAA,CAAG,mBAAA,CAAoBnD,CAAAA,CAAG,EAAA,CAAIA,CAAAA,CAAG,aAAa,CAAC,CAAA,CACjE8E,CAAAA,CAAa,KAAA,EAAM,CACnBI,EAAAA,CAAmB,KAAK,CAAA,CACxBrB,CAAAA,CAAc,IAAI,CAAA,EAEtB,CAAA,KAAA,CAAWzC,CAAAA,CAAI,MAAA,EAAUA,CAAAA,CAAI,SAAA,EAAaA,CAAAA,CAAI,MAAA,IAC5CuC,EAAS,KAAK,CAAA,CACdY,CAAAA,CAAe,KAAA,EAAM,CAAA,CAEvB,MACF,CAGA,GAAIf,CAAAA,GAAc,WAAA,EAAeA,CAAAA,GAAc,QAAA,CAAU,CACvD,GAAIE,IAAU,KAAA,CAERtC,CAAAA,CAAI,MAAA,GACNuC,CAAAA,CAAS,QAAQ,CAAA,CAGfW,CAAAA,CADEd,CAAAA,GAAc,WAAA,CACHL,CAAAA,CAAG,eAAA,EAAgB,CAEnBA,CAAAA,CAAG,kBAAA,EAFiB,CAAA,CAAA,CAAA,KAKhC,CAEL,IAAMgE,CAAAA,CAAO/F,CAAAA,CAAI,IAAA,CAAOwE,EAAAA,CAAO,CAAA,CAC/B,GAAIqB,CAAAA,GAAU,GAAA,EAAO7F,CAAAA,CAAI,SAAA,CACvBmD,CAAAA,CAAe,MAAA,CAAO4C,CAAAA,CAAMzH,CAAAA,CAAU,MAAA,CAAQoH,EAAiB,CAAA,CAAA,KAAA,GACtDG,CAAAA,GAAU,GAAA,EAAO7F,CAAAA,CAAI,OAAA,CAC9BmD,CAAAA,CAAe,MAAA,CAAO,CAAC4C,CAAAA,CAAMzH,CAAAA,CAAU,MAAA,CAAQoH,EAAiB,CAAA,CAAA,KAAA,GACvD1F,CAAAA,CAAI,MAAA,CAAQ,CACrB,IAAMpB,CAAAA,CAAKN,CAAAA,CAAU6E,CAAAA,CAAe,aAAa,CAAA,CAC7CvE,CAAAA,GACFyE,EAAAA,CAAoBzE,CAAE,CAAA,CACtB2E,EAAAA,CAAkBxB,CAAAA,CAAG,mBAAA,CAAoBnD,CAAAA,CAAG,EAAA,CAAIA,CAAAA,CAAG,aAAa,CAAC,CAAA,CACjE8E,CAAAA,CAAa,KAAA,EAAM,CACnBI,EAAAA,CAAmB,KAAK,CAAA,CACxBrB,CAAAA,CAAc,IAAI,CAAA,EAEtB,CAAA,KAAA,CAAWzC,CAAAA,CAAI,MAAA,EAAUA,CAAAA,CAAI,SAAA,EAAaA,CAAAA,CAAI,MAAA,IAC5CuC,CAAAA,CAAS,KAAK,CAAA,CACdY,CAAAA,CAAe,KAAA,EAAM,EAEzB,CACA,MACF,CACF,CAAC,CAAA,CAGD,IAAMsD,EAAAA,CACJrE,CAAAA,GAAc,cAAA,EAAkBE,CAAAA,GAAU,KAAA,EAAS,CAACE,CAAAA,CAChDkE,EAAAA,CAAe,CAACD,EAAAA,CAGhBE,EAAiD,EAAC,CACxD,OAAI1C,CAAAA,EACF0C,CAAAA,CAAY,IAAA,CAAK,CAAE,GAAA,CAAK,KAAA,CAAO,MAAA,CAAQ,QAAS,CAAC,CAAA,CACjDA,CAAAA,CAAY,KAAK,CAAE,GAAA,CAAK,UAAA,CAAY,MAAA,CAAQ,SAAU,CAAC,CAAA,CACvDA,CAAAA,CAAY,IAAA,CAAK,CAAE,GAAA,CAAK,KAAA,CAAO,MAAA,CAAQ,MAAO,CAAC,CAAA,EACtCrE,CAAAA,GAAU,QAAA,GACnBqE,CAAAA,CAAY,IAAA,CAAK,CAAE,GAAA,CAAK,KAAA,CAAO,MAAA,CAAQ,UAAW,CAAC,CAAA,CACnDA,CAAAA,CAAY,IAAA,CAAK,CAAE,GAAA,CAAK,UAAA,CAAY,MAAA,CAAQ,SAAU,CAAC,CAAA,CAAA,CAEpD1C,CAAAA,GACC3B,CAAAA,GAAU,KAAA,CACRF,CAAAA,GAAc,cAAA,EAChBuE,CAAAA,CAAY,IAAA,CAAK,CAAE,GAAA,CAAK,MAAO,MAAA,CAAQ,UAAW,CAAC,CAAA,CACnDA,CAAAA,CAAY,IAAA,CAAK,CAAE,GAAA,CAAK,OAAA,CAAS,MAAA,CAAQ,WAAY,CAAC,CAAA,EAEtDA,CAAAA,CAAY,IAAA,CAAK,CAAE,GAAA,CAAK,OAAA,CAAS,MAAA,CAAQ,QAAS,CAAC,CAAA,CAE5C,CAACnE,CAAAA,EAAc,CAACqB,CAAAA,EACzB8C,CAAAA,CAAY,IAAA,CAAK,CAAE,GAAA,CAAK,QAAS,MAAA,CAAQ,QAAS,CAAC,CAAA,CACnDA,CAAAA,CAAY,IAAA,CAAK,CAAE,GAAA,CAAK,KAAA,CAAO,MAAA,CAAQ,MAAO,CAAC,CAAA,EACtCnE,CAAAA,EAAc,CAACqB,CAAAA,EACxB8C,CAAAA,CAAY,IAAA,CAAK,CAAE,GAAA,CAAK,OAAA,CAAS,MAAA,CAAQ,cAAe,CAAC,CAAA,CACzDA,CAAAA,CAAY,IAAA,CAAK,CAAE,GAAA,CAAK,GAAA,CAAK,OAAQ,UAAW,CAAC,CAAA,CACjDA,CAAAA,CAAY,IAAA,CAAK,CAAE,GAAA,CAAK,KAAA,CAAO,MAAA,CAAQ,MAAO,CAAC,CAAA,EAE/CA,CAAAA,CAAY,IAAA,CAAK,CAAE,GAAA,CAAK,KAAA,CAAO,MAAA,CAAQ,MAAO,CAAC,CAAA,CAAA,CAGnDA,CAAAA,CAAY,IAAA,CAAK,CAAE,GAAA,CAAK,MAAA,CAAQ,MAAA,CAAQ,aAAc,CAAC,EACvDA,CAAAA,CAAY,IAAA,CAAK,CAAE,GAAA,CAAK,GAAA,CAAK,MAAA,CAAQ,MAAO,CAAC,CAAA,CAG3CnM,IAAAA,CAACC,GAAAA,CAAA,CAAI,aAAA,CAAc,QAAA,CAAS,KAAA,CAAON,CAAAA,CAAO,MAAA,CAAQoE,CAAAA,CAEhD,QAAA,CAAA,CAAA/D,IAAAA,CAACC,GAAAA,CAAA,CAAI,WAAA,CAAY,OAAA,CAAQ,WAAA,CAAY,MAAA,CAAO,QAAA,CAAU,CAAA,CAAG,KAAA,CAAON,CAAAA,CAC9D,UAAAS,GAAAA,CAACD,IAAAA,CAAA,CAAK,IAAA,CAAI,IAAA,CAAC,KAAA,CAAM,MAAA,CAAO,QAAA,CAAA,gBAAA,CAExB,CAAA,CACAC,GAAAA,CAACD,IAAAA,CAAA,CAAK,QAAA,CAAA,GAAA,CAAC,CAAA,CACPC,IAACD,IAAAA,CAAA,CAAK,QAAA,CAAQ,IAAA,CAAC,QAAA,CAAA,QAAA,CAAM,CAAA,CAAA,CACvB,CAAA,CAGAH,IAAAA,CAACC,GAAAA,CAAA,CAAI,aAAA,CAAc,KAAA,CAAM,KAAA,CAAON,CAAAA,CAAO,SAAU,CAAA,CAE/C,QAAA,CAAA,CAAAS,GAAAA,CAACH,GAAAA,CAAA,CAAI,aAAA,CAAc,QAAA,CAAS,KAAA,CAAOgK,EAAAA,CACjC,QAAA,CAAAjK,IAAAA,CAACT,CAAAA,CAAA,CACC,KAAA,CAAM,YAAA,CACN,KAAA,CAAO0M,EAAAA,CAAY,MAAA,CAAS,MAAA,CAC5B,KAAA,CAAOhC,EAAAA,CACP,QAAA,CAAU,CAAA,CAET,QAAA,CAAA,CAAA9N,EAAAA,CAAa,GAAA,CAAI,CAACiQ,CAAAA,CAASC,CAAAA,GAC1BrM,IAAAA,CAACC,IAAA,CAA8B,aAAA,CAAc,QAAA,CAC1C,QAAA,CAAA,CAAAoM,CAAAA,CAAK,CAAA,EAAKjM,GAAAA,CAACD,IAAAA,CAAA,CAAK,QAAA,CAAA,GAAA,CAAC,CAAA,CACjBiM,CAAAA,CAAQ,KAAA,EACPhM,GAAAA,CAACD,KAAA,CAAK,QAAA,CAAQ,IAAA,CAAC,IAAA,CAAI,IAAA,CAChB,QAAA,CAAAiM,CAAAA,CAAQ,KAAA,CACX,CAAA,CAEDA,CAAAA,CAAQ,KAAA,CAAM,GAAA,CAAKE,CAAAA,EAClBtM,IAAAA,CAACG,KAAA,CACC,QAAA,CAAA,CAAAH,IAAAA,CAACG,IAAAA,CAAA,CACC,IAAA,CAAMyH,CAAAA,GAAc0E,CAAAA,CAAK,GAAA,CACxB,GAAI1E,CAAAA,GAAc0E,CAAAA,CAAK,GAAA,CACpB,CAAE,KAAA,CAAO,MAAgB,CAAA,CACzB,EAAC,CAEJ,QAAA,CAAA,CAAA1E,CAAAA,GAAc0E,CAAAA,CAAK,GAAA,CAAM,IAAA,CAAO,IAAA,CAChCA,CAAAA,CAAK,KAAA,CAAA,CACR,CAAA,CACAtM,IAAAA,CAACG,IAAAA,CAAA,CAAK,QAAA,CAAQ,IAAA,CAAC,QAAA,CAAA,CAAA,IAAA,CAAGmM,CAAAA,CAAK,QAAA,CAAS,GAAA,CAAA,CAAC,CAAA,CAAA,CAAA,CAVxBA,CAAAA,CAAK,GAWhB,CACD,CAAA,CAAA,CAAA,CApBOF,CAAAA,CAAQ,KAAA,EAASC,CAqB3B,CACD,CAAA,CAEAzE,CAAAA,GAAc,cAAA,EACbxH,GAAAA,CAAC8G,EAAAA,CAAA,CACC,MAAA,CAAQC,CAAAA,CACR,aAAA,CAAesB,CAAAA,CAAY,aAAA,CAC3B,UAAA,CAAYA,CAAAA,CAAY,YAAA,CACxB,WAAA,CAAa4B,GACb,KAAA,CAAOJ,EAAAA,CAAY,CAAA,CACrB,CAAA,CAAA,CAEJ,CAAA,CACF,CAAA,CAGCrC,CAAAA,GAAc,cAAA,EAAkB,CAACI,CAAAA,EAChC5H,GAAAA,CAACwD,EAAAA,CAAA,CACC,YAAA,CAAcoH,EAAAA,EAAe,EAAA,EAAM,EAAA,CACnC,KAAA,CAAOA,EAAAA,CACP,SAAA,CAAWlH,CAAAA,CACX,aAAA,CACEgE,CAAAA,GAAU,QAAA,CAAWa,CAAAA,CAAe,aAAA,CAAgB,EAAA,CAEtD,YAAA,CAAcb,CAAAA,GAAU,QAAA,CAAWa,EAAe,YAAA,CAAe,CAAA,CACjE,KAAA,CAAOwB,CAAAA,CACP,MAAA,CAAQC,CAAAA,CACR,KAAA,CAAO8B,EAAAA,CAAe,MAAA,CAAS,MAAA,CAC/B,QAAA,CAAU3D,CAAAA,CACZ,CAAA,CAEDX,CAAAA,GAAc,gBAAkB6B,CAAAA,EAAgBb,CAAAA,EAC/CxI,GAAAA,CAAC4G,EAAAA,CAAA,CACC,QAAA,CAAU4B,CAAAA,CACV,QAAA,CAAUiB,EAAAA,CACV,KAAA,CAAOM,CAAAA,CACP,MAAA,CAAQC,CAAAA,CACR,YAAA,CAAcT,GACd,KAAA,CAAM,MAAA,CACR,CAAA,CAED/B,CAAAA,GAAc,cAAA,EACbI,CAAAA,EACAY,CAAAA,EACA,CAACS,CAAAA,EACD,CAACI,CAAAA,EACCrJ,GAAAA,CAACuF,EAAAA,CAAA,CACC,QAAA,CAAUiD,CAAAA,CACV,MAAA,CAAQE,EAAAA,CACR,KAAA,CAAOqB,CAAAA,CACP,MAAA,CAAQC,CAAAA,CACR,aAAA,CAAelB,CAAAA,CAAa,aAAA,CAC5B,YAAA,CAAcA,CAAAA,CAAa,YAAA,CAC3B,KAAA,CAAM,MAAA,CACR,EAEHtB,CAAAA,GAAc,cAAA,EACbI,CAAAA,EACAqB,CAAAA,EACA,CAACI,CAAAA,EACDN,EAAAA,EACE/I,GAAAA,CAACgG,EAAAA,CAAA,CACC,KAAA,CAAO+C,EAAAA,CACP,KAAA,CAAOgB,CAAAA,CACP,OAAQC,CAAAA,CACR,YAAA,CAAcb,EAAAA,CACd,KAAA,CAAM,MAAA,CACR,CAAA,CAEH3B,CAAAA,GAAc,WAAA,EAAe,CAACI,CAAAA,EAC7B5H,GAAAA,CAACwD,EAAAA,CAAA,CACC,YAAA,CAAa,mBACb,SAAA,CAAWE,CAAAA,CACX,aAAA,CACEgE,CAAAA,GAAU,QAAA,CAAWa,CAAAA,CAAe,aAAA,CAAgB,EAAA,CAEtD,YAAA,CAAcb,CAAAA,GAAU,QAAA,CAAWa,CAAAA,CAAe,YAAA,CAAe,CAAA,CACjE,KAAA,CAAOwB,CAAAA,CACP,MAAA,CAAQC,CAAAA,CACR,KAAA,CAAOtC,CAAAA,GAAU,QAAA,CAAW,MAAA,CAAS,MAAA,CACvC,CAAA,CAEDF,CAAAA,GAAc,WAAA,EAAe6B,CAAAA,EAAgBb,CAAAA,EAC5CxI,GAAAA,CAAC4G,EAAAA,CAAA,CACC,QAAA,CAAU4B,CAAAA,CACV,QAAA,CAAUiB,EAAAA,CACV,KAAA,CAAOM,CAAAA,CACP,MAAA,CAAQC,CAAAA,CACR,YAAA,CAAcT,EAAAA,CACd,KAAA,CAAM,MAAA,CACR,CAAA,CAED/B,CAAAA,GAAc,aACbI,CAAAA,EACAY,CAAAA,EACA,CAACS,CAAAA,EACD,CAACI,CAAAA,EACCrJ,GAAAA,CAACuF,EAAAA,CAAA,CACC,QAAA,CAAUiD,CAAAA,CACV,MAAA,CAAQE,EAAAA,CACR,KAAA,CAAOqB,EACP,MAAA,CAAQC,CAAAA,CACR,aAAA,CAAelB,CAAAA,CAAa,aAAA,CAC5B,YAAA,CAAcA,CAAAA,CAAa,YAAA,CAC3B,KAAA,CAAM,MAAA,CACR,CAAA,CAEHtB,CAAAA,GAAc,WAAA,EACbI,CAAAA,EACAqB,CAAAA,EACA,CAACI,CAAAA,EACDN,EAAAA,EACE/I,GAAAA,CAACgG,EAAAA,CAAA,CACC,KAAA,CAAO+C,EAAAA,CACP,KAAA,CAAOgB,CAAAA,CACP,MAAA,CAAQC,CAAAA,CACR,YAAA,CAAcb,EAAAA,CACd,KAAA,CAAM,OACR,CAAA,CAEH3B,CAAAA,GAAc,QAAA,EAAY,CAACI,CAAAA,EAC1B5H,GAAAA,CAACwD,EAAAA,CAAA,CACC,YAAA,CAAa,kBAAA,CACb,SAAA,CAAWE,CAAAA,CACX,aAAA,CACEgE,CAAAA,GAAU,QAAA,CAAWa,CAAAA,CAAe,aAAA,CAAgB,EAAA,CAEtD,YAAA,CAAcb,CAAAA,GAAU,QAAA,CAAWa,CAAAA,CAAe,YAAA,CAAe,CAAA,CACjE,KAAA,CAAOwB,CAAAA,CACP,MAAA,CAAQC,CAAAA,CACR,KAAA,CAAOtC,CAAAA,GAAU,SAAW,MAAA,CAAS,MAAA,CACvC,CAAA,CAEDF,CAAAA,GAAc,QAAA,EAAY6B,CAAAA,EAAgBb,CAAAA,EACzCxI,GAAAA,CAAC4G,EAAAA,CAAA,CACC,QAAA,CAAU4B,CAAAA,CACV,QAAA,CAAUiB,EAAAA,CACV,KAAA,CAAOM,CAAAA,CACP,MAAA,CAAQC,CAAAA,CACR,YAAA,CAAcT,EAAAA,CACd,KAAA,CAAM,MAAA,CACR,CAAA,CAED/B,CAAAA,GAAc,QAAA,EACbI,CAAAA,EACAY,CAAAA,EACA,CAACS,CAAAA,EACD,CAACI,GACCrJ,GAAAA,CAACuF,EAAAA,CAAA,CACC,QAAA,CAAUiD,CAAAA,CACV,MAAA,CAAQE,EAAAA,CACR,KAAA,CAAOqB,CAAAA,CACP,MAAA,CAAQC,CAAAA,CACR,aAAA,CAAelB,CAAAA,CAAa,aAAA,CAC5B,aAAcA,CAAAA,CAAa,YAAA,CAC3B,KAAA,CAAM,MAAA,CACR,CAAA,CAEHtB,CAAAA,GAAc,QAAA,EACbI,CAAAA,EACAqB,CAAAA,EACA,CAACI,CAAAA,EACDN,EAAAA,EACE/I,GAAAA,CAACgG,EAAAA,CAAA,CACC,KAAA,CAAO+C,EAAAA,CACP,KAAA,CAAOgB,CAAAA,CACP,MAAA,CAAQC,CAAAA,CACR,YAAA,CAAcb,EAAAA,CACd,KAAA,CAAM,MAAA,CACR,CAAA,CAEH3B,CAAAA,GAAc,QAAA,EAAY,CAACyB,CAAAA,EAC1BjJ,GAAAA,CAAC+F,EAAAA,CAAA,CACC,MAAA,CAAQhB,EAAAA,CACR,aAAA,CAAe2C,CAAAA,GAAU,QAAA,CAAWmB,EAAAA,CAAY,aAAA,CAAgB,EAAA,CAChE,YAAA,CAAcnB,CAAAA,GAAU,QAAA,CAAWmB,EAAAA,CAAY,aAAe,CAAA,CAC9D,KAAA,CAAOkB,CAAAA,CACP,MAAA,CAAQC,CAAAA,CACR,KAAA,CAAOtC,CAAAA,GAAU,QAAA,CAAW,MAAA,CAAS,MAAA,CACvC,CAAA,CAEDF,CAAAA,GAAc,QAAA,EAAYyB,CAAAA,EAAmBF,IAC5C/I,GAAAA,CAACgG,EAAAA,CAAA,CACC,KAAA,CAAO+C,EAAAA,CACP,KAAA,CAAOgB,CAAAA,CACP,MAAA,CAAQC,CAAAA,CACR,YAAA,CAAcb,EAAAA,CACd,KAAA,CAAM,MAAA,CACR,CAAA,CAIFvJ,KAACC,GAAAA,CAAA,CAAI,aAAA,CAAc,QAAA,CAAS,KAAA,CAAOiK,EAAAA,CACjC,QAAA,CAAA,CAAAlK,IAAAA,CAACT,CAAAA,CAAA,CAAM,KAAA,CAAM,SAAA,CAAU,KAAA,CAAO2K,EAAAA,CAAY,QAAA,CAAU,CAAA,CAClD,QAAA,CAAA,CAAA9J,GAAAA,CAACI,EAAAA,CAAA,CACC,MAAA,CAAQ6H,CAAAA,CACR,OAAA,CAAS6B,EAAAA,CAAa,CAAA,CACtB,KAAA,CAAO,CACL,CAAE,GAAA,CAAK,CAAA,CAAG,MAAO,MAAO,CAAA,CACxB,GAAI,KAAA,CAAM,IAAA,CAAK,CAAE,MAAA,CAAQ,CAAE,CAAA,CAAG,CAACtD,CAAAA,CAAG3F,CAAAA,IAAO,CACvC,GAAA,CAAA,CAAMA,EAAI,CAAA,EAAK,CAAA,CACf,KAAA,CAAO,OACT,CAAA,CAAE,CAAA,CACF,GAAI,KAAA,CAAM,IAAA,CAAK,CAAE,MAAA,CAAQ,CAAE,CAAA,CAAG,CAAC2F,EAAG3F,CAAAA,IAAO,CACvC,GAAA,CAAK,EAAA,CAAA,CAAMA,CAAAA,CAAI,CAAA,EAAK,EAAA,CACpB,KAAA,CAAO,QACT,CAAA,CAAE,CAAA,CACF,GAAI,KAAA,CAAM,IAAA,CAAK,CAAE,MAAA,CAAQ,CAAE,CAAA,CAAG,CAAC2F,CAAAA,CAAG3F,CAAAA,IAAO,CACvC,GAAA,CAAK,GAAA,CAAA,CAAOA,CAAAA,CAAI,CAAA,EAAK,EAAA,CACrB,KAAA,CAAO,KACT,CAAA,CAAE,CACJ,CAAA,CACA,KAAA,CAAM,yBAAA,CACR,CAAA,CACAb,GAAAA,CAACD,IAAAA,CAAA,CAAK,QAAA,CAAA,GAAA,CAAC,CAAA,CACPC,GAAAA,CAACD,IAAAA,CAAA,CAAK,IAAA,CAAI,IAAA,CAAC,QAAA,CAAQ,IAAA,CAAC,QAAA,CAAA,YAAA,CAEpB,CAAA,CAEE,CACE,CAAC,WAAA,CAAapC,CAAAA,CAAOoK,CAAAA,CAAQ,cAAc,CAAA,CAAG,MAAM,CAAA,CACpD,CAAC,WAAA,CAAapK,CAAAA,CAAOoK,EAAQ,kBAAkB,CAAA,CAAG,OAAO,CAAA,CACzD,CACE,QAAA,CACApK,CAAAA,CAAOoK,CAAAA,CAAQ,eAAe,CAAA,CAC9BA,CAAAA,CAAQ,eAAA,CAAkB,CAAA,CAAI,KAAA,CAAQ,OACxC,CAAA,CACA,CACE,SAAA,CACApK,CAAAA,CAAOoK,CAAAA,CAAQ,gBAAgB,CAAA,CAC/BA,CAAAA,CAAQ,gBAAA,CAAmB,CAAA,CAAI,QAAA,CAAW,OAC5C,CAAA,CACA,CACE,YAAA,CACA,IAAIA,CAAAA,CAAQ,SAAA,CAAY,GAAA,EAAK,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,CAAA,CACvCA,CAAAA,CAAQ,SAAA,CAAY,EAAA,CAAM,KAAA,CAAQ,OACpC,CAAA,CACA,CAAC,eAAgBpK,CAAAA,CAAOoK,CAAAA,CAAQ,WAAW,CAAA,CAAG,EAAE,CAClD,CAAA,CACA,GAAA,CAAI,CAAC,CAACvH,CAAAA,CAAO2L,CAAAA,CAAO7M,CAAK,CAAA,GACzBM,KAACC,GAAAA,CAAA,CACC,QAAA,CAAA,CAAAD,IAAAA,CAACG,IAAAA,CAAA,CAAM,QAAA,CAAA,CAAAS,CAAAA,CAAM,GAAA,CAAA,CAAC,CAAA,CACdR,GAAAA,CAACH,GAAAA,CAAA,CAAI,QAAA,CAAU,CAAA,CAAG,cAAA,CAAe,UAAA,CAC/B,QAAA,CAAAG,GAAAA,CAACD,IAAAA,CAAA,CAAK,IAAA,CAAI,IAAA,CAAE,GAAIT,CAAAA,CAAQ,CAAE,KAAA,CAAAA,CAAM,CAAA,CAAI,GACjC,QAAA,CAAA6M,CAAAA,CACH,CAAA,CACF,CAAA,CAAA,CAAA,CANQ3L,CAOV,CACD,CAAA,CACDR,GAAAA,CAACD,IAAAA,CAAA,CAAK,QAAA,CAAA,GAAA,CAAC,CAAA,CACPC,GAAAA,CAACD,IAAAA,CAAA,CAAK,IAAA,CAAI,IAAA,CAAC,QAAA,CAAQ,IAAA,CAAC,QAAA,CAAA,cAAA,CAEpB,CAAA,CAEE,CACE,CAAC,KAAA,CAAO1D,CAAAA,CAAe0L,CAAAA,CAAQ,aAAa,CAAA,CAAG,EAAE,CAAA,CACjD,CAAC,KAAA,CAAO1L,CAAAA,CAAe0L,CAAAA,CAAQ,aAAa,CAAA,CAAG,EAAE,CAAA,CACjD,CAAC,KAAA,CAAO1L,CAAAA,CAAe0L,CAAAA,CAAQ,aAAa,CAAA,CAAG,EAAE,CAAA,CACjD,CAAC,KAAA,CAAO1L,CAAAA,CAAe0L,CAAAA,CAAQ,aAAa,CAAA,CAAG,EAAE,CACnD,CAAA,CACA,GAAA,CAAI,CAAC,CAACvH,CAAAA,CAAO2L,CAAAA,CAAO7M,CAAK,IACzBM,IAAAA,CAACC,GAAAA,CAAA,CACC,QAAA,CAAA,CAAAD,IAAAA,CAACG,IAAAA,CAAA,CAAM,QAAA,CAAA,CAAAS,CAAAA,CAAM,GAAA,CAAA,CAAC,CAAA,CACdR,GAAAA,CAACH,GAAAA,CAAA,CAAI,SAAU,CAAA,CAAG,cAAA,CAAe,UAAA,CAC/B,QAAA,CAAAG,GAAAA,CAACD,IAAAA,CAAA,CAAK,IAAA,CAAI,IAAA,CAAE,GAAIT,CAAAA,CAAQ,CAAE,KAAA,CAAAA,CAAM,EAAI,EAAC,CAClC,QAAA,CAAA6M,CAAAA,CACH,CAAA,CACF,CAAA,CAAA,CAAA,CANQ3L,CAOV,CACD,CAAA,CAAA,CACH,CAAA,CAEAR,GAAAA,CAACb,CAAAA,CAAA,CAAM,KAAA,CAAM,QAAA,CAAS,KAAA,CAAO2K,EAAAA,CAC1B,QAAA,CAAAiC,CAAAA,CAAY,GAAA,CAAKG,CAAAA,EAChBtM,IAAAA,CAACC,GAAAA,CAAA,CACC,QAAA,CAAA,CAAAG,GAAAA,CAACD,IAAAA,CAAA,CAAM,QAAA,CAAAmM,CAAAA,CAAK,OAAO,CAAA,CACnBlM,GAAAA,CAACH,GAAAA,CAAA,CAAI,QAAA,CAAU,CAAA,CAAG,cAAA,CAAe,UAAA,CAC/B,QAAA,CAAAD,IAAAA,CAACG,IAAAA,CAAA,CAAK,KAAA,CAAM,QAAA,CAAS,QAAA,CAAA,CAAA,GAAA,CAAEmM,CAAAA,CAAK,GAAA,CAAI,GAAA,CAAA,CAAC,CAAA,CACnC,CAAA,CAAA,CAAA,CAJQA,CAAAA,CAAK,GAKf,CACD,CAAA,CACH,CAAA,CAAA,CACF,CAAA,CAAA,CACF,CAAA,CAAA,CACF,CAEJ,CAEA,eAAsBE,GAAUC,CAAAA,CAA+B,CAC7D,IAAIlF,CAAAA,CACJ,GAAI,CACFA,CAAAA,CAAK,MAAMmF,CAAAA,CAAY,IAAA,CAAKD,CAAM,EACpC,CAAA,MAAS9O,CAAAA,CAAK,CACZ,IAAMgP,CAAAA,CAAMhP,CAAAA,YAAe,KAAA,CAAQA,CAAAA,CAAI,OAAA,CAAU,MAAA,CAAOA,CAAG,CAAA,CAC3D,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,CAAA,mCAAA,EAAsCgP,CAAG;AAAA,CAAI,CAAA,CAClE,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,SAASF,CAAM;AAAA,CAAI,CAAA,CACxC,OAAA,CAAQ,MAAA,CAAO,KAAA,CACb,CAAA;AAAA,CACF,EACA,OAAA,CAAQ,IAAA,CAAK,CAAC,EAChB,CAGA,MADiBG,MAAAA,CAAOxM,GAAAA,CAACkH,EAAAA,CAAA,CAAI,EAAA,CAAIC,CAAAA,CAAI,CAAE,CAAA,CACxB,gBACjB","file":"app.js","sourcesContent":["export type NavItem = \"capabilities\" | \"exchanges\" | \"errors\" | \"events\";\n\nexport type NavSection = {\n label?: string;\n items: { key: NavItem; label: string; shortcut: string }[];\n};\n\nexport const NAV_SECTIONS: NavSection[] = [\n {\n items: [{ key: \"capabilities\", label: \"Capabilities\", shortcut: \"1\" }],\n },\n {\n items: [\n { key: \"exchanges\", label: \"Exchanges\", shortcut: \"2\" },\n { key: \"errors\", label: \"Errors\", shortcut: \"3\" },\n { key: \"events\", label: \"Events\", shortcut: \"4\" },\n ],\n },\n];\n\nexport const ALL_NAV_ITEMS = NAV_SECTIONS.flatMap((s) => s.items);\n\nexport interface RouteSummary {\n id: string;\n status: string;\n totalExchanges: number;\n completedExchanges: number;\n failedExchanges: number;\n droppedExchanges: number;\n avgDurationMs: number | null;\n}\n\nexport interface ExchangeRecord {\n id: string;\n routeId: string;\n contextId: string;\n correlationId: string;\n status: string;\n startedAt: string;\n completedAt: string | null;\n durationMs: number | null;\n error: string | null;\n}\n\nexport interface EventRecord {\n id?: number;\n timestamp: string;\n contextId: string;\n eventName: string;\n details: string;\n}\n\nexport interface Metrics {\n totalRoutes: number;\n totalExchanges: number;\n completedExchanges: number;\n failedExchanges: number;\n droppedExchanges: number;\n errorRate: number;\n avgDurationMs: number | null;\n p90DurationMs: number | null;\n p95DurationMs: number | null;\n p99DurationMs: number | null;\n}\n\nexport interface ExchangeSnapshot {\n headers: string;\n body: string | null;\n truncated: boolean;\n}\n\nexport interface RouteActivity {\n throughput: number[];\n recentErrors: number;\n}\n","export function truncate(str: string, maxLen: number): string {\n if (maxLen <= 0) return \"\";\n return str.length > maxLen ? str.slice(0, maxLen - 1) + \"\\u2026\" : str;\n}\n\nexport function formatDuration(ms: number | null): string {\n if (ms === null || ms === undefined) return \"-\";\n if (!Number.isFinite(ms) || ms < 0) return \"-\";\n if (ms === 0) return \"<1ms\";\n if (ms < 1000) return `${Math.round(ms)}ms`;\n return `${(ms / 1000).toFixed(1)}s`;\n}\n\nexport function statusColor(status: string): string {\n switch (status) {\n case \"completed\":\n case \"started\":\n return \"green\";\n case \"failed\":\n return \"red\";\n case \"stopped\":\n case \"dropped\":\n return \"yellow\";\n default:\n return \"white\";\n }\n}\n\nexport function col(str: string, len: number | undefined): string {\n if (len === undefined) return str;\n if (len <= 0) return \"\";\n if (str.length > len) return str.slice(0, len - 1) + \"\\u2026\";\n return str.padEnd(len);\n}\n\n// Fixed column widths for the Details column so fields line up across rows.\n// All event types share the same 4-column layout:\n// [col1: 10] [col2: 10] [exId: 12] [dur: 6] [extra]\n// Step events: operation (adapter) id… dur metadata\n// Exchange events: routeId (status) id… dur\nconst DET = {\n COL1: 10, // operation or routeId\n COL2: 10, // (adapter) or (err)/(reason)/(dropped)\n EX: 12, // \"789003e7 \"\n DUR: 6, // \"1ms \" \"10.0s \"\n} as const;\n\nexport interface DetailColumns {\n step: string;\n adapter: string;\n exchange: string;\n duration: string;\n meta: string;\n}\n\n/**\n * Parse a JSON event detail string into structured columns.\n * Shared normalizer used by both formatDetails and formatDetailColumns.\n */\nfunction parseEventDetail(raw: string): DetailColumns | null {\n try {\n const d = JSON.parse(raw) as Record<string, unknown>;\n\n const exchange =\n \"exchangeId\" in d ? `${String(d[\"exchangeId\"]).slice(0, 8)}` : \"\";\n const duration =\n \"duration\" in d ? formatDuration(d[\"duration\"] as number) : \"\";\n\n // Step/operation events\n if (\"operation\" in d && \"routeId\" in d) {\n const adapter =\n \"adapter\" in d\n ? `(${d[\"adapter\"]})`\n : \"adapterId\" in d\n ? `(${d[\"adapterId\"]})`\n : \"\";\n let meta = \"\";\n if (\n \"metadata\" in d &&\n typeof d[\"metadata\"] === \"object\" &&\n d[\"metadata\"] !== null\n ) {\n const m = d[\"metadata\"] as Record<string, unknown>;\n const keys = Object.keys(m).slice(0, 2);\n if (keys.length > 0) meta = keys.map((k) => `${k}=${m[k]}`).join(\" \");\n }\n return {\n step: String(d[\"operation\"]),\n adapter,\n exchange,\n duration,\n meta,\n };\n }\n\n // Exchange events\n if (\"routeId\" in d && \"exchangeId\" in d) {\n const qualifier =\n \"error\" in d\n ? \"(err)\"\n : \"reason\" in d\n ? `(${String(d[\"reason\"]).slice(0, 8)})`\n : \"\";\n return {\n step: String(d[\"routeId\"]),\n adapter: qualifier,\n exchange,\n duration,\n meta: \"\",\n };\n }\n\n // Route lifecycle events\n if (\"route\" in d && typeof d[\"route\"] === \"object\" && d[\"route\"] !== null) {\n const route = d[\"route\"] as {\n routeId?: string;\n definition?: { id?: string };\n };\n return {\n step: route.routeId ?? route.definition?.id ?? \"?\",\n adapter: \"\",\n exchange: \"\",\n duration: \"\",\n meta: \"\",\n };\n }\n\n // Plugin events\n if (\"pluginId\" in d) {\n return {\n step: `plugin=${d[\"pluginId\"]}`,\n adapter: \"\",\n exchange: \"\",\n duration: \"\",\n meta: \"\",\n };\n }\n\n // Error events\n if (\"error\" in d) {\n const err = d[\"error\"];\n const msg =\n typeof err === \"object\" && err !== null && \"message\" in err\n ? String((err as { message: string }).message)\n : String(err);\n return {\n step: msg,\n adapter: \"\",\n exchange: \"\",\n duration: \"\",\n meta: \"\",\n };\n }\n\n return null;\n } catch {\n return null;\n }\n}\n\nexport function formatDetails(_eventName: string, raw: string): string {\n const parsed = parseEventDetail(raw);\n if (!parsed) {\n return raw.length > 100 ? raw.slice(0, 97) + \"...\" : raw;\n }\n\n // Non-columnar events (plugin, route lifecycle, error) have no exchange/duration\n if (!parsed.exchange && !parsed.duration && !parsed.adapter) {\n return parsed.step;\n }\n\n return [\n col(parsed.step, DET.COL1),\n col(parsed.adapter, DET.COL2),\n col(parsed.exchange, DET.EX),\n col(parsed.duration, DET.DUR),\n parsed.meta,\n ]\n .join(\" \")\n .trimEnd();\n}\n\n/**\n * Structured version of formatDetails that returns individual columns\n * so the component can control alignment per-column.\n */\nexport function formatDetailColumns(\n _eventName: string,\n raw: string,\n): DetailColumns {\n const parsed = parseEventDetail(raw);\n if (!parsed) {\n return { step: raw, adapter: \"\", exchange: \"\", duration: \"\", meta: \"\" };\n }\n return parsed;\n}\n\n/**\n * Render a single-line sparkline from an array of values.\n * Uses Unicode block characters (▁▂▃▄▅▆▇█).\n * Empty/zero-only input returns spaces of the same length.\n */\nexport function sparkline(values: number[]): string {\n if (values.length === 0) return \"\";\n const blocks = [\n \" \",\n \"\\u2581\",\n \"\\u2582\",\n \"\\u2583\",\n \"\\u2584\",\n \"\\u2585\",\n \"\\u2586\",\n \"\\u2587\",\n \"\\u2588\",\n ];\n const max = Math.max(...values, 1);\n return values\n .map((v) => {\n const idx = Math.max(0, Math.min(8, Math.round((v / max) * 8)));\n return blocks[Number.isFinite(idx) ? idx : 0];\n })\n .join(\"\");\n}\n\nexport function fmtNum(n: number): string {\n return n.toLocaleString(\"en-US\");\n}\n\n/**\n * Adjust scroll offset so the selected item stays visible without centering.\n * The cursor moves freely within the visible window; the list only scrolls\n * when the cursor hits the top or bottom edge.\n *\n * @param selected - New selected index\n * @param currentOffset - Current scroll offset (tracked as state by the caller)\n * @param visibleRows - Number of rows visible in the list\n * @returns Updated scroll offset\n */\nexport function adjustScrollOffset(\n selected: number,\n currentOffset: number,\n visibleRows: number,\n): number {\n if (visibleRows <= 0) return currentOffset;\n if (selected < currentOffset) return selected;\n if (selected >= currentOffset + visibleRows)\n return selected - visibleRows + 1;\n return currentOffset;\n}\n","import { useState, useCallback } from \"react\";\nimport { adjustScrollOffset } from \"../utils.js\";\n\nexport interface ScrollListState {\n selectedIndex: number;\n scrollOffset: number;\n /** Move selection by delta (positive = down, negative = up). */\n moveBy: (delta: number, listLength: number, visibleRows: number) => void;\n /** Jump to an absolute index. */\n moveTo: (index: number, listLength: number, visibleRows: number) => void;\n /** Reset selection and scroll to the beginning. */\n reset: () => void;\n}\n\n/**\n * Manages a paired (selectedIndex, scrollOffset) state for scrollable lists.\n * Keeps the selected item visible without centering.\n *\n * `listLength` and `visibleRows` are passed at call time (not stored)\n * because they change every render (terminal resize, data load).\n */\nexport function useScrollList(initialIndex = 0): ScrollListState {\n const [selectedIndex, setSelectedIndex] = useState(initialIndex);\n const [scrollOffset, setScrollOffset] = useState(0);\n\n const moveTo = useCallback(\n (index: number, listLength: number, visibleRows: number) => {\n const clamped = Math.max(0, Math.min(index, listLength - 1));\n setSelectedIndex(clamped);\n setScrollOffset((off) => adjustScrollOffset(clamped, off, visibleRows));\n },\n [],\n );\n\n const moveBy = useCallback(\n (delta: number, listLength: number, visibleRows: number) => {\n setSelectedIndex((prev) => {\n const next = Math.max(0, Math.min(prev + delta, listLength - 1));\n setScrollOffset((off) => adjustScrollOffset(next, off, visibleRows));\n return next;\n });\n },\n [],\n );\n\n const reset = useCallback(() => {\n setSelectedIndex(0);\n setScrollOffset(0);\n }, []);\n\n return { selectedIndex, scrollOffset, moveBy, moveTo, reset };\n}\n","import type { ReactNode } from \"react\";\nimport { Box, Text } from \"ink\";\n\nexport function Panel({\n title,\n subtitle,\n color = \"gray\",\n width,\n flexGrow,\n paddingX = 1,\n children,\n}: {\n title?: string;\n subtitle?: ReactNode;\n color?: string;\n width?: number;\n flexGrow?: number;\n paddingX?: number;\n children: ReactNode;\n}) {\n // Border adds 2 chars per side; padding adds paddingX per side\n const innerWidth = width ? width - 2 - paddingX * 2 : 20;\n\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor={color}\n paddingX={paddingX}\n width={width}\n flexGrow={flexGrow}\n >\n {title && (\n <>\n <Text bold>\n {title}\n {subtitle && <> {subtitle}</>}\n </Text>\n <Text dimColor>{\"\\u2500\".repeat(Math.max(innerWidth, 1))}</Text>\n </>\n )}\n {children}\n </Box>\n );\n}\n","import { Text } from \"ink\";\n\n/**\n * Braille layout: 1 bucket per character, both columns.\n *\n * Left Right\n * 0x01 0x08 sub-row 0 (top)\n * 0x02 0x10 sub-row 1\n * 0x04 0x20 sub-row 2\n * 0x40 0x80 sub-row 3 (bottom)\n *\n * Each terminal character represents 1 time bucket.\n * Both columns mirror the same data for btop-style dot density.\n * Each terminal row packs up to 4 step levels vertically.\n */\nconst BRAILLE_DOTS = [\n 0x40 | 0x80,\n 0x04 | 0x20,\n 0x02 | 0x10,\n 0x01 | 0x08,\n] as const; // bottom to top\nconst BRAILLE_BASE = 0x2800;\n\nexport interface DotStep {\n max: number;\n color: string;\n}\n\n/** Default 5-step config: gray baseline, green low, yellow mid, red high. */\nexport const DEFAULT_STEPS: DotStep[] = [\n { max: 0, color: \"gray\" },\n { max: 10, color: \"green\" },\n { max: 20, color: \"green\" },\n { max: 30, color: \"yellow\" },\n { max: 40, color: \"yellow\" },\n { max: 50, color: \"red\" },\n];\n\n/**\n * Stacked dot graph using braille characters.\n *\n * 1 bucket = 1 terminal character. Both braille columns mirror the same\n * data for btop-style dot density. Each character can stack up to 4 step\n * levels vertically.\n *\n * - 0 exchanges: gray baseline dot (bottom)\n * - 1-9 exchanges: green dot (bottom)\n * - 10-19 exchanges: two green dots stacked\n * - etc., stacking upward with per-level colors\n */\nexport function DotGraph({\n values,\n columns,\n steps = DEFAULT_STEPS,\n label,\n}: {\n values: number[];\n columns: number;\n steps?: DotStep[];\n label?: string;\n}) {\n const dotHeight = steps.length - 1;\n\n // Right-align: newest on right, pad left with zeros\n const data =\n values.length >= columns\n ? values.slice(values.length - columns)\n : [\n ...(new Array(columns - values.length).fill(0) as number[]),\n ...values,\n ];\n\n // Map each value to a step index (0 = baseline, 1..dotHeight)\n const heights = data.map((v) => {\n if (v <= 0) return 0;\n for (let i = 1; i < steps.length; i++) {\n if (v < steps[i]!.max) return i;\n }\n return dotHeight;\n });\n\n const termRows = Math.ceil(dotHeight / 4);\n\n // Build terminal rows from top to bottom\n const rows: JSX.Element[] = [];\n for (let tr = termRows - 1; tr >= 0; tr--) {\n const baseStep = tr * 4;\n\n // For each bucket, compute the braille bits and color for this terminal row\n const segments: { text: string; color: string }[] = [];\n\n for (let ci = 0; ci < data.length; ci++) {\n const h = heights[ci]!;\n let bits = 0;\n let color = \"\";\n\n for (let sr = 0; sr < 4; sr++) {\n const stepLevel = baseStep + sr + 1;\n if (stepLevel > dotHeight) break;\n\n // Show dot if height reaches this level, or baseline dot for zero values\n const on = h >= stepLevel || (h === 0 && stepLevel === 1);\n if (on) {\n bits |= BRAILLE_DOTS[sr]!;\n // Color: gray for baseline (zero), step color for data\n color = h === 0 ? steps[0]!.color : steps[stepLevel]!.color;\n }\n }\n\n const char = String.fromCharCode(BRAILLE_BASE + bits);\n const last = segments[segments.length - 1];\n if (last && last.color === color) {\n last.text += char;\n } else {\n segments.push({ text: char, color });\n }\n }\n\n rows.push(\n <Text key={tr}>\n {segments.map((s, i) =>\n s.color ? (\n <Text key={i} color={s.color}>\n {s.text}\n </Text>\n ) : (\n <Text key={i}>{s.text}</Text>\n ),\n )}\n </Text>,\n );\n }\n\n return (\n <>\n {rows}\n {label && <Text dimColor>{label}</Text>}\n </>\n );\n}\n","import { Text } from \"ink\";\nimport type { RouteSummary } from \"../types.js\";\nimport { statusColor, fmtNum, formatDuration } from \"../utils.js\";\n\nexport function RouteHeader({ route }: { route: RouteSummary }) {\n return (\n <>\n <Text>\n Capability:{\" \"}\n <Text bold color=\"cyan\">\n {route.id}\n </Text>\n </Text>\n <Text>\n Status:{\" \"}\n <Text bold color={statusColor(route.status)}>\n {route.status}\n </Text>\n {\" \"}Exchanges: <Text bold>{fmtNum(route.totalExchanges)}</Text>\n {\" \"}Errors:{\" \"}\n <Text\n bold\n {...(route.failedExchanges > 0 ? { color: \"red\" as const } : {})}\n >\n {fmtNum(route.failedExchanges)}\n </Text>\n {\" \"}Dropped:{\" \"}\n <Text\n bold\n {...(route.droppedExchanges > 0 ? { color: \"yellow\" as const } : {})}\n >\n {fmtNum(route.droppedExchanges)}\n </Text>\n {\" \"}Avg: <Text bold>{formatDuration(route.avgDurationMs)}</Text>\n </Text>\n </>\n );\n}\n","import { Fragment, type ReactNode } from \"react\";\nimport { Box, Text } from \"ink\";\nimport { col } from \"../utils.js\";\n\nexport interface ColumnDef<T> {\n /** Header label */\n header: string;\n /** Fixed character width, or \"flex\" to fill remaining space */\n width: number | \"flex\";\n /** Text alignment. Default: \"left\" */\n align?: \"left\" | \"right\";\n /** Render cell content. `colWidth` is the resolved width for fixed columns, undefined for flex. */\n render: (\n row: T,\n selected: boolean,\n colWidth: number | undefined,\n ) => ReactNode;\n}\n\nexport interface TableProps<T> {\n columns: ColumnDef<T>[];\n data: T[];\n /** Unique key for each row */\n rowKey: (row: T, index: number) => string;\n /** Selected row index in full data array, or -1/undefined for no selection */\n selectedIndex?: number;\n /** First visible row (scroll offset) */\n scrollOffset: number;\n /** Number of visible rows */\n visibleRows: number;\n /** Gap between columns in characters. Default: 2 */\n gap?: number;\n /** Message when data is empty */\n emptyMessage?: string;\n /**\n * Optional full-row override for special rows (e.g., group headers).\n * Return undefined to use normal column rendering.\n */\n renderFullRow?: (row: T, index: number) => ReactNode | undefined;\n}\n\nexport function Table<T>({\n columns,\n data,\n rowKey,\n selectedIndex,\n scrollOffset,\n visibleRows,\n gap = 2,\n emptyMessage = \"No data\",\n renderFullRow,\n}: TableProps<T>) {\n const gapStr = \" \".repeat(gap);\n\n // Header\n const header = (\n <Box>\n {columns.map((c, ci) => {\n const isLast = ci === columns.length - 1;\n const after = isLast ? \"\" : gapStr;\n\n if (c.width === \"flex\") {\n return (\n <Fragment key={ci}>\n <Box flexGrow={1}>\n <Text bold dimColor>\n {c.header}\n </Text>\n </Box>\n {after && <Text>{after}</Text>}\n </Fragment>\n );\n }\n\n const text =\n c.align === \"right\"\n ? c.header.padStart(c.width)\n : col(c.header, c.width);\n\n return (\n <Fragment key={ci}>\n <Text bold dimColor>\n {text}\n </Text>\n {after && <Text>{after}</Text>}\n </Fragment>\n );\n })}\n </Box>\n );\n\n if (data.length === 0) {\n return (\n <>\n {header}\n <Text dimColor>{emptyMessage}</Text>\n </>\n );\n }\n\n const visible = data.slice(scrollOffset, scrollOffset + visibleRows);\n const remaining = data.length - scrollOffset - visibleRows;\n\n return (\n <>\n {header}\n {visible.map((row, vi) => {\n const dataIndex = scrollOffset + vi;\n const selected = dataIndex === selectedIndex;\n\n // Full-row override (e.g., group headers)\n const fullRow = renderFullRow?.(row, dataIndex);\n if (fullRow !== undefined) {\n return <Box key={rowKey(row, dataIndex)}>{fullRow}</Box>;\n }\n\n return (\n <Box key={rowKey(row, dataIndex)}>\n {columns.map((c, ci) => {\n const isLast = ci === columns.length - 1;\n const after = isLast ? \"\" : gapStr;\n const resolved = c.width === \"flex\" ? undefined : c.width;\n const cell = c.render(row, selected, resolved);\n\n if (c.width === \"flex\") {\n return (\n <Fragment key={ci}>\n <Box flexGrow={1}>\n <Text wrap=\"truncate\">{cell}</Text>\n </Box>\n {after && <Text>{after}</Text>}\n </Fragment>\n );\n }\n\n return (\n <Fragment key={ci}>\n {cell}\n {after && <Text>{after}</Text>}\n </Fragment>\n );\n })}\n </Box>\n );\n })}\n <Text dimColor>{remaining > 0 ? \"\\u2193 more\" : \" \"}</Text>\n </>\n );\n}\n","import { Text } from \"ink\";\nimport type { EventRecord } from \"../types.js\";\nimport { col, formatDetailColumns, type DetailColumns } from \"../utils.js\";\nimport type { ColumnDef } from \"./table.js\";\n\n/**\n * Build the 4 standard event detail columns (Step, Adapter, Exchange, Duration).\n *\n * The accessor extracts an EventRecord from whatever row type T the table uses.\n * Returns undefined when the row has no event data (e.g., group headers).\n *\n * JSON is parsed once per row and shared across all 4 columns via a WeakMap cache.\n */\nexport function eventDetailColumns<T>(\n accessor: (row: T) => EventRecord | undefined,\n): ColumnDef<T>[] {\n const cache = new WeakMap<EventRecord, DetailColumns>();\n\n function getColumns(row: T): DetailColumns | undefined {\n const ev = accessor(row);\n if (!ev) return undefined;\n let cols = cache.get(ev);\n if (!cols) {\n cols = formatDetailColumns(ev.eventName, ev.details);\n cache.set(ev, cols);\n }\n return cols;\n }\n\n return [\n {\n header: \"Step\",\n width: 10,\n render: (row, _sel, w) => {\n const cols = getColumns(row);\n if (!cols) return <Text>{col(\"\", w)}</Text>;\n return <Text>{col(cols.step, w)}</Text>;\n },\n },\n {\n header: \"Adapter\",\n width: 10,\n render: (row, _sel, w) => {\n const cols = getColumns(row);\n if (!cols) return <Text>{col(\"\", w)}</Text>;\n return <Text>{col(cols.adapter, w)}</Text>;\n },\n },\n {\n header: \"Exchange\",\n width: 12,\n render: (row, _sel, w) => {\n const cols = getColumns(row);\n if (!cols) return <Text>{col(\"\", w)}</Text>;\n return <Text>{col(cols.exchange, w)}</Text>;\n },\n },\n {\n header: \"Duration\",\n width: 8,\n align: \"right\" as const,\n render: (row) => {\n const cols = getColumns(row);\n if (!cols) return <Text>{\"\"}</Text>;\n return <Text>{cols.duration.padStart(8)}</Text>;\n },\n },\n ];\n}\n\n/**\n * Selector column that shows \"> \" for the selected row.\n */\nexport function selectorColumn<T>(): ColumnDef<T> {\n return {\n header: \"\",\n width: 2,\n render: (_row, selected) => (\n <Text {...(selected ? { color: \"cyan\" as const } : {})} bold={selected}>\n {selected ? \"> \" : \" \"}\n </Text>\n ),\n };\n}\n","import { Box, Text } from \"ink\";\nimport type { ExchangeRecord, RouteSummary, RouteActivity } from \"../types.js\";\nimport { statusColor, formatDuration, col } from \"../utils.js\";\nimport { PANEL_TABLE_CHROME } from \"../layout.js\";\nimport { Panel } from \"./panel.js\";\nimport { RouteHeader } from \"./route-header.js\";\nimport { DotGraph, DEFAULT_STEPS } from \"./dot-graph.js\";\nimport { Table, type ColumnDef } from \"./table.js\";\nimport { selectorColumn } from \"./event-columns.js\";\n\nconst exchangeColumns: ColumnDef<ExchangeRecord>[] = [\n selectorColumn<ExchangeRecord>(),\n {\n header: \"ID\",\n width: \"flex\",\n render: (row, selected) => (\n <Text {...(selected ? { color: \"cyan\" as const } : {})} bold={selected}>\n {row.id}\n </Text>\n ),\n },\n {\n header: \"Status\",\n width: 9,\n render: (row, _sel, w) => (\n <Text color={statusColor(row.status)}>{col(row.status, w)}</Text>\n ),\n },\n {\n header: \"Duration\",\n width: 8,\n align: \"right\",\n render: (row) => <Text>{formatDuration(row.durationMs).padStart(8)}</Text>,\n },\n {\n header: \"Time\",\n width: 8,\n render: (row, _sel, w) => (\n <Text dimColor>\n {col(row.startedAt.replace(\"T\", \" \").slice(11, 19), w)}\n </Text>\n ),\n },\n];\n\nexport function CenterExchangeList({\n capabilityId,\n route,\n exchanges,\n selectedIndex,\n scrollOffset,\n width,\n height,\n color = \"gray\",\n activity,\n}: {\n capabilityId: string;\n route?: RouteSummary;\n exchanges: ExchangeRecord[];\n selectedIndex: number;\n scrollOffset: number;\n width: number;\n height: number;\n color?: string;\n activity?: RouteActivity | undefined;\n}) {\n const graphTermRows = Math.ceil((DEFAULT_STEPS.length - 1) / 4);\n const headerRows = route ? 2 + graphTermRows + 2 : 0;\n const tableRows = Math.max(height - PANEL_TABLE_CHROME - headerRows, 3);\n\n const title = route ? \"EXCHANGES\" : `EXCHANGES: ${capabilityId}`;\n\n return (\n <Box flexDirection=\"column\" width={width} flexGrow={1}>\n {route && (\n <Panel width={width}>\n <RouteHeader route={route} />\n <Text> </Text>\n <DotGraph\n values={activity ? activity.throughput : []}\n columns={width - 4}\n label=\"Exchanges per 5s bucket\"\n />\n </Panel>\n )}\n <Panel title={title} width={width} flexGrow={1} color={color}>\n <Table\n columns={exchangeColumns}\n data={exchanges}\n rowKey={(ex) => ex.id + ex.contextId}\n selectedIndex={selectedIndex}\n scrollOffset={scrollOffset}\n visibleRows={tableRows}\n emptyMessage=\"No exchanges\"\n />\n </Panel>\n </Box>\n );\n}\n","import { Text } from \"ink\";\n\n/** Token types for JSON syntax coloring. */\nexport type TokenType =\n | \"key\"\n | \"string\"\n | \"number\"\n | \"boolean\"\n | \"null\"\n | \"brace\";\n\nexport interface JsonToken {\n text: string;\n type: TokenType;\n}\n\n/**\n * Tokenize a single line of pretty-printed JSON into colored segments.\n * Handles: keys, string values, numbers, booleans, null, and structural chars.\n */\nexport function tokenizeLine(line: string): JsonToken[] {\n const tokens: JsonToken[] = [];\n const re =\n /(\"(?:[^\"\\\\]|\\\\.)*\")\\s*:|(\"(?:[^\"\\\\]|\\\\.)*\")|(-?\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?)|(\\btrue\\b|\\bfalse\\b)|(\\bnull\\b)|([{}[\\],:])/g;\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = re.exec(line)) !== null) {\n // Plain text before this match (whitespace / indent)\n if (match.index > lastIndex) {\n tokens.push({ text: line.slice(lastIndex, match.index), type: \"brace\" });\n }\n\n if (match[1] !== undefined) {\n // Key (the colon is part of the regex but we split it out)\n tokens.push({ text: match[1], type: \"key\" });\n tokens.push({ text: \":\", type: \"brace\" });\n } else if (match[2] !== undefined) {\n tokens.push({ text: match[2], type: \"string\" });\n } else if (match[3] !== undefined) {\n tokens.push({ text: match[3], type: \"number\" });\n } else if (match[4] !== undefined) {\n tokens.push({ text: match[4], type: \"boolean\" });\n } else if (match[5] !== undefined) {\n tokens.push({ text: match[5], type: \"null\" });\n } else if (match[6] !== undefined) {\n tokens.push({ text: match[6], type: \"brace\" });\n }\n\n lastIndex = match.index + match[0].length;\n }\n\n // Trailing text\n if (lastIndex < line.length) {\n tokens.push({ text: line.slice(lastIndex), type: \"brace\" });\n }\n\n return tokens;\n}\n\nexport const TOKEN_COLORS: Record<TokenType, string> = {\n key: \"cyan\",\n string: \"green\",\n number: \"yellow\",\n boolean: \"yellow\",\n null: \"red\",\n brace: \"gray\",\n};\n\n/**\n * Parse a JSON string into pretty-printed lines, truncating long lines.\n */\nexport function formatJson(raw: string, maxWidth: number): string[] {\n try {\n const parsed = JSON.parse(raw) as unknown;\n const pretty = JSON.stringify(parsed, null, 2);\n return pretty.split(\"\\n\").map((line) => {\n const clampedMax = Math.max(1, maxWidth);\n return line.length > clampedMax\n ? line.slice(0, Math.max(0, clampedMax - 1)) + \"\\u2026\"\n : line;\n });\n } catch {\n const clampedMax = Math.max(1, maxWidth);\n return raw\n .split(\"\\n\")\n .map((line) =>\n line.length > clampedMax\n ? line.slice(0, Math.max(0, clampedMax - 1)) + \"\\u2026\"\n : line,\n );\n }\n}\n\n/**\n * Render a single line of JSON with syntax coloring.\n */\nexport function ColoredJsonLine({ line }: { line: string }) {\n const tokens = tokenizeLine(line);\n if (tokens.length === 0) return <Text>{line}</Text>;\n return (\n <Text>\n {tokens.map((token, i) => (\n <Text key={i} color={TOKEN_COLORS[token.type]}>\n {token.text}\n </Text>\n ))}\n </Text>\n );\n}\n\n/**\n * Safely parse a JSON details string.\n */\nexport function parseDetails(raw: string): Record<string, unknown> | null {\n try {\n const parsed: unknown = JSON.parse(raw);\n if (\n typeof parsed !== \"object\" ||\n parsed === null ||\n Array.isArray(parsed)\n ) {\n return null;\n }\n return parsed as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n","import { Box, Text } from \"ink\";\nimport type { ExchangeRecord, EventRecord } from \"../types.js\";\nimport { statusColor, formatDuration, col, truncate } from \"../utils.js\";\nimport { DETAIL_INFO_CHROME } from \"../layout.js\";\nimport { Panel } from \"./panel.js\";\nimport { Table, type ColumnDef } from \"./table.js\";\nimport { selectorColumn, eventDetailColumns } from \"./event-columns.js\";\nimport { parseDetails } from \"./json-format.js\";\n\ntype DisplayRow = {\n type: \"header\" | \"event\";\n text?: string;\n event?: EventRecord;\n indent: number;\n};\n\n/**\n * Group events by exchangeId to show parent/child flow.\n */\nfunction groupEventsByExchange(\n events: EventRecord[],\n parentExchangeId: string,\n): { exchangeId: string; label: string; events: EventRecord[] }[] {\n const groups = new Map<\n string,\n { exchangeId: string; label: string; events: EventRecord[] }\n >();\n let childIndex = 0;\n\n groups.set(parentExchangeId, {\n exchangeId: parentExchangeId,\n label: \"parent\",\n events: [],\n });\n\n for (const ev of events) {\n const d = parseDetails(ev.details);\n const exId = d ? String(d[\"exchangeId\"] ?? \"\") : \"\";\n const key = !exId || exId === parentExchangeId ? parentExchangeId : exId;\n\n if (!groups.has(key)) {\n childIndex++;\n groups.set(key, {\n exchangeId: key,\n label: `child ${childIndex}`,\n events: [],\n });\n }\n groups.get(key)!.events.push(ev);\n }\n\n return Array.from(groups.values());\n}\n\nconst detailColumns: ColumnDef<DisplayRow>[] = [\n selectorColumn<DisplayRow>(),\n {\n header: \"Time\",\n width: 8,\n render: (row, _sel, w) => {\n if (!row.event) return <Text>{col(\"\", w)}</Text>;\n const indent = \" \".repeat(row.indent);\n return (\n <Text dimColor>\n {indent}\n {row.event.timestamp.replace(\"T\", \" \").slice(11, 19)}\n </Text>\n );\n },\n },\n {\n header: \"Event\",\n width: \"flex\",\n render: (row) => {\n if (!row.event) return <Text />;\n return <Text color=\"cyan\">{row.event.eventName}</Text>;\n },\n },\n ...eventDetailColumns<DisplayRow>((row) => row.event),\n];\n\nexport function CenterExchangeDetail({\n exchange,\n events,\n width,\n height,\n scrollOffset,\n selectedIndex = -1,\n color = \"gray\",\n}: {\n exchange: ExchangeRecord;\n events: EventRecord[];\n width: number;\n height: number;\n scrollOffset: number;\n selectedIndex?: number;\n color?: string;\n}) {\n const hasExtra = exchange.error ? 2 : 0;\n const eventRows = Math.max(height - DETAIL_INFO_CHROME - hasExtra, 3);\n\n const groups = groupEventsByExchange(events, exchange.id);\n const hasChildren = groups.length > 1;\n\n const displayRows: DisplayRow[] = [];\n for (const group of groups) {\n if (hasChildren) {\n displayRows.push({\n type: \"header\",\n text: `${group.label} (${group.exchangeId.slice(0, 8)}) - ${group.events.length} events`,\n indent: 0,\n });\n }\n for (const ev of group.events) {\n displayRows.push({\n type: \"event\",\n event: ev,\n indent: hasChildren ? 2 : 0,\n });\n }\n }\n\n const eventsTitle = hasChildren\n ? `EXCHANGE FLOW (${groups.length} exchanges, ${events.length} events)`\n : `RELATED EVENTS (${events.length})`;\n\n return (\n <Box flexDirection=\"column\" width={width} flexGrow={1}>\n <Panel width={width}>\n <Text>\n Capability:{\" \"}\n <Text bold color=\"cyan\">\n {exchange.routeId}\n </Text>\n </Text>\n <Text>\n Exchange:{\" \"}\n <Text bold color=\"cyan\">\n {truncate(exchange.id, width - 14)}\n </Text>\n </Text>\n <Text>\n Status:{\" \"}\n <Text bold color={statusColor(exchange.status)}>\n {exchange.status}\n </Text>\n {exchange.durationMs !== null && (\n <Text>\n {\" \"}Duration:{\" \"}\n <Text bold>{formatDuration(exchange.durationMs)}</Text>\n </Text>\n )}\n {\" \"}Started: <Text bold>{exchange.startedAt}</Text>\n {exchange.completedAt && (\n <Text>\n {\" \"}Completed: <Text bold>{exchange.completedAt}</Text>\n </Text>\n )}\n </Text>\n {exchange.error && exchange.status === \"failed\" && (\n <>\n <Text> </Text>\n <Text color=\"red\">Error: {exchange.error}</Text>\n </>\n )}\n {exchange.error && exchange.status === \"dropped\" && (\n <>\n <Text> </Text>\n <Text color=\"yellow\">Reason: {exchange.error}</Text>\n </>\n )}\n </Panel>\n\n <Panel title={eventsTitle} width={width} flexGrow={1} color={color}>\n <Table\n columns={detailColumns}\n data={displayRows}\n rowKey={(row, i) =>\n row.type === \"header\"\n ? `h-${i}`\n : `${row.event?.id ?? row.event?.timestamp}-${i}`\n }\n selectedIndex={selectedIndex}\n scrollOffset={scrollOffset}\n visibleRows={eventRows}\n emptyMessage=\"No related events found\"\n renderFullRow={(row) =>\n row.type === \"header\" ? (\n <Text bold color=\"yellow\">\n {row.text}\n </Text>\n ) : undefined\n }\n />\n </Panel>\n </Box>\n );\n}\n","import { Text } from \"ink\";\nimport type { EventRecord } from \"../types.js\";\nimport { col } from \"../utils.js\";\nimport { PANEL_TABLE_CHROME } from \"../layout.js\";\nimport { Panel } from \"./panel.js\";\nimport { Table, type ColumnDef } from \"./table.js\";\nimport { selectorColumn, eventDetailColumns } from \"./event-columns.js\";\n\nconst eventColumns: ColumnDef<EventRecord>[] = [\n selectorColumn<EventRecord>(),\n {\n header: \"Time\",\n width: 19,\n render: (row, selected, w) => (\n <Text {...(selected ? { color: \"cyan\" as const } : {})} bold={selected}>\n {col(row.timestamp.replace(\"T\", \" \").slice(0, 19), w)}\n </Text>\n ),\n },\n {\n header: \"Event\",\n width: \"flex\",\n render: (row) => <Text color=\"cyan\">{row.eventName}</Text>,\n },\n ...eventDetailColumns<EventRecord>((row) => row),\n];\n\nexport function EventsView({\n events,\n selectedIndex,\n scrollOffset,\n width,\n height,\n color = \"gray\",\n}: {\n events: EventRecord[];\n selectedIndex: number;\n scrollOffset: number;\n width: number;\n height: number;\n color?: string;\n}) {\n const tableRows = Math.max(height - PANEL_TABLE_CHROME, 5);\n\n return (\n <Panel\n title=\"EVENTS\"\n subtitle={<Text dimColor>({events.length} total)</Text>}\n width={width}\n flexGrow={1}\n color={color}\n >\n <Table\n columns={eventColumns}\n data={events}\n rowKey={(ev, i) =>\n ev.id !== undefined ? String(ev.id) : `${ev.timestamp}-${i}`\n }\n selectedIndex={selectedIndex}\n scrollOffset={scrollOffset}\n visibleRows={tableRows}\n emptyMessage=\"No events recorded yet.\"\n />\n </Panel>\n );\n}\n","import { Box, Text } from \"ink\";\nimport type { EventRecord } from \"../types.js\";\nimport { Panel } from \"./panel.js\";\nimport { formatJson, ColoredJsonLine, parseDetails } from \"./json-format.js\";\n\nexport function EventDetail({\n event,\n width,\n height,\n scrollOffset,\n color = \"cyan\",\n}: {\n event: EventRecord;\n width: number;\n height: number;\n scrollOffset: number;\n color?: string;\n}) {\n const d = parseDetails(event.details);\n const routeId =\n d && typeof d[\"routeId\"] === \"string\" ? d[\"routeId\"] : undefined;\n const exchangeId =\n d && typeof d[\"exchangeId\"] === \"string\" ? d[\"exchangeId\"] : undefined;\n\n // Header lines: context (always) + capability + exchange + event + time\n const headerLines = 1 + (routeId ? 1 : 0) + (exchangeId ? 1 : 0) + 2;\n // Top panel: border (2) + content lines\n const headerHeight = 2 + headerLines;\n // Bottom panel: border (2) + title/separator (2) + footer (1) = 5\n const jsonChrome = 5;\n const jsonWidth = Math.max(width - 6, 20);\n const jsonLines = formatJson(event.details, jsonWidth);\n const visibleRows = Math.max(height - headerHeight - jsonChrome, 3);\n const visible = jsonLines.slice(scrollOffset, scrollOffset + visibleRows);\n\n return (\n <Box flexDirection=\"column\" width={width} flexGrow={1}>\n <Panel width={width}>\n <Text>\n Context:{\" \"}\n <Text bold color=\"cyan\">\n {event.contextId}\n </Text>\n </Text>\n {routeId && (\n <Text>\n Capability:{\" \"}\n <Text bold color=\"cyan\">\n {routeId}\n </Text>\n </Text>\n )}\n {exchangeId && (\n <Text>\n Exchange:{\" \"}\n <Text bold color=\"cyan\">\n {exchangeId}\n </Text>\n </Text>\n )}\n <Text>\n Event:{\" \"}\n <Text bold color=\"cyan\">\n {event.eventName}\n </Text>\n </Text>\n <Text>\n Time: <Text bold>{event.timestamp.replace(\"T\", \" \")}</Text>\n </Text>\n </Panel>\n\n <Panel\n title=\"DETAILS\"\n subtitle={\n <Text dimColor>\n ({scrollOffset + 1}-\n {Math.min(scrollOffset + visibleRows, jsonLines.length)}/\n {jsonLines.length} lines)\n </Text>\n }\n width={width}\n flexGrow={1}\n color={color}\n >\n {visible.map((line, i) => (\n <ColoredJsonLine key={scrollOffset + i} line={line} />\n ))}\n {visible.length < visibleRows &&\n Array.from({ length: visibleRows - visible.length }).map((_, i) => (\n <Text key={`pad-${i}`}> </Text>\n ))}\n </Panel>\n </Box>\n );\n}\n","import { Box, Text } from \"ink\";\nimport type { ExchangeRecord, ExchangeSnapshot } from \"../types.js\";\nimport { statusColor, formatDuration, truncate } from \"../utils.js\";\nimport { Panel } from \"./panel.js\";\nimport { formatJson, ColoredJsonLine } from \"./json-format.js\";\n\n/**\n * Build the scrollable lines for the deep view: headers + body sections.\n */\nfunction buildSnapshotLines(\n snapshot: ExchangeSnapshot,\n maxWidth: number,\n): string[] {\n const lines: string[] = [];\n\n lines.push(\"HEADERS\");\n lines.push(...formatJson(snapshot.headers, maxWidth));\n lines.push(\"\");\n lines.push(\"BODY\");\n if (snapshot.body !== null) {\n lines.push(...formatJson(snapshot.body, maxWidth));\n if (snapshot.truncated) {\n lines.push(\"\");\n lines.push(\"[Body truncated to configured limit]\");\n }\n } else {\n lines.push(\"[null]\");\n }\n\n return lines;\n}\n\nexport function ExchangeDeepView({\n exchange,\n snapshot,\n width,\n height,\n scrollOffset,\n color = \"cyan\",\n}: {\n exchange: ExchangeRecord;\n snapshot: ExchangeSnapshot | null;\n width: number;\n height: number;\n scrollOffset: number;\n color?: string;\n}) {\n // Header panel: border (2) + content (3 lines: capability + exchange + status)\n const headerHeight = 5;\n // JSON panel chrome: border (2) + title (1) + separator (1) + footer (1)\n const jsonChrome = 5;\n const jsonWidth = Math.max(width - 6, 20);\n const visibleRows = Math.max(height - headerHeight - jsonChrome, 3);\n\n const hasSnapshot = snapshot !== null;\n const jsonLines = hasSnapshot\n ? buildSnapshotLines(snapshot, jsonWidth)\n : [\n \"[Snapshots not captured]\",\n \"\",\n \"Enable with:\",\n \" telemetry({ sqlite: { captureSnapshots: true } })\",\n ];\n\n const visible = jsonLines.slice(scrollOffset, scrollOffset + visibleRows);\n\n return (\n <Box flexDirection=\"column\" width={width} flexGrow={1}>\n <Panel width={width}>\n <Text>\n Capability:{\" \"}\n <Text bold color=\"cyan\">\n {exchange.routeId}\n </Text>\n </Text>\n <Text>\n Exchange:{\" \"}\n <Text bold color=\"cyan\">\n {truncate(exchange.id, width - 14)}\n </Text>\n </Text>\n <Text>\n Status:{\" \"}\n <Text bold color={statusColor(exchange.status)}>\n {exchange.status}\n </Text>\n {exchange.durationMs !== null && (\n <Text>\n {\" \"}Duration:{\" \"}\n <Text bold>{formatDuration(exchange.durationMs)}</Text>\n </Text>\n )}\n </Text>\n </Panel>\n\n <Panel\n title=\"EXCHANGE SNAPSHOT\"\n subtitle={\n <Text dimColor>\n ({scrollOffset + 1}-\n {Math.min(scrollOffset + visibleRows, jsonLines.length)}/\n {jsonLines.length} lines)\n </Text>\n }\n width={width}\n flexGrow={1}\n color={color}\n >\n {visible.map((line, i) => {\n if (line === \"HEADERS\" || line === \"BODY\") {\n return (\n <Text key={scrollOffset + i} bold color=\"yellow\">\n {line}\n </Text>\n );\n }\n if (line.startsWith(\"[\")) {\n return (\n <Text key={scrollOffset + i} dimColor>\n {line}\n </Text>\n );\n }\n return <ColoredJsonLine key={scrollOffset + i} line={line} />;\n })}\n {visible.length < visibleRows &&\n Array.from({ length: visibleRows - visible.length }).map((_, i) => (\n <Text key={`pad-${i}`}> </Text>\n ))}\n </Panel>\n </Box>\n );\n}\n","import { Text } from \"ink\";\nimport type { RouteSummary } from \"../types.js\";\nimport { truncate } from \"../utils.js\";\n\nfunction dotColor(route: RouteSummary): string {\n if (route.failedExchanges > 0) return \"red\";\n if (route.totalExchanges > 0) return \"green\";\n return \"yellow\";\n}\n\nexport function CapabilityList({\n routes,\n selectedIndex,\n listOffset,\n visibleRows,\n width,\n}: {\n routes: RouteSummary[];\n selectedIndex: number;\n listOffset: number;\n visibleRows: number;\n width: number;\n}) {\n const offset = listOffset;\n\n return (\n <>\n <Text> </Text>\n <Text bold dimColor>\n {\"\\u2500\".repeat(width + 2)}\n </Text>\n {routes.length === 0 ? (\n <Text dimColor>No capabilities</Text>\n ) : (\n routes.slice(offset, offset + visibleRows).map((route, vi) => {\n const i = offset + vi;\n return (\n <Text key={route.id} wrap=\"truncate\">\n <Text\n {...(i === selectedIndex ? { color: \"cyan\" as const } : {})}\n bold={i === selectedIndex}\n >\n {i === selectedIndex ? \"> \" : \" \"}\n </Text>\n <Text color={dotColor(route)}>{\"\\u25CF \"}</Text>\n <Text\n {...(i === selectedIndex ? { color: \"cyan\" as const } : {})}\n bold={i === selectedIndex}\n >\n {truncate(route.id, width - 2)}\n </Text>\n </Text>\n );\n })\n )}\n {routes.length > visibleRows && (\n <Text dimColor>\n {selectedIndex + 1}/{routes.length}\n </Text>\n )}\n </>\n );\n}\n","import { useState, useEffect, useCallback } from \"react\";\nimport { render, Box, Text, useInput, useApp, useStdout } from \"ink\";\nimport { TelemetryDb } from \"./db.js\";\nimport type {\n NavItem,\n RouteSummary,\n ExchangeRecord,\n ExchangeSnapshot,\n EventRecord,\n Metrics,\n RouteActivity,\n} from \"./types.js\";\nimport { NAV_SECTIONS, ALL_NAV_ITEMS } from \"./types.js\";\nimport { fmtNum, formatDuration } from \"./utils.js\";\nimport { useScrollList } from \"./hooks/use-scroll-list.js\";\nimport { PANEL_TABLE_CHROME, DETAIL_INFO_CHROME, NAV_JUMP } from \"./layout.js\";\nimport { Panel } from \"./components/panel.js\";\nimport { DotGraph, DEFAULT_STEPS } from \"./components/dot-graph.js\";\nimport { CenterExchangeList } from \"./components/center-exchange-list.js\";\nimport { CenterExchangeDetail } from \"./components/center-exchange-detail.js\";\nimport { EventsView } from \"./components/events-view.js\";\nimport { EventDetail } from \"./components/event-detail.js\";\nimport { ExchangeDeepView } from \"./components/exchange-deep-view.js\";\nimport { CapabilityList } from \"./components/capability-list.js\";\n\n/**\n * Focus tracks which panel owns the cursor.\n * - \"nav\": left panel (route list / nav items)\n * - \"center\": center panel (exchange list, events, detail)\n */\ntype Focus = \"nav\" | \"center\";\n\nfunction App({ db }: { db: TelemetryDb }) {\n const { exit } = useApp();\n const { stdout } = useStdout();\n const width = stdout?.columns ?? 80;\n const height = stdout?.rows ?? 24;\n\n const [activeNav, setActiveNav] = useState<NavItem>(\"capabilities\");\n const [focus, setFocus] = useState<Focus>(\"nav\");\n const [showDetail, setShowDetail] = useState(false);\n\n const [routes, setRoutes] = useState<RouteSummary[]>([]);\n const [metrics, setMetrics] = useState<Metrics>({\n totalRoutes: 0,\n totalExchanges: 0,\n completedExchanges: 0,\n failedExchanges: 0,\n droppedExchanges: 0,\n errorRate: 0,\n avgDurationMs: null,\n p90DurationMs: null,\n p95DurationMs: null,\n p99DurationMs: null,\n });\n const [liveTraffic, setLiveTraffic] = useState<number[]>([]);\n const [selectedRouteActivity, setSelectedRouteActivity] = useState<\n RouteActivity | undefined\n >(undefined);\n const routeScroll = useScrollList();\n const [exchanges, setExchanges] = useState<ExchangeRecord[]>([]);\n const exchangeScroll = useScrollList();\n const [selectedExchange, setSelectedExchange] = useState<\n ExchangeRecord | undefined\n >(undefined);\n const [exchangeEvents, setExchangeEvents] = useState<EventRecord[]>([]);\n const [events, setEvents] = useState<EventRecord[]>([]);\n const eventScroll = useScrollList();\n const detailScroll = useScrollList();\n const [selectedEvent, setSelectedEvent] = useState<EventRecord | undefined>(\n undefined,\n );\n const [showEventDetail, setShowEventDetail] = useState(false);\n const [eventDetailScroll, setEventDetailScroll] = useState(0);\n const [showDeepView, setShowDeepView] = useState(false);\n const [deepViewScroll, setDeepViewScroll] = useState(0);\n const [exchangeSnapshot, setExchangeSnapshot] =\n useState<ExchangeSnapshot | null>(null);\n const PAGE_SIZE = 50;\n const JUMP = NAV_JUMP;\n\n // Layout dimensions (needed by both refresh and render)\n const leftWidth = Math.max(Math.min(Math.floor(width * 0.18), 26), 16);\n const rightWidth = Math.max(Math.min(Math.floor(width * 0.22), 30), 20);\n const centerWidth = Math.max(width - leftWidth - rightWidth, 30);\n const bodyHeight = Math.max(height - 5, 10);\n const navHeaderRows = 10;\n const navListHeight = Math.max(bodyHeight - navHeaderRows, 3);\n\n const refresh = useCallback(() => {\n try {\n // Always refresh: routes, metrics, graphs\n const routeSummary = db.getRouteSummary();\n setRoutes(routeSummary);\n setMetrics(db.getMetrics());\n const liveCols = rightWidth - 4;\n setLiveTraffic(db.getLiveTrafficBuckets(liveCols, 5));\n\n // Only load activity for the currently selected route\n const routeCols = centerWidth - 4;\n const curRoute = routeSummary[routeScroll.selectedIndex];\n if (curRoute) {\n setSelectedRouteActivity(\n db.getSingleRouteActivity(curRoute.id, routeCols, 5),\n );\n }\n\n // Skip list refresh when cursor is active (user is browsing)\n if (focus === \"center\") return;\n\n if (activeNav === \"capabilities\") {\n const route = routeSummary[routeScroll.selectedIndex];\n if (route) {\n setExchanges(db.getExchangesByRoute(route.id, PAGE_SIZE));\n }\n } else if (activeNav === \"exchanges\") {\n setExchanges(db.getAllExchanges(PAGE_SIZE));\n } else if (activeNav === \"errors\") {\n setExchanges(db.getFailedExchanges(PAGE_SIZE));\n } else if (activeNav === \"events\") {\n setEvents(db.getRecentEvents({ limit: 200 }));\n }\n } catch {\n // Database may be temporarily locked\n }\n }, [\n db,\n activeNav,\n routeScroll.selectedIndex,\n rightWidth,\n centerWidth,\n focus,\n ]);\n\n useEffect(() => {\n refresh();\n const timer = setInterval(refresh, 2000);\n return () => {\n clearInterval(timer);\n };\n }, [refresh]);\n\n const selectRoute = useCallback(\n (index: number) => {\n routeScroll.moveTo(index, routes.length, navListHeight);\n exchangeScroll.reset();\n const route = routes[index];\n if (route) {\n setExchanges(db.getExchangesByRoute(route.id, PAGE_SIZE));\n }\n },\n [db, routes, routeScroll, exchangeScroll, navListHeight],\n );\n\n const switchNav = useCallback(\n (nav: NavItem) => {\n setActiveNav(nav);\n setShowDetail(false);\n setShowEventDetail(false);\n setShowDeepView(false);\n setFocus(\"nav\");\n exchangeScroll.reset();\n if (nav === \"exchanges\") {\n setExchanges(db.getAllExchanges(PAGE_SIZE));\n } else if (nav === \"errors\") {\n setExchanges(db.getFailedExchanges(PAGE_SIZE));\n } else if (nav === \"events\") {\n eventScroll.reset();\n setEvents(db.getRecentEvents({ limit: 200 }));\n }\n },\n [db, exchangeScroll, eventScroll],\n );\n\n const selectedRoute = routes[routeScroll.selectedIndex];\n\n // Visible row counts mirror the view components\n // Must match CenterExchangeList: 2 (capability + stats) + graphTermRows + 2 (label + spacer)\n const graphTermRows = Math.ceil((DEFAULT_STEPS.length - 1) / 4);\n const exchangeHeaderRows = selectedRoute ? 2 + graphTermRows + 2 : 0;\n const exchangeTableRows = Math.max(\n bodyHeight - PANEL_TABLE_CHROME - exchangeHeaderRows,\n 3,\n );\n const eventsTableRows = Math.max(bodyHeight - PANEL_TABLE_CHROME, 5);\n\n useInput((input, key) => {\n if (input === \"q\") {\n db.close();\n exit();\n return;\n }\n\n // Number shortcuts to switch nav (always available)\n const navByShortcut = ALL_NAV_ITEMS.find((n) => n.shortcut === input);\n if (navByShortcut) {\n switchNav(navByShortcut.key);\n return;\n }\n\n // Events view: overview -> browse -> detail\n if (activeNav === \"events\") {\n if (showEventDetail) {\n // Detail view: scroll JSON, Esc to go back to list\n const step = key.ctrl ? JUMP : 1;\n if (input === \"j\" || key.downArrow) {\n setEventDetailScroll((i) => i + step);\n } else if (input === \"k\" || key.upArrow) {\n setEventDetailScroll((i) => Math.max(i - step, 0));\n } else if (key.escape || key.backspace || key.delete) {\n setShowEventDetail(false);\n setEventDetailScroll(0);\n }\n return;\n }\n if (focus === \"nav\") {\n if (key.return) {\n setFocus(\"center\");\n }\n } else {\n const step = key.ctrl ? JUMP : 1;\n if (input === \"j\" || key.downArrow) {\n eventScroll.moveBy(step, events.length, eventsTableRows);\n } else if (input === \"k\" || key.upArrow) {\n eventScroll.moveBy(-step, events.length, eventsTableRows);\n } else if (key.return) {\n const ev = events[eventScroll.selectedIndex];\n if (ev) {\n setSelectedEvent(ev);\n setEventDetailScroll(0);\n setShowEventDetail(true);\n }\n } else if (key.escape || key.backspace || key.delete) {\n setFocus(\"nav\");\n eventScroll.reset();\n }\n }\n return;\n }\n\n // Exchange deep view: scrollable JSON of headers + body\n if (showDeepView) {\n const step = key.ctrl ? JUMP : 1;\n if (input === \"j\" || key.downArrow) {\n setDeepViewScroll((i) => i + step);\n } else if (input === \"k\" || key.upArrow) {\n setDeepViewScroll((i) => Math.max(i - step, 0));\n } else if (key.escape || key.backspace || key.delete) {\n setShowDeepView(false);\n setDeepViewScroll(0);\n }\n return;\n }\n\n // Exchange detail (any nav)\n if (showDetail && !showEventDetail) {\n const hasExtra = selectedExchange?.error ? 2 : 0;\n const detailEventRows = Math.max(\n bodyHeight - DETAIL_INFO_CHROME - hasExtra,\n 3,\n );\n // Count group headers: when events span multiple exchanges, each group gets a header row\n const uniqueExchangeIds = new Set(\n exchangeEvents.map((ev) => {\n try {\n const d = JSON.parse(ev.details) as Record<string, unknown>;\n return String(d[\"exchangeId\"] ?? \"\");\n } catch {\n return \"\";\n }\n }),\n );\n const groupCount = Math.max(uniqueExchangeIds.size, 1);\n const headerRows = groupCount > 1 ? groupCount : 0;\n const totalDisplayRows = exchangeEvents.length + headerRows;\n const step = key.ctrl ? JUMP : 1;\n if (input === \"j\" || key.downArrow) {\n detailScroll.moveBy(step, totalDisplayRows, detailEventRows);\n } else if (input === \"k\" || key.upArrow) {\n detailScroll.moveBy(-step, totalDisplayRows, detailEventRows);\n } else if (key.return) {\n // Resolve the selected display row to an EventRecord (skip headers)\n // Build the same display row list the component builds\n let rowIndex = 0;\n let targetEvent: EventRecord | undefined;\n const parentId = selectedExchange?.id ?? \"\";\n const groups = new Map<string, EventRecord[]>();\n groups.set(parentId, []);\n for (const ev of exchangeEvents) {\n try {\n const d = JSON.parse(ev.details) as Record<string, unknown>;\n const exId = String(d[\"exchangeId\"] ?? \"\");\n const gKey = !exId || exId === parentId ? parentId : exId;\n if (!groups.has(gKey)) groups.set(gKey, []);\n groups.get(gKey)!.push(ev);\n } catch {\n groups.get(parentId)!.push(ev);\n }\n }\n const hasChildren = groups.size > 1;\n for (const [, groupEvents] of groups) {\n if (hasChildren) rowIndex++; // header row\n for (const ev of groupEvents) {\n if (rowIndex === detailScroll.selectedIndex) {\n targetEvent = ev;\n }\n rowIndex++;\n }\n }\n if (targetEvent) {\n setSelectedEvent(targetEvent);\n setEventDetailScroll(0);\n setShowEventDetail(true);\n }\n } else if (input === \"e\" && selectedExchange) {\n const snapshot = db.getExchangeSnapshot(selectedExchange.id);\n setExchangeSnapshot(snapshot);\n setDeepViewScroll(0);\n setShowDeepView(true);\n } else if (key.escape || key.backspace || key.delete) {\n detailScroll.reset();\n setShowDetail(false);\n }\n return;\n }\n\n // Event detail from exchange detail: Esc goes back to exchange detail\n if (showDetail && showEventDetail) {\n const step = key.ctrl ? JUMP : 1;\n if (input === \"j\" || key.downArrow) {\n setEventDetailScroll((i) => i + step);\n } else if (input === \"k\" || key.upArrow) {\n setEventDetailScroll((i) => Math.max(i - step, 0));\n } else if (key.escape || key.backspace || key.delete) {\n setShowEventDetail(false);\n setEventDetailScroll(0);\n }\n return;\n }\n\n // Capabilities: nav focus (left panel)\n if (activeNav === \"capabilities\" && focus === \"nav\") {\n if (input === \"j\" || key.downArrow) {\n selectRoute(Math.min(routeScroll.selectedIndex + 1, routes.length - 1));\n } else if (input === \"k\" || key.upArrow) {\n selectRoute(Math.max(routeScroll.selectedIndex - 1, 0));\n } else if (key.return) {\n setFocus(\"center\");\n // Load all exchanges for browsing (auto-refresh uses PAGE_SIZE)\n const route = routes[routeScroll.selectedIndex];\n if (route) {\n setExchanges(db.getExchangesByRoute(route.id));\n }\n }\n return;\n }\n\n // Capabilities: center focus (exchange list)\n if (activeNav === \"capabilities\" && focus === \"center\") {\n const step = key.ctrl ? JUMP : 1;\n if (input === \"j\" || key.downArrow) {\n exchangeScroll.moveBy(step, exchanges.length, exchangeTableRows);\n } else if (input === \"k\" || key.upArrow) {\n exchangeScroll.moveBy(-step, exchanges.length, exchangeTableRows);\n } else if (key.return) {\n const ex = exchanges[exchangeScroll.selectedIndex];\n if (ex) {\n setSelectedExchange(ex);\n setExchangeEvents(db.getEventsByExchange(ex.id, ex.correlationId));\n detailScroll.reset();\n setShowEventDetail(false);\n setShowDetail(true);\n }\n } else if (key.escape || key.backspace || key.delete) {\n setFocus(\"nav\");\n exchangeScroll.reset();\n }\n return;\n }\n\n // Exchanges / Errors: overview (nav focus) or browsing (center focus)\n if (activeNav === \"exchanges\" || activeNav === \"errors\") {\n if (focus === \"nav\") {\n // Overview mode: Enter to freeze and browse\n if (key.return) {\n setFocus(\"center\");\n // Load full data set for browsing\n if (activeNav === \"exchanges\") {\n setExchanges(db.getAllExchanges());\n } else {\n setExchanges(db.getFailedExchanges());\n }\n }\n } else {\n // Browsing mode: navigate with pointer\n const step = key.ctrl ? JUMP : 1;\n if (input === \"j\" || key.downArrow) {\n exchangeScroll.moveBy(step, exchanges.length, exchangeTableRows);\n } else if (input === \"k\" || key.upArrow) {\n exchangeScroll.moveBy(-step, exchanges.length, exchangeTableRows);\n } else if (key.return) {\n const ex = exchanges[exchangeScroll.selectedIndex];\n if (ex) {\n setSelectedExchange(ex);\n setExchangeEvents(db.getEventsByExchange(ex.id, ex.correlationId));\n detailScroll.reset();\n setShowEventDetail(false);\n setShowDetail(true);\n }\n } else if (key.escape || key.backspace || key.delete) {\n setFocus(\"nav\");\n exchangeScroll.reset();\n }\n }\n return;\n }\n });\n\n // Determine which panel is active for border highlighting\n const navActive =\n activeNav === \"capabilities\" && focus === \"nav\" && !showDetail;\n const centerActive = !navActive;\n\n // Keymap items based on context\n const keymapItems: { key: string; action: string }[] = [];\n if (showDeepView) {\n keymapItems.push({ key: \"j/k\", action: \"Scroll\" });\n keymapItems.push({ key: \"Ctrl+j/k\", action: \"Jump 10\" });\n keymapItems.push({ key: \"Esc\", action: \"Back\" });\n } else if (focus === \"center\") {\n keymapItems.push({ key: \"j/k\", action: \"Navigate\" });\n keymapItems.push({ key: \"Ctrl+j/k\", action: \"Jump 10\" });\n }\n if (!showDeepView) {\n if (focus === \"nav\") {\n if (activeNav === \"capabilities\") {\n keymapItems.push({ key: \"j/k\", action: \"Navigate\" });\n keymapItems.push({ key: \"Enter\", action: \"Exchanges\" });\n } else {\n keymapItems.push({ key: \"Enter\", action: \"Browse\" });\n }\n } else if (!showDetail && !showEventDetail) {\n keymapItems.push({ key: \"Enter\", action: \"Detail\" });\n keymapItems.push({ key: \"Esc\", action: \"Back\" });\n } else if (showDetail && !showEventDetail) {\n keymapItems.push({ key: \"Enter\", action: \"Event detail\" });\n keymapItems.push({ key: \"e\", action: \"Snapshot\" });\n keymapItems.push({ key: \"Esc\", action: \"Back\" });\n } else {\n keymapItems.push({ key: \"Esc\", action: \"Back\" });\n }\n }\n keymapItems.push({ key: \"1..4\", action: \"Switch view\" });\n keymapItems.push({ key: \"q\", action: \"Quit\" });\n\n return (\n <Box flexDirection=\"column\" width={width} height={height}>\n {/* Title bar */}\n <Box borderStyle=\"round\" borderColor=\"cyan\" paddingX={1} width={width}>\n <Text bold color=\"cyan\">\n ROUTECRAFT TUI\n </Text>\n <Text> </Text>\n <Text dimColor>v0.4.0</Text>\n </Box>\n\n {/* 3-column body */}\n <Box flexDirection=\"row\" width={width} flexGrow={1}>\n {/* Left column: Navigation (top) + Keymap (bottom) */}\n <Box flexDirection=\"column\" width={leftWidth}>\n <Panel\n title=\"NAVIGATION\"\n color={navActive ? \"cyan\" : \"gray\"}\n width={leftWidth}\n flexGrow={1}\n >\n {NAV_SECTIONS.map((section, si) => (\n <Box key={section.label ?? si} flexDirection=\"column\">\n {si > 0 && <Text> </Text>}\n {section.label && (\n <Text dimColor bold>\n {section.label}\n </Text>\n )}\n {section.items.map((item) => (\n <Text key={item.key}>\n <Text\n bold={activeNav === item.key}\n {...(activeNav === item.key\n ? { color: \"cyan\" as const }\n : {})}\n >\n {activeNav === item.key ? \"> \" : \" \"}\n {item.label}\n </Text>\n <Text dimColor> ({item.shortcut})</Text>\n </Text>\n ))}\n </Box>\n ))}\n\n {activeNav === \"capabilities\" && (\n <CapabilityList\n routes={routes}\n selectedIndex={routeScroll.selectedIndex}\n listOffset={routeScroll.scrollOffset}\n visibleRows={navListHeight}\n width={leftWidth - 6}\n />\n )}\n </Panel>\n </Box>\n\n {/* Center */}\n {activeNav === \"capabilities\" && !showDetail && (\n <CenterExchangeList\n capabilityId={selectedRoute?.id ?? \"\"}\n route={selectedRoute}\n exchanges={exchanges}\n selectedIndex={\n focus === \"center\" ? exchangeScroll.selectedIndex : -1\n }\n scrollOffset={focus === \"center\" ? exchangeScroll.scrollOffset : 0}\n width={centerWidth}\n height={bodyHeight}\n color={centerActive ? \"cyan\" : \"gray\"}\n activity={selectedRouteActivity}\n />\n )}\n {activeNav === \"capabilities\" && showDeepView && selectedExchange && (\n <ExchangeDeepView\n exchange={selectedExchange}\n snapshot={exchangeSnapshot}\n width={centerWidth}\n height={bodyHeight}\n scrollOffset={deepViewScroll}\n color=\"cyan\"\n />\n )}\n {activeNav === \"capabilities\" &&\n showDetail &&\n selectedExchange &&\n !showEventDetail &&\n !showDeepView && (\n <CenterExchangeDetail\n exchange={selectedExchange}\n events={exchangeEvents}\n width={centerWidth}\n height={bodyHeight}\n selectedIndex={detailScroll.selectedIndex}\n scrollOffset={detailScroll.scrollOffset}\n color=\"cyan\"\n />\n )}\n {activeNav === \"capabilities\" &&\n showDetail &&\n showEventDetail &&\n !showDeepView &&\n selectedEvent && (\n <EventDetail\n event={selectedEvent}\n width={centerWidth}\n height={bodyHeight}\n scrollOffset={eventDetailScroll}\n color=\"cyan\"\n />\n )}\n {activeNav === \"exchanges\" && !showDetail && (\n <CenterExchangeList\n capabilityId=\"All Capabilities\"\n exchanges={exchanges}\n selectedIndex={\n focus === \"center\" ? exchangeScroll.selectedIndex : -1\n }\n scrollOffset={focus === \"center\" ? exchangeScroll.scrollOffset : 0}\n width={centerWidth}\n height={bodyHeight}\n color={focus === \"center\" ? \"cyan\" : \"gray\"}\n />\n )}\n {activeNav === \"exchanges\" && showDeepView && selectedExchange && (\n <ExchangeDeepView\n exchange={selectedExchange}\n snapshot={exchangeSnapshot}\n width={centerWidth}\n height={bodyHeight}\n scrollOffset={deepViewScroll}\n color=\"cyan\"\n />\n )}\n {activeNav === \"exchanges\" &&\n showDetail &&\n selectedExchange &&\n !showEventDetail &&\n !showDeepView && (\n <CenterExchangeDetail\n exchange={selectedExchange}\n events={exchangeEvents}\n width={centerWidth}\n height={bodyHeight}\n selectedIndex={detailScroll.selectedIndex}\n scrollOffset={detailScroll.scrollOffset}\n color=\"cyan\"\n />\n )}\n {activeNav === \"exchanges\" &&\n showDetail &&\n showEventDetail &&\n !showDeepView &&\n selectedEvent && (\n <EventDetail\n event={selectedEvent}\n width={centerWidth}\n height={bodyHeight}\n scrollOffset={eventDetailScroll}\n color=\"cyan\"\n />\n )}\n {activeNav === \"errors\" && !showDetail && (\n <CenterExchangeList\n capabilityId=\"Failed Exchanges\"\n exchanges={exchanges}\n selectedIndex={\n focus === \"center\" ? exchangeScroll.selectedIndex : -1\n }\n scrollOffset={focus === \"center\" ? exchangeScroll.scrollOffset : 0}\n width={centerWidth}\n height={bodyHeight}\n color={focus === \"center\" ? \"cyan\" : \"gray\"}\n />\n )}\n {activeNav === \"errors\" && showDeepView && selectedExchange && (\n <ExchangeDeepView\n exchange={selectedExchange}\n snapshot={exchangeSnapshot}\n width={centerWidth}\n height={bodyHeight}\n scrollOffset={deepViewScroll}\n color=\"cyan\"\n />\n )}\n {activeNav === \"errors\" &&\n showDetail &&\n selectedExchange &&\n !showEventDetail &&\n !showDeepView && (\n <CenterExchangeDetail\n exchange={selectedExchange}\n events={exchangeEvents}\n width={centerWidth}\n height={bodyHeight}\n selectedIndex={detailScroll.selectedIndex}\n scrollOffset={detailScroll.scrollOffset}\n color=\"cyan\"\n />\n )}\n {activeNav === \"errors\" &&\n showDetail &&\n showEventDetail &&\n !showDeepView &&\n selectedEvent && (\n <EventDetail\n event={selectedEvent}\n width={centerWidth}\n height={bodyHeight}\n scrollOffset={eventDetailScroll}\n color=\"cyan\"\n />\n )}\n {activeNav === \"events\" && !showEventDetail && (\n <EventsView\n events={events}\n selectedIndex={focus === \"center\" ? eventScroll.selectedIndex : -1}\n scrollOffset={focus === \"center\" ? eventScroll.scrollOffset : 0}\n width={centerWidth}\n height={bodyHeight}\n color={focus === \"center\" ? \"cyan\" : \"gray\"}\n />\n )}\n {activeNav === \"events\" && showEventDetail && selectedEvent && (\n <EventDetail\n event={selectedEvent}\n width={centerWidth}\n height={bodyHeight}\n scrollOffset={eventDetailScroll}\n color=\"cyan\"\n />\n )}\n\n {/* Right: Metrics + Keymap */}\n <Box flexDirection=\"column\" width={rightWidth}>\n <Panel title=\"METRICS\" width={rightWidth} flexGrow={1}>\n <DotGraph\n values={liveTraffic}\n columns={rightWidth - 4}\n steps={[\n { max: 0, color: \"gray\" },\n ...(Array.from({ length: 7 }, (_, i) => ({\n max: (i + 1) * 5,\n color: \"green\",\n })) as { max: number; color: string }[]),\n ...(Array.from({ length: 7 }, (_, i) => ({\n max: 35 + (i + 1) * 10,\n color: \"yellow\",\n })) as { max: number; color: string }[]),\n ...(Array.from({ length: 6 }, (_, i) => ({\n max: 105 + (i + 1) * 25,\n color: \"red\",\n })) as { max: number; color: string }[]),\n ]}\n label=\"Exchanges per 5s bucket\"\n />\n <Text> </Text>\n <Text bold dimColor>\n THROUGHPUT\n </Text>\n {(\n [\n [\"Exchanges\", fmtNum(metrics.totalExchanges), \"cyan\"],\n [\"Completed\", fmtNum(metrics.completedExchanges), \"green\"],\n [\n \"Errors\",\n fmtNum(metrics.failedExchanges),\n metrics.failedExchanges > 0 ? \"red\" : \"green\",\n ],\n [\n \"Dropped\",\n fmtNum(metrics.droppedExchanges),\n metrics.droppedExchanges > 0 ? \"yellow\" : \"green\",\n ],\n [\n \"Error Rate\",\n `${(metrics.errorRate * 100).toFixed(1)}%`,\n metrics.errorRate > 0.1 ? \"red\" : \"green\",\n ],\n [\"Capabilities\", fmtNum(metrics.totalRoutes), \"\"],\n ] as [string, string, string][]\n ).map(([label, value, color]) => (\n <Box key={label}>\n <Text>{label}:</Text>\n <Box flexGrow={1} justifyContent=\"flex-end\">\n <Text bold {...(color ? { color } : {})}>\n {value}\n </Text>\n </Box>\n </Box>\n ))}\n <Text> </Text>\n <Text bold dimColor>\n LATENCY (5m)\n </Text>\n {(\n [\n [\"Avg\", formatDuration(metrics.avgDurationMs), \"\"],\n [\"p90\", formatDuration(metrics.p90DurationMs), \"\"],\n [\"p95\", formatDuration(metrics.p95DurationMs), \"\"],\n [\"p99\", formatDuration(metrics.p99DurationMs), \"\"],\n ] as [string, string, string][]\n ).map(([label, value, color]) => (\n <Box key={label}>\n <Text>{label}:</Text>\n <Box flexGrow={1} justifyContent=\"flex-end\">\n <Text bold {...(color ? { color } : {})}>\n {value}\n </Text>\n </Box>\n </Box>\n ))}\n </Panel>\n\n <Panel title=\"KEYMAP\" width={rightWidth}>\n {keymapItems.map((item) => (\n <Box key={item.key}>\n <Text>{item.action}</Text>\n <Box flexGrow={1} justifyContent=\"flex-end\">\n <Text color=\"yellow\">[{item.key}]</Text>\n </Box>\n </Box>\n ))}\n </Panel>\n </Box>\n </Box>\n </Box>\n );\n}\n\nexport async function renderTui(dbPath: string): Promise<void> {\n let db: TelemetryDb;\n try {\n db = await TelemetryDb.open(dbPath);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`Failed to open telemetry database: ${msg}\\n`);\n process.stderr.write(`Path: ${dbPath}\\n`);\n process.stderr.write(\n \"Make sure you have a running Routecraft context with telemetry() enabled.\\n\",\n );\n process.exit(1);\n }\n\n const instance = render(<App db={db} />);\n await instance.waitUntilExit();\n}\n"]}
1
+ {"version":3,"sources":["../../src/tui/types.ts","../../src/tui/utils.ts","../../src/tui/hooks/use-scroll-list.ts","../../src/tui/components/panel.tsx","../../src/tui/components/dot-graph.tsx","../../src/tui/components/route-header.tsx","../../src/tui/components/table.tsx","../../src/tui/components/event-columns.tsx","../../src/tui/components/center-exchange-list.tsx","../../src/tui/components/json-format.tsx","../../src/tui/components/center-exchange-detail.tsx","../../src/tui/components/events-view.tsx","../../src/tui/components/event-detail.tsx","../../src/tui/components/exchange-deep-view.tsx","../../src/tui/components/capability-list.tsx","../../src/tui/app.tsx"],"names":["NAV_SECTIONS","ALL_NAV_ITEMS","s","truncate","str","maxLen","formatDuration","ms","statusColor","status","col","len","parseEventDetail","raw","d","exchange","duration","adapter","meta","m","keys","k","qualifier","route","err","formatDetailColumns","_eventName","parsed","fmtNum","n","adjustScrollOffset","selected","currentOffset","visibleRows","useScrollList","initialIndex","selectedIndex","setSelectedIndex","useState","scrollOffset","setScrollOffset","moveTo","useCallback","index","listLength","clamped","off","moveBy","delta","prev","next","reset","Panel","title","subtitle","color","width","flexGrow","paddingX","children","innerWidth","jsxs","Box","Fragment","Text","jsx","BRAILLE_DOTS","BRAILLE_BASE","DEFAULT_STEPS","DotGraph","values","columns","steps","label","dotHeight","data","heights","v","i","termRows","rows","tr","baseStep","segments","ci","h","bits","sr","stepLevel","char","last","RouteHeader","Table","rowKey","gap","emptyMessage","renderFullRow","gapStr","header","c","after","text","visible","remaining","row","vi","dataIndex","fullRow","resolved","cell","eventDetailColumns","accessor","cache","getColumns","ev","cols","_sel","w","selectorColumn","_row","exchangeColumns","CenterExchangeList","capabilityId","exchanges","height","activity","graphTermRows","headerRows","tableRows","ex","tokenizeLine","line","tokens","re","lastIndex","match","TOKEN_COLORS","formatJson","maxWidth","clampedMax","ColoredJsonLine","token","parseDetails","groupEventsByExchange","events","parentExchangeId","groups","childIndex","exId","key","detailColumns","indent","CenterExchangeDetail","hasExtra","eventRows","hasChildren","displayRows","group","eventsTitle","eventColumns","EventsView","EventDetail","event","routeId","exchangeId","headerHeight","jsonChrome","jsonWidth","jsonLines","_","buildSnapshotLines","snapshot","lines","ExchangeDeepView","dotColor","CapabilityList","routes","listOffset","offset","App","db","exit","useApp","stdout","useStdout","activeNav","setActiveNav","focus","setFocus","showDetail","setShowDetail","setRoutes","metrics","setMetrics","liveTraffic","setLiveTraffic","selectedRouteActivity","setSelectedRouteActivity","routeScroll","setExchanges","exchangeScroll","selectedExchange","setSelectedExchange","exchangeEvents","setExchangeEvents","setEvents","eventScroll","detailScroll","selectedEvent","setSelectedEvent","showEventDetail","setShowEventDetail","eventDetailScroll","setEventDetailScroll","showDeepView","setShowDeepView","deepViewScroll","setDeepViewScroll","exchangeSnapshot","setExchangeSnapshot","PAGE_SIZE","JUMP","leftWidth","rightWidth","centerWidth","bodyHeight","navListHeight","refresh","routeSummary","liveCols","routeCols","curRoute","useEffect","timer","selectRoute","switchNav","nav","selectedRoute","exchangeHeaderRows","exchangeTableRows","eventsTableRows","useInput","input","navByShortcut","step","detailEventRows","uniqueExchangeIds","groupCount","totalDisplayRows","rowIndex","targetEvent","parentId","gKey","groupEvents","navActive","centerActive","keymapItems","section","si","item","value","renderTui","dbPath","TelemetryDb","msg","render"],"mappings":"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","file":"app.js","sourcesContent":["export type NavItem = \"capabilities\" | \"exchanges\" | \"errors\" | \"events\";\n\nexport type NavSection = {\n label?: string;\n items: { key: NavItem; label: string; shortcut: string }[];\n};\n\nexport const NAV_SECTIONS: NavSection[] = [\n {\n items: [{ key: \"capabilities\", label: \"Capabilities\", shortcut: \"1\" }],\n },\n {\n items: [\n { key: \"exchanges\", label: \"Exchanges\", shortcut: \"2\" },\n { key: \"errors\", label: \"Errors\", shortcut: \"3\" },\n { key: \"events\", label: \"Events\", shortcut: \"4\" },\n ],\n },\n];\n\nexport const ALL_NAV_ITEMS = NAV_SECTIONS.flatMap((s) => s.items);\n\nexport interface RouteSummary {\n id: string;\n status: string;\n totalExchanges: number;\n completedExchanges: number;\n failedExchanges: number;\n droppedExchanges: number;\n avgDurationMs: number | null;\n}\n\nexport interface ExchangeRecord {\n id: string;\n routeId: string;\n contextId: string;\n correlationId: string;\n status: string;\n startedAt: string;\n completedAt: string | null;\n durationMs: number | null;\n error: string | null;\n}\n\nexport interface EventRecord {\n id?: number;\n timestamp: string;\n contextId: string;\n eventName: string;\n details: string;\n}\n\nexport interface Metrics {\n totalRoutes: number;\n totalExchanges: number;\n completedExchanges: number;\n failedExchanges: number;\n droppedExchanges: number;\n errorRate: number;\n avgDurationMs: number | null;\n p90DurationMs: number | null;\n p95DurationMs: number | null;\n p99DurationMs: number | null;\n}\n\nexport interface ExchangeSnapshot {\n headers: string;\n body: string | null;\n truncated: boolean;\n}\n\nexport interface RouteActivity {\n throughput: number[];\n recentErrors: number;\n}\n","export function truncate(str: string, maxLen: number): string {\n if (maxLen <= 0) return \"\";\n return str.length > maxLen ? str.slice(0, maxLen - 1) + \"\\u2026\" : str;\n}\n\nexport function formatDuration(ms: number | null): string {\n if (ms === null || ms === undefined) return \"-\";\n if (!Number.isFinite(ms) || ms < 0) return \"-\";\n if (ms === 0) return \"<1ms\";\n if (ms < 1000) return `${Math.round(ms)}ms`;\n return `${(ms / 1000).toFixed(1)}s`;\n}\n\nexport function statusColor(status: string): string {\n switch (status) {\n case \"completed\":\n case \"started\":\n return \"green\";\n case \"failed\":\n return \"red\";\n case \"stopped\":\n case \"dropped\":\n return \"yellow\";\n default:\n return \"white\";\n }\n}\n\nexport function col(str: string, len: number | undefined): string {\n if (len === undefined) return str;\n if (len <= 0) return \"\";\n if (str.length > len) return str.slice(0, len - 1) + \"\\u2026\";\n return str.padEnd(len);\n}\n\n// Fixed column widths for the Details column so fields line up across rows.\n// All event types share the same 4-column layout:\n// [col1: 10] [col2: 10] [exId: 12] [dur: 6] [extra]\n// Step events: operation (adapter) id… dur metadata\n// Exchange events: routeId (status) id… dur\nconst DET = {\n COL1: 10, // operation or routeId\n COL2: 10, // (adapter) or (err)/(reason)/(dropped)\n EX: 12, // \"789003e7 \"\n DUR: 6, // \"1ms \" \"10.0s \"\n} as const;\n\nexport interface DetailColumns {\n step: string;\n adapter: string;\n exchange: string;\n duration: string;\n meta: string;\n}\n\n/**\n * Parse a JSON event detail string into structured columns.\n * Shared normalizer used by both formatDetails and formatDetailColumns.\n */\nfunction parseEventDetail(raw: string): DetailColumns | null {\n try {\n const d = JSON.parse(raw) as Record<string, unknown>;\n\n const exchange =\n \"exchangeId\" in d ? `${String(d[\"exchangeId\"]).slice(0, 8)}` : \"\";\n const duration =\n \"duration\" in d ? formatDuration(d[\"duration\"] as number) : \"\";\n\n // Step/operation events\n if (\"operation\" in d && \"routeId\" in d) {\n const adapter =\n \"adapter\" in d\n ? `(${d[\"adapter\"]})`\n : \"adapterId\" in d\n ? `(${d[\"adapterId\"]})`\n : \"\";\n let meta = \"\";\n if (\n \"metadata\" in d &&\n typeof d[\"metadata\"] === \"object\" &&\n d[\"metadata\"] !== null\n ) {\n const m = d[\"metadata\"] as Record<string, unknown>;\n const keys = Object.keys(m).slice(0, 2);\n if (keys.length > 0) meta = keys.map((k) => `${k}=${m[k]}`).join(\" \");\n }\n return {\n step: String(d[\"operation\"]),\n adapter,\n exchange,\n duration,\n meta,\n };\n }\n\n // Exchange events\n if (\"routeId\" in d && \"exchangeId\" in d) {\n const qualifier =\n \"error\" in d\n ? \"(err)\"\n : \"reason\" in d\n ? `(${String(d[\"reason\"]).slice(0, 8)})`\n : \"\";\n return {\n step: String(d[\"routeId\"]),\n adapter: qualifier,\n exchange,\n duration,\n meta: \"\",\n };\n }\n\n // Route lifecycle events\n if (\"route\" in d && typeof d[\"route\"] === \"object\" && d[\"route\"] !== null) {\n const route = d[\"route\"] as {\n routeId?: string;\n definition?: { id?: string };\n };\n return {\n step: route.routeId ?? route.definition?.id ?? \"?\",\n adapter: \"\",\n exchange: \"\",\n duration: \"\",\n meta: \"\",\n };\n }\n\n // Plugin events\n if (\"pluginId\" in d) {\n return {\n step: `plugin=${d[\"pluginId\"]}`,\n adapter: \"\",\n exchange: \"\",\n duration: \"\",\n meta: \"\",\n };\n }\n\n // Error events\n if (\"error\" in d) {\n const err = d[\"error\"];\n const msg =\n typeof err === \"object\" && err !== null && \"message\" in err\n ? String((err as { message: string }).message)\n : String(err);\n return {\n step: msg,\n adapter: \"\",\n exchange: \"\",\n duration: \"\",\n meta: \"\",\n };\n }\n\n return null;\n } catch {\n return null;\n }\n}\n\nexport function formatDetails(_eventName: string, raw: string): string {\n const parsed = parseEventDetail(raw);\n if (!parsed) {\n return raw.length > 100 ? raw.slice(0, 97) + \"...\" : raw;\n }\n\n // Non-columnar events (plugin, route lifecycle, error) have no exchange/duration\n if (!parsed.exchange && !parsed.duration && !parsed.adapter) {\n return parsed.step;\n }\n\n return [\n col(parsed.step, DET.COL1),\n col(parsed.adapter, DET.COL2),\n col(parsed.exchange, DET.EX),\n col(parsed.duration, DET.DUR),\n parsed.meta,\n ]\n .join(\" \")\n .trimEnd();\n}\n\n/**\n * Structured version of formatDetails that returns individual columns\n * so the component can control alignment per-column.\n */\nexport function formatDetailColumns(\n _eventName: string,\n raw: string,\n): DetailColumns {\n const parsed = parseEventDetail(raw);\n if (!parsed) {\n return { step: raw, adapter: \"\", exchange: \"\", duration: \"\", meta: \"\" };\n }\n return parsed;\n}\n\n/**\n * Render a single-line sparkline from an array of values.\n * Uses Unicode block characters (▁▂▃▄▅▆▇█).\n * Empty/zero-only input returns spaces of the same length.\n */\nexport function sparkline(values: number[]): string {\n if (values.length === 0) return \"\";\n const blocks = [\n \" \",\n \"\\u2581\",\n \"\\u2582\",\n \"\\u2583\",\n \"\\u2584\",\n \"\\u2585\",\n \"\\u2586\",\n \"\\u2587\",\n \"\\u2588\",\n ];\n const max = Math.max(...values, 1);\n return values\n .map((v) => {\n const idx = Math.max(0, Math.min(8, Math.round((v / max) * 8)));\n return blocks[Number.isFinite(idx) ? idx : 0];\n })\n .join(\"\");\n}\n\nexport function fmtNum(n: number): string {\n return n.toLocaleString(\"en-US\");\n}\n\n/**\n * Adjust scroll offset so the selected item stays visible without centering.\n * The cursor moves freely within the visible window; the list only scrolls\n * when the cursor hits the top or bottom edge.\n *\n * @param selected - New selected index\n * @param currentOffset - Current scroll offset (tracked as state by the caller)\n * @param visibleRows - Number of rows visible in the list\n * @returns Updated scroll offset\n */\nexport function adjustScrollOffset(\n selected: number,\n currentOffset: number,\n visibleRows: number,\n): number {\n if (visibleRows <= 0) return currentOffset;\n if (selected < currentOffset) return selected;\n if (selected >= currentOffset + visibleRows)\n return selected - visibleRows + 1;\n return currentOffset;\n}\n","import { useState, useCallback } from \"react\";\nimport { adjustScrollOffset } from \"../utils.js\";\n\nexport interface ScrollListState {\n selectedIndex: number;\n scrollOffset: number;\n /** Move selection by delta (positive = down, negative = up). */\n moveBy: (delta: number, listLength: number, visibleRows: number) => void;\n /** Jump to an absolute index. */\n moveTo: (index: number, listLength: number, visibleRows: number) => void;\n /** Reset selection and scroll to the beginning. */\n reset: () => void;\n}\n\n/**\n * Manages a paired (selectedIndex, scrollOffset) state for scrollable lists.\n * Keeps the selected item visible without centering.\n *\n * `listLength` and `visibleRows` are passed at call time (not stored)\n * because they change every render (terminal resize, data load).\n */\nexport function useScrollList(initialIndex = 0): ScrollListState {\n const [selectedIndex, setSelectedIndex] = useState(initialIndex);\n const [scrollOffset, setScrollOffset] = useState(0);\n\n const moveTo = useCallback(\n (index: number, listLength: number, visibleRows: number) => {\n const clamped = Math.max(0, Math.min(index, listLength - 1));\n setSelectedIndex(clamped);\n setScrollOffset((off) => adjustScrollOffset(clamped, off, visibleRows));\n },\n [],\n );\n\n const moveBy = useCallback(\n (delta: number, listLength: number, visibleRows: number) => {\n setSelectedIndex((prev) => {\n const next = Math.max(0, Math.min(prev + delta, listLength - 1));\n setScrollOffset((off) => adjustScrollOffset(next, off, visibleRows));\n return next;\n });\n },\n [],\n );\n\n const reset = useCallback(() => {\n setSelectedIndex(0);\n setScrollOffset(0);\n }, []);\n\n return { selectedIndex, scrollOffset, moveBy, moveTo, reset };\n}\n","import type { ReactNode } from \"react\";\nimport { Box, Text } from \"ink\";\n\nexport function Panel({\n title,\n subtitle,\n color = \"gray\",\n width,\n flexGrow,\n paddingX = 1,\n children,\n}: {\n title?: string;\n subtitle?: ReactNode;\n color?: string;\n width?: number;\n flexGrow?: number;\n paddingX?: number;\n children: ReactNode;\n}) {\n // Border adds 2 chars per side; padding adds paddingX per side\n const innerWidth = width ? width - 2 - paddingX * 2 : 20;\n\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor={color}\n paddingX={paddingX}\n width={width}\n flexGrow={flexGrow}\n >\n {title && (\n <>\n <Text bold>\n {title}\n {subtitle && <> {subtitle}</>}\n </Text>\n <Text dimColor>{\"\\u2500\".repeat(Math.max(innerWidth, 1))}</Text>\n </>\n )}\n {children}\n </Box>\n );\n}\n","import type { JSX } from \"react\";\nimport { Text } from \"ink\";\n\n/**\n * Braille layout: 1 bucket per character, both columns.\n *\n * Left Right\n * 0x01 0x08 sub-row 0 (top)\n * 0x02 0x10 sub-row 1\n * 0x04 0x20 sub-row 2\n * 0x40 0x80 sub-row 3 (bottom)\n *\n * Each terminal character represents 1 time bucket.\n * Both columns mirror the same data for btop-style dot density.\n * Each terminal row packs up to 4 step levels vertically.\n */\nconst BRAILLE_DOTS = [\n 0x40 | 0x80,\n 0x04 | 0x20,\n 0x02 | 0x10,\n 0x01 | 0x08,\n] as const; // bottom to top\nconst BRAILLE_BASE = 0x2800;\n\nexport interface DotStep {\n max: number;\n color: string;\n}\n\n/** Default 5-step config: gray baseline, green low, yellow mid, red high. */\nexport const DEFAULT_STEPS: DotStep[] = [\n { max: 0, color: \"gray\" },\n { max: 10, color: \"green\" },\n { max: 20, color: \"green\" },\n { max: 30, color: \"yellow\" },\n { max: 40, color: \"yellow\" },\n { max: 50, color: \"red\" },\n];\n\n/**\n * Stacked dot graph using braille characters.\n *\n * 1 bucket = 1 terminal character. Both braille columns mirror the same\n * data for btop-style dot density. Each character can stack up to 4 step\n * levels vertically.\n *\n * - 0 exchanges: gray baseline dot (bottom)\n * - 1-9 exchanges: green dot (bottom)\n * - 10-19 exchanges: two green dots stacked\n * - etc., stacking upward with per-level colors\n */\nexport function DotGraph({\n values,\n columns,\n steps = DEFAULT_STEPS,\n label,\n}: {\n values: number[];\n columns: number;\n steps?: DotStep[];\n label?: string;\n}) {\n const dotHeight = steps.length - 1;\n\n // Right-align: newest on right, pad left with zeros\n const data =\n values.length >= columns\n ? values.slice(values.length - columns)\n : [\n ...(new Array(columns - values.length).fill(0) as number[]),\n ...values,\n ];\n\n // Map each value to a step index (0 = baseline, 1..dotHeight)\n const heights = data.map((v) => {\n if (v <= 0) return 0;\n for (let i = 1; i < steps.length; i++) {\n if (v < steps[i]!.max) return i;\n }\n return dotHeight;\n });\n\n const termRows = Math.ceil(dotHeight / 4);\n\n // Build terminal rows from top to bottom\n const rows: JSX.Element[] = [];\n for (let tr = termRows - 1; tr >= 0; tr--) {\n const baseStep = tr * 4;\n\n // For each bucket, compute the braille bits and color for this terminal row\n const segments: { text: string; color: string }[] = [];\n\n for (let ci = 0; ci < data.length; ci++) {\n const h = heights[ci]!;\n let bits = 0;\n let color = \"\";\n\n for (let sr = 0; sr < 4; sr++) {\n const stepLevel = baseStep + sr + 1;\n if (stepLevel > dotHeight) break;\n\n // Show dot if height reaches this level, or baseline dot for zero values\n const on = h >= stepLevel || (h === 0 && stepLevel === 1);\n if (on) {\n bits |= BRAILLE_DOTS[sr]!;\n // Color: gray for baseline (zero), step color for data\n color = h === 0 ? steps[0]!.color : steps[stepLevel]!.color;\n }\n }\n\n const char = String.fromCharCode(BRAILLE_BASE + bits);\n const last = segments[segments.length - 1];\n if (last && last.color === color) {\n last.text += char;\n } else {\n segments.push({ text: char, color });\n }\n }\n\n rows.push(\n <Text key={tr}>\n {segments.map((s, i) =>\n s.color ? (\n <Text key={i} color={s.color}>\n {s.text}\n </Text>\n ) : (\n <Text key={i}>{s.text}</Text>\n ),\n )}\n </Text>,\n );\n }\n\n return (\n <>\n {rows}\n {label && <Text dimColor>{label}</Text>}\n </>\n );\n}\n","import { Text } from \"ink\";\nimport type { RouteSummary } from \"../types.js\";\nimport { statusColor, fmtNum, formatDuration } from \"../utils.js\";\n\nexport function RouteHeader({ route }: { route: RouteSummary }) {\n return (\n <>\n <Text>\n Capability:{\" \"}\n <Text bold color=\"cyan\">\n {route.id}\n </Text>\n </Text>\n <Text>\n Status:{\" \"}\n <Text bold color={statusColor(route.status)}>\n {route.status}\n </Text>\n {\" \"}Exchanges: <Text bold>{fmtNum(route.totalExchanges)}</Text>\n {\" \"}Errors:{\" \"}\n <Text\n bold\n {...(route.failedExchanges > 0 ? { color: \"red\" as const } : {})}\n >\n {fmtNum(route.failedExchanges)}\n </Text>\n {\" \"}Dropped:{\" \"}\n <Text\n bold\n {...(route.droppedExchanges > 0 ? { color: \"yellow\" as const } : {})}\n >\n {fmtNum(route.droppedExchanges)}\n </Text>\n {\" \"}Avg: <Text bold>{formatDuration(route.avgDurationMs)}</Text>\n </Text>\n </>\n );\n}\n","import { Fragment, type ReactNode } from \"react\";\nimport { Box, Text } from \"ink\";\nimport { col } from \"../utils.js\";\n\nexport interface ColumnDef<T> {\n /** Header label */\n header: string;\n /** Fixed character width, or \"flex\" to fill remaining space */\n width: number | \"flex\";\n /** Text alignment. Default: \"left\" */\n align?: \"left\" | \"right\";\n /** Render cell content. `colWidth` is the resolved width for fixed columns, undefined for flex. */\n render: (\n row: T,\n selected: boolean,\n colWidth: number | undefined,\n ) => ReactNode;\n}\n\nexport interface TableProps<T> {\n columns: ColumnDef<T>[];\n data: T[];\n /** Unique key for each row */\n rowKey: (row: T, index: number) => string;\n /** Selected row index in full data array, or -1/undefined for no selection */\n selectedIndex?: number;\n /** First visible row (scroll offset) */\n scrollOffset: number;\n /** Number of visible rows */\n visibleRows: number;\n /** Gap between columns in characters. Default: 2 */\n gap?: number;\n /** Message when data is empty */\n emptyMessage?: string;\n /**\n * Optional full-row override for special rows (e.g., group headers).\n * Return undefined to use normal column rendering.\n */\n renderFullRow?: (row: T, index: number) => ReactNode | undefined;\n}\n\nexport function Table<T>({\n columns,\n data,\n rowKey,\n selectedIndex,\n scrollOffset,\n visibleRows,\n gap = 2,\n emptyMessage = \"No data\",\n renderFullRow,\n}: TableProps<T>) {\n const gapStr = \" \".repeat(gap);\n\n // Header\n const header = (\n <Box>\n {columns.map((c, ci) => {\n const isLast = ci === columns.length - 1;\n const after = isLast ? \"\" : gapStr;\n\n if (c.width === \"flex\") {\n return (\n <Fragment key={ci}>\n <Box flexGrow={1}>\n <Text bold dimColor>\n {c.header}\n </Text>\n </Box>\n {after && <Text>{after}</Text>}\n </Fragment>\n );\n }\n\n const text =\n c.align === \"right\"\n ? c.header.padStart(c.width)\n : col(c.header, c.width);\n\n return (\n <Fragment key={ci}>\n <Text bold dimColor>\n {text}\n </Text>\n {after && <Text>{after}</Text>}\n </Fragment>\n );\n })}\n </Box>\n );\n\n if (data.length === 0) {\n return (\n <>\n {header}\n <Text dimColor>{emptyMessage}</Text>\n </>\n );\n }\n\n const visible = data.slice(scrollOffset, scrollOffset + visibleRows);\n const remaining = data.length - scrollOffset - visibleRows;\n\n return (\n <>\n {header}\n {visible.map((row, vi) => {\n const dataIndex = scrollOffset + vi;\n const selected = dataIndex === selectedIndex;\n\n // Full-row override (e.g., group headers)\n const fullRow = renderFullRow?.(row, dataIndex);\n if (fullRow !== undefined) {\n return <Box key={rowKey(row, dataIndex)}>{fullRow}</Box>;\n }\n\n return (\n <Box key={rowKey(row, dataIndex)}>\n {columns.map((c, ci) => {\n const isLast = ci === columns.length - 1;\n const after = isLast ? \"\" : gapStr;\n const resolved = c.width === \"flex\" ? undefined : c.width;\n const cell = c.render(row, selected, resolved);\n\n if (c.width === \"flex\") {\n return (\n <Fragment key={ci}>\n <Box flexGrow={1}>\n <Text wrap=\"truncate\">{cell}</Text>\n </Box>\n {after && <Text>{after}</Text>}\n </Fragment>\n );\n }\n\n return (\n <Fragment key={ci}>\n {cell}\n {after && <Text>{after}</Text>}\n </Fragment>\n );\n })}\n </Box>\n );\n })}\n <Text dimColor>{remaining > 0 ? \"\\u2193 more\" : \" \"}</Text>\n </>\n );\n}\n","import { Text } from \"ink\";\nimport type { EventRecord } from \"../types.js\";\nimport { col, formatDetailColumns, type DetailColumns } from \"../utils.js\";\nimport type { ColumnDef } from \"./table.js\";\n\n/**\n * Build the 4 standard event detail columns (Step, Adapter, Exchange, Duration).\n *\n * The accessor extracts an EventRecord from whatever row type T the table uses.\n * Returns undefined when the row has no event data (e.g., group headers).\n *\n * JSON is parsed once per row and shared across all 4 columns via a WeakMap cache.\n */\nexport function eventDetailColumns<T>(\n accessor: (row: T) => EventRecord | undefined,\n): ColumnDef<T>[] {\n const cache = new WeakMap<EventRecord, DetailColumns>();\n\n function getColumns(row: T): DetailColumns | undefined {\n const ev = accessor(row);\n if (!ev) return undefined;\n let cols = cache.get(ev);\n if (!cols) {\n cols = formatDetailColumns(ev.eventName, ev.details);\n cache.set(ev, cols);\n }\n return cols;\n }\n\n return [\n {\n header: \"Step\",\n width: 10,\n render: (row, _sel, w) => {\n const cols = getColumns(row);\n if (!cols) return <Text>{col(\"\", w)}</Text>;\n return <Text>{col(cols.step, w)}</Text>;\n },\n },\n {\n header: \"Adapter\",\n width: 10,\n render: (row, _sel, w) => {\n const cols = getColumns(row);\n if (!cols) return <Text>{col(\"\", w)}</Text>;\n return <Text>{col(cols.adapter, w)}</Text>;\n },\n },\n {\n header: \"Exchange\",\n width: 12,\n render: (row, _sel, w) => {\n const cols = getColumns(row);\n if (!cols) return <Text>{col(\"\", w)}</Text>;\n return <Text>{col(cols.exchange, w)}</Text>;\n },\n },\n {\n header: \"Duration\",\n width: 8,\n align: \"right\" as const,\n render: (row) => {\n const cols = getColumns(row);\n if (!cols) return <Text>{\"\"}</Text>;\n return <Text>{cols.duration.padStart(8)}</Text>;\n },\n },\n ];\n}\n\n/**\n * Selector column that shows \"> \" for the selected row.\n */\nexport function selectorColumn<T>(): ColumnDef<T> {\n return {\n header: \"\",\n width: 2,\n render: (_row, selected) => (\n <Text {...(selected ? { color: \"cyan\" as const } : {})} bold={selected}>\n {selected ? \"> \" : \" \"}\n </Text>\n ),\n };\n}\n","import { Box, Text } from \"ink\";\nimport type { ExchangeRecord, RouteSummary, RouteActivity } from \"../types.js\";\nimport { statusColor, formatDuration, col } from \"../utils.js\";\nimport { PANEL_TABLE_CHROME } from \"../layout.js\";\nimport { Panel } from \"./panel.js\";\nimport { RouteHeader } from \"./route-header.js\";\nimport { DotGraph, DEFAULT_STEPS } from \"./dot-graph.js\";\nimport { Table, type ColumnDef } from \"./table.js\";\nimport { selectorColumn } from \"./event-columns.js\";\n\nconst exchangeColumns: ColumnDef<ExchangeRecord>[] = [\n selectorColumn<ExchangeRecord>(),\n {\n header: \"ID\",\n width: \"flex\",\n render: (row, selected) => (\n <Text {...(selected ? { color: \"cyan\" as const } : {})} bold={selected}>\n {row.id}\n </Text>\n ),\n },\n {\n header: \"Status\",\n width: 9,\n render: (row, _sel, w) => (\n <Text color={statusColor(row.status)}>{col(row.status, w)}</Text>\n ),\n },\n {\n header: \"Duration\",\n width: 8,\n align: \"right\",\n render: (row) => <Text>{formatDuration(row.durationMs).padStart(8)}</Text>,\n },\n {\n header: \"Time\",\n width: 8,\n render: (row, _sel, w) => (\n <Text dimColor>\n {col(row.startedAt.replace(\"T\", \" \").slice(11, 19), w)}\n </Text>\n ),\n },\n];\n\nexport function CenterExchangeList({\n capabilityId,\n route,\n exchanges,\n selectedIndex,\n scrollOffset,\n width,\n height,\n color = \"gray\",\n activity,\n}: {\n capabilityId: string;\n route?: RouteSummary;\n exchanges: ExchangeRecord[];\n selectedIndex: number;\n scrollOffset: number;\n width: number;\n height: number;\n color?: string;\n activity?: RouteActivity | undefined;\n}) {\n const graphTermRows = Math.ceil((DEFAULT_STEPS.length - 1) / 4);\n const headerRows = route ? 2 + graphTermRows + 2 : 0;\n const tableRows = Math.max(height - PANEL_TABLE_CHROME - headerRows, 3);\n\n const title = route ? \"EXCHANGES\" : `EXCHANGES: ${capabilityId}`;\n\n return (\n <Box flexDirection=\"column\" width={width} flexGrow={1}>\n {route && (\n <Panel width={width}>\n <RouteHeader route={route} />\n <Text> </Text>\n <DotGraph\n values={activity ? activity.throughput : []}\n columns={width - 4}\n label=\"Exchanges per 5s bucket\"\n />\n </Panel>\n )}\n <Panel title={title} width={width} flexGrow={1} color={color}>\n <Table\n columns={exchangeColumns}\n data={exchanges}\n rowKey={(ex) => ex.id + ex.contextId}\n selectedIndex={selectedIndex}\n scrollOffset={scrollOffset}\n visibleRows={tableRows}\n emptyMessage=\"No exchanges\"\n />\n </Panel>\n </Box>\n );\n}\n","import { Text } from \"ink\";\n\n/** Token types for JSON syntax coloring. */\nexport type TokenType =\n | \"key\"\n | \"string\"\n | \"number\"\n | \"boolean\"\n | \"null\"\n | \"brace\";\n\nexport interface JsonToken {\n text: string;\n type: TokenType;\n}\n\n/**\n * Tokenize a single line of pretty-printed JSON into colored segments.\n * Handles: keys, string values, numbers, booleans, null, and structural chars.\n */\nexport function tokenizeLine(line: string): JsonToken[] {\n const tokens: JsonToken[] = [];\n const re =\n /(\"(?:[^\"\\\\]|\\\\.)*\")\\s*:|(\"(?:[^\"\\\\]|\\\\.)*\")|(-?\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?)|(\\btrue\\b|\\bfalse\\b)|(\\bnull\\b)|([{}[\\],:])/g;\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = re.exec(line)) !== null) {\n // Plain text before this match (whitespace / indent)\n if (match.index > lastIndex) {\n tokens.push({ text: line.slice(lastIndex, match.index), type: \"brace\" });\n }\n\n if (match[1] !== undefined) {\n // Key (the colon is part of the regex but we split it out)\n tokens.push({ text: match[1], type: \"key\" });\n tokens.push({ text: \":\", type: \"brace\" });\n } else if (match[2] !== undefined) {\n tokens.push({ text: match[2], type: \"string\" });\n } else if (match[3] !== undefined) {\n tokens.push({ text: match[3], type: \"number\" });\n } else if (match[4] !== undefined) {\n tokens.push({ text: match[4], type: \"boolean\" });\n } else if (match[5] !== undefined) {\n tokens.push({ text: match[5], type: \"null\" });\n } else if (match[6] !== undefined) {\n tokens.push({ text: match[6], type: \"brace\" });\n }\n\n lastIndex = match.index + match[0].length;\n }\n\n // Trailing text\n if (lastIndex < line.length) {\n tokens.push({ text: line.slice(lastIndex), type: \"brace\" });\n }\n\n return tokens;\n}\n\nexport const TOKEN_COLORS: Record<TokenType, string> = {\n key: \"cyan\",\n string: \"green\",\n number: \"yellow\",\n boolean: \"yellow\",\n null: \"red\",\n brace: \"gray\",\n};\n\n/**\n * Parse a JSON string into pretty-printed lines, truncating long lines.\n */\nexport function formatJson(raw: string, maxWidth: number): string[] {\n try {\n const parsed = JSON.parse(raw) as unknown;\n const pretty = JSON.stringify(parsed, null, 2);\n return pretty.split(\"\\n\").map((line) => {\n const clampedMax = Math.max(1, maxWidth);\n return line.length > clampedMax\n ? line.slice(0, Math.max(0, clampedMax - 1)) + \"\\u2026\"\n : line;\n });\n } catch {\n const clampedMax = Math.max(1, maxWidth);\n return raw\n .split(\"\\n\")\n .map((line) =>\n line.length > clampedMax\n ? line.slice(0, Math.max(0, clampedMax - 1)) + \"\\u2026\"\n : line,\n );\n }\n}\n\n/**\n * Render a single line of JSON with syntax coloring.\n */\nexport function ColoredJsonLine({ line }: { line: string }) {\n const tokens = tokenizeLine(line);\n if (tokens.length === 0) return <Text>{line}</Text>;\n return (\n <Text>\n {tokens.map((token, i) => (\n <Text key={i} color={TOKEN_COLORS[token.type]}>\n {token.text}\n </Text>\n ))}\n </Text>\n );\n}\n\n/**\n * Safely parse a JSON details string.\n */\nexport function parseDetails(raw: string): Record<string, unknown> | null {\n try {\n const parsed: unknown = JSON.parse(raw);\n if (\n typeof parsed !== \"object\" ||\n parsed === null ||\n Array.isArray(parsed)\n ) {\n return null;\n }\n return parsed as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n","import { Box, Text } from \"ink\";\nimport type { ExchangeRecord, EventRecord } from \"../types.js\";\nimport { statusColor, formatDuration, col, truncate } from \"../utils.js\";\nimport { DETAIL_INFO_CHROME } from \"../layout.js\";\nimport { Panel } from \"./panel.js\";\nimport { Table, type ColumnDef } from \"./table.js\";\nimport { selectorColumn, eventDetailColumns } from \"./event-columns.js\";\nimport { parseDetails } from \"./json-format.js\";\n\ntype DisplayRow = {\n type: \"header\" | \"event\";\n text?: string;\n event?: EventRecord;\n indent: number;\n};\n\n/**\n * Group events by exchangeId to show parent/child flow.\n */\nfunction groupEventsByExchange(\n events: EventRecord[],\n parentExchangeId: string,\n): { exchangeId: string; label: string; events: EventRecord[] }[] {\n const groups = new Map<\n string,\n { exchangeId: string; label: string; events: EventRecord[] }\n >();\n let childIndex = 0;\n\n groups.set(parentExchangeId, {\n exchangeId: parentExchangeId,\n label: \"parent\",\n events: [],\n });\n\n for (const ev of events) {\n const d = parseDetails(ev.details);\n const exId = d ? String(d[\"exchangeId\"] ?? \"\") : \"\";\n const key = !exId || exId === parentExchangeId ? parentExchangeId : exId;\n\n if (!groups.has(key)) {\n childIndex++;\n groups.set(key, {\n exchangeId: key,\n label: `child ${childIndex}`,\n events: [],\n });\n }\n groups.get(key)!.events.push(ev);\n }\n\n return Array.from(groups.values());\n}\n\nconst detailColumns: ColumnDef<DisplayRow>[] = [\n selectorColumn<DisplayRow>(),\n {\n header: \"Time\",\n width: 8,\n render: (row, _sel, w) => {\n if (!row.event) return <Text>{col(\"\", w)}</Text>;\n const indent = \" \".repeat(row.indent);\n return (\n <Text dimColor>\n {indent}\n {row.event.timestamp.replace(\"T\", \" \").slice(11, 19)}\n </Text>\n );\n },\n },\n {\n header: \"Event\",\n width: \"flex\",\n render: (row) => {\n if (!row.event) return <Text />;\n return <Text color=\"cyan\">{row.event.eventName}</Text>;\n },\n },\n ...eventDetailColumns<DisplayRow>((row) => row.event),\n];\n\nexport function CenterExchangeDetail({\n exchange,\n events,\n width,\n height,\n scrollOffset,\n selectedIndex = -1,\n color = \"gray\",\n}: {\n exchange: ExchangeRecord;\n events: EventRecord[];\n width: number;\n height: number;\n scrollOffset: number;\n selectedIndex?: number;\n color?: string;\n}) {\n const hasExtra = exchange.error ? 2 : 0;\n const eventRows = Math.max(height - DETAIL_INFO_CHROME - hasExtra, 3);\n\n const groups = groupEventsByExchange(events, exchange.id);\n const hasChildren = groups.length > 1;\n\n const displayRows: DisplayRow[] = [];\n for (const group of groups) {\n if (hasChildren) {\n displayRows.push({\n type: \"header\",\n text: `${group.label} (${group.exchangeId.slice(0, 8)}) - ${group.events.length} events`,\n indent: 0,\n });\n }\n for (const ev of group.events) {\n displayRows.push({\n type: \"event\",\n event: ev,\n indent: hasChildren ? 2 : 0,\n });\n }\n }\n\n const eventsTitle = hasChildren\n ? `EXCHANGE FLOW (${groups.length} exchanges, ${events.length} events)`\n : `RELATED EVENTS (${events.length})`;\n\n return (\n <Box flexDirection=\"column\" width={width} flexGrow={1}>\n <Panel width={width}>\n <Text>\n Capability:{\" \"}\n <Text bold color=\"cyan\">\n {exchange.routeId}\n </Text>\n </Text>\n <Text>\n Exchange:{\" \"}\n <Text bold color=\"cyan\">\n {truncate(exchange.id, width - 14)}\n </Text>\n </Text>\n <Text>\n Status:{\" \"}\n <Text bold color={statusColor(exchange.status)}>\n {exchange.status}\n </Text>\n {exchange.durationMs !== null && (\n <Text>\n {\" \"}Duration:{\" \"}\n <Text bold>{formatDuration(exchange.durationMs)}</Text>\n </Text>\n )}\n {\" \"}Started: <Text bold>{exchange.startedAt}</Text>\n {exchange.completedAt && (\n <Text>\n {\" \"}Completed: <Text bold>{exchange.completedAt}</Text>\n </Text>\n )}\n </Text>\n {exchange.error && exchange.status === \"failed\" && (\n <>\n <Text> </Text>\n <Text color=\"red\">Error: {exchange.error}</Text>\n </>\n )}\n {exchange.error && exchange.status === \"dropped\" && (\n <>\n <Text> </Text>\n <Text color=\"yellow\">Reason: {exchange.error}</Text>\n </>\n )}\n </Panel>\n\n <Panel title={eventsTitle} width={width} flexGrow={1} color={color}>\n <Table\n columns={detailColumns}\n data={displayRows}\n rowKey={(row, i) =>\n row.type === \"header\"\n ? `h-${i}`\n : `${row.event?.id ?? row.event?.timestamp}-${i}`\n }\n selectedIndex={selectedIndex}\n scrollOffset={scrollOffset}\n visibleRows={eventRows}\n emptyMessage=\"No related events found\"\n renderFullRow={(row) =>\n row.type === \"header\" ? (\n <Text bold color=\"yellow\">\n {row.text}\n </Text>\n ) : undefined\n }\n />\n </Panel>\n </Box>\n );\n}\n","import { Text } from \"ink\";\nimport type { EventRecord } from \"../types.js\";\nimport { col } from \"../utils.js\";\nimport { PANEL_TABLE_CHROME } from \"../layout.js\";\nimport { Panel } from \"./panel.js\";\nimport { Table, type ColumnDef } from \"./table.js\";\nimport { selectorColumn, eventDetailColumns } from \"./event-columns.js\";\n\nconst eventColumns: ColumnDef<EventRecord>[] = [\n selectorColumn<EventRecord>(),\n {\n header: \"Time\",\n width: 19,\n render: (row, selected, w) => (\n <Text {...(selected ? { color: \"cyan\" as const } : {})} bold={selected}>\n {col(row.timestamp.replace(\"T\", \" \").slice(0, 19), w)}\n </Text>\n ),\n },\n {\n header: \"Event\",\n width: \"flex\",\n render: (row) => <Text color=\"cyan\">{row.eventName}</Text>,\n },\n ...eventDetailColumns<EventRecord>((row) => row),\n];\n\nexport function EventsView({\n events,\n selectedIndex,\n scrollOffset,\n width,\n height,\n color = \"gray\",\n}: {\n events: EventRecord[];\n selectedIndex: number;\n scrollOffset: number;\n width: number;\n height: number;\n color?: string;\n}) {\n const tableRows = Math.max(height - PANEL_TABLE_CHROME, 5);\n\n return (\n <Panel\n title=\"EVENTS\"\n subtitle={<Text dimColor>({events.length} total)</Text>}\n width={width}\n flexGrow={1}\n color={color}\n >\n <Table\n columns={eventColumns}\n data={events}\n rowKey={(ev, i) =>\n ev.id !== undefined ? String(ev.id) : `${ev.timestamp}-${i}`\n }\n selectedIndex={selectedIndex}\n scrollOffset={scrollOffset}\n visibleRows={tableRows}\n emptyMessage=\"No events recorded yet.\"\n />\n </Panel>\n );\n}\n","import { Box, Text } from \"ink\";\nimport type { EventRecord } from \"../types.js\";\nimport { Panel } from \"./panel.js\";\nimport { formatJson, ColoredJsonLine, parseDetails } from \"./json-format.js\";\n\nexport function EventDetail({\n event,\n width,\n height,\n scrollOffset,\n color = \"cyan\",\n}: {\n event: EventRecord;\n width: number;\n height: number;\n scrollOffset: number;\n color?: string;\n}) {\n const d = parseDetails(event.details);\n const routeId =\n d && typeof d[\"routeId\"] === \"string\" ? d[\"routeId\"] : undefined;\n const exchangeId =\n d && typeof d[\"exchangeId\"] === \"string\" ? d[\"exchangeId\"] : undefined;\n\n // Header lines: context (always) + capability + exchange + event + time\n const headerLines = 1 + (routeId ? 1 : 0) + (exchangeId ? 1 : 0) + 2;\n // Top panel: border (2) + content lines\n const headerHeight = 2 + headerLines;\n // Bottom panel: border (2) + title/separator (2) + footer (1) = 5\n const jsonChrome = 5;\n const jsonWidth = Math.max(width - 6, 20);\n const jsonLines = formatJson(event.details, jsonWidth);\n const visibleRows = Math.max(height - headerHeight - jsonChrome, 3);\n const visible = jsonLines.slice(scrollOffset, scrollOffset + visibleRows);\n\n return (\n <Box flexDirection=\"column\" width={width} flexGrow={1}>\n <Panel width={width}>\n <Text>\n Context:{\" \"}\n <Text bold color=\"cyan\">\n {event.contextId}\n </Text>\n </Text>\n {routeId && (\n <Text>\n Capability:{\" \"}\n <Text bold color=\"cyan\">\n {routeId}\n </Text>\n </Text>\n )}\n {exchangeId && (\n <Text>\n Exchange:{\" \"}\n <Text bold color=\"cyan\">\n {exchangeId}\n </Text>\n </Text>\n )}\n <Text>\n Event:{\" \"}\n <Text bold color=\"cyan\">\n {event.eventName}\n </Text>\n </Text>\n <Text>\n Time: <Text bold>{event.timestamp.replace(\"T\", \" \")}</Text>\n </Text>\n </Panel>\n\n <Panel\n title=\"DETAILS\"\n subtitle={\n <Text dimColor>\n ({scrollOffset + 1}-\n {Math.min(scrollOffset + visibleRows, jsonLines.length)}/\n {jsonLines.length} lines)\n </Text>\n }\n width={width}\n flexGrow={1}\n color={color}\n >\n {visible.map((line, i) => (\n <ColoredJsonLine key={scrollOffset + i} line={line} />\n ))}\n {visible.length < visibleRows &&\n Array.from({ length: visibleRows - visible.length }).map((_, i) => (\n <Text key={`pad-${i}`}> </Text>\n ))}\n </Panel>\n </Box>\n );\n}\n","import { Box, Text } from \"ink\";\nimport type { ExchangeRecord, ExchangeSnapshot } from \"../types.js\";\nimport { statusColor, formatDuration, truncate } from \"../utils.js\";\nimport { Panel } from \"./panel.js\";\nimport { formatJson, ColoredJsonLine } from \"./json-format.js\";\n\n/**\n * Build the scrollable lines for the deep view: headers + body sections.\n */\nfunction buildSnapshotLines(\n snapshot: ExchangeSnapshot,\n maxWidth: number,\n): string[] {\n const lines: string[] = [];\n\n lines.push(\"HEADERS\");\n lines.push(...formatJson(snapshot.headers, maxWidth));\n lines.push(\"\");\n lines.push(\"BODY\");\n if (snapshot.body !== null) {\n lines.push(...formatJson(snapshot.body, maxWidth));\n if (snapshot.truncated) {\n lines.push(\"\");\n lines.push(\"[Body truncated to configured limit]\");\n }\n } else {\n lines.push(\"[null]\");\n }\n\n return lines;\n}\n\nexport function ExchangeDeepView({\n exchange,\n snapshot,\n width,\n height,\n scrollOffset,\n color = \"cyan\",\n}: {\n exchange: ExchangeRecord;\n snapshot: ExchangeSnapshot | null;\n width: number;\n height: number;\n scrollOffset: number;\n color?: string;\n}) {\n // Header panel: border (2) + content (3 lines: capability + exchange + status)\n const headerHeight = 5;\n // JSON panel chrome: border (2) + title (1) + separator (1) + footer (1)\n const jsonChrome = 5;\n const jsonWidth = Math.max(width - 6, 20);\n const visibleRows = Math.max(height - headerHeight - jsonChrome, 3);\n\n const hasSnapshot = snapshot !== null;\n const jsonLines = hasSnapshot\n ? buildSnapshotLines(snapshot, jsonWidth)\n : [\n \"[Snapshots not captured]\",\n \"\",\n \"Enable with:\",\n \" telemetry({ sqlite: { captureSnapshots: true } })\",\n ];\n\n const visible = jsonLines.slice(scrollOffset, scrollOffset + visibleRows);\n\n return (\n <Box flexDirection=\"column\" width={width} flexGrow={1}>\n <Panel width={width}>\n <Text>\n Capability:{\" \"}\n <Text bold color=\"cyan\">\n {exchange.routeId}\n </Text>\n </Text>\n <Text>\n Exchange:{\" \"}\n <Text bold color=\"cyan\">\n {truncate(exchange.id, width - 14)}\n </Text>\n </Text>\n <Text>\n Status:{\" \"}\n <Text bold color={statusColor(exchange.status)}>\n {exchange.status}\n </Text>\n {exchange.durationMs !== null && (\n <Text>\n {\" \"}Duration:{\" \"}\n <Text bold>{formatDuration(exchange.durationMs)}</Text>\n </Text>\n )}\n </Text>\n </Panel>\n\n <Panel\n title=\"EXCHANGE SNAPSHOT\"\n subtitle={\n <Text dimColor>\n ({scrollOffset + 1}-\n {Math.min(scrollOffset + visibleRows, jsonLines.length)}/\n {jsonLines.length} lines)\n </Text>\n }\n width={width}\n flexGrow={1}\n color={color}\n >\n {visible.map((line, i) => {\n if (line === \"HEADERS\" || line === \"BODY\") {\n return (\n <Text key={scrollOffset + i} bold color=\"yellow\">\n {line}\n </Text>\n );\n }\n if (line.startsWith(\"[\")) {\n return (\n <Text key={scrollOffset + i} dimColor>\n {line}\n </Text>\n );\n }\n return <ColoredJsonLine key={scrollOffset + i} line={line} />;\n })}\n {visible.length < visibleRows &&\n Array.from({ length: visibleRows - visible.length }).map((_, i) => (\n <Text key={`pad-${i}`}> </Text>\n ))}\n </Panel>\n </Box>\n );\n}\n","import { Text } from \"ink\";\nimport type { RouteSummary } from \"../types.js\";\nimport { truncate } from \"../utils.js\";\n\nfunction dotColor(route: RouteSummary): string {\n if (route.failedExchanges > 0) return \"red\";\n if (route.totalExchanges > 0) return \"green\";\n return \"yellow\";\n}\n\nexport function CapabilityList({\n routes,\n selectedIndex,\n listOffset,\n visibleRows,\n width,\n}: {\n routes: RouteSummary[];\n selectedIndex: number;\n listOffset: number;\n visibleRows: number;\n width: number;\n}) {\n const offset = listOffset;\n\n return (\n <>\n <Text> </Text>\n <Text bold dimColor>\n {\"\\u2500\".repeat(width + 2)}\n </Text>\n {routes.length === 0 ? (\n <Text dimColor>No capabilities</Text>\n ) : (\n routes.slice(offset, offset + visibleRows).map((route, vi) => {\n const i = offset + vi;\n return (\n <Text key={route.id} wrap=\"truncate\">\n <Text\n {...(i === selectedIndex ? { color: \"cyan\" as const } : {})}\n bold={i === selectedIndex}\n >\n {i === selectedIndex ? \"> \" : \" \"}\n </Text>\n <Text color={dotColor(route)}>{\"\\u25CF \"}</Text>\n <Text\n {...(i === selectedIndex ? { color: \"cyan\" as const } : {})}\n bold={i === selectedIndex}\n >\n {truncate(route.id, width - 2)}\n </Text>\n </Text>\n );\n })\n )}\n {routes.length > visibleRows && (\n <Text dimColor>\n {selectedIndex + 1}/{routes.length}\n </Text>\n )}\n </>\n );\n}\n","import { useState, useEffect, useCallback } from \"react\";\nimport { render, Box, Text, useInput, useApp, useStdout } from \"ink\";\nimport { TelemetryDb } from \"./db.js\";\nimport type {\n NavItem,\n RouteSummary,\n ExchangeRecord,\n ExchangeSnapshot,\n EventRecord,\n Metrics,\n RouteActivity,\n} from \"./types.js\";\nimport { NAV_SECTIONS, ALL_NAV_ITEMS } from \"./types.js\";\nimport { fmtNum, formatDuration } from \"./utils.js\";\nimport { useScrollList } from \"./hooks/use-scroll-list.js\";\nimport { PANEL_TABLE_CHROME, DETAIL_INFO_CHROME, NAV_JUMP } from \"./layout.js\";\nimport { Panel } from \"./components/panel.js\";\nimport { DotGraph, DEFAULT_STEPS } from \"./components/dot-graph.js\";\nimport { CenterExchangeList } from \"./components/center-exchange-list.js\";\nimport { CenterExchangeDetail } from \"./components/center-exchange-detail.js\";\nimport { EventsView } from \"./components/events-view.js\";\nimport { EventDetail } from \"./components/event-detail.js\";\nimport { ExchangeDeepView } from \"./components/exchange-deep-view.js\";\nimport { CapabilityList } from \"./components/capability-list.js\";\n\n/**\n * Focus tracks which panel owns the cursor.\n * - \"nav\": left panel (route list / nav items)\n * - \"center\": center panel (exchange list, events, detail)\n */\ntype Focus = \"nav\" | \"center\";\n\nfunction App({ db }: { db: TelemetryDb }) {\n const { exit } = useApp();\n const { stdout } = useStdout();\n const width = stdout?.columns ?? 80;\n const height = stdout?.rows ?? 24;\n\n const [activeNav, setActiveNav] = useState<NavItem>(\"capabilities\");\n const [focus, setFocus] = useState<Focus>(\"nav\");\n const [showDetail, setShowDetail] = useState(false);\n\n const [routes, setRoutes] = useState<RouteSummary[]>([]);\n const [metrics, setMetrics] = useState<Metrics>({\n totalRoutes: 0,\n totalExchanges: 0,\n completedExchanges: 0,\n failedExchanges: 0,\n droppedExchanges: 0,\n errorRate: 0,\n avgDurationMs: null,\n p90DurationMs: null,\n p95DurationMs: null,\n p99DurationMs: null,\n });\n const [liveTraffic, setLiveTraffic] = useState<number[]>([]);\n const [selectedRouteActivity, setSelectedRouteActivity] = useState<\n RouteActivity | undefined\n >(undefined);\n const routeScroll = useScrollList();\n const [exchanges, setExchanges] = useState<ExchangeRecord[]>([]);\n const exchangeScroll = useScrollList();\n const [selectedExchange, setSelectedExchange] = useState<\n ExchangeRecord | undefined\n >(undefined);\n const [exchangeEvents, setExchangeEvents] = useState<EventRecord[]>([]);\n const [events, setEvents] = useState<EventRecord[]>([]);\n const eventScroll = useScrollList();\n const detailScroll = useScrollList();\n const [selectedEvent, setSelectedEvent] = useState<EventRecord | undefined>(\n undefined,\n );\n const [showEventDetail, setShowEventDetail] = useState(false);\n const [eventDetailScroll, setEventDetailScroll] = useState(0);\n const [showDeepView, setShowDeepView] = useState(false);\n const [deepViewScroll, setDeepViewScroll] = useState(0);\n const [exchangeSnapshot, setExchangeSnapshot] =\n useState<ExchangeSnapshot | null>(null);\n const PAGE_SIZE = 50;\n const JUMP = NAV_JUMP;\n\n // Layout dimensions (needed by both refresh and render)\n const leftWidth = Math.max(Math.min(Math.floor(width * 0.18), 26), 16);\n const rightWidth = Math.max(Math.min(Math.floor(width * 0.22), 30), 20);\n const centerWidth = Math.max(width - leftWidth - rightWidth, 30);\n const bodyHeight = Math.max(height - 5, 10);\n const navHeaderRows = 10;\n const navListHeight = Math.max(bodyHeight - navHeaderRows, 3);\n\n const refresh = useCallback(() => {\n try {\n // Always refresh: routes, metrics, graphs\n const routeSummary = db.getRouteSummary();\n setRoutes(routeSummary);\n setMetrics(db.getMetrics());\n const liveCols = rightWidth - 4;\n setLiveTraffic(db.getLiveTrafficBuckets(liveCols, 5));\n\n // Only load activity for the currently selected route\n const routeCols = centerWidth - 4;\n const curRoute = routeSummary[routeScroll.selectedIndex];\n if (curRoute) {\n setSelectedRouteActivity(\n db.getSingleRouteActivity(curRoute.id, routeCols, 5),\n );\n }\n\n // Skip list refresh when cursor is active (user is browsing)\n if (focus === \"center\") return;\n\n if (activeNav === \"capabilities\") {\n const route = routeSummary[routeScroll.selectedIndex];\n if (route) {\n setExchanges(db.getExchangesByRoute(route.id, PAGE_SIZE));\n }\n } else if (activeNav === \"exchanges\") {\n setExchanges(db.getAllExchanges(PAGE_SIZE));\n } else if (activeNav === \"errors\") {\n setExchanges(db.getFailedExchanges(PAGE_SIZE));\n } else if (activeNav === \"events\") {\n setEvents(db.getRecentEvents({ limit: 200 }));\n }\n } catch {\n // Database may be temporarily locked\n }\n }, [\n db,\n activeNav,\n routeScroll.selectedIndex,\n rightWidth,\n centerWidth,\n focus,\n ]);\n\n useEffect(() => {\n refresh();\n const timer = setInterval(refresh, 2000);\n return () => {\n clearInterval(timer);\n };\n }, [refresh]);\n\n const selectRoute = useCallback(\n (index: number) => {\n routeScroll.moveTo(index, routes.length, navListHeight);\n exchangeScroll.reset();\n const route = routes[index];\n if (route) {\n setExchanges(db.getExchangesByRoute(route.id, PAGE_SIZE));\n }\n },\n [db, routes, routeScroll, exchangeScroll, navListHeight],\n );\n\n const switchNav = useCallback(\n (nav: NavItem) => {\n setActiveNav(nav);\n setShowDetail(false);\n setShowEventDetail(false);\n setShowDeepView(false);\n setFocus(\"nav\");\n exchangeScroll.reset();\n if (nav === \"exchanges\") {\n setExchanges(db.getAllExchanges(PAGE_SIZE));\n } else if (nav === \"errors\") {\n setExchanges(db.getFailedExchanges(PAGE_SIZE));\n } else if (nav === \"events\") {\n eventScroll.reset();\n setEvents(db.getRecentEvents({ limit: 200 }));\n }\n },\n [db, exchangeScroll, eventScroll],\n );\n\n const selectedRoute = routes[routeScroll.selectedIndex];\n\n // Visible row counts mirror the view components\n // Must match CenterExchangeList: 2 (capability + stats) + graphTermRows + 2 (label + spacer)\n const graphTermRows = Math.ceil((DEFAULT_STEPS.length - 1) / 4);\n const exchangeHeaderRows = selectedRoute ? 2 + graphTermRows + 2 : 0;\n const exchangeTableRows = Math.max(\n bodyHeight - PANEL_TABLE_CHROME - exchangeHeaderRows,\n 3,\n );\n const eventsTableRows = Math.max(bodyHeight - PANEL_TABLE_CHROME, 5);\n\n useInput((input, key) => {\n if (input === \"q\") {\n db.close();\n exit();\n return;\n }\n\n // Number shortcuts to switch nav (always available)\n const navByShortcut = ALL_NAV_ITEMS.find((n) => n.shortcut === input);\n if (navByShortcut) {\n switchNav(navByShortcut.key);\n return;\n }\n\n // Events view: overview -> browse -> detail\n if (activeNav === \"events\") {\n if (showEventDetail) {\n // Detail view: scroll JSON, Esc to go back to list\n const step = key.ctrl ? JUMP : 1;\n if (input === \"j\" || key.downArrow) {\n setEventDetailScroll((i) => i + step);\n } else if (input === \"k\" || key.upArrow) {\n setEventDetailScroll((i) => Math.max(i - step, 0));\n } else if (key.escape || key.backspace || key.delete) {\n setShowEventDetail(false);\n setEventDetailScroll(0);\n }\n return;\n }\n if (focus === \"nav\") {\n if (key.return) {\n setFocus(\"center\");\n }\n } else {\n const step = key.ctrl ? JUMP : 1;\n if (input === \"j\" || key.downArrow) {\n eventScroll.moveBy(step, events.length, eventsTableRows);\n } else if (input === \"k\" || key.upArrow) {\n eventScroll.moveBy(-step, events.length, eventsTableRows);\n } else if (key.return) {\n const ev = events[eventScroll.selectedIndex];\n if (ev) {\n setSelectedEvent(ev);\n setEventDetailScroll(0);\n setShowEventDetail(true);\n }\n } else if (key.escape || key.backspace || key.delete) {\n setFocus(\"nav\");\n eventScroll.reset();\n }\n }\n return;\n }\n\n // Exchange deep view: scrollable JSON of headers + body\n if (showDeepView) {\n const step = key.ctrl ? JUMP : 1;\n if (input === \"j\" || key.downArrow) {\n setDeepViewScroll((i) => i + step);\n } else if (input === \"k\" || key.upArrow) {\n setDeepViewScroll((i) => Math.max(i - step, 0));\n } else if (key.escape || key.backspace || key.delete) {\n setShowDeepView(false);\n setDeepViewScroll(0);\n }\n return;\n }\n\n // Exchange detail (any nav)\n if (showDetail && !showEventDetail) {\n const hasExtra = selectedExchange?.error ? 2 : 0;\n const detailEventRows = Math.max(\n bodyHeight - DETAIL_INFO_CHROME - hasExtra,\n 3,\n );\n // Count group headers: when events span multiple exchanges, each group gets a header row\n const uniqueExchangeIds = new Set(\n exchangeEvents.map((ev) => {\n try {\n const d = JSON.parse(ev.details) as Record<string, unknown>;\n return String(d[\"exchangeId\"] ?? \"\");\n } catch {\n return \"\";\n }\n }),\n );\n const groupCount = Math.max(uniqueExchangeIds.size, 1);\n const headerRows = groupCount > 1 ? groupCount : 0;\n const totalDisplayRows = exchangeEvents.length + headerRows;\n const step = key.ctrl ? JUMP : 1;\n if (input === \"j\" || key.downArrow) {\n detailScroll.moveBy(step, totalDisplayRows, detailEventRows);\n } else if (input === \"k\" || key.upArrow) {\n detailScroll.moveBy(-step, totalDisplayRows, detailEventRows);\n } else if (key.return) {\n // Resolve the selected display row to an EventRecord (skip headers)\n // Build the same display row list the component builds\n let rowIndex = 0;\n let targetEvent: EventRecord | undefined;\n const parentId = selectedExchange?.id ?? \"\";\n const groups = new Map<string, EventRecord[]>();\n groups.set(parentId, []);\n for (const ev of exchangeEvents) {\n try {\n const d = JSON.parse(ev.details) as Record<string, unknown>;\n const exId = String(d[\"exchangeId\"] ?? \"\");\n const gKey = !exId || exId === parentId ? parentId : exId;\n if (!groups.has(gKey)) groups.set(gKey, []);\n groups.get(gKey)!.push(ev);\n } catch {\n groups.get(parentId)!.push(ev);\n }\n }\n const hasChildren = groups.size > 1;\n for (const [, groupEvents] of groups) {\n if (hasChildren) rowIndex++; // header row\n for (const ev of groupEvents) {\n if (rowIndex === detailScroll.selectedIndex) {\n targetEvent = ev;\n }\n rowIndex++;\n }\n }\n if (targetEvent) {\n setSelectedEvent(targetEvent);\n setEventDetailScroll(0);\n setShowEventDetail(true);\n }\n } else if (input === \"e\" && selectedExchange) {\n const snapshot = db.getExchangeSnapshot(selectedExchange.id);\n setExchangeSnapshot(snapshot);\n setDeepViewScroll(0);\n setShowDeepView(true);\n } else if (key.escape || key.backspace || key.delete) {\n detailScroll.reset();\n setShowDetail(false);\n }\n return;\n }\n\n // Event detail from exchange detail: Esc goes back to exchange detail\n if (showDetail && showEventDetail) {\n const step = key.ctrl ? JUMP : 1;\n if (input === \"j\" || key.downArrow) {\n setEventDetailScroll((i) => i + step);\n } else if (input === \"k\" || key.upArrow) {\n setEventDetailScroll((i) => Math.max(i - step, 0));\n } else if (key.escape || key.backspace || key.delete) {\n setShowEventDetail(false);\n setEventDetailScroll(0);\n }\n return;\n }\n\n // Capabilities: nav focus (left panel)\n if (activeNav === \"capabilities\" && focus === \"nav\") {\n if (input === \"j\" || key.downArrow) {\n selectRoute(Math.min(routeScroll.selectedIndex + 1, routes.length - 1));\n } else if (input === \"k\" || key.upArrow) {\n selectRoute(Math.max(routeScroll.selectedIndex - 1, 0));\n } else if (key.return) {\n setFocus(\"center\");\n // Load all exchanges for browsing (auto-refresh uses PAGE_SIZE)\n const route = routes[routeScroll.selectedIndex];\n if (route) {\n setExchanges(db.getExchangesByRoute(route.id));\n }\n }\n return;\n }\n\n // Capabilities: center focus (exchange list)\n if (activeNav === \"capabilities\" && focus === \"center\") {\n const step = key.ctrl ? JUMP : 1;\n if (input === \"j\" || key.downArrow) {\n exchangeScroll.moveBy(step, exchanges.length, exchangeTableRows);\n } else if (input === \"k\" || key.upArrow) {\n exchangeScroll.moveBy(-step, exchanges.length, exchangeTableRows);\n } else if (key.return) {\n const ex = exchanges[exchangeScroll.selectedIndex];\n if (ex) {\n setSelectedExchange(ex);\n setExchangeEvents(db.getEventsByExchange(ex.id, ex.correlationId));\n detailScroll.reset();\n setShowEventDetail(false);\n setShowDetail(true);\n }\n } else if (key.escape || key.backspace || key.delete) {\n setFocus(\"nav\");\n exchangeScroll.reset();\n }\n return;\n }\n\n // Exchanges / Errors: overview (nav focus) or browsing (center focus)\n if (activeNav === \"exchanges\" || activeNav === \"errors\") {\n if (focus === \"nav\") {\n // Overview mode: Enter to freeze and browse\n if (key.return) {\n setFocus(\"center\");\n // Load full data set for browsing\n if (activeNav === \"exchanges\") {\n setExchanges(db.getAllExchanges());\n } else {\n setExchanges(db.getFailedExchanges());\n }\n }\n } else {\n // Browsing mode: navigate with pointer\n const step = key.ctrl ? JUMP : 1;\n if (input === \"j\" || key.downArrow) {\n exchangeScroll.moveBy(step, exchanges.length, exchangeTableRows);\n } else if (input === \"k\" || key.upArrow) {\n exchangeScroll.moveBy(-step, exchanges.length, exchangeTableRows);\n } else if (key.return) {\n const ex = exchanges[exchangeScroll.selectedIndex];\n if (ex) {\n setSelectedExchange(ex);\n setExchangeEvents(db.getEventsByExchange(ex.id, ex.correlationId));\n detailScroll.reset();\n setShowEventDetail(false);\n setShowDetail(true);\n }\n } else if (key.escape || key.backspace || key.delete) {\n setFocus(\"nav\");\n exchangeScroll.reset();\n }\n }\n return;\n }\n });\n\n // Determine which panel is active for border highlighting\n const navActive =\n activeNav === \"capabilities\" && focus === \"nav\" && !showDetail;\n const centerActive = !navActive;\n\n // Keymap items based on context\n const keymapItems: { key: string; action: string }[] = [];\n if (showDeepView) {\n keymapItems.push({ key: \"j/k\", action: \"Scroll\" });\n keymapItems.push({ key: \"Ctrl+j/k\", action: \"Jump 10\" });\n keymapItems.push({ key: \"Esc\", action: \"Back\" });\n } else if (focus === \"center\") {\n keymapItems.push({ key: \"j/k\", action: \"Navigate\" });\n keymapItems.push({ key: \"Ctrl+j/k\", action: \"Jump 10\" });\n }\n if (!showDeepView) {\n if (focus === \"nav\") {\n if (activeNav === \"capabilities\") {\n keymapItems.push({ key: \"j/k\", action: \"Navigate\" });\n keymapItems.push({ key: \"Enter\", action: \"Exchanges\" });\n } else {\n keymapItems.push({ key: \"Enter\", action: \"Browse\" });\n }\n } else if (!showDetail && !showEventDetail) {\n keymapItems.push({ key: \"Enter\", action: \"Detail\" });\n keymapItems.push({ key: \"Esc\", action: \"Back\" });\n } else if (showDetail && !showEventDetail) {\n keymapItems.push({ key: \"Enter\", action: \"Event detail\" });\n keymapItems.push({ key: \"e\", action: \"Snapshot\" });\n keymapItems.push({ key: \"Esc\", action: \"Back\" });\n } else {\n keymapItems.push({ key: \"Esc\", action: \"Back\" });\n }\n }\n keymapItems.push({ key: \"1..4\", action: \"Switch view\" });\n keymapItems.push({ key: \"q\", action: \"Quit\" });\n\n return (\n <Box flexDirection=\"column\" width={width} height={height}>\n {/* Title bar */}\n <Box borderStyle=\"round\" borderColor=\"cyan\" paddingX={1} width={width}>\n <Text bold color=\"cyan\">\n ROUTECRAFT TUI\n </Text>\n <Text> </Text>\n <Text dimColor>v0.4.0</Text>\n </Box>\n\n {/* 3-column body */}\n <Box flexDirection=\"row\" width={width} flexGrow={1}>\n {/* Left column: Navigation (top) + Keymap (bottom) */}\n <Box flexDirection=\"column\" width={leftWidth}>\n <Panel\n title=\"NAVIGATION\"\n color={navActive ? \"cyan\" : \"gray\"}\n width={leftWidth}\n flexGrow={1}\n >\n {NAV_SECTIONS.map((section, si) => (\n <Box key={section.label ?? si} flexDirection=\"column\">\n {si > 0 && <Text> </Text>}\n {section.label && (\n <Text dimColor bold>\n {section.label}\n </Text>\n )}\n {section.items.map((item) => (\n <Text key={item.key}>\n <Text\n bold={activeNav === item.key}\n {...(activeNav === item.key\n ? { color: \"cyan\" as const }\n : {})}\n >\n {activeNav === item.key ? \"> \" : \" \"}\n {item.label}\n </Text>\n <Text dimColor> ({item.shortcut})</Text>\n </Text>\n ))}\n </Box>\n ))}\n\n {activeNav === \"capabilities\" && (\n <CapabilityList\n routes={routes}\n selectedIndex={routeScroll.selectedIndex}\n listOffset={routeScroll.scrollOffset}\n visibleRows={navListHeight}\n width={leftWidth - 6}\n />\n )}\n </Panel>\n </Box>\n\n {/* Center */}\n {activeNav === \"capabilities\" && !showDetail && (\n <CenterExchangeList\n capabilityId={selectedRoute?.id ?? \"\"}\n route={selectedRoute}\n exchanges={exchanges}\n selectedIndex={\n focus === \"center\" ? exchangeScroll.selectedIndex : -1\n }\n scrollOffset={focus === \"center\" ? exchangeScroll.scrollOffset : 0}\n width={centerWidth}\n height={bodyHeight}\n color={centerActive ? \"cyan\" : \"gray\"}\n activity={selectedRouteActivity}\n />\n )}\n {activeNav === \"capabilities\" && showDeepView && selectedExchange && (\n <ExchangeDeepView\n exchange={selectedExchange}\n snapshot={exchangeSnapshot}\n width={centerWidth}\n height={bodyHeight}\n scrollOffset={deepViewScroll}\n color=\"cyan\"\n />\n )}\n {activeNav === \"capabilities\" &&\n showDetail &&\n selectedExchange &&\n !showEventDetail &&\n !showDeepView && (\n <CenterExchangeDetail\n exchange={selectedExchange}\n events={exchangeEvents}\n width={centerWidth}\n height={bodyHeight}\n selectedIndex={detailScroll.selectedIndex}\n scrollOffset={detailScroll.scrollOffset}\n color=\"cyan\"\n />\n )}\n {activeNav === \"capabilities\" &&\n showDetail &&\n showEventDetail &&\n !showDeepView &&\n selectedEvent && (\n <EventDetail\n event={selectedEvent}\n width={centerWidth}\n height={bodyHeight}\n scrollOffset={eventDetailScroll}\n color=\"cyan\"\n />\n )}\n {activeNav === \"exchanges\" && !showDetail && (\n <CenterExchangeList\n capabilityId=\"All Capabilities\"\n exchanges={exchanges}\n selectedIndex={\n focus === \"center\" ? exchangeScroll.selectedIndex : -1\n }\n scrollOffset={focus === \"center\" ? exchangeScroll.scrollOffset : 0}\n width={centerWidth}\n height={bodyHeight}\n color={focus === \"center\" ? \"cyan\" : \"gray\"}\n />\n )}\n {activeNav === \"exchanges\" && showDeepView && selectedExchange && (\n <ExchangeDeepView\n exchange={selectedExchange}\n snapshot={exchangeSnapshot}\n width={centerWidth}\n height={bodyHeight}\n scrollOffset={deepViewScroll}\n color=\"cyan\"\n />\n )}\n {activeNav === \"exchanges\" &&\n showDetail &&\n selectedExchange &&\n !showEventDetail &&\n !showDeepView && (\n <CenterExchangeDetail\n exchange={selectedExchange}\n events={exchangeEvents}\n width={centerWidth}\n height={bodyHeight}\n selectedIndex={detailScroll.selectedIndex}\n scrollOffset={detailScroll.scrollOffset}\n color=\"cyan\"\n />\n )}\n {activeNav === \"exchanges\" &&\n showDetail &&\n showEventDetail &&\n !showDeepView &&\n selectedEvent && (\n <EventDetail\n event={selectedEvent}\n width={centerWidth}\n height={bodyHeight}\n scrollOffset={eventDetailScroll}\n color=\"cyan\"\n />\n )}\n {activeNav === \"errors\" && !showDetail && (\n <CenterExchangeList\n capabilityId=\"Failed Exchanges\"\n exchanges={exchanges}\n selectedIndex={\n focus === \"center\" ? exchangeScroll.selectedIndex : -1\n }\n scrollOffset={focus === \"center\" ? exchangeScroll.scrollOffset : 0}\n width={centerWidth}\n height={bodyHeight}\n color={focus === \"center\" ? \"cyan\" : \"gray\"}\n />\n )}\n {activeNav === \"errors\" && showDeepView && selectedExchange && (\n <ExchangeDeepView\n exchange={selectedExchange}\n snapshot={exchangeSnapshot}\n width={centerWidth}\n height={bodyHeight}\n scrollOffset={deepViewScroll}\n color=\"cyan\"\n />\n )}\n {activeNav === \"errors\" &&\n showDetail &&\n selectedExchange &&\n !showEventDetail &&\n !showDeepView && (\n <CenterExchangeDetail\n exchange={selectedExchange}\n events={exchangeEvents}\n width={centerWidth}\n height={bodyHeight}\n selectedIndex={detailScroll.selectedIndex}\n scrollOffset={detailScroll.scrollOffset}\n color=\"cyan\"\n />\n )}\n {activeNav === \"errors\" &&\n showDetail &&\n showEventDetail &&\n !showDeepView &&\n selectedEvent && (\n <EventDetail\n event={selectedEvent}\n width={centerWidth}\n height={bodyHeight}\n scrollOffset={eventDetailScroll}\n color=\"cyan\"\n />\n )}\n {activeNav === \"events\" && !showEventDetail && (\n <EventsView\n events={events}\n selectedIndex={focus === \"center\" ? eventScroll.selectedIndex : -1}\n scrollOffset={focus === \"center\" ? eventScroll.scrollOffset : 0}\n width={centerWidth}\n height={bodyHeight}\n color={focus === \"center\" ? \"cyan\" : \"gray\"}\n />\n )}\n {activeNav === \"events\" && showEventDetail && selectedEvent && (\n <EventDetail\n event={selectedEvent}\n width={centerWidth}\n height={bodyHeight}\n scrollOffset={eventDetailScroll}\n color=\"cyan\"\n />\n )}\n\n {/* Right: Metrics + Keymap */}\n <Box flexDirection=\"column\" width={rightWidth}>\n <Panel title=\"METRICS\" width={rightWidth} flexGrow={1}>\n <DotGraph\n values={liveTraffic}\n columns={rightWidth - 4}\n steps={[\n { max: 0, color: \"gray\" },\n ...(Array.from({ length: 7 }, (_, i) => ({\n max: (i + 1) * 5,\n color: \"green\",\n })) as { max: number; color: string }[]),\n ...(Array.from({ length: 7 }, (_, i) => ({\n max: 35 + (i + 1) * 10,\n color: \"yellow\",\n })) as { max: number; color: string }[]),\n ...(Array.from({ length: 6 }, (_, i) => ({\n max: 105 + (i + 1) * 25,\n color: \"red\",\n })) as { max: number; color: string }[]),\n ]}\n label=\"Exchanges per 5s bucket\"\n />\n <Text> </Text>\n <Text bold dimColor>\n THROUGHPUT\n </Text>\n {(\n [\n [\"Exchanges\", fmtNum(metrics.totalExchanges), \"cyan\"],\n [\"Completed\", fmtNum(metrics.completedExchanges), \"green\"],\n [\n \"Errors\",\n fmtNum(metrics.failedExchanges),\n metrics.failedExchanges > 0 ? \"red\" : \"green\",\n ],\n [\n \"Dropped\",\n fmtNum(metrics.droppedExchanges),\n metrics.droppedExchanges > 0 ? \"yellow\" : \"green\",\n ],\n [\n \"Error Rate\",\n `${(metrics.errorRate * 100).toFixed(1)}%`,\n metrics.errorRate > 0.1 ? \"red\" : \"green\",\n ],\n [\"Capabilities\", fmtNum(metrics.totalRoutes), \"\"],\n ] as [string, string, string][]\n ).map(([label, value, color]) => (\n <Box key={label}>\n <Text>{label}:</Text>\n <Box flexGrow={1} justifyContent=\"flex-end\">\n <Text bold {...(color ? { color } : {})}>\n {value}\n </Text>\n </Box>\n </Box>\n ))}\n <Text> </Text>\n <Text bold dimColor>\n LATENCY (5m)\n </Text>\n {(\n [\n [\"Avg\", formatDuration(metrics.avgDurationMs), \"\"],\n [\"p90\", formatDuration(metrics.p90DurationMs), \"\"],\n [\"p95\", formatDuration(metrics.p95DurationMs), \"\"],\n [\"p99\", formatDuration(metrics.p99DurationMs), \"\"],\n ] as [string, string, string][]\n ).map(([label, value, color]) => (\n <Box key={label}>\n <Text>{label}:</Text>\n <Box flexGrow={1} justifyContent=\"flex-end\">\n <Text bold {...(color ? { color } : {})}>\n {value}\n </Text>\n </Box>\n </Box>\n ))}\n </Panel>\n\n <Panel title=\"KEYMAP\" width={rightWidth}>\n {keymapItems.map((item) => (\n <Box key={item.key}>\n <Text>{item.action}</Text>\n <Box flexGrow={1} justifyContent=\"flex-end\">\n <Text color=\"yellow\">[{item.key}]</Text>\n </Box>\n </Box>\n ))}\n </Panel>\n </Box>\n </Box>\n </Box>\n );\n}\n\nexport async function renderTui(dbPath: string): Promise<void> {\n let db: TelemetryDb;\n try {\n db = await TelemetryDb.open(dbPath);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`Failed to open telemetry database: ${msg}\\n`);\n process.stderr.write(`Path: ${dbPath}\\n`);\n process.stderr.write(\n \"Make sure you have a running Routecraft context with telemetry() enabled.\\n\",\n );\n process.exit(1);\n }\n\n const instance = render(<App db={db} />);\n await instance.waitUntilExit();\n}\n"]}
package/dist/tui/db.d.ts CHANGED
@@ -39,8 +39,8 @@ declare class TelemetryDb {
39
39
  /**
40
40
  * Open a telemetry database in read-only mode.
41
41
  *
42
- * Uses dynamic `import()` so the module resolves correctly under pnpm's
43
- * strict hoisting (CJS `require()` from an ESM bundle does not follow
42
+ * Uses dynamic `import()` so the module resolves correctly under Bun's
43
+ * isolated linker (CJS `require()` from an ESM bundle does not follow
44
44
  * the package's own dependency graph).
45
45
  */
46
46
  static open(dbPath: string): Promise<TelemetryDb>;
package/dist/tui/db.js CHANGED
@@ -1,2 +1,2 @@
1
- export{a as TelemetryDb}from'../chunk-DPJWCR2V.js';//# sourceMappingURL=db.js.map
1
+ export{a as TelemetryDb}from'../chunk-3CIF67XJ.js';//# sourceMappingURL=db.js.map
2
2
  //# sourceMappingURL=db.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@routecraft/cli",
3
- "version": "0.5.0-canary.44",
3
+ "version": "0.5.0-canary.45",
4
4
  "description": "CLI for running Routecraft routes",
5
5
  "private": false,
6
6
  "type": "module",
@@ -19,11 +19,11 @@
19
19
  "build": "tsup src/index.ts src/tui/app.tsx src/tui/db.ts --format esm --dts --external react --external ink --external better-sqlite3",
20
20
  "test": "vitest",
21
21
  "test:coverage": "vitest --coverage",
22
- "prepublishOnly": "pnpm run build"
22
+ "prepublishOnly": "bun run build"
23
23
  },
24
24
  "dependencies": {
25
25
  "@opentelemetry/sdk-trace-base": "^2.7.1",
26
- "@routecraft/routecraft": "^0.5.0-canary.44",
26
+ "@routecraft/routecraft": "^0.5.0-canary.45",
27
27
  "agent-browser": "^0.17.1",
28
28
  "better-sqlite3": "^11.10.0",
29
29
  "cheerio": "^1.2.0",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/tui/db.ts"],"names":["escapeLike","TelemetryDb","_TelemetryDb","db","key","sql","s","dbPath","Database","mod","wdb","c","routeId","limit","exchangeId","correlationId","searchId","info","col","options","sinceId","params","escaped","row","durations","r","percentile","bucketCount","bucketWidthSec","nowSec","snapped","windowStart","rows","result","tRows","eRow","throughput","sorted","p","idx","lo","hi"],"mappings":"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","file":"chunk-DPJWCR2V.js","sourcesContent":["import type { TelemetryEvent } from \"@routecraft/routecraft\";\n\n/** Exchange row shape from the telemetry SQLite database. */\ninterface TelemetryExchange {\n id: string;\n routeId: string;\n contextId: string;\n correlationId: string;\n status: string;\n startedAt: string;\n completedAt: string | null;\n durationMs: number | null;\n error: string | null;\n}\n\n/**\n * Minimal type for the better-sqlite3 database to avoid hard dependency.\n */\ninterface Database {\n prepare(sql: string): Statement;\n close(): void;\n pragma(pragma: string): unknown;\n}\n\ninterface Statement {\n all(...params: unknown[]): unknown[];\n get(...params: unknown[]): unknown;\n run(...params: unknown[]): unknown;\n}\n\ntype DatabaseConstructor = new (\n filename: string,\n options?: { readonly?: boolean },\n) => Database;\n\n/**\n * Read-only accessor for the telemetry SQLite database.\n * Used by the TUI to query historical data without affecting the running engine.\n *\n * Use the static `open()` factory instead of the constructor directly.\n */\n/** Escape LIKE metacharacters so they match literally. */\nfunction escapeLike(s: string): string {\n return s.replace(/[%_\\\\]/g, \"\\\\$&\");\n}\n\nexport class TelemetryDb {\n private db: Database;\n private stmtCache = new Map<string, Statement>();\n\n private constructor(db: Database) {\n this.db = db;\n }\n\n /** Prepare and cache a statement by key. Avoids re-parsing on every call. */\n private stmt(key: string, sql: string): Statement {\n let s = this.stmtCache.get(key);\n if (!s) {\n s = this.db.prepare(sql);\n this.stmtCache.set(key, s);\n }\n return s;\n }\n\n /**\n * Open a telemetry database in read-only mode.\n *\n * Uses dynamic `import()` so the module resolves correctly under pnpm's\n * strict hoisting (CJS `require()` from an ESM bundle does not follow\n * the package's own dependency graph).\n */\n static async open(dbPath: string): Promise<TelemetryDb> {\n let Database: DatabaseConstructor;\n try {\n const mod = await import(\"better-sqlite3\");\n Database = (\n \"default\" in mod && typeof mod.default === \"function\"\n ? mod.default\n : mod\n ) as DatabaseConstructor;\n } catch {\n throw new Error(\n \"better-sqlite3 is not installed. Install it with: pnpm add better-sqlite3\",\n );\n }\n\n const db = new Database(dbPath, { readonly: true });\n try {\n db.pragma(\"journal_mode = WAL\");\n } catch {\n // Read-only connection cannot change journal mode; safe to ignore\n }\n\n // Ensure indexes exist for TUI query performance.\n // If the DB was created before indexes were added, create them now\n // using a separate writable connection.\n {\n const wdb = new Database(dbPath);\n try {\n wdb\n .prepare(\n \"CREATE INDEX IF NOT EXISTS idx_exchanges_started_at ON exchanges(started_at)\",\n )\n .run();\n wdb\n .prepare(\n \"CREATE INDEX IF NOT EXISTS idx_exchanges_route_started ON exchanges(route_id, started_at)\",\n )\n .run();\n wdb\n .prepare(\n \"CREATE INDEX IF NOT EXISTS idx_exchanges_correlation_id ON exchanges(correlation_id)\",\n )\n .run();\n // Add exchange_id/correlation_id columns to events table if missing\n const cols = wdb.prepare(\"PRAGMA table_info(events)\").all() as Array<{\n name: string;\n }>;\n if (!cols.some((c) => c.name === \"exchange_id\")) {\n wdb.prepare(\"ALTER TABLE events ADD COLUMN exchange_id TEXT\").run();\n wdb\n .prepare(\"ALTER TABLE events ADD COLUMN correlation_id TEXT\")\n .run();\n }\n wdb\n .prepare(\n \"CREATE INDEX IF NOT EXISTS idx_events_exchange_id ON events(exchange_id)\",\n )\n .run();\n wdb\n .prepare(\n \"CREATE INDEX IF NOT EXISTS idx_events_correlation_id ON events(correlation_id)\",\n )\n .run();\n // Ensure exchange_snapshots table exists for older databases\n wdb\n .prepare(\n `CREATE TABLE IF NOT EXISTS exchange_snapshots (\n exchange_id TEXT NOT NULL,\n context_id TEXT NOT NULL,\n headers TEXT NOT NULL,\n body TEXT,\n truncated INTEGER NOT NULL DEFAULT 0,\n captured_at TEXT NOT NULL DEFAULT (datetime('now')),\n PRIMARY KEY (exchange_id, context_id)\n )`,\n )\n .run();\n } catch {\n // Best-effort; the writer will create them on next restart\n } finally {\n wdb.close();\n }\n }\n\n return new TelemetryDb(db);\n }\n\n /**\n * Get a summary of all routes with aggregated metrics.\n * Routes are grouped by ID across all context runs so that restarting\n * the same application does not create duplicate rows.\n */\n getRouteSummary(): Array<{\n id: string;\n status: string;\n totalExchanges: number;\n completedExchanges: number;\n failedExchanges: number;\n droppedExchanges: number;\n avgDurationMs: number | null;\n }> {\n const s = this.stmt(\n \"routeSummary\",\n `WITH unique_routes AS (\n SELECT\n id,\n MAX(registered_at) AS registered_at,\n (SELECT r2.status FROM routes r2\n WHERE r2.id = r.id\n ORDER BY r2.registered_at DESC LIMIT 1) AS status\n FROM routes r\n GROUP BY id\n ),\n exchange_counts AS (\n SELECT\n route_id,\n COUNT(*) AS total,\n SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) AS completed,\n SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) AS failed,\n SUM(CASE WHEN status = 'dropped' THEN 1 ELSE 0 END) AS dropped\n FROM exchanges\n GROUP BY route_id\n ),\n recent_avg AS (\n SELECT route_id, AVG(duration_ms) AS avgDur\n FROM exchanges\n WHERE started_at >= datetime('now', '-5 minutes')\n GROUP BY route_id\n )\n SELECT\n ur.id,\n ur.status,\n COALESCE(ec.total, 0) AS totalExchanges,\n COALESCE(ec.completed, 0) AS completedExchanges,\n COALESCE(ec.failed, 0) AS failedExchanges,\n COALESCE(ec.dropped, 0) AS droppedExchanges,\n ra.avgDur AS avgDurationMs\n FROM unique_routes ur\n LEFT JOIN exchange_counts ec ON ur.id = ec.route_id\n LEFT JOIN recent_avg ra ON ur.id = ra.route_id\n ORDER BY ur.registered_at DESC`,\n );\n return s.all() as Array<{\n id: string;\n status: string;\n totalExchanges: number;\n completedExchanges: number;\n failedExchanges: number;\n droppedExchanges: number;\n avgDurationMs: number | null;\n }>;\n }\n\n /**\n * Get exchanges for a specific route, ordered by most recent first.\n */\n getExchangesByRoute(routeId: string, limit = -1): TelemetryExchange[] {\n const s = this.stmt(\n \"exchangesByRoute\",\n `SELECT\n id,\n route_id AS routeId,\n context_id AS contextId,\n correlation_id AS correlationId,\n status,\n started_at AS startedAt,\n completed_at AS completedAt,\n duration_ms AS durationMs,\n error\n FROM exchanges\n WHERE route_id = ?\n ORDER BY started_at DESC\n LIMIT ?`,\n );\n return s.all(routeId, limit) as TelemetryExchange[];\n }\n\n /**\n * Get all exchanges across all routes, ordered by most recent first.\n */\n getAllExchanges(limit = -1): TelemetryExchange[] {\n const s = this.stmt(\n \"allExchanges\",\n `SELECT\n id,\n route_id AS routeId,\n context_id AS contextId,\n correlation_id AS correlationId,\n status,\n started_at AS startedAt,\n completed_at AS completedAt,\n duration_ms AS durationMs,\n error\n FROM exchanges\n ORDER BY started_at DESC\n LIMIT ?`,\n );\n return s.all(limit) as TelemetryExchange[];\n }\n\n /**\n * Get all failed exchanges across all routes, ordered by most recent first.\n * Shows every failed exchange including child exchanges from split/multicast,\n * without deduplication by correlation chain.\n */\n getFailedExchanges(limit = -1): TelemetryExchange[] {\n const s = this.stmt(\n \"failedExchanges\",\n `SELECT\n id,\n route_id AS routeId,\n context_id AS contextId,\n correlation_id AS correlationId,\n status,\n started_at AS startedAt,\n completed_at AS completedAt,\n duration_ms AS durationMs,\n error\n FROM exchanges\n WHERE status = 'failed'\n ORDER BY started_at DESC\n LIMIT ?`,\n );\n return s.all(limit) as TelemetryExchange[];\n }\n\n /**\n * Get events for an exchange and all related exchanges sharing the\n * same correlation ID. Uses indexed exchange_id/correlation_id columns\n * with a fallback to details LIKE for databases created before the\n * column migration.\n */\n getEventsByExchange(\n exchangeId: string,\n correlationId: string,\n ): TelemetryEvent[] {\n const searchId = correlationId || exchangeId;\n\n // Try indexed column lookup first (fast path)\n const hasColumns = this.hasEventIdColumns();\n if (hasColumns) {\n const s = this.stmt(\n \"eventsByExchangeIndexed\",\n `SELECT\n id,\n timestamp,\n context_id AS contextId,\n event_name AS eventName,\n details\n FROM events\n WHERE exchange_id = ? OR correlation_id = ?\n ORDER BY id ASC`,\n );\n return s.all(searchId, searchId) as TelemetryEvent[];\n }\n\n // Fallback: full-text LIKE scan for older databases\n const s = this.stmt(\n \"eventsByExchangeFallback\",\n `SELECT\n id,\n timestamp,\n context_id AS contextId,\n event_name AS eventName,\n details\n FROM events\n WHERE details LIKE '%' || ? || '%' ESCAPE '\\\\'\n ORDER BY id ASC`,\n );\n return s.all(escapeLike(searchId)) as TelemetryEvent[];\n }\n\n /** Check whether the events table has the exchange_id column. */\n private hasEventIdColumns(): boolean {\n if (this._hasEventIdColumns !== undefined) return this._hasEventIdColumns;\n try {\n const info = this.db.prepare(\"PRAGMA table_info(events)\").all() as Array<{\n name: string;\n }>;\n this._hasEventIdColumns = info.some((col) => col.name === \"exchange_id\");\n } catch {\n this._hasEventIdColumns = false;\n }\n return this._hasEventIdColumns;\n }\n private _hasEventIdColumns: boolean | undefined;\n\n /**\n * Get recent events, optionally filtered by event name pattern or route ID.\n */\n getRecentEvents(options?: {\n limit?: number;\n eventNameFilter?: string;\n routeIdFilter?: string;\n sinceId?: number;\n }): TelemetryEvent[] {\n const limit = options?.limit ?? 100;\n const sinceId = options?.sinceId ?? 0;\n\n let sql = `\n SELECT\n id,\n timestamp,\n context_id AS contextId,\n event_name AS eventName,\n details\n FROM events\n WHERE id > ?\n `;\n const params: unknown[] = [sinceId];\n\n if (options?.eventNameFilter) {\n sql += \" AND event_name LIKE ? ESCAPE '\\\\'\";\n params.push(`%${escapeLike(options.eventNameFilter)}%`);\n }\n\n if (options?.routeIdFilter) {\n sql +=\n \" AND (event_name LIKE ? ESCAPE '\\\\' OR details LIKE ? ESCAPE '\\\\')\";\n const escaped = escapeLike(options.routeIdFilter);\n params.push(`%${escaped}%`, `%${escaped}%`);\n }\n\n sql += \" ORDER BY id DESC LIMIT ?\";\n params.push(limit);\n\n const stmt = this.db.prepare(sql);\n return stmt.all(...params) as TelemetryEvent[];\n }\n\n /**\n * Get aggregated metrics for the dashboard, including duration percentiles.\n * Percentiles are computed over exchanges from the last 5 minutes.\n */\n getMetrics(): import(\"./types.js\").Metrics {\n const s = this.stmt(\n \"metrics\",\n `SELECT\n (SELECT COUNT(DISTINCT id) FROM routes) AS totalRoutes,\n (SELECT COUNT(*) FROM exchanges) AS totalExchanges,\n (SELECT COUNT(*) FROM exchanges WHERE status = 'completed') AS completedExchanges,\n (SELECT COUNT(*) FROM exchanges WHERE status = 'failed') AS failedExchanges,\n (SELECT COUNT(*) FROM exchanges WHERE status = 'dropped') AS droppedExchanges,\n (SELECT AVG(duration_ms) FROM exchanges\n WHERE started_at >= datetime('now', '-5 minutes')) AS avgDurationMs`,\n );\n const row = s.get() as {\n totalRoutes: number;\n totalExchanges: number;\n completedExchanges: number;\n failedExchanges: number;\n droppedExchanges: number;\n avgDurationMs: number | null;\n };\n\n // Compute percentiles from recent exchanges with non-null durations\n const pctStmt = this.stmt(\n \"percentiles\",\n `SELECT duration_ms\n FROM exchanges\n WHERE duration_ms IS NOT NULL\n AND started_at >= datetime('now', '-5 minutes')\n ORDER BY duration_ms ASC`,\n );\n const durations = (pctStmt.all() as Array<{ duration_ms: number }>).map(\n (r) => r.duration_ms,\n );\n\n return {\n ...row,\n errorRate:\n row.totalExchanges > 0 ? row.failedExchanges / row.totalExchanges : 0,\n p90DurationMs: percentile(durations, 0.9),\n p95DurationMs: percentile(durations, 0.95),\n p99DurationMs: percentile(durations, 0.99),\n };\n }\n\n /**\n * Get exchange counts for a rolling window using fine-grained buckets.\n * Default: 60 buckets of 5 seconds = 5-minute rolling window.\n * Returns values oldest-first for sparkline rendering.\n */\n getLiveTrafficBuckets(bucketCount = 60, bucketWidthSec = 5): number[] {\n const nowSec = Math.floor(Date.now() / 1000);\n const snapped = Math.floor(nowSec / bucketWidthSec) * bucketWidthSec;\n const windowStart = snapped - (bucketCount - 1) * bucketWidthSec;\n\n const s = this.stmt(\n \"liveTraffic\",\n `SELECT\n CAST((CAST(strftime('%s', started_at) AS INTEGER) - ?) / ? AS INTEGER) AS bucket,\n COUNT(*) AS cnt\n FROM exchanges\n WHERE CAST(strftime('%s', started_at) AS INTEGER) >= ?\n AND CAST(strftime('%s', started_at) AS INTEGER) <= ?\n GROUP BY bucket`,\n );\n const rows = s.all(\n windowStart,\n bucketWidthSec,\n windowStart,\n snapped + bucketWidthSec,\n ) as Array<{ bucket: number; cnt: number }>;\n\n const result = new Array(bucketCount).fill(0) as number[];\n for (const row of rows) {\n if (row.bucket >= 0 && row.bucket < bucketCount) {\n result[row.bucket] += row.cnt;\n }\n }\n return result;\n }\n\n /**\n * Get activity data for a single route: throughput sparkline + recent error count.\n */\n getSingleRouteActivity(\n routeId: string,\n bucketCount = 12,\n bucketWidthSec = 5,\n ): { throughput: number[]; recentErrors: number } {\n const nowSec = Math.floor(Date.now() / 1000);\n const snapped = Math.floor(nowSec / bucketWidthSec) * bucketWidthSec;\n const windowStart = snapped - (bucketCount - 1) * bucketWidthSec;\n\n const tStmt = this.stmt(\n \"singleRouteActivity\",\n `SELECT\n CAST((CAST(strftime('%s', started_at) AS INTEGER) - ?) / ? AS INTEGER) AS bucket,\n COUNT(*) AS cnt\n FROM exchanges\n WHERE route_id = ?\n AND CAST(strftime('%s', started_at) AS INTEGER) >= ?\n GROUP BY bucket`,\n );\n const tRows = tStmt.all(\n windowStart,\n bucketWidthSec,\n routeId,\n windowStart,\n ) as Array<{ bucket: number; cnt: number }>;\n\n const eStmt = this.stmt(\n \"singleRouteErrors\",\n `SELECT COUNT(*) AS cnt\n FROM exchanges\n WHERE route_id = ?\n AND status = 'failed'\n AND CAST(strftime('%s', started_at) AS INTEGER) >= ?`,\n );\n const eRow = eStmt.get(routeId, windowStart) as { cnt: number } | undefined;\n\n const throughput = new Array(bucketCount).fill(0) as number[];\n for (const row of tRows) {\n if (row.bucket >= 0 && row.bucket < bucketCount) {\n throughput[row.bucket] = row.cnt;\n }\n }\n\n return { throughput, recentErrors: eRow?.cnt ?? 0 };\n }\n\n /**\n * Get the maximum event ID (for tailing/polling).\n */\n getMaxEventId(): number {\n const stmt = this.db.prepare(\n \"SELECT COALESCE(MAX(id), 0) AS maxId FROM events\",\n );\n const row = stmt.get() as { maxId: number };\n return row.maxId;\n }\n\n /**\n * Get the exchange snapshot (headers and body) for a given exchange.\n * Returns null if no snapshot was captured.\n */\n getExchangeSnapshot(\n exchangeId: string,\n ): import(\"./types.js\").ExchangeSnapshot | null {\n try {\n const s = this.stmt(\n \"exchangeSnapshot\",\n `SELECT headers, body, truncated\n FROM exchange_snapshots\n WHERE exchange_id = ?\n LIMIT 1`,\n );\n const row = s.get(exchangeId) as\n | { headers: string; body: string | null; truncated: number }\n | undefined;\n if (!row) return null;\n return {\n headers: row.headers,\n body: row.body,\n truncated: row.truncated !== 0,\n };\n } catch {\n // Table may not exist in very old databases\n return null;\n }\n }\n\n /**\n * Close the database connection.\n */\n close(): void {\n this.db.close();\n }\n}\n\n/**\n * Compute a percentile from a sorted array of numbers using linear interpolation.\n * Returns null if the array is empty.\n */\nfunction percentile(sorted: number[], p: number): number | null {\n if (sorted.length === 0) return null;\n const idx = p * (sorted.length - 1);\n const lo = Math.floor(idx);\n const hi = Math.ceil(idx);\n if (lo === hi) return sorted[lo]!;\n return sorted[lo]! + (sorted[hi]! - sorted[lo]!) * (idx - lo);\n}\n"]}