File size: 2,710 Bytes
cd8bd0a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
/**
 * Database module: InspectorCustomHosts
 * CRUD operations for inspector_custom_hosts table.
 */

import { getDbInstance } from "./core.ts";
import type { InspectorCustomHostRow } from "./_rowTypes.ts";

// SQLite stores booleans as integers
interface InspectorCustomHostDbRow {
  host: string;
  enabled: number;
  label: string | null;
  kind: string;
  added_at: string;
  last_seen_at: string | null;
}

function mapRow(row: InspectorCustomHostDbRow): InspectorCustomHostRow {
  return {
    host: row.host,
    enabled: row.enabled === 1,
    label: row.label,
    kind: row.kind as "llm" | "app" | "custom",
    added_at: row.added_at,
    last_seen_at: row.last_seen_at,
  };
}

export function listCustomHosts(opts?: { enabledOnly?: boolean }): InspectorCustomHostRow[] {
  const db = getDbInstance();
  const enabledOnly = opts?.enabledOnly === true;

  const rows = enabledOnly
    ? (db
        .prepare("SELECT * FROM inspector_custom_hosts WHERE enabled = 1 ORDER BY host ASC")
        .all() as InspectorCustomHostDbRow[])
    : (db
        .prepare("SELECT * FROM inspector_custom_hosts ORDER BY host ASC")
        .all() as InspectorCustomHostDbRow[]);

  return rows.map(mapRow);
}

export function addCustomHost(
  host: string,
  kind: "llm" | "app" | "custom" = "custom",
  label?: string
): void {
  const db = getDbInstance();
  const now = new Date().toISOString();
  db.prepare(
    `INSERT OR IGNORE INTO inspector_custom_hosts (host, enabled, label, kind, added_at)
     VALUES (?, 1, ?, ?, ?)`
  ).run(host, label ?? null, kind, now);
}

export function removeCustomHost(host: string): void {
  const db = getDbInstance();
  db.prepare("DELETE FROM inspector_custom_hosts WHERE host = ?").run(host);
}

export function toggleCustomHost(host: string, enabled: boolean): void {
  const db = getDbInstance();
  db.prepare("UPDATE inspector_custom_hosts SET enabled = ? WHERE host = ?").run(
    enabled ? 1 : 0,
    host
  );
}

export function touchLastSeen(host: string): void {
  const db = getDbInstance();
  const now = new Date().toISOString();
  db.prepare("UPDATE inspector_custom_hosts SET last_seen_at = ? WHERE host = ?").run(now, host);
}

/**
 * Returns true when `host` is present in inspector_custom_hosts with enabled=1.
 * Used by agentBridgeHook to distinguish custom-host intercepts from agent-bridge
 * intercepts so that Mode 2 (Custom Hosts) entries appear in the "Custom" profile.
 */
export function isCustomHost(host: string): boolean {
  const db = getDbInstance();
  const row = db
    .prepare("SELECT 1 AS found FROM inspector_custom_hosts WHERE host = ? AND enabled = 1")
    .get(host) as { found: number } | undefined;
  return row !== undefined;
}