@fml-inc/panopticon 0.1.2 → 0.1.3

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.
Files changed (45) hide show
  1. package/dist/{chunk-NE7VBLQD.js → chunk-2PMFNSGA.js} +3 -3
  2. package/dist/{chunk-OROLSIWZ.js → chunk-5FRYHDPJ.js} +5 -5
  3. package/dist/{chunk-OW52TNVA.js → chunk-5IPC5XXZ.js} +4 -4
  4. package/dist/{chunk-3ZT3V7FP.js → chunk-75IXBXBO.js} +5 -5
  5. package/dist/{chunk-WXPT6KG7.js → chunk-7NBZ4NMJ.js} +2 -2
  6. package/dist/{chunk-FMAHQRIU.js → chunk-OSWBZKK5.js} +2 -2
  7. package/dist/{chunk-MEVW27U4.js → chunk-P5KAIE3O.js} +2 -2
  8. package/dist/{chunk-J3HVD4VI.js → chunk-RNICEX6N.js} +2 -2
  9. package/dist/{chunk-HRNZUHTA.js → chunk-RRHBTXHB.js} +3 -3
  10. package/dist/{chunk-V3XR2TAN.js → chunk-UD6H6EP6.js} +2 -2
  11. package/dist/{chunk-GPTBERQD.js → chunk-UDUBRSIG.js} +2 -2
  12. package/dist/{chunk-N7NCNJZU.js → chunk-UEEWG7FD.js} +4 -4
  13. package/dist/{chunk-SKZHAYNF.js → chunk-UM5U6FPH.js} +14 -7
  14. package/dist/chunk-UM5U6FPH.js.map +1 -0
  15. package/dist/{chunk-BKGQJ76N.js → chunk-YV2AN73J.js} +11 -11
  16. package/dist/cli.js +4 -4
  17. package/dist/db.js +1 -1
  18. package/dist/doctor.js +4 -4
  19. package/dist/hooks/handler.js +4 -4
  20. package/dist/index.js +14 -14
  21. package/dist/otlp/server.js +5 -5
  22. package/dist/pricing.js +2 -2
  23. package/dist/proxy/server.js +4 -4
  24. package/dist/prune.js +2 -2
  25. package/dist/query.js +2 -2
  26. package/dist/{reparse-VHUSGCPN.js → reparse-TFYD67WP.js} +5 -5
  27. package/dist/server.js +12 -12
  28. package/dist/setup.js +3 -3
  29. package/dist/sync/index.js +4 -4
  30. package/package.json +1 -1
  31. package/dist/chunk-SKZHAYNF.js.map +0 -1
  32. /package/dist/{chunk-NE7VBLQD.js.map → chunk-2PMFNSGA.js.map} +0 -0
  33. /package/dist/{chunk-OROLSIWZ.js.map → chunk-5FRYHDPJ.js.map} +0 -0
  34. /package/dist/{chunk-OW52TNVA.js.map → chunk-5IPC5XXZ.js.map} +0 -0
  35. /package/dist/{chunk-3ZT3V7FP.js.map → chunk-75IXBXBO.js.map} +0 -0
  36. /package/dist/{chunk-WXPT6KG7.js.map → chunk-7NBZ4NMJ.js.map} +0 -0
  37. /package/dist/{chunk-FMAHQRIU.js.map → chunk-OSWBZKK5.js.map} +0 -0
  38. /package/dist/{chunk-MEVW27U4.js.map → chunk-P5KAIE3O.js.map} +0 -0
  39. /package/dist/{chunk-J3HVD4VI.js.map → chunk-RNICEX6N.js.map} +0 -0
  40. /package/dist/{chunk-HRNZUHTA.js.map → chunk-RRHBTXHB.js.map} +0 -0
  41. /package/dist/{chunk-V3XR2TAN.js.map → chunk-UD6H6EP6.js.map} +0 -0
  42. /package/dist/{chunk-GPTBERQD.js.map → chunk-UDUBRSIG.js.map} +0 -0
  43. /package/dist/{chunk-N7NCNJZU.js.map → chunk-UEEWG7FD.js.map} +0 -0
  44. /package/dist/{chunk-BKGQJ76N.js.map → chunk-YV2AN73J.js.map} +0 -0
  45. /package/dist/{reparse-VHUSGCPN.js.map → reparse-TFYD67WP.js.map} +0 -0
@@ -9,7 +9,7 @@ import {
9
9
  upsertSession,
10
10
  upsertSessionCwd,
11
11
  upsertSessionRepository
12
- } from "./chunk-V3XR2TAN.js";
12
+ } from "./chunk-UD6H6EP6.js";
13
13
  import {
14
14
  resolveRepoFromCwd
15
15
  } from "./chunk-YVRWVDIA.js";
@@ -21,7 +21,7 @@ import {
21
21
  import {
22
22
  addBreadcrumb,
23
23
  captureException
24
- } from "./chunk-J3HVD4VI.js";
24
+ } from "./chunk-RNICEX6N.js";
25
25
  import {
26
26
  log
27
27
  } from "./chunk-7Q3BJMLG.js";
@@ -1697,4 +1697,4 @@ export {
1697
1697
  handleProxyRequest,
1698
1698
  createProxyServer
1699
1699
  };
1700
- //# sourceMappingURL=chunk-NE7VBLQD.js.map
1700
+ //# sourceMappingURL=chunk-2PMFNSGA.js.map
@@ -3,7 +3,7 @@ import {
3
3
  upsertSession,
4
4
  upsertSessionCwd,
5
5
  upsertSessionRepository
6
- } from "./chunk-V3XR2TAN.js";
6
+ } from "./chunk-UD6H6EP6.js";
7
7
  import {
8
8
  resolveRepoFromCwd
9
9
  } from "./chunk-YVRWVDIA.js";
@@ -12,7 +12,7 @@ import {
12
12
  } from "./chunk-7Q3BJMLG.js";
13
13
  import {
14
14
  refreshIfStale
15
- } from "./chunk-FMAHQRIU.js";
15
+ } from "./chunk-OSWBZKK5.js";
16
16
  import {
17
17
  allTargets
18
18
  } from "./chunk-QVK6VGCV.js";
@@ -24,7 +24,7 @@ import {
24
24
  markResyncComplete,
25
25
  needsResync,
26
26
  runMigrations
27
- } from "./chunk-SKZHAYNF.js";
27
+ } from "./chunk-UM5U6FPH.js";
28
28
  import {
29
29
  config
30
30
  } from "./chunk-K7YUPLES.js";
@@ -799,7 +799,7 @@ function createScannerLoop(opts) {
799
799
  reparseChecked = true;
800
800
  if (needsResync()) {
801
801
  log.scanner.info("Data version outdated \u2014 running atomic reparse...");
802
- import("./reparse-VHUSGCPN.js").then(({ reparseAll: reparseAll2 }) => {
802
+ import("./reparse-TFYD67WP.js").then(({ reparseAll: reparseAll2 }) => {
803
803
  try {
804
804
  const result = reparseAll2((msg) => log.scanner.info(msg));
805
805
  if (result.success) {
@@ -1119,4 +1119,4 @@ export {
1119
1119
  reparseAll,
1120
1120
  createScannerLoop
1121
1121
  };
1122
- //# sourceMappingURL=chunk-OROLSIWZ.js.map
1122
+ //# sourceMappingURL=chunk-5FRYHDPJ.js.map
@@ -3,16 +3,16 @@ import {
3
3
  insertOtelMetrics,
4
4
  insertOtelSpans,
5
5
  upsertSession
6
- } from "./chunk-V3XR2TAN.js";
6
+ } from "./chunk-UD6H6EP6.js";
7
7
  import {
8
8
  captureException
9
- } from "./chunk-J3HVD4VI.js";
9
+ } from "./chunk-RNICEX6N.js";
10
10
  import {
11
11
  log
12
12
  } from "./chunk-7Q3BJMLG.js";
13
13
  import {
14
14
  refreshIfStale
15
- } from "./chunk-FMAHQRIU.js";
15
+ } from "./chunk-OSWBZKK5.js";
16
16
  import {
17
17
  allTargets
18
18
  } from "./chunk-QVK6VGCV.js";
@@ -1069,4 +1069,4 @@ export {
1069
1069
  handleOtlpRequest,
1070
1070
  createOtlpServer
1071
1071
  };
1072
- //# sourceMappingURL=chunk-OW52TNVA.js.map
1072
+ //# sourceMappingURL=chunk-5IPC5XXZ.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  captureException
3
- } from "./chunk-J3HVD4VI.js";
3
+ } from "./chunk-RNICEX6N.js";
4
4
  import {
5
5
  log
6
6
  } from "./chunk-7Q3BJMLG.js";
@@ -10,14 +10,14 @@ import {
10
10
  readWatermark,
11
11
  watermarkKey,
12
12
  writeWatermark
13
- } from "./chunk-MEVW27U4.js";
13
+ } from "./chunk-P5KAIE3O.js";
14
14
  import {
15
15
  loadUnifiedConfig,
16
16
  saveUnifiedConfig
17
17
  } from "./chunk-QK5442ZP.js";
18
18
  import {
19
19
  getDb
20
- } from "./chunk-SKZHAYNF.js";
20
+ } from "./chunk-UM5U6FPH.js";
21
21
 
22
22
  // src/sync/config.ts
23
23
  function loadSyncConfig() {
@@ -182,7 +182,7 @@ function createSyncLoop(opts) {
182
182
  const postBatchSize = opts.postBatchSize ?? DEFAULT_POST_BATCH_SIZE;
183
183
  const idleMs = opts.idleIntervalMs ?? DEFAULT_IDLE_MS;
184
184
  const catchUpMs = opts.catchUpIntervalMs ?? DEFAULT_CATCHUP_MS;
185
- const panopticonVersion = true ? "0.1.2+430c018" : "dev";
185
+ const panopticonVersion = true ? "0.1.3+1deea73" : "dev";
186
186
  function resolveHeaders(target) {
187
187
  const headers = { ...target.headers };
188
188
  headers["X-Panopticon-Version"] = panopticonVersion;
@@ -425,4 +425,4 @@ export {
425
425
  listTargets,
426
426
  createSyncLoop
427
427
  };
428
- //# sourceMappingURL=chunk-3ZT3V7FP.js.map
428
+ //# sourceMappingURL=chunk-75IXBXBO.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getDb
3
- } from "./chunk-SKZHAYNF.js";
3
+ } from "./chunk-UM5U6FPH.js";
4
4
  import {
5
5
  config
6
6
  } from "./chunk-K7YUPLES.js";
@@ -131,4 +131,4 @@ export {
131
131
  pruneExecute,
132
132
  autoPrune
133
133
  };
134
- //# sourceMappingURL=chunk-WXPT6KG7.js.map
134
+ //# sourceMappingURL=chunk-7NBZ4NMJ.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getDb
3
- } from "./chunk-SKZHAYNF.js";
3
+ } from "./chunk-UM5U6FPH.js";
4
4
  import {
5
5
  config
6
6
  } from "./chunk-K7YUPLES.js";
@@ -155,4 +155,4 @@ export {
155
155
  refreshIfStale,
156
156
  COST_EXPR
157
157
  };
158
- //# sourceMappingURL=chunk-FMAHQRIU.js.map
158
+ //# sourceMappingURL=chunk-OSWBZKK5.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getDb
3
- } from "./chunk-SKZHAYNF.js";
3
+ } from "./chunk-UM5U6FPH.js";
4
4
 
5
5
  // src/sync/reader.ts
6
6
  function parseJson(raw) {
@@ -786,4 +786,4 @@ export {
786
786
  writeWatermark,
787
787
  resetWatermarks
788
788
  };
789
- //# sourceMappingURL=chunk-MEVW27U4.js.map
789
+ //# sourceMappingURL=chunk-P5KAIE3O.js.map
@@ -19,7 +19,7 @@ import {
19
19
  } from "@sentry/core";
20
20
  var initialized = false;
21
21
  function getVersion() {
22
- return true ? "0.1.2+430c018" : "dev";
22
+ return true ? "0.1.3+1deea73" : "dev";
23
23
  }
24
24
  var SCRUBBED_BREADCRUMB_FIELDS = [
25
25
  "prompt",
@@ -167,4 +167,4 @@ export {
167
167
  setTag,
168
168
  flushSentry
169
169
  };
170
- //# sourceMappingURL=chunk-J3HVD4VI.js.map
170
+ //# sourceMappingURL=chunk-RNICEX6N.js.map
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  refreshPricing
3
- } from "./chunk-FMAHQRIU.js";
3
+ } from "./chunk-OSWBZKK5.js";
4
4
  import {
5
5
  allTargets
6
6
  } from "./chunk-QVK6VGCV.js";
7
7
  import {
8
8
  closeDb,
9
9
  getDb
10
- } from "./chunk-SKZHAYNF.js";
10
+ } from "./chunk-UM5U6FPH.js";
11
11
  import {
12
12
  config,
13
13
  ensureDataDir
@@ -127,4 +127,4 @@ export {
127
127
  fetchPricing,
128
128
  configureShellEnv
129
129
  };
130
- //# sourceMappingURL=chunk-HRNZUHTA.js.map
130
+ //# sourceMappingURL=chunk-RRHBTXHB.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getDb
3
- } from "./chunk-SKZHAYNF.js";
3
+ } from "./chunk-UM5U6FPH.js";
4
4
 
5
5
  // src/db/store.ts
6
6
  import { createHash } from "crypto";
@@ -411,4 +411,4 @@ export {
411
411
  incrementEventTypeCount,
412
412
  insertHookEvent
413
413
  };
414
- //# sourceMappingURL=chunk-V3XR2TAN.js.map
414
+ //# sourceMappingURL=chunk-UD6H6EP6.js.map
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-QVK6VGCV.js";
4
4
  import {
5
5
  getDb
6
- } from "./chunk-SKZHAYNF.js";
6
+ } from "./chunk-UM5U6FPH.js";
7
7
 
8
8
  // src/db/query.ts
9
9
  function parseSince(since) {
@@ -623,4 +623,4 @@ export {
623
623
  rawQuery,
624
624
  dbStats
625
625
  };
626
- //# sourceMappingURL=chunk-GPTBERQD.js.map
626
+ //# sourceMappingURL=chunk-UDUBRSIG.js.map
@@ -1,20 +1,20 @@
1
1
  import {
2
2
  readWatermark,
3
3
  watermarkKey
4
- } from "./chunk-MEVW27U4.js";
4
+ } from "./chunk-P5KAIE3O.js";
5
5
  import {
6
6
  loadUnifiedConfig
7
7
  } from "./chunk-QK5442ZP.js";
8
8
  import {
9
9
  dbStats
10
- } from "./chunk-GPTBERQD.js";
10
+ } from "./chunk-UDUBRSIG.js";
11
11
  import {
12
12
  allTargets
13
13
  } from "./chunk-QVK6VGCV.js";
14
14
  import {
15
15
  closeDb,
16
16
  getDb
17
- } from "./chunk-SKZHAYNF.js";
17
+ } from "./chunk-UM5U6FPH.js";
18
18
  import {
19
19
  config
20
20
  } from "./chunk-K7YUPLES.js";
@@ -261,4 +261,4 @@ async function doctor() {
261
261
  export {
262
262
  doctor
263
263
  };
264
- //# sourceMappingURL=chunk-N7NCNJZU.js.map
264
+ //# sourceMappingURL=chunk-UEEWG7FD.js.map
@@ -22,13 +22,20 @@ function runMigrations(db, migrations = MIGRATIONS) {
22
22
  )
23
23
  `);
24
24
  if (!trackingExists) {
25
- const stamp = db.prepare(
26
- "INSERT INTO schema_migrations (id, name) VALUES (?, ?)"
27
- );
28
- for (const m of migrations) {
29
- stamp.run(m.id, m.name);
25
+ let hasData = false;
26
+ try {
27
+ hasData = !!db.prepare("SELECT 1 FROM sessions LIMIT 1").get();
28
+ } catch {
29
+ }
30
+ if (!hasData) {
31
+ const stamp = db.prepare(
32
+ "INSERT INTO schema_migrations (id, name) VALUES (?, ?)"
33
+ );
34
+ for (const m of migrations) {
35
+ stamp.run(m.id, m.name);
36
+ }
37
+ return;
30
38
  }
31
- return;
32
39
  }
33
40
  const applied = new Set(
34
41
  db.prepare("SELECT id FROM schema_migrations").all().map((r) => r.id)
@@ -515,4 +522,4 @@ export {
515
522
  markResyncComplete,
516
523
  closeDb
517
524
  };
518
- //# sourceMappingURL=chunk-SKZHAYNF.js.map
525
+ //# sourceMappingURL=chunk-UM5U6FPH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/db/migrations.ts","../src/db/schema.ts"],"sourcesContent":["/**\n * Schema migration system for panopticon's embedded SQLite database.\n *\n * ## Conventions\n *\n * 1. SCHEMA_SQL in schema.ts is ALWAYS the latest desired schema.\n * It uses CREATE TABLE IF NOT EXISTS, making it idempotent.\n *\n * 2. When adding a column: update the CREATE TABLE in SCHEMA_SQL\n * AND add a migration here with ALTER TABLE ADD COLUMN.\n * Both must exist. SCHEMA_SQL handles fresh DBs; migrations\n * handle existing DBs.\n *\n * 3. When adding a new table: add it to SCHEMA_SQL. No migration\n * needed (CREATE TABLE IF NOT EXISTS handles it).\n *\n * 4. When adding an index: add it to SCHEMA_SQL. No migration\n * needed (CREATE INDEX IF NOT EXISTS handles it).\n *\n * 5. For complex changes (data backfill, column rename via rebuild,\n * virtual table recreation): add an `up` function migration.\n * Update SCHEMA_SQL to reflect the final state.\n *\n * 6. Never reorder or remove migrations. Only append.\n *\n * 7. Migration IDs are sequential integers starting from 1.\n *\n * 8. No down migrations. This is an embedded app — users always\n * upgrade forward. Rolling back means reinstalling.\n */\n\nimport type Database from \"better-sqlite3\";\n\nexport interface Migration {\n id: number;\n name: string;\n /** Simple migrations: single SQL statement. */\n sql?: string;\n /** Complex migrations: function that receives the db handle. */\n up?: (db: Database.Database) => void;\n}\n\n// ---------------------------------------------------------------------------\n// Migration registry — append only, never reorder or remove\n// ---------------------------------------------------------------------------\n\nexport const MIGRATIONS: Migration[] = [\n {\n id: 1,\n name: \"add_plugin_hooks_to_user_config\",\n sql: \"ALTER TABLE user_config_snapshots ADD COLUMN plugin_hooks JSON NOT NULL DEFAULT '[]'\",\n },\n];\n\n// ---------------------------------------------------------------------------\n// Migration runner\n// ---------------------------------------------------------------------------\n\n/**\n * Apply pending schema migrations to the database.\n *\n * On a fresh database (where SCHEMA_SQL just created all tables with all\n * columns), the `schema_migrations` table won't exist yet. In that case\n * we stamp all migrations as applied without executing them — SCHEMA_SQL\n * already reflects the final state.\n *\n * On an existing database, unapplied migrations run sequentially inside\n * transactions.\n */\nexport function runMigrations(\n db: Database.Database,\n migrations: Migration[] = MIGRATIONS,\n): void {\n const trackingExists = db\n .prepare(\n \"SELECT 1 FROM sqlite_master WHERE type='table' AND name='schema_migrations'\",\n )\n .get();\n\n db.exec(`\n CREATE TABLE IF NOT EXISTS schema_migrations (\n id INTEGER PRIMARY KEY,\n name TEXT NOT NULL,\n applied_at TEXT NOT NULL DEFAULT (datetime('now'))\n )\n `);\n\n if (!trackingExists) {\n // No tracking table could mean:\n // a) Truly fresh DB — SCHEMA_SQL just created all tables with all columns\n // b) Pre-migration-system DB — tables existed before migrations were added,\n // and CREATE TABLE IF NOT EXISTS didn't add new columns\n //\n // Distinguish by checking for existing data. A fresh DB has no rows yet.\n let hasData = false;\n try {\n hasData = !!db.prepare(\"SELECT 1 FROM sessions LIMIT 1\").get();\n } catch {\n // sessions table doesn't exist — definitely a fresh/test DB\n }\n\n if (!hasData) {\n // Fresh database: SCHEMA_SQL already created everything.\n // Stamp all migrations as applied without executing them.\n const stamp = db.prepare(\n \"INSERT INTO schema_migrations (id, name) VALUES (?, ?)\",\n );\n for (const m of migrations) {\n stamp.run(m.id, m.name);\n }\n return;\n }\n // Pre-migration-system DB: fall through to run migrations normally\n }\n\n // Existing database: run unapplied migrations sequentially\n const applied = new Set(\n (\n db.prepare(\"SELECT id FROM schema_migrations\").all() as Array<{\n id: number;\n }>\n ).map((r) => r.id),\n );\n\n for (const migration of migrations) {\n if (applied.has(migration.id)) continue;\n const run = db.transaction(() => {\n if (migration.sql) {\n db.exec(migration.sql);\n } else if (migration.up) {\n migration.up(db);\n }\n db.prepare(\"INSERT INTO schema_migrations (id, name) VALUES (?, ?)\").run(\n migration.id,\n migration.name,\n );\n });\n run();\n }\n}\n","import fs from \"node:fs\";\nimport { gunzipSync } from \"node:zlib\";\nimport Database from \"better-sqlite3\";\nimport { config } from \"../config.js\";\nimport { runMigrations } from \"./migrations.js\";\n\nexport { runMigrations } from \"./migrations.js\";\n\nexport const SCHEMA_SQL = `\n\n-- ── OTLP tables ─────────────────────────────────────────────────────────────\n\nCREATE TABLE IF NOT EXISTS otel_logs (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n timestamp_ns INTEGER NOT NULL,\n observed_timestamp_ns INTEGER,\n severity_number INTEGER,\n severity_text TEXT,\n body TEXT,\n attributes JSON,\n resource_attributes JSON,\n session_id TEXT,\n prompt_id TEXT,\n trace_id TEXT,\n span_id TEXT,\n sync_id TEXT DEFAULT (hex(randomblob(8)))\n);\n\nCREATE TABLE IF NOT EXISTS otel_metrics (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n timestamp_ns INTEGER NOT NULL,\n name TEXT NOT NULL,\n value REAL NOT NULL,\n metric_type TEXT,\n unit TEXT,\n attributes JSON,\n resource_attributes JSON,\n session_id TEXT,\n sync_id TEXT DEFAULT (hex(randomblob(8)))\n);\n\nCREATE TABLE IF NOT EXISTS otel_spans (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n trace_id TEXT NOT NULL,\n span_id TEXT NOT NULL,\n parent_span_id TEXT,\n name TEXT NOT NULL,\n kind INTEGER,\n start_time_ns INTEGER NOT NULL,\n end_time_ns INTEGER NOT NULL,\n status_code INTEGER,\n status_message TEXT,\n attributes JSON,\n resource_attributes JSON,\n session_id TEXT,\n UNIQUE(trace_id, span_id)\n);\n\n-- ── Hook events ─────────────────────────────────────────────────────────────\n\nCREATE TABLE IF NOT EXISTS hook_events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n session_id TEXT NOT NULL,\n event_type TEXT NOT NULL,\n timestamp_ms INTEGER NOT NULL,\n cwd TEXT,\n repository TEXT,\n tool_name TEXT,\n payload BLOB NOT NULL,\n user_prompt TEXT,\n file_path TEXT,\n command TEXT,\n plan TEXT,\n allowed_prompts TEXT,\n tool_result TEXT,\n target TEXT,\n sync_id TEXT DEFAULT (hex(randomblob(8)))\n);\n\nCREATE VIRTUAL TABLE IF NOT EXISTS hook_events_fts USING fts5(\n payload,\n content='',\n contentless_delete=1,\n tokenize='trigram'\n);\n\n-- ── Sessions ────────────────────────────────────────────────────────────────\n\nCREATE TABLE IF NOT EXISTS sessions (\n session_id TEXT PRIMARY KEY,\n target TEXT,\n started_at_ms INTEGER,\n ended_at_ms INTEGER,\n cwd TEXT,\n first_prompt TEXT,\n permission_mode TEXT,\n agent_version TEXT,\n model TEXT,\n cli_version TEXT,\n scanner_file_path TEXT,\n total_input_tokens INTEGER DEFAULT 0,\n total_output_tokens INTEGER DEFAULT 0,\n total_cache_read_tokens INTEGER DEFAULT 0,\n total_cache_creation_tokens INTEGER DEFAULT 0,\n total_reasoning_tokens INTEGER DEFAULT 0,\n turn_count INTEGER DEFAULT 0,\n otel_input_tokens INTEGER DEFAULT 0,\n otel_output_tokens INTEGER DEFAULT 0,\n otel_cache_read_tokens INTEGER DEFAULT 0,\n otel_cache_creation_tokens INTEGER DEFAULT 0,\n models TEXT,\n has_hooks INTEGER DEFAULT 0,\n has_otel INTEGER DEFAULT 0,\n has_scanner INTEGER DEFAULT 0,\n summary TEXT,\n summary_version INTEGER DEFAULT 0,\n sync_dirty INTEGER DEFAULT 0,\n sync_seq INTEGER DEFAULT 0,\n tool_counts JSON DEFAULT '{}',\n hook_tool_counts JSON DEFAULT '{}',\n event_type_counts JSON DEFAULT '{}',\n hook_event_type_counts JSON DEFAULT '{}',\n project TEXT,\n machine TEXT NOT NULL DEFAULT 'local',\n message_count INTEGER DEFAULT 0,\n user_message_count INTEGER DEFAULT 0,\n parent_session_id TEXT,\n relationship_type TEXT DEFAULT '',\n is_automated INTEGER DEFAULT 0,\n created_at INTEGER\n);\n\nCREATE TABLE IF NOT EXISTS session_repositories (\n session_id TEXT NOT NULL,\n repository TEXT NOT NULL,\n first_seen_ms INTEGER NOT NULL,\n git_user_name TEXT,\n git_user_email TEXT,\n branch TEXT,\n UNIQUE(session_id, repository)\n);\n\nCREATE TABLE IF NOT EXISTS session_cwds (\n session_id TEXT NOT NULL,\n cwd TEXT NOT NULL,\n first_seen_ms INTEGER NOT NULL,\n UNIQUE(session_id, cwd)\n);\n\n-- ── Messages ────────────────────────────────────────────────────────────────\n\nCREATE TABLE IF NOT EXISTS messages (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n session_id TEXT NOT NULL,\n ordinal INTEGER NOT NULL,\n role TEXT NOT NULL,\n content TEXT NOT NULL,\n timestamp_ms INTEGER,\n has_thinking INTEGER NOT NULL DEFAULT 0,\n has_tool_use INTEGER NOT NULL DEFAULT 0,\n content_length INTEGER NOT NULL DEFAULT 0,\n is_system INTEGER NOT NULL DEFAULT 0,\n model TEXT NOT NULL DEFAULT '',\n token_usage TEXT NOT NULL DEFAULT '',\n context_tokens INTEGER NOT NULL DEFAULT 0,\n output_tokens INTEGER NOT NULL DEFAULT 0,\n has_context_tokens INTEGER NOT NULL DEFAULT 0,\n has_output_tokens INTEGER NOT NULL DEFAULT 0,\n uuid TEXT,\n parent_uuid TEXT,\n UNIQUE(session_id, ordinal)\n);\n\nCREATE VIRTUAL TABLE IF NOT EXISTS messages_fts USING fts5(\n content,\n content='',\n contentless_delete=1,\n tokenize='trigram'\n);\n\n-- ── Tool calls ──────────────────────────────────────────────────────────────\n\nCREATE TABLE IF NOT EXISTS tool_calls (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n message_id INTEGER NOT NULL,\n session_id TEXT NOT NULL,\n tool_name TEXT NOT NULL,\n category TEXT NOT NULL,\n tool_use_id TEXT,\n input_json TEXT,\n skill_name TEXT,\n result_content_length INTEGER,\n result_content TEXT,\n duration_ms INTEGER,\n subagent_session_id TEXT,\n sync_id TEXT DEFAULT (hex(randomblob(8)))\n);\n\n-- ── Scanner tables ──────────────────────────────────────────────────────────\n\nCREATE TABLE IF NOT EXISTS scanner_turns (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n session_id TEXT NOT NULL,\n source TEXT NOT NULL,\n turn_index INTEGER NOT NULL,\n timestamp_ms INTEGER NOT NULL,\n model TEXT,\n role TEXT,\n content_preview TEXT,\n input_tokens INTEGER DEFAULT 0,\n output_tokens INTEGER DEFAULT 0,\n cache_read_tokens INTEGER DEFAULT 0,\n cache_creation_tokens INTEGER DEFAULT 0,\n reasoning_tokens INTEGER DEFAULT 0,\n sync_id TEXT DEFAULT (hex(randomblob(8))),\n UNIQUE(session_id, source, turn_index)\n);\n\nCREATE TABLE IF NOT EXISTS scanner_events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n session_id TEXT NOT NULL,\n source TEXT NOT NULL,\n event_type TEXT NOT NULL,\n timestamp_ms INTEGER NOT NULL,\n tool_name TEXT,\n tool_input TEXT,\n tool_output TEXT,\n content TEXT,\n metadata JSON,\n sync_id TEXT DEFAULT (hex(randomblob(8))),\n UNIQUE(session_id, source, event_type, timestamp_ms, tool_name)\n);\n\nCREATE TABLE IF NOT EXISTS scanner_file_watermarks (\n file_path TEXT PRIMARY KEY,\n byte_offset INTEGER NOT NULL DEFAULT 0,\n last_scanned_ms INTEGER NOT NULL,\n archived_size INTEGER DEFAULT 0\n);\n\n-- ── Session summaries ───────────────────────────────────────────────────────\n\nCREATE TABLE IF NOT EXISTS session_summary_deltas (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n session_id TEXT NOT NULL,\n delta_index INTEGER NOT NULL,\n created_at_ms INTEGER NOT NULL,\n from_turn INTEGER NOT NULL,\n to_turn INTEGER NOT NULL,\n content TEXT NOT NULL,\n method TEXT NOT NULL DEFAULT 'deterministic',\n UNIQUE(session_id, delta_index)\n);\n\n-- ── Model pricing ───────────────────────────────────────────────────────────\n\nCREATE TABLE IF NOT EXISTS model_pricing (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n model_id TEXT NOT NULL,\n input_per_m REAL NOT NULL,\n output_per_m REAL NOT NULL,\n cache_read_per_m REAL NOT NULL DEFAULT 0,\n cache_write_per_m REAL NOT NULL DEFAULT 0,\n updated_ms INTEGER NOT NULL\n);\n\n-- ── Config snapshots ────────────────────────────────────────────────────────\n\nCREATE TABLE IF NOT EXISTS user_config_snapshots (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n device_name TEXT NOT NULL,\n snapshot_at_ms INTEGER NOT NULL,\n content_hash TEXT NOT NULL,\n permissions JSON NOT NULL DEFAULT '{}',\n enabled_plugins JSON NOT NULL DEFAULT '[]',\n hooks JSON NOT NULL DEFAULT '[]',\n commands JSON NOT NULL DEFAULT '[]',\n rules JSON NOT NULL DEFAULT '[]',\n skills JSON NOT NULL DEFAULT '[]',\n plugin_hooks JSON NOT NULL DEFAULT '[]'\n);\n\nCREATE TABLE IF NOT EXISTS repo_config_snapshots (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n repository TEXT NOT NULL,\n cwd TEXT NOT NULL,\n session_id TEXT,\n snapshot_at_ms INTEGER NOT NULL,\n content_hash TEXT NOT NULL,\n hooks JSON NOT NULL DEFAULT '[]',\n mcp_servers JSON NOT NULL DEFAULT '[]',\n commands JSON NOT NULL DEFAULT '[]',\n agents JSON NOT NULL DEFAULT '[]',\n rules JSON NOT NULL DEFAULT '[]',\n local_hooks JSON NOT NULL DEFAULT '[]',\n local_mcp_servers JSON NOT NULL DEFAULT '[]',\n local_permissions JSON NOT NULL DEFAULT '{}',\n local_is_gitignored INTEGER NOT NULL DEFAULT 1,\n instructions JSON NOT NULL DEFAULT '[]'\n);\n\n-- ── Sync watermarks ─────────────────────────────────────────────────────────\n\nCREATE TABLE IF NOT EXISTS watermarks (\n key TEXT PRIMARY KEY,\n value INTEGER NOT NULL\n);\n\n-- ── Per-session sync state ─────────────────────────────────────────────────\n\nDROP TABLE IF EXISTS pending_session_sync;\n\nCREATE TABLE IF NOT EXISTS target_session_sync (\n session_id TEXT NOT NULL,\n target TEXT NOT NULL,\n confirmed INTEGER DEFAULT 0,\n sync_seq INTEGER DEFAULT 0,\n synced_seq INTEGER DEFAULT 0,\n wm_messages INTEGER DEFAULT 0,\n wm_tool_calls INTEGER DEFAULT 0,\n wm_scanner_turns INTEGER DEFAULT 0,\n wm_scanner_events INTEGER DEFAULT 0,\n wm_hook_events INTEGER DEFAULT 0,\n wm_otel_logs INTEGER DEFAULT 0,\n wm_otel_metrics INTEGER DEFAULT 0,\n wm_otel_spans INTEGER DEFAULT 0,\n PRIMARY KEY (session_id, target)\n);\n\n-- ── Indexes ─────────────────────────────────────────────────────────────────\n\n-- otel_logs\nCREATE INDEX IF NOT EXISTS idx_logs_session ON otel_logs(session_id);\nCREATE INDEX IF NOT EXISTS idx_logs_body ON otel_logs(body);\nCREATE INDEX IF NOT EXISTS idx_logs_ts ON otel_logs(timestamp_ns);\nCREATE INDEX IF NOT EXISTS idx_logs_prompt ON otel_logs(prompt_id);\n\n-- otel_metrics\nCREATE INDEX IF NOT EXISTS idx_metrics_session ON otel_metrics(session_id);\nCREATE INDEX IF NOT EXISTS idx_metrics_name ON otel_metrics(name);\nCREATE INDEX IF NOT EXISTS idx_metrics_ts ON otel_metrics(timestamp_ns);\n\n-- otel_spans\nCREATE INDEX IF NOT EXISTS idx_spans_session ON otel_spans(session_id);\nCREATE INDEX IF NOT EXISTS idx_spans_trace ON otel_spans(trace_id);\nCREATE INDEX IF NOT EXISTS idx_spans_start ON otel_spans(start_time_ns);\n\n-- hook_events\nCREATE INDEX IF NOT EXISTS idx_hooks_session ON hook_events(session_id);\nCREATE INDEX IF NOT EXISTS idx_hooks_type ON hook_events(event_type);\nCREATE INDEX IF NOT EXISTS idx_hooks_tool ON hook_events(tool_name);\nCREATE INDEX IF NOT EXISTS idx_hooks_ts ON hook_events(timestamp_ms);\nCREATE INDEX IF NOT EXISTS idx_hooks_file_path ON hook_events(file_path);\nCREATE INDEX IF NOT EXISTS idx_hooks_target ON hook_events(target);\n\n-- sessions\nCREATE INDEX IF NOT EXISTS idx_sessions_target ON sessions(target);\nCREATE INDEX IF NOT EXISTS idx_sessions_started ON sessions(started_at_ms);\nCREATE INDEX IF NOT EXISTS idx_sessions_sync_seq ON sessions(sync_seq);\nCREATE INDEX IF NOT EXISTS idx_sessions_project ON sessions(project);\nCREATE INDEX IF NOT EXISTS idx_sessions_machine ON sessions(machine);\nCREATE INDEX IF NOT EXISTS idx_sessions_parent ON sessions(parent_session_id)\n WHERE parent_session_id IS NOT NULL;\n\n-- session_repositories\nCREATE INDEX IF NOT EXISTS idx_session_repos_session ON session_repositories(session_id);\nCREATE INDEX IF NOT EXISTS idx_session_repos_repo ON session_repositories(repository);\n\n-- session_cwds\nCREATE INDEX IF NOT EXISTS idx_session_cwds_session ON session_cwds(session_id);\n\n-- messages\nCREATE INDEX IF NOT EXISTS idx_messages_session_ordinal ON messages(session_id, ordinal);\nCREATE INDEX IF NOT EXISTS idx_messages_session_role ON messages(session_id, role);\n\n-- tool_calls\nCREATE INDEX IF NOT EXISTS idx_tool_calls_session ON tool_calls(session_id);\nCREATE INDEX IF NOT EXISTS idx_tool_calls_category ON tool_calls(category);\nCREATE INDEX IF NOT EXISTS idx_tool_calls_skill ON tool_calls(skill_name)\n WHERE skill_name IS NOT NULL;\nCREATE INDEX IF NOT EXISTS idx_tool_calls_subagent ON tool_calls(subagent_session_id)\n WHERE subagent_session_id IS NOT NULL;\n\n-- scanner_turns\nCREATE INDEX IF NOT EXISTS idx_scanner_turns_session ON scanner_turns(session_id);\nCREATE INDEX IF NOT EXISTS idx_scanner_turns_ts ON scanner_turns(timestamp_ms);\n\n-- scanner_events\nCREATE INDEX IF NOT EXISTS idx_scanner_events_session ON scanner_events(session_id);\nCREATE INDEX IF NOT EXISTS idx_scanner_events_type ON scanner_events(event_type);\n\n-- session_summary_deltas\nCREATE INDEX IF NOT EXISTS idx_summary_deltas_session ON session_summary_deltas(session_id);\n\n-- model_pricing\nCREATE INDEX IF NOT EXISTS idx_model_pricing_model ON model_pricing(model_id, updated_ms);\n\n-- user_config_snapshots\nCREATE INDEX IF NOT EXISTS idx_user_config_ts ON user_config_snapshots(snapshot_at_ms);\nCREATE INDEX IF NOT EXISTS idx_user_config_device_hash ON user_config_snapshots(device_name, content_hash);\n\n-- repo_config_snapshots\nCREATE INDEX IF NOT EXISTS idx_repo_config_repo_ts ON repo_config_snapshots(repository, snapshot_at_ms);\nCREATE INDEX IF NOT EXISTS idx_repo_config_session ON repo_config_snapshots(session_id);\nCREATE INDEX IF NOT EXISTS idx_repo_config_repo_hash ON repo_config_snapshots(repository, content_hash);\n\n`;\n\n/**\n * Scanner data version. Increment when parser logic changes in ways that\n * affect stored data (new fields extracted, content formatting changes,\n * fork detection improvements, etc.). On startup, if the DB's user_version\n * is lower than this, a full resync is triggered automatically.\n */\nexport const SCANNER_DATA_VERSION = 1;\n\n// ---------------------------------------------------------------------------\n// Database initialization\n// ---------------------------------------------------------------------------\n\nlet _db: Database.Database | null = null;\nlet _needsResync = false;\n\nfunction registerCompressionFunctions(db: Database.Database): void {\n db.function(\"decompress\", (blob: Buffer | null) =>\n blob ? gunzipSync(blob).toString() : null,\n );\n}\n\nexport function getDb(): Database.Database {\n // If the db file was deleted (e.g. uninstall --purge) while this process\n // still holds a stale connection, drop it so we don't serve old data.\n if (_db && !fs.existsSync(config.dbPath)) {\n try {\n _db.close();\n } catch {}\n _db = null;\n }\n if (_db) return _db;\n\n // Don't auto-create the data directory — callers that need to bootstrap\n // the DB (install, initDb, hook handler) call ensureDataDir() first.\n if (!fs.existsSync(config.dataDir)) {\n throw new Error(\n `Panopticon data directory not found: ${config.dataDir}. Run \"panopticon install\" to set up.`,\n );\n }\n\n _db = new Database(config.dbPath);\n _db.pragma(\"auto_vacuum = INCREMENTAL\");\n _db.pragma(\"journal_mode = WAL\");\n _db.pragma(\"busy_timeout = 5000\");\n\n registerCompressionFunctions(_db);\n _db.exec(SCHEMA_SQL);\n runMigrations(_db);\n\n // Check data version for resync\n const currentVersion = (_db.pragma(\"user_version\", { simple: true }) ??\n 0) as number;\n if (currentVersion < SCANNER_DATA_VERSION) {\n _needsResync = true;\n } else {\n _needsResync = false;\n }\n\n return _db;\n}\n\n/** True when the DB was opened with a stale data version. */\nexport function needsResync(): boolean {\n return _needsResync;\n}\n\n/** Mark resync as complete and stamp the current data version. */\nexport function markResyncComplete(): void {\n _needsResync = false;\n const db = getDb();\n db.pragma(`user_version = ${SCANNER_DATA_VERSION}`);\n}\n\nexport function closeDb(): void {\n if (_db) {\n _db.close();\n _db = null;\n }\n}\n"],"mappings":";;;;;AA8CO,IAAM,aAA0B;AAAA,EACrC;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,KAAK;AAAA,EACP;AACF;AAiBO,SAAS,cACd,IACA,aAA0B,YACpB;AACN,QAAM,iBAAiB,GACpB;AAAA,IACC;AAAA,EACF,EACC,IAAI;AAEP,KAAG,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAMP;AAED,MAAI,CAAC,gBAAgB;AAOnB,QAAI,UAAU;AACd,QAAI;AACF,gBAAU,CAAC,CAAC,GAAG,QAAQ,gCAAgC,EAAE,IAAI;AAAA,IAC/D,QAAQ;AAAA,IAER;AAEA,QAAI,CAAC,SAAS;AAGZ,YAAM,QAAQ,GAAG;AAAA,QACf;AAAA,MACF;AACA,iBAAW,KAAK,YAAY;AAC1B,cAAM,IAAI,EAAE,IAAI,EAAE,IAAI;AAAA,MACxB;AACA;AAAA,IACF;AAAA,EAEF;AAGA,QAAM,UAAU,IAAI;AAAA,IAEhB,GAAG,QAAQ,kCAAkC,EAAE,IAAI,EAGnD,IAAI,CAAC,MAAM,EAAE,EAAE;AAAA,EACnB;AAEA,aAAW,aAAa,YAAY;AAClC,QAAI,QAAQ,IAAI,UAAU,EAAE,EAAG;AAC/B,UAAM,MAAM,GAAG,YAAY,MAAM;AAC/B,UAAI,UAAU,KAAK;AACjB,WAAG,KAAK,UAAU,GAAG;AAAA,MACvB,WAAW,UAAU,IAAI;AACvB,kBAAU,GAAG,EAAE;AAAA,MACjB;AACA,SAAG,QAAQ,wDAAwD,EAAE;AAAA,QACnE,UAAU;AAAA,QACV,UAAU;AAAA,MACZ;AAAA,IACF,CAAC;AACD,QAAI;AAAA,EACN;AACF;;;AC3IA,OAAO,QAAQ;AACf,SAAS,kBAAkB;AAC3B,OAAO,cAAc;AAMd,IAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsZnB,IAAM,uBAAuB;AAMpC,IAAI,MAAgC;AACpC,IAAI,eAAe;AAEnB,SAAS,6BAA6B,IAA6B;AACjE,KAAG;AAAA,IAAS;AAAA,IAAc,CAAC,SACzB,OAAO,WAAW,IAAI,EAAE,SAAS,IAAI;AAAA,EACvC;AACF;AAEO,SAAS,QAA2B;AAGzC,MAAI,OAAO,CAAC,GAAG,WAAW,OAAO,MAAM,GAAG;AACxC,QAAI;AACF,UAAI,MAAM;AAAA,IACZ,QAAQ;AAAA,IAAC;AACT,UAAM;AAAA,EACR;AACA,MAAI,IAAK,QAAO;AAIhB,MAAI,CAAC,GAAG,WAAW,OAAO,OAAO,GAAG;AAClC,UAAM,IAAI;AAAA,MACR,wCAAwC,OAAO,OAAO;AAAA,IACxD;AAAA,EACF;AAEA,QAAM,IAAI,SAAS,OAAO,MAAM;AAChC,MAAI,OAAO,2BAA2B;AACtC,MAAI,OAAO,oBAAoB;AAC/B,MAAI,OAAO,qBAAqB;AAEhC,+BAA6B,GAAG;AAChC,MAAI,KAAK,UAAU;AACnB,gBAAc,GAAG;AAGjB,QAAM,iBAAkB,IAAI,OAAO,gBAAgB,EAAE,QAAQ,KAAK,CAAC,KACjE;AACF,MAAI,iBAAiB,sBAAsB;AACzC,mBAAe;AAAA,EACjB,OAAO;AACL,mBAAe;AAAA,EACjB;AAEA,SAAO;AACT;AAGO,SAAS,cAAuB;AACrC,SAAO;AACT;AAGO,SAAS,qBAA2B;AACzC,iBAAe;AACf,QAAM,KAAK,MAAM;AACjB,KAAG,OAAO,kBAAkB,oBAAoB,EAAE;AACpD;AAEO,SAAS,UAAgB;AAC9B,MAAI,KAAK;AACP,QAAI,MAAM;AACV,UAAM;AAAA,EACR;AACF;","names":[]}
@@ -1,45 +1,45 @@
1
1
  import {
2
2
  handleOtlpRequest
3
- } from "./chunk-OW52TNVA.js";
3
+ } from "./chunk-5IPC5XXZ.js";
4
4
  import {
5
5
  handleProxyRequest,
6
6
  processHookEvent,
7
7
  tunnelWebSocket
8
- } from "./chunk-NE7VBLQD.js";
8
+ } from "./chunk-2PMFNSGA.js";
9
9
  import {
10
10
  addTarget,
11
11
  createSyncLoop,
12
12
  listTargets,
13
13
  removeTarget
14
- } from "./chunk-3ZT3V7FP.js";
14
+ } from "./chunk-75IXBXBO.js";
15
15
  import {
16
16
  createScannerLoop
17
- } from "./chunk-OROLSIWZ.js";
17
+ } from "./chunk-5FRYHDPJ.js";
18
18
  import {
19
19
  autoPrune,
20
20
  pruneEstimate,
21
21
  pruneExecute
22
- } from "./chunk-WXPT6KG7.js";
22
+ } from "./chunk-7NBZ4NMJ.js";
23
23
  import {
24
24
  addBreadcrumb,
25
25
  captureException,
26
26
  flushSentry,
27
27
  initSentry,
28
28
  setTag
29
- } from "./chunk-J3HVD4VI.js";
29
+ } from "./chunk-RNICEX6N.js";
30
30
  import {
31
31
  log
32
32
  } from "./chunk-7Q3BJMLG.js";
33
33
  import {
34
34
  refreshPricing
35
- } from "./chunk-FMAHQRIU.js";
35
+ } from "./chunk-OSWBZKK5.js";
36
36
  import {
37
37
  TABLE_SYNC_REGISTRY,
38
38
  readWatermark,
39
39
  resetWatermarks,
40
40
  watermarkKey,
41
41
  writeWatermark
42
- } from "./chunk-MEVW27U4.js";
42
+ } from "./chunk-P5KAIE3O.js";
43
43
  import {
44
44
  loadUnifiedConfig
45
45
  } from "./chunk-QK5442ZP.js";
@@ -53,10 +53,10 @@ import {
53
53
  rawQuery,
54
54
  search,
55
55
  sessionTimeline
56
- } from "./chunk-GPTBERQD.js";
56
+ } from "./chunk-UDUBRSIG.js";
57
57
  import {
58
58
  getDb
59
- } from "./chunk-SKZHAYNF.js";
59
+ } from "./chunk-UM5U6FPH.js";
60
60
  import {
61
61
  config
62
62
  } from "./chunk-K7YUPLES.js";
@@ -472,4 +472,4 @@ export {
472
472
  syncAwarePrune,
473
473
  createUnifiedServer
474
474
  };
475
- //# sourceMappingURL=chunk-BKGQJ76N.js.map
475
+ //# sourceMappingURL=chunk-YV2AN73J.js.map
package/dist/cli.js CHANGED
@@ -32,7 +32,7 @@ import {
32
32
  } from "./chunk-7Q3BJMLG.js";
33
33
  import {
34
34
  refreshPricing as refreshPricing2
35
- } from "./chunk-FMAHQRIU.js";
35
+ } from "./chunk-OSWBZKK5.js";
36
36
  import {
37
37
  loadUnifiedConfig
38
38
  } from "./chunk-QK5442ZP.js";
@@ -45,7 +45,7 @@ import {
45
45
  import {
46
46
  closeDb,
47
47
  getDb
48
- } from "./chunk-SKZHAYNF.js";
48
+ } from "./chunk-UM5U6FPH.js";
49
49
  import {
50
50
  config,
51
51
  ensureDataDir
@@ -334,7 +334,7 @@ function removeShellEnv() {
334
334
  }
335
335
  var program = new Command();
336
336
  program.name("panopticon").description("Observability for Claude Code").version(
337
- true ? "0.1.2+430c018" : "dev"
337
+ true ? "0.1.3+1deea73" : "dev"
338
338
  );
339
339
  program.command("install").alias("setup").description("Build, register plugin, init DB, configure shell").option(
340
340
  "--target <target>",
@@ -462,7 +462,7 @@ program.command("uninstall").description("Remove panopticon hooks, shell config,
462
462
  }
463
463
  });
464
464
  program.command("update").description("Update panopticon to the latest version").action(async () => {
465
- const currentVersion = true ? "0.1.2+430c018" : "unknown";
465
+ const currentVersion = true ? "0.1.3+1deea73" : "unknown";
466
466
  console.log(`Current: ${currentVersion}`);
467
467
  console.log(
468
468
  "To update, re-run the install command for your package manager:\n"
package/dist/db.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  closeDb,
3
3
  getDb
4
- } from "./chunk-SKZHAYNF.js";
4
+ } from "./chunk-UM5U6FPH.js";
5
5
  import {
6
6
  config,
7
7
  ensureDataDir
package/dist/doctor.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  doctor
3
- } from "./chunk-N7NCNJZU.js";
4
- import "./chunk-MEVW27U4.js";
3
+ } from "./chunk-UEEWG7FD.js";
4
+ import "./chunk-P5KAIE3O.js";
5
5
  import "./chunk-QK5442ZP.js";
6
- import "./chunk-GPTBERQD.js";
6
+ import "./chunk-UDUBRSIG.js";
7
7
  import "./chunk-ZEC4LRKS.js";
8
8
  import "./chunk-QVK6VGCV.js";
9
- import "./chunk-SKZHAYNF.js";
9
+ import "./chunk-UM5U6FPH.js";
10
10
  import "./chunk-K7YUPLES.js";
11
11
  export {
12
12
  doctor
@@ -3,15 +3,15 @@ import {
3
3
  addBreadcrumb,
4
4
  captureException,
5
5
  initSentry
6
- } from "../chunk-J3HVD4VI.js";
6
+ } from "../chunk-RNICEX6N.js";
7
7
  import {
8
8
  logPaths,
9
9
  openLogFd
10
10
  } from "../chunk-7Q3BJMLG.js";
11
11
  import {
12
12
  refreshIfStale
13
- } from "../chunk-FMAHQRIU.js";
14
- import "../chunk-SKZHAYNF.js";
13
+ } from "../chunk-OSWBZKK5.js";
14
+ import "../chunk-UM5U6FPH.js";
15
15
  import {
16
16
  config,
17
17
  ensureDataDir
@@ -80,7 +80,7 @@ async function waitForServer(port, timeoutMs = 3e3) {
80
80
 
81
81
  // src/hooks/handler.ts
82
82
  function getAgentVersion() {
83
- return true ? "0.1.2+430c018" : void 0;
83
+ return true ? "0.1.3+1deea73" : void 0;
84
84
  }
85
85
  function logHook(message, meta) {
86
86
  try {
package/dist/index.js CHANGED
@@ -5,12 +5,12 @@ import {
5
5
  import {
6
6
  createUnifiedServer,
7
7
  syncAwarePrune
8
- } from "./chunk-BKGQJ76N.js";
9
- import "./chunk-OW52TNVA.js";
10
- import "./chunk-NE7VBLQD.js";
11
- import "./chunk-3ZT3V7FP.js";
12
- import "./chunk-OROLSIWZ.js";
13
- import "./chunk-V3XR2TAN.js";
8
+ } from "./chunk-YV2AN73J.js";
9
+ import "./chunk-5IPC5XXZ.js";
10
+ import "./chunk-2PMFNSGA.js";
11
+ import "./chunk-75IXBXBO.js";
12
+ import "./chunk-5FRYHDPJ.js";
13
+ import "./chunk-UD6H6EP6.js";
14
14
  import {
15
15
  resolveRepoFromCwd
16
16
  } from "./chunk-YVRWVDIA.js";
@@ -18,26 +18,26 @@ import {
18
18
  autoPrune,
19
19
  pruneEstimate,
20
20
  pruneExecute
21
- } from "./chunk-WXPT6KG7.js";
21
+ } from "./chunk-7NBZ4NMJ.js";
22
22
  import {
23
23
  readConfig,
24
24
  writeFile,
25
25
  writeSettings
26
26
  } from "./chunk-3ILOOWUF.js";
27
- import "./chunk-J3HVD4VI.js";
27
+ import "./chunk-RNICEX6N.js";
28
28
  import "./chunk-7Q3BJMLG.js";
29
29
  import {
30
30
  configureShellEnv,
31
31
  fetchPricing,
32
32
  initDb
33
- } from "./chunk-HRNZUHTA.js";
33
+ } from "./chunk-RRHBTXHB.js";
34
34
  import {
35
35
  refreshPricing
36
- } from "./chunk-FMAHQRIU.js";
36
+ } from "./chunk-OSWBZKK5.js";
37
37
  import {
38
38
  doctor
39
- } from "./chunk-N7NCNJZU.js";
40
- import "./chunk-MEVW27U4.js";
39
+ } from "./chunk-UEEWG7FD.js";
40
+ import "./chunk-P5KAIE3O.js";
41
41
  import {
42
42
  loadRetentionConfig,
43
43
  loadUnifiedConfig,
@@ -53,13 +53,13 @@ import {
53
53
  rawQuery,
54
54
  search,
55
55
  sessionTimeline
56
- } from "./chunk-GPTBERQD.js";
56
+ } from "./chunk-UDUBRSIG.js";
57
57
  import "./chunk-ZEC4LRKS.js";
58
58
  import "./chunk-QVK6VGCV.js";
59
59
  import {
60
60
  closeDb,
61
61
  getDb
62
- } from "./chunk-SKZHAYNF.js";
62
+ } from "./chunk-UM5U6FPH.js";
63
63
  import {
64
64
  config,
65
65
  ensureDataDir
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  createOtlpServer,
3
3
  handleOtlpRequest
4
- } from "../chunk-OW52TNVA.js";
5
- import "../chunk-V3XR2TAN.js";
6
- import "../chunk-J3HVD4VI.js";
4
+ } from "../chunk-5IPC5XXZ.js";
5
+ import "../chunk-UD6H6EP6.js";
6
+ import "../chunk-RNICEX6N.js";
7
7
  import "../chunk-7Q3BJMLG.js";
8
- import "../chunk-FMAHQRIU.js";
8
+ import "../chunk-OSWBZKK5.js";
9
9
  import "../chunk-ZEC4LRKS.js";
10
10
  import "../chunk-QVK6VGCV.js";
11
- import "../chunk-SKZHAYNF.js";
11
+ import "../chunk-UM5U6FPH.js";
12
12
  import "../chunk-K7YUPLES.js";
13
13
  export {
14
14
  createOtlpServer,
package/dist/pricing.js CHANGED
@@ -2,8 +2,8 @@ import {
2
2
  COST_EXPR,
3
3
  refreshIfStale,
4
4
  refreshPricing
5
- } from "./chunk-FMAHQRIU.js";
6
- import "./chunk-SKZHAYNF.js";
5
+ } from "./chunk-OSWBZKK5.js";
6
+ import "./chunk-UM5U6FPH.js";
7
7
  import "./chunk-K7YUPLES.js";
8
8
  export {
9
9
  COST_EXPR,
@@ -2,15 +2,15 @@ import {
2
2
  createProxyServer,
3
3
  handleProxyRequest,
4
4
  tunnelWebSocket
5
- } from "../chunk-NE7VBLQD.js";
6
- import "../chunk-V3XR2TAN.js";
5
+ } from "../chunk-2PMFNSGA.js";
6
+ import "../chunk-UD6H6EP6.js";
7
7
  import "../chunk-YVRWVDIA.js";
8
8
  import "../chunk-3ILOOWUF.js";
9
- import "../chunk-J3HVD4VI.js";
9
+ import "../chunk-RNICEX6N.js";
10
10
  import "../chunk-7Q3BJMLG.js";
11
11
  import "../chunk-ZEC4LRKS.js";
12
12
  import "../chunk-QVK6VGCV.js";
13
- import "../chunk-SKZHAYNF.js";
13
+ import "../chunk-UM5U6FPH.js";
14
14
  import "../chunk-K7YUPLES.js";
15
15
  export {
16
16
  createProxyServer,
package/dist/prune.js CHANGED
@@ -2,8 +2,8 @@ import {
2
2
  autoPrune,
3
3
  pruneEstimate,
4
4
  pruneExecute
5
- } from "./chunk-WXPT6KG7.js";
6
- import "./chunk-SKZHAYNF.js";
5
+ } from "./chunk-7NBZ4NMJ.js";
6
+ import "./chunk-UM5U6FPH.js";
7
7
  import "./chunk-K7YUPLES.js";
8
8
  export {
9
9
  autoPrune,
package/dist/query.js CHANGED
@@ -8,10 +8,10 @@ import {
8
8
  rawQuery,
9
9
  search,
10
10
  sessionTimeline
11
- } from "./chunk-GPTBERQD.js";
11
+ } from "./chunk-UDUBRSIG.js";
12
12
  import "./chunk-ZEC4LRKS.js";
13
13
  import "./chunk-QVK6VGCV.js";
14
- import "./chunk-SKZHAYNF.js";
14
+ import "./chunk-UM5U6FPH.js";
15
15
  import "./chunk-K7YUPLES.js";
16
16
  export {
17
17
  activitySummary,
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  reparseAll
3
- } from "./chunk-OROLSIWZ.js";
4
- import "./chunk-V3XR2TAN.js";
3
+ } from "./chunk-5FRYHDPJ.js";
4
+ import "./chunk-UD6H6EP6.js";
5
5
  import "./chunk-YVRWVDIA.js";
6
6
  import "./chunk-7Q3BJMLG.js";
7
- import "./chunk-FMAHQRIU.js";
7
+ import "./chunk-OSWBZKK5.js";
8
8
  import "./chunk-QVK6VGCV.js";
9
- import "./chunk-SKZHAYNF.js";
9
+ import "./chunk-UM5U6FPH.js";
10
10
  import "./chunk-K7YUPLES.js";
11
11
  export {
12
12
  reparseAll
13
13
  };
14
- //# sourceMappingURL=reparse-VHUSGCPN.js.map
14
+ //# sourceMappingURL=reparse-TFYD67WP.js.map
package/dist/server.js CHANGED
@@ -1,23 +1,23 @@
1
1
  import {
2
2
  createUnifiedServer
3
- } from "./chunk-BKGQJ76N.js";
4
- import "./chunk-OW52TNVA.js";
5
- import "./chunk-NE7VBLQD.js";
6
- import "./chunk-3ZT3V7FP.js";
7
- import "./chunk-OROLSIWZ.js";
8
- import "./chunk-V3XR2TAN.js";
3
+ } from "./chunk-YV2AN73J.js";
4
+ import "./chunk-5IPC5XXZ.js";
5
+ import "./chunk-2PMFNSGA.js";
6
+ import "./chunk-75IXBXBO.js";
7
+ import "./chunk-5FRYHDPJ.js";
8
+ import "./chunk-UD6H6EP6.js";
9
9
  import "./chunk-YVRWVDIA.js";
10
- import "./chunk-WXPT6KG7.js";
10
+ import "./chunk-7NBZ4NMJ.js";
11
11
  import "./chunk-3ILOOWUF.js";
12
- import "./chunk-J3HVD4VI.js";
12
+ import "./chunk-RNICEX6N.js";
13
13
  import "./chunk-7Q3BJMLG.js";
14
- import "./chunk-FMAHQRIU.js";
15
- import "./chunk-MEVW27U4.js";
14
+ import "./chunk-OSWBZKK5.js";
15
+ import "./chunk-P5KAIE3O.js";
16
16
  import "./chunk-QK5442ZP.js";
17
- import "./chunk-GPTBERQD.js";
17
+ import "./chunk-UDUBRSIG.js";
18
18
  import "./chunk-ZEC4LRKS.js";
19
19
  import "./chunk-QVK6VGCV.js";
20
- import "./chunk-SKZHAYNF.js";
20
+ import "./chunk-UM5U6FPH.js";
21
21
  import "./chunk-K7YUPLES.js";
22
22
  export {
23
23
  createUnifiedServer
package/dist/setup.js CHANGED
@@ -2,11 +2,11 @@ import {
2
2
  configureShellEnv,
3
3
  fetchPricing,
4
4
  initDb
5
- } from "./chunk-HRNZUHTA.js";
6
- import "./chunk-FMAHQRIU.js";
5
+ } from "./chunk-RRHBTXHB.js";
6
+ import "./chunk-OSWBZKK5.js";
7
7
  import "./chunk-ZEC4LRKS.js";
8
8
  import "./chunk-QVK6VGCV.js";
9
- import "./chunk-SKZHAYNF.js";
9
+ import "./chunk-UM5U6FPH.js";
10
10
  import {
11
11
  config
12
12
  } from "./chunk-K7YUPLES.js";
@@ -5,17 +5,17 @@ import {
5
5
  loadSyncConfig,
6
6
  removeTarget,
7
7
  saveSyncConfig
8
- } from "../chunk-3ZT3V7FP.js";
9
- import "../chunk-J3HVD4VI.js";
8
+ } from "../chunk-75IXBXBO.js";
9
+ import "../chunk-RNICEX6N.js";
10
10
  import "../chunk-7Q3BJMLG.js";
11
11
  import {
12
12
  TABLE_SYNC_REGISTRY,
13
13
  readWatermark,
14
14
  resetWatermarks,
15
15
  watermarkKey
16
- } from "../chunk-MEVW27U4.js";
16
+ } from "../chunk-P5KAIE3O.js";
17
17
  import "../chunk-QK5442ZP.js";
18
- import "../chunk-SKZHAYNF.js";
18
+ import "../chunk-UM5U6FPH.js";
19
19
  import "../chunk-K7YUPLES.js";
20
20
  export {
21
21
  TABLE_SYNC_REGISTRY,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fml-inc/panopticon",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Observability for Claude Code — captures OTel signals and hook events, queryable via MCP",
5
5
  "type": "module",
6
6
  "engines": {
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/db/migrations.ts","../src/db/schema.ts"],"sourcesContent":["/**\n * Schema migration system for panopticon's embedded SQLite database.\n *\n * ## Conventions\n *\n * 1. SCHEMA_SQL in schema.ts is ALWAYS the latest desired schema.\n * It uses CREATE TABLE IF NOT EXISTS, making it idempotent.\n *\n * 2. When adding a column: update the CREATE TABLE in SCHEMA_SQL\n * AND add a migration here with ALTER TABLE ADD COLUMN.\n * Both must exist. SCHEMA_SQL handles fresh DBs; migrations\n * handle existing DBs.\n *\n * 3. When adding a new table: add it to SCHEMA_SQL. No migration\n * needed (CREATE TABLE IF NOT EXISTS handles it).\n *\n * 4. When adding an index: add it to SCHEMA_SQL. No migration\n * needed (CREATE INDEX IF NOT EXISTS handles it).\n *\n * 5. For complex changes (data backfill, column rename via rebuild,\n * virtual table recreation): add an `up` function migration.\n * Update SCHEMA_SQL to reflect the final state.\n *\n * 6. Never reorder or remove migrations. Only append.\n *\n * 7. Migration IDs are sequential integers starting from 1.\n *\n * 8. No down migrations. This is an embedded app — users always\n * upgrade forward. Rolling back means reinstalling.\n */\n\nimport type Database from \"better-sqlite3\";\n\nexport interface Migration {\n id: number;\n name: string;\n /** Simple migrations: single SQL statement. */\n sql?: string;\n /** Complex migrations: function that receives the db handle. */\n up?: (db: Database.Database) => void;\n}\n\n// ---------------------------------------------------------------------------\n// Migration registry — append only, never reorder or remove\n// ---------------------------------------------------------------------------\n\nexport const MIGRATIONS: Migration[] = [\n {\n id: 1,\n name: \"add_plugin_hooks_to_user_config\",\n sql: \"ALTER TABLE user_config_snapshots ADD COLUMN plugin_hooks JSON NOT NULL DEFAULT '[]'\",\n },\n];\n\n// ---------------------------------------------------------------------------\n// Migration runner\n// ---------------------------------------------------------------------------\n\n/**\n * Apply pending schema migrations to the database.\n *\n * On a fresh database (where SCHEMA_SQL just created all tables with all\n * columns), the `schema_migrations` table won't exist yet. In that case\n * we stamp all migrations as applied without executing them — SCHEMA_SQL\n * already reflects the final state.\n *\n * On an existing database, unapplied migrations run sequentially inside\n * transactions.\n */\nexport function runMigrations(\n db: Database.Database,\n migrations: Migration[] = MIGRATIONS,\n): void {\n const trackingExists = db\n .prepare(\n \"SELECT 1 FROM sqlite_master WHERE type='table' AND name='schema_migrations'\",\n )\n .get();\n\n db.exec(`\n CREATE TABLE IF NOT EXISTS schema_migrations (\n id INTEGER PRIMARY KEY,\n name TEXT NOT NULL,\n applied_at TEXT NOT NULL DEFAULT (datetime('now'))\n )\n `);\n\n if (!trackingExists) {\n // Fresh database: SCHEMA_SQL already created everything.\n // Stamp all migrations as applied without executing them.\n const stamp = db.prepare(\n \"INSERT INTO schema_migrations (id, name) VALUES (?, ?)\",\n );\n for (const m of migrations) {\n stamp.run(m.id, m.name);\n }\n return;\n }\n\n // Existing database: run unapplied migrations sequentially\n const applied = new Set(\n (\n db.prepare(\"SELECT id FROM schema_migrations\").all() as Array<{\n id: number;\n }>\n ).map((r) => r.id),\n );\n\n for (const migration of migrations) {\n if (applied.has(migration.id)) continue;\n const run = db.transaction(() => {\n if (migration.sql) {\n db.exec(migration.sql);\n } else if (migration.up) {\n migration.up(db);\n }\n db.prepare(\"INSERT INTO schema_migrations (id, name) VALUES (?, ?)\").run(\n migration.id,\n migration.name,\n );\n });\n run();\n }\n}\n","import fs from \"node:fs\";\nimport { gunzipSync } from \"node:zlib\";\nimport Database from \"better-sqlite3\";\nimport { config } from \"../config.js\";\nimport { runMigrations } from \"./migrations.js\";\n\nexport { runMigrations } from \"./migrations.js\";\n\nexport const SCHEMA_SQL = `\n\n-- ── OTLP tables ─────────────────────────────────────────────────────────────\n\nCREATE TABLE IF NOT EXISTS otel_logs (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n timestamp_ns INTEGER NOT NULL,\n observed_timestamp_ns INTEGER,\n severity_number INTEGER,\n severity_text TEXT,\n body TEXT,\n attributes JSON,\n resource_attributes JSON,\n session_id TEXT,\n prompt_id TEXT,\n trace_id TEXT,\n span_id TEXT,\n sync_id TEXT DEFAULT (hex(randomblob(8)))\n);\n\nCREATE TABLE IF NOT EXISTS otel_metrics (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n timestamp_ns INTEGER NOT NULL,\n name TEXT NOT NULL,\n value REAL NOT NULL,\n metric_type TEXT,\n unit TEXT,\n attributes JSON,\n resource_attributes JSON,\n session_id TEXT,\n sync_id TEXT DEFAULT (hex(randomblob(8)))\n);\n\nCREATE TABLE IF NOT EXISTS otel_spans (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n trace_id TEXT NOT NULL,\n span_id TEXT NOT NULL,\n parent_span_id TEXT,\n name TEXT NOT NULL,\n kind INTEGER,\n start_time_ns INTEGER NOT NULL,\n end_time_ns INTEGER NOT NULL,\n status_code INTEGER,\n status_message TEXT,\n attributes JSON,\n resource_attributes JSON,\n session_id TEXT,\n UNIQUE(trace_id, span_id)\n);\n\n-- ── Hook events ─────────────────────────────────────────────────────────────\n\nCREATE TABLE IF NOT EXISTS hook_events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n session_id TEXT NOT NULL,\n event_type TEXT NOT NULL,\n timestamp_ms INTEGER NOT NULL,\n cwd TEXT,\n repository TEXT,\n tool_name TEXT,\n payload BLOB NOT NULL,\n user_prompt TEXT,\n file_path TEXT,\n command TEXT,\n plan TEXT,\n allowed_prompts TEXT,\n tool_result TEXT,\n target TEXT,\n sync_id TEXT DEFAULT (hex(randomblob(8)))\n);\n\nCREATE VIRTUAL TABLE IF NOT EXISTS hook_events_fts USING fts5(\n payload,\n content='',\n contentless_delete=1,\n tokenize='trigram'\n);\n\n-- ── Sessions ────────────────────────────────────────────────────────────────\n\nCREATE TABLE IF NOT EXISTS sessions (\n session_id TEXT PRIMARY KEY,\n target TEXT,\n started_at_ms INTEGER,\n ended_at_ms INTEGER,\n cwd TEXT,\n first_prompt TEXT,\n permission_mode TEXT,\n agent_version TEXT,\n model TEXT,\n cli_version TEXT,\n scanner_file_path TEXT,\n total_input_tokens INTEGER DEFAULT 0,\n total_output_tokens INTEGER DEFAULT 0,\n total_cache_read_tokens INTEGER DEFAULT 0,\n total_cache_creation_tokens INTEGER DEFAULT 0,\n total_reasoning_tokens INTEGER DEFAULT 0,\n turn_count INTEGER DEFAULT 0,\n otel_input_tokens INTEGER DEFAULT 0,\n otel_output_tokens INTEGER DEFAULT 0,\n otel_cache_read_tokens INTEGER DEFAULT 0,\n otel_cache_creation_tokens INTEGER DEFAULT 0,\n models TEXT,\n has_hooks INTEGER DEFAULT 0,\n has_otel INTEGER DEFAULT 0,\n has_scanner INTEGER DEFAULT 0,\n summary TEXT,\n summary_version INTEGER DEFAULT 0,\n sync_dirty INTEGER DEFAULT 0,\n sync_seq INTEGER DEFAULT 0,\n tool_counts JSON DEFAULT '{}',\n hook_tool_counts JSON DEFAULT '{}',\n event_type_counts JSON DEFAULT '{}',\n hook_event_type_counts JSON DEFAULT '{}',\n project TEXT,\n machine TEXT NOT NULL DEFAULT 'local',\n message_count INTEGER DEFAULT 0,\n user_message_count INTEGER DEFAULT 0,\n parent_session_id TEXT,\n relationship_type TEXT DEFAULT '',\n is_automated INTEGER DEFAULT 0,\n created_at INTEGER\n);\n\nCREATE TABLE IF NOT EXISTS session_repositories (\n session_id TEXT NOT NULL,\n repository TEXT NOT NULL,\n first_seen_ms INTEGER NOT NULL,\n git_user_name TEXT,\n git_user_email TEXT,\n branch TEXT,\n UNIQUE(session_id, repository)\n);\n\nCREATE TABLE IF NOT EXISTS session_cwds (\n session_id TEXT NOT NULL,\n cwd TEXT NOT NULL,\n first_seen_ms INTEGER NOT NULL,\n UNIQUE(session_id, cwd)\n);\n\n-- ── Messages ────────────────────────────────────────────────────────────────\n\nCREATE TABLE IF NOT EXISTS messages (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n session_id TEXT NOT NULL,\n ordinal INTEGER NOT NULL,\n role TEXT NOT NULL,\n content TEXT NOT NULL,\n timestamp_ms INTEGER,\n has_thinking INTEGER NOT NULL DEFAULT 0,\n has_tool_use INTEGER NOT NULL DEFAULT 0,\n content_length INTEGER NOT NULL DEFAULT 0,\n is_system INTEGER NOT NULL DEFAULT 0,\n model TEXT NOT NULL DEFAULT '',\n token_usage TEXT NOT NULL DEFAULT '',\n context_tokens INTEGER NOT NULL DEFAULT 0,\n output_tokens INTEGER NOT NULL DEFAULT 0,\n has_context_tokens INTEGER NOT NULL DEFAULT 0,\n has_output_tokens INTEGER NOT NULL DEFAULT 0,\n uuid TEXT,\n parent_uuid TEXT,\n UNIQUE(session_id, ordinal)\n);\n\nCREATE VIRTUAL TABLE IF NOT EXISTS messages_fts USING fts5(\n content,\n content='',\n contentless_delete=1,\n tokenize='trigram'\n);\n\n-- ── Tool calls ──────────────────────────────────────────────────────────────\n\nCREATE TABLE IF NOT EXISTS tool_calls (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n message_id INTEGER NOT NULL,\n session_id TEXT NOT NULL,\n tool_name TEXT NOT NULL,\n category TEXT NOT NULL,\n tool_use_id TEXT,\n input_json TEXT,\n skill_name TEXT,\n result_content_length INTEGER,\n result_content TEXT,\n duration_ms INTEGER,\n subagent_session_id TEXT,\n sync_id TEXT DEFAULT (hex(randomblob(8)))\n);\n\n-- ── Scanner tables ──────────────────────────────────────────────────────────\n\nCREATE TABLE IF NOT EXISTS scanner_turns (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n session_id TEXT NOT NULL,\n source TEXT NOT NULL,\n turn_index INTEGER NOT NULL,\n timestamp_ms INTEGER NOT NULL,\n model TEXT,\n role TEXT,\n content_preview TEXT,\n input_tokens INTEGER DEFAULT 0,\n output_tokens INTEGER DEFAULT 0,\n cache_read_tokens INTEGER DEFAULT 0,\n cache_creation_tokens INTEGER DEFAULT 0,\n reasoning_tokens INTEGER DEFAULT 0,\n sync_id TEXT DEFAULT (hex(randomblob(8))),\n UNIQUE(session_id, source, turn_index)\n);\n\nCREATE TABLE IF NOT EXISTS scanner_events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n session_id TEXT NOT NULL,\n source TEXT NOT NULL,\n event_type TEXT NOT NULL,\n timestamp_ms INTEGER NOT NULL,\n tool_name TEXT,\n tool_input TEXT,\n tool_output TEXT,\n content TEXT,\n metadata JSON,\n sync_id TEXT DEFAULT (hex(randomblob(8))),\n UNIQUE(session_id, source, event_type, timestamp_ms, tool_name)\n);\n\nCREATE TABLE IF NOT EXISTS scanner_file_watermarks (\n file_path TEXT PRIMARY KEY,\n byte_offset INTEGER NOT NULL DEFAULT 0,\n last_scanned_ms INTEGER NOT NULL,\n archived_size INTEGER DEFAULT 0\n);\n\n-- ── Session summaries ───────────────────────────────────────────────────────\n\nCREATE TABLE IF NOT EXISTS session_summary_deltas (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n session_id TEXT NOT NULL,\n delta_index INTEGER NOT NULL,\n created_at_ms INTEGER NOT NULL,\n from_turn INTEGER NOT NULL,\n to_turn INTEGER NOT NULL,\n content TEXT NOT NULL,\n method TEXT NOT NULL DEFAULT 'deterministic',\n UNIQUE(session_id, delta_index)\n);\n\n-- ── Model pricing ───────────────────────────────────────────────────────────\n\nCREATE TABLE IF NOT EXISTS model_pricing (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n model_id TEXT NOT NULL,\n input_per_m REAL NOT NULL,\n output_per_m REAL NOT NULL,\n cache_read_per_m REAL NOT NULL DEFAULT 0,\n cache_write_per_m REAL NOT NULL DEFAULT 0,\n updated_ms INTEGER NOT NULL\n);\n\n-- ── Config snapshots ────────────────────────────────────────────────────────\n\nCREATE TABLE IF NOT EXISTS user_config_snapshots (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n device_name TEXT NOT NULL,\n snapshot_at_ms INTEGER NOT NULL,\n content_hash TEXT NOT NULL,\n permissions JSON NOT NULL DEFAULT '{}',\n enabled_plugins JSON NOT NULL DEFAULT '[]',\n hooks JSON NOT NULL DEFAULT '[]',\n commands JSON NOT NULL DEFAULT '[]',\n rules JSON NOT NULL DEFAULT '[]',\n skills JSON NOT NULL DEFAULT '[]',\n plugin_hooks JSON NOT NULL DEFAULT '[]'\n);\n\nCREATE TABLE IF NOT EXISTS repo_config_snapshots (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n repository TEXT NOT NULL,\n cwd TEXT NOT NULL,\n session_id TEXT,\n snapshot_at_ms INTEGER NOT NULL,\n content_hash TEXT NOT NULL,\n hooks JSON NOT NULL DEFAULT '[]',\n mcp_servers JSON NOT NULL DEFAULT '[]',\n commands JSON NOT NULL DEFAULT '[]',\n agents JSON NOT NULL DEFAULT '[]',\n rules JSON NOT NULL DEFAULT '[]',\n local_hooks JSON NOT NULL DEFAULT '[]',\n local_mcp_servers JSON NOT NULL DEFAULT '[]',\n local_permissions JSON NOT NULL DEFAULT '{}',\n local_is_gitignored INTEGER NOT NULL DEFAULT 1,\n instructions JSON NOT NULL DEFAULT '[]'\n);\n\n-- ── Sync watermarks ─────────────────────────────────────────────────────────\n\nCREATE TABLE IF NOT EXISTS watermarks (\n key TEXT PRIMARY KEY,\n value INTEGER NOT NULL\n);\n\n-- ── Per-session sync state ─────────────────────────────────────────────────\n\nDROP TABLE IF EXISTS pending_session_sync;\n\nCREATE TABLE IF NOT EXISTS target_session_sync (\n session_id TEXT NOT NULL,\n target TEXT NOT NULL,\n confirmed INTEGER DEFAULT 0,\n sync_seq INTEGER DEFAULT 0,\n synced_seq INTEGER DEFAULT 0,\n wm_messages INTEGER DEFAULT 0,\n wm_tool_calls INTEGER DEFAULT 0,\n wm_scanner_turns INTEGER DEFAULT 0,\n wm_scanner_events INTEGER DEFAULT 0,\n wm_hook_events INTEGER DEFAULT 0,\n wm_otel_logs INTEGER DEFAULT 0,\n wm_otel_metrics INTEGER DEFAULT 0,\n wm_otel_spans INTEGER DEFAULT 0,\n PRIMARY KEY (session_id, target)\n);\n\n-- ── Indexes ─────────────────────────────────────────────────────────────────\n\n-- otel_logs\nCREATE INDEX IF NOT EXISTS idx_logs_session ON otel_logs(session_id);\nCREATE INDEX IF NOT EXISTS idx_logs_body ON otel_logs(body);\nCREATE INDEX IF NOT EXISTS idx_logs_ts ON otel_logs(timestamp_ns);\nCREATE INDEX IF NOT EXISTS idx_logs_prompt ON otel_logs(prompt_id);\n\n-- otel_metrics\nCREATE INDEX IF NOT EXISTS idx_metrics_session ON otel_metrics(session_id);\nCREATE INDEX IF NOT EXISTS idx_metrics_name ON otel_metrics(name);\nCREATE INDEX IF NOT EXISTS idx_metrics_ts ON otel_metrics(timestamp_ns);\n\n-- otel_spans\nCREATE INDEX IF NOT EXISTS idx_spans_session ON otel_spans(session_id);\nCREATE INDEX IF NOT EXISTS idx_spans_trace ON otel_spans(trace_id);\nCREATE INDEX IF NOT EXISTS idx_spans_start ON otel_spans(start_time_ns);\n\n-- hook_events\nCREATE INDEX IF NOT EXISTS idx_hooks_session ON hook_events(session_id);\nCREATE INDEX IF NOT EXISTS idx_hooks_type ON hook_events(event_type);\nCREATE INDEX IF NOT EXISTS idx_hooks_tool ON hook_events(tool_name);\nCREATE INDEX IF NOT EXISTS idx_hooks_ts ON hook_events(timestamp_ms);\nCREATE INDEX IF NOT EXISTS idx_hooks_file_path ON hook_events(file_path);\nCREATE INDEX IF NOT EXISTS idx_hooks_target ON hook_events(target);\n\n-- sessions\nCREATE INDEX IF NOT EXISTS idx_sessions_target ON sessions(target);\nCREATE INDEX IF NOT EXISTS idx_sessions_started ON sessions(started_at_ms);\nCREATE INDEX IF NOT EXISTS idx_sessions_sync_seq ON sessions(sync_seq);\nCREATE INDEX IF NOT EXISTS idx_sessions_project ON sessions(project);\nCREATE INDEX IF NOT EXISTS idx_sessions_machine ON sessions(machine);\nCREATE INDEX IF NOT EXISTS idx_sessions_parent ON sessions(parent_session_id)\n WHERE parent_session_id IS NOT NULL;\n\n-- session_repositories\nCREATE INDEX IF NOT EXISTS idx_session_repos_session ON session_repositories(session_id);\nCREATE INDEX IF NOT EXISTS idx_session_repos_repo ON session_repositories(repository);\n\n-- session_cwds\nCREATE INDEX IF NOT EXISTS idx_session_cwds_session ON session_cwds(session_id);\n\n-- messages\nCREATE INDEX IF NOT EXISTS idx_messages_session_ordinal ON messages(session_id, ordinal);\nCREATE INDEX IF NOT EXISTS idx_messages_session_role ON messages(session_id, role);\n\n-- tool_calls\nCREATE INDEX IF NOT EXISTS idx_tool_calls_session ON tool_calls(session_id);\nCREATE INDEX IF NOT EXISTS idx_tool_calls_category ON tool_calls(category);\nCREATE INDEX IF NOT EXISTS idx_tool_calls_skill ON tool_calls(skill_name)\n WHERE skill_name IS NOT NULL;\nCREATE INDEX IF NOT EXISTS idx_tool_calls_subagent ON tool_calls(subagent_session_id)\n WHERE subagent_session_id IS NOT NULL;\n\n-- scanner_turns\nCREATE INDEX IF NOT EXISTS idx_scanner_turns_session ON scanner_turns(session_id);\nCREATE INDEX IF NOT EXISTS idx_scanner_turns_ts ON scanner_turns(timestamp_ms);\n\n-- scanner_events\nCREATE INDEX IF NOT EXISTS idx_scanner_events_session ON scanner_events(session_id);\nCREATE INDEX IF NOT EXISTS idx_scanner_events_type ON scanner_events(event_type);\n\n-- session_summary_deltas\nCREATE INDEX IF NOT EXISTS idx_summary_deltas_session ON session_summary_deltas(session_id);\n\n-- model_pricing\nCREATE INDEX IF NOT EXISTS idx_model_pricing_model ON model_pricing(model_id, updated_ms);\n\n-- user_config_snapshots\nCREATE INDEX IF NOT EXISTS idx_user_config_ts ON user_config_snapshots(snapshot_at_ms);\nCREATE INDEX IF NOT EXISTS idx_user_config_device_hash ON user_config_snapshots(device_name, content_hash);\n\n-- repo_config_snapshots\nCREATE INDEX IF NOT EXISTS idx_repo_config_repo_ts ON repo_config_snapshots(repository, snapshot_at_ms);\nCREATE INDEX IF NOT EXISTS idx_repo_config_session ON repo_config_snapshots(session_id);\nCREATE INDEX IF NOT EXISTS idx_repo_config_repo_hash ON repo_config_snapshots(repository, content_hash);\n\n`;\n\n/**\n * Scanner data version. Increment when parser logic changes in ways that\n * affect stored data (new fields extracted, content formatting changes,\n * fork detection improvements, etc.). On startup, if the DB's user_version\n * is lower than this, a full resync is triggered automatically.\n */\nexport const SCANNER_DATA_VERSION = 1;\n\n// ---------------------------------------------------------------------------\n// Database initialization\n// ---------------------------------------------------------------------------\n\nlet _db: Database.Database | null = null;\nlet _needsResync = false;\n\nfunction registerCompressionFunctions(db: Database.Database): void {\n db.function(\"decompress\", (blob: Buffer | null) =>\n blob ? gunzipSync(blob).toString() : null,\n );\n}\n\nexport function getDb(): Database.Database {\n // If the db file was deleted (e.g. uninstall --purge) while this process\n // still holds a stale connection, drop it so we don't serve old data.\n if (_db && !fs.existsSync(config.dbPath)) {\n try {\n _db.close();\n } catch {}\n _db = null;\n }\n if (_db) return _db;\n\n // Don't auto-create the data directory — callers that need to bootstrap\n // the DB (install, initDb, hook handler) call ensureDataDir() first.\n if (!fs.existsSync(config.dataDir)) {\n throw new Error(\n `Panopticon data directory not found: ${config.dataDir}. Run \"panopticon install\" to set up.`,\n );\n }\n\n _db = new Database(config.dbPath);\n _db.pragma(\"auto_vacuum = INCREMENTAL\");\n _db.pragma(\"journal_mode = WAL\");\n _db.pragma(\"busy_timeout = 5000\");\n\n registerCompressionFunctions(_db);\n _db.exec(SCHEMA_SQL);\n runMigrations(_db);\n\n // Check data version for resync\n const currentVersion = (_db.pragma(\"user_version\", { simple: true }) ??\n 0) as number;\n if (currentVersion < SCANNER_DATA_VERSION) {\n _needsResync = true;\n } else {\n _needsResync = false;\n }\n\n return _db;\n}\n\n/** True when the DB was opened with a stale data version. */\nexport function needsResync(): boolean {\n return _needsResync;\n}\n\n/** Mark resync as complete and stamp the current data version. */\nexport function markResyncComplete(): void {\n _needsResync = false;\n const db = getDb();\n db.pragma(`user_version = ${SCANNER_DATA_VERSION}`);\n}\n\nexport function closeDb(): void {\n if (_db) {\n _db.close();\n _db = null;\n }\n}\n"],"mappings":";;;;;AA8CO,IAAM,aAA0B;AAAA,EACrC;AAAA,IACE,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,KAAK;AAAA,EACP;AACF;AAiBO,SAAS,cACd,IACA,aAA0B,YACpB;AACN,QAAM,iBAAiB,GACpB;AAAA,IACC;AAAA,EACF,EACC,IAAI;AAEP,KAAG,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAMP;AAED,MAAI,CAAC,gBAAgB;AAGnB,UAAM,QAAQ,GAAG;AAAA,MACf;AAAA,IACF;AACA,eAAW,KAAK,YAAY;AAC1B,YAAM,IAAI,EAAE,IAAI,EAAE,IAAI;AAAA,IACxB;AACA;AAAA,EACF;AAGA,QAAM,UAAU,IAAI;AAAA,IAEhB,GAAG,QAAQ,kCAAkC,EAAE,IAAI,EAGnD,IAAI,CAAC,MAAM,EAAE,EAAE;AAAA,EACnB;AAEA,aAAW,aAAa,YAAY;AAClC,QAAI,QAAQ,IAAI,UAAU,EAAE,EAAG;AAC/B,UAAM,MAAM,GAAG,YAAY,MAAM;AAC/B,UAAI,UAAU,KAAK;AACjB,WAAG,KAAK,UAAU,GAAG;AAAA,MACvB,WAAW,UAAU,IAAI;AACvB,kBAAU,GAAG,EAAE;AAAA,MACjB;AACA,SAAG,QAAQ,wDAAwD,EAAE;AAAA,QACnE,UAAU;AAAA,QACV,UAAU;AAAA,MACZ;AAAA,IACF,CAAC;AACD,QAAI;AAAA,EACN;AACF;;;AC3HA,OAAO,QAAQ;AACf,SAAS,kBAAkB;AAC3B,OAAO,cAAc;AAMd,IAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsZnB,IAAM,uBAAuB;AAMpC,IAAI,MAAgC;AACpC,IAAI,eAAe;AAEnB,SAAS,6BAA6B,IAA6B;AACjE,KAAG;AAAA,IAAS;AAAA,IAAc,CAAC,SACzB,OAAO,WAAW,IAAI,EAAE,SAAS,IAAI;AAAA,EACvC;AACF;AAEO,SAAS,QAA2B;AAGzC,MAAI,OAAO,CAAC,GAAG,WAAW,OAAO,MAAM,GAAG;AACxC,QAAI;AACF,UAAI,MAAM;AAAA,IACZ,QAAQ;AAAA,IAAC;AACT,UAAM;AAAA,EACR;AACA,MAAI,IAAK,QAAO;AAIhB,MAAI,CAAC,GAAG,WAAW,OAAO,OAAO,GAAG;AAClC,UAAM,IAAI;AAAA,MACR,wCAAwC,OAAO,OAAO;AAAA,IACxD;AAAA,EACF;AAEA,QAAM,IAAI,SAAS,OAAO,MAAM;AAChC,MAAI,OAAO,2BAA2B;AACtC,MAAI,OAAO,oBAAoB;AAC/B,MAAI,OAAO,qBAAqB;AAEhC,+BAA6B,GAAG;AAChC,MAAI,KAAK,UAAU;AACnB,gBAAc,GAAG;AAGjB,QAAM,iBAAkB,IAAI,OAAO,gBAAgB,EAAE,QAAQ,KAAK,CAAC,KACjE;AACF,MAAI,iBAAiB,sBAAsB;AACzC,mBAAe;AAAA,EACjB,OAAO;AACL,mBAAe;AAAA,EACjB;AAEA,SAAO;AACT;AAGO,SAAS,cAAuB;AACrC,SAAO;AACT;AAGO,SAAS,qBAA2B;AACzC,iBAAe;AACf,QAAM,KAAK,MAAM;AACjB,KAAG,OAAO,kBAAkB,oBAAoB,EAAE;AACpD;AAEO,SAAS,UAAgB;AAC9B,MAAI,KAAK;AACP,QAAI,MAAM;AACV,UAAM;AAAA,EACR;AACF;","names":[]}