@fml-inc/panopticon 0.1.0
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/.claude-plugin/plugin.json +10 -0
- package/LICENSE +5 -0
- package/README.md +363 -0
- package/bin/hook-handler +3 -0
- package/bin/mcp-server +3 -0
- package/bin/panopticon +3 -0
- package/bin/proxy +3 -0
- package/bin/server +3 -0
- package/dist/api/client.d.ts +67 -0
- package/dist/api/client.js +48 -0
- package/dist/api/client.js.map +1 -0
- package/dist/chunk-3BUJ7URA.js +387 -0
- package/dist/chunk-3BUJ7URA.js.map +1 -0
- package/dist/chunk-3TZAKV3M.js +158 -0
- package/dist/chunk-3TZAKV3M.js.map +1 -0
- package/dist/chunk-4SM2H22C.js +169 -0
- package/dist/chunk-4SM2H22C.js.map +1 -0
- package/dist/chunk-7Q3BJMLG.js +62 -0
- package/dist/chunk-7Q3BJMLG.js.map +1 -0
- package/dist/chunk-BVOE7A2Z.js +412 -0
- package/dist/chunk-BVOE7A2Z.js.map +1 -0
- package/dist/chunk-CF4GPWLI.js +170 -0
- package/dist/chunk-CF4GPWLI.js.map +1 -0
- package/dist/chunk-DZ5HJFB4.js +467 -0
- package/dist/chunk-DZ5HJFB4.js.map +1 -0
- package/dist/chunk-HQCY722C.js +428 -0
- package/dist/chunk-HQCY722C.js.map +1 -0
- package/dist/chunk-HRCEIYKU.js +134 -0
- package/dist/chunk-HRCEIYKU.js.map +1 -0
- package/dist/chunk-K7YUPLES.js +76 -0
- package/dist/chunk-K7YUPLES.js.map +1 -0
- package/dist/chunk-L7G27XWF.js +130 -0
- package/dist/chunk-L7G27XWF.js.map +1 -0
- package/dist/chunk-LWXF7YRG.js +626 -0
- package/dist/chunk-LWXF7YRG.js.map +1 -0
- package/dist/chunk-NXH7AONS.js +1120 -0
- package/dist/chunk-NXH7AONS.js.map +1 -0
- package/dist/chunk-QK5442ZP.js +55 -0
- package/dist/chunk-QK5442ZP.js.map +1 -0
- package/dist/chunk-QVK6VGCV.js +1703 -0
- package/dist/chunk-QVK6VGCV.js.map +1 -0
- package/dist/chunk-RX2RXHBH.js +1699 -0
- package/dist/chunk-RX2RXHBH.js.map +1 -0
- package/dist/chunk-SEXU2WYG.js +788 -0
- package/dist/chunk-SEXU2WYG.js.map +1 -0
- package/dist/chunk-SUGSQ4YI.js +264 -0
- package/dist/chunk-SUGSQ4YI.js.map +1 -0
- package/dist/chunk-TGXFVAID.js +138 -0
- package/dist/chunk-TGXFVAID.js.map +1 -0
- package/dist/chunk-WLBNFVIG.js +447 -0
- package/dist/chunk-WLBNFVIG.js.map +1 -0
- package/dist/chunk-XLTCUH5A.js +1072 -0
- package/dist/chunk-XLTCUH5A.js.map +1 -0
- package/dist/chunk-YVRWVDIA.js +146 -0
- package/dist/chunk-YVRWVDIA.js.map +1 -0
- package/dist/chunk-ZEC4LRKS.js +176 -0
- package/dist/chunk-ZEC4LRKS.js.map +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +1084 -0
- package/dist/cli.js.map +1 -0
- package/dist/config-NwoZC-GM.d.ts +20 -0
- package/dist/db.d.ts +46 -0
- package/dist/db.js +15 -0
- package/dist/db.js.map +1 -0
- package/dist/doctor.d.ts +37 -0
- package/dist/doctor.js +14 -0
- package/dist/doctor.js.map +1 -0
- package/dist/hooks/handler.d.ts +23 -0
- package/dist/hooks/handler.js +295 -0
- package/dist/hooks/handler.js.map +1 -0
- package/dist/index.d.ts +57 -0
- package/dist/index.js +101 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/server.d.ts +1 -0
- package/dist/mcp/server.js +243 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/otlp/server.d.ts +7 -0
- package/dist/otlp/server.js +17 -0
- package/dist/otlp/server.js.map +1 -0
- package/dist/permissions.d.ts +33 -0
- package/dist/permissions.js +14 -0
- package/dist/permissions.js.map +1 -0
- package/dist/pricing.d.ts +29 -0
- package/dist/pricing.js +13 -0
- package/dist/pricing.js.map +1 -0
- package/dist/proxy/server.d.ts +10 -0
- package/dist/proxy/server.js +20 -0
- package/dist/proxy/server.js.map +1 -0
- package/dist/prune.d.ts +18 -0
- package/dist/prune.js +13 -0
- package/dist/prune.js.map +1 -0
- package/dist/query.d.ts +56 -0
- package/dist/query.js +27 -0
- package/dist/query.js.map +1 -0
- package/dist/reparse-636YZCE3.js +14 -0
- package/dist/reparse-636YZCE3.js.map +1 -0
- package/dist/repo.d.ts +17 -0
- package/dist/repo.js +9 -0
- package/dist/repo.js.map +1 -0
- package/dist/scanner.d.ts +73 -0
- package/dist/scanner.js +15 -0
- package/dist/scanner.js.map +1 -0
- package/dist/sdk.d.ts +82 -0
- package/dist/sdk.js +208 -0
- package/dist/sdk.js.map +1 -0
- package/dist/server.d.ts +5 -0
- package/dist/server.js +25 -0
- package/dist/server.js.map +1 -0
- package/dist/setup.d.ts +35 -0
- package/dist/setup.js +19 -0
- package/dist/setup.js.map +1 -0
- package/dist/sync/index.d.ts +29 -0
- package/dist/sync/index.js +32 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/targets.d.ts +279 -0
- package/dist/targets.js +20 -0
- package/dist/targets.js.map +1 -0
- package/dist/types-D-MYCBol.d.ts +128 -0
- package/dist/types.d.ts +164 -0
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -0
- package/hooks/hooks.json +274 -0
- package/package.json +124 -0
- package/skills/panopticon-optimize/SKILL.md +222 -0
package/LICENSE
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
# Panopticon
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
<img src="panopticon.jpg" alt="Panopticon — Willey Reveley, 1791" width="480">
|
|
5
|
+
<br>
|
|
6
|
+
<em>Elevation and plan of Jeremy Bentham's Panopticon, drawn by Willey Reveley in 1791</em>
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
<br>
|
|
10
|
+
|
|
11
|
+
Self-contained observability for AI coding tools. Captures OpenTelemetry signals, hook events, API traffic, and local session files from Claude Code, Gemini CLI, and Codex CLI — stored in SQLite, queryable via MCP.
|
|
12
|
+
|
|
13
|
+
No Docker, no external services. Just Node.js.
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install -g @fml-inc/panopticon
|
|
19
|
+
panopticon install
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
This initializes the database, registers hooks and MCP servers in each detected tool, and configures OTel environment variables in your shell. Start a new session to activate.
|
|
23
|
+
|
|
24
|
+
To install for a specific tool only:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
panopticon install --target claude
|
|
28
|
+
panopticon install --target gemini
|
|
29
|
+
panopticon install --target codex
|
|
30
|
+
panopticon install --target claude-desktop
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Options:
|
|
34
|
+
|
|
35
|
+
| Flag | Description |
|
|
36
|
+
|------|-------------|
|
|
37
|
+
| `--target <t>` | Target: `claude`, `gemini`, `codex`, `claude-desktop`, or `all` (default: `all`) |
|
|
38
|
+
| `--proxy` | Route API traffic through the panopticon proxy |
|
|
39
|
+
| `--force` | Overwrite customized env vars with defaults |
|
|
40
|
+
|
|
41
|
+
### From source
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
git clone https://github.com/fml-inc/panopticon.git && cd panopticon
|
|
45
|
+
pnpm install && pnpm build
|
|
46
|
+
npm pack
|
|
47
|
+
npm install -g ./fml-inc-panopticon-*.tgz
|
|
48
|
+
panopticon install
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## How it works
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
55
|
+
│ Claude Code / Gemini CLI / Codex CLI │
|
|
56
|
+
│ │
|
|
57
|
+
│ ┌──────────┐ ┌──────────────┐ ┌───────────┐ ┌────────┐ │
|
|
58
|
+
│ │ OTel SDK │ │ Plugin Hooks │ │ Session │ │ API │ │
|
|
59
|
+
│ │ │ │ │ │ Files │ │ Proxy │ │
|
|
60
|
+
│ └────┬─────┘ └──────┬───────┘ └─────┬─────┘ └───┬────┘ │
|
|
61
|
+
└───────┼───────────────┼───────────────┼──────────────┼───────┘
|
|
62
|
+
│ │ │ │
|
|
63
|
+
▼ ▼ │ ▼
|
|
64
|
+
┌───────────────────────────────────────┼──────────────────────┐
|
|
65
|
+
│ Unified Panopticon Server (:4318) │
|
|
66
|
+
│ │ │
|
|
67
|
+
│ /v1/logs, /v1/metrics /hooks │ /proxy/anthropic │
|
|
68
|
+
│ (OTLP ingest) (hook JSON) │ /proxy/openai │
|
|
69
|
+
│ │ /proxy/google │
|
|
70
|
+
└──────────────────────┬────────────────┼──────────────────────┘
|
|
71
|
+
│ │
|
|
72
|
+
▼ ▼
|
|
73
|
+
┌─────────────────────────────────────┐
|
|
74
|
+
│ SQLite (WAL mode) │
|
|
75
|
+
│ │
|
|
76
|
+
│ sessions (unified, all sources) │
|
|
77
|
+
│ hook_events / otel_logs / metrics │
|
|
78
|
+
│ scanner_turns / scanner_events │
|
|
79
|
+
└──┬──────────┬──────────────┬────────┘
|
|
80
|
+
│ │ │
|
|
81
|
+
▼ ▼ ▼
|
|
82
|
+
┌──────────┐ ┌──────────┐ ┌───────────┐
|
|
83
|
+
│ MCP │ │ Sync │ │ Scanner │
|
|
84
|
+
│ Server │ │ Loop │ │ Loop │
|
|
85
|
+
│ (stdio) │ │ (OTLP) │ │ (60s poll)│
|
|
86
|
+
└──────────┘ └──────────┘ └───────────┘
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Five data pipelines feed one database:**
|
|
90
|
+
|
|
91
|
+
1. **Hook events** — Plugin hooks capture SessionStart, tool use (pre/post), prompts, and session end. Rich payloads including tool inputs and outputs.
|
|
92
|
+
|
|
93
|
+
2. **OTel logs** — Native telemetry events: API requests/responses, tool calls, user prompts, config, model routing. Includes cost, token counts, durations, model info.
|
|
94
|
+
|
|
95
|
+
3. **OTel metrics** — Time series: `token.usage`, `cost.usage`, `session.count`, `active_time.total`, `lines_of_code.count`, `commit.count`, `pull_request.count`.
|
|
96
|
+
|
|
97
|
+
4. **Session file scanner** — Reads local JSONL/JSON session files written by each CLI. Extracts per-turn token usage (input, output, cache read, cache creation, reasoning), tool calls, API errors, agent reasoning, and file snapshots. More complete than OTel for token data (captures ~2x the turns) and provides historical backfill for sessions before panopticon was installed.
|
|
98
|
+
|
|
99
|
+
5. **API proxy** — Transparent HTTP proxy for Anthropic, OpenAI, and Google AI APIs. Captures request/response pairs and emits them as hook events and OTel data. Enable with `panopticon install --proxy`.
|
|
100
|
+
|
|
101
|
+
All pipelines feed a **unified sessions table** — each session accumulates data from whichever sources are active, in any order, via COALESCE upserts.
|
|
102
|
+
|
|
103
|
+
**Sync** (optional) — OTLP export that tails the local SQLite and POSTs merged events to a remote OTLP receiver. Useful for forwarding to Grafana, Honeycomb, Datadog, etc.
|
|
104
|
+
|
|
105
|
+
**Scanner** — Polls local CLI session files every 60 seconds. Extracts per-turn token usage and events that OTel misses (reasoning tokens, cache breakdowns, tool calls with arguments/output, API errors with retry metadata). Backfills historical sessions from before panopticon was installed.
|
|
106
|
+
|
|
107
|
+
## Supported tools
|
|
108
|
+
|
|
109
|
+
| Tool | Hooks | OTel | Scanner | Proxy | Notes |
|
|
110
|
+
|------|-------|------|---------|-------|-------|
|
|
111
|
+
| Claude Code | Plugin marketplace | Native OTel SDK | `~/.claude/projects/` JSONL | Anthropic API | Full coverage; scanner captures API errors, file snapshots |
|
|
112
|
+
| Gemini CLI | `settings.json` hooks | Native OTel SDK (HTTP) | `~/.gemini/tmp/` JSON | Google AI API | Scanner captures tool calls, reasoning thoughts |
|
|
113
|
+
| Codex CLI | `hooks.json` | Native OTel SDK (HTTP) | `~/.codex/sessions/` JSONL | OpenAI API | Scanner captures tool calls, reasoning tokens, agent messages |
|
|
114
|
+
| Claude Desktop | MCP server | — | — | — | MCP query tools only |
|
|
115
|
+
|
|
116
|
+
Each tool is implemented as a **target adapter** in `src/targets/`. To add support for a new tool, create a single adapter file that declares config paths, hook events, shell env vars, event normalization, detection logic, and proxy routing — then register it in `src/targets/index.ts`.
|
|
117
|
+
|
|
118
|
+
## MCP tools
|
|
119
|
+
|
|
120
|
+
Once installed, these tools are available to the AI coding tool via MCP:
|
|
121
|
+
|
|
122
|
+
| Tool | Description |
|
|
123
|
+
|------|-------------|
|
|
124
|
+
| `panopticon_sessions` | List recent sessions with stats (event count, tools used, cost) |
|
|
125
|
+
| `panopticon_session_timeline` | Chronological events for a session (hooks + OTel merged) |
|
|
126
|
+
| `panopticon_tool_stats` | Per-tool aggregates: call count, success/failure |
|
|
127
|
+
| `panopticon_costs` | Token/cost breakdowns by session, model, or day |
|
|
128
|
+
| `panopticon_summary` | Activity summary for a time window (sessions, prompts, tools, files, costs) |
|
|
129
|
+
| `panopticon_plans` | Plans created via ExitPlanMode with full markdown content |
|
|
130
|
+
| `panopticon_search` | Full-text search across hook payloads (FTS5) and OTel log bodies |
|
|
131
|
+
| `panopticon_get_event` | Fetch full untruncated details for a specific event by source and ID |
|
|
132
|
+
| `panopticon_query` | Raw read-only SQL against the database |
|
|
133
|
+
| `panopticon_status` | Database row counts |
|
|
134
|
+
| `panopticon_permissions_show` | Show current permission approvals and allowed tools/commands |
|
|
135
|
+
| `panopticon_permissions_apply` | Apply permission rules (allowed tools/commands via PreToolUse hook) |
|
|
136
|
+
|
|
137
|
+
## CLI
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
panopticon install Register hooks, init DB, configure shell
|
|
141
|
+
--target <t> Target: claude, gemini, codex, claude-desktop, all (default: all)
|
|
142
|
+
--proxy Route API traffic through the panopticon proxy
|
|
143
|
+
--force Overwrite customized env vars with defaults
|
|
144
|
+
|
|
145
|
+
panopticon uninstall Remove hooks, shell config, and optionally all data
|
|
146
|
+
--target <t> Uninstall from a specific target only
|
|
147
|
+
--purge Also remove database and all data
|
|
148
|
+
|
|
149
|
+
panopticon update Show instructions to update via npm
|
|
150
|
+
|
|
151
|
+
panopticon start Start the server (background)
|
|
152
|
+
panopticon stop Stop the server
|
|
153
|
+
panopticon status Show server status and database stats
|
|
154
|
+
panopticon doctor Check system health, server, database, and configuration
|
|
155
|
+
|
|
156
|
+
panopticon logs [daemon] View daemon logs (server, otlp, mcp, proxy)
|
|
157
|
+
-f, --follow Follow log output (like tail -f)
|
|
158
|
+
-n <lines> Number of lines to show (default 50)
|
|
159
|
+
|
|
160
|
+
panopticon sessions List recent sessions with stats
|
|
161
|
+
--limit <n> Max sessions to return (default 20)
|
|
162
|
+
--since <duration> Time filter (e.g. "24h", "7d")
|
|
163
|
+
panopticon timeline <id> Chronological events for a session
|
|
164
|
+
panopticon tools Per-tool usage aggregates
|
|
165
|
+
panopticon costs Token usage and cost breakdowns
|
|
166
|
+
--group-by <g> Group by session, model, or day
|
|
167
|
+
panopticon summary Activity summary
|
|
168
|
+
panopticon plans List plans from ExitPlanMode events
|
|
169
|
+
panopticon search <query> Full-text search across all events
|
|
170
|
+
panopticon event <src> <id> Get full details for a specific event
|
|
171
|
+
panopticon query <sql> Raw read-only SQL query
|
|
172
|
+
panopticon db-stats Show database row counts
|
|
173
|
+
|
|
174
|
+
panopticon scan Scan local session files (incremental)
|
|
175
|
+
panopticon scan reset Reset scanner and re-scan from scratch
|
|
176
|
+
[source] Optionally reset only: claude, codex, gemini
|
|
177
|
+
panopticon scan compare Compare scanner data against hooks/OTLP data
|
|
178
|
+
|
|
179
|
+
panopticon prune Delete old data from the database
|
|
180
|
+
--older-than 30d Max age (default: 30d)
|
|
181
|
+
--dry-run Show estimate without deleting
|
|
182
|
+
--vacuum Reclaim disk space after pruning
|
|
183
|
+
--yes Skip confirmation prompt
|
|
184
|
+
|
|
185
|
+
panopticon refresh-pricing Fetch latest model pricing from OpenRouter
|
|
186
|
+
panopticon permissions show Show current approval rules
|
|
187
|
+
panopticon permissions apply Apply permission rules (JSON from stdin)
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
The server auto-starts on `SessionStart` via hook, so manual start/stop is rarely needed.
|
|
191
|
+
|
|
192
|
+
## Logs
|
|
193
|
+
|
|
194
|
+
Daemon stdout/stderr is written to platform-specific log directories:
|
|
195
|
+
|
|
196
|
+
| Platform | Path |
|
|
197
|
+
|----------|------|
|
|
198
|
+
| macOS | `~/Library/Logs/panopticon/` |
|
|
199
|
+
| Linux | `~/.local/state/panopticon/logs/` |
|
|
200
|
+
| Windows | `%LOCALAPPDATA%/panopticon/logs/` |
|
|
201
|
+
|
|
202
|
+
Log files: `server.log`, `mcp-server.log`, `hook-handler.log`, `proxy.log`.
|
|
203
|
+
|
|
204
|
+
## Configuration
|
|
205
|
+
|
|
206
|
+
**Environment variables** set by `panopticon install` in your shell profile:
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
# Shared OTel (always set)
|
|
210
|
+
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
|
|
211
|
+
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
|
|
212
|
+
OTEL_METRICS_EXPORTER=otlp
|
|
213
|
+
OTEL_LOGS_EXPORTER=otlp
|
|
214
|
+
OTEL_LOG_TOOL_DETAILS=1
|
|
215
|
+
OTEL_LOG_USER_PROMPTS=1
|
|
216
|
+
OTEL_METRIC_EXPORT_INTERVAL=10000
|
|
217
|
+
|
|
218
|
+
# Target-specific (set per --target)
|
|
219
|
+
CLAUDE_CODE_ENABLE_TELEMETRY=1 # Claude Code
|
|
220
|
+
ANTHROPIC_BASE_URL=http://localhost:4318/proxy/anthropic # Claude Code (--proxy only)
|
|
221
|
+
GEMINI_TELEMETRY_ENABLED=true # Gemini CLI
|
|
222
|
+
GEMINI_TELEMETRY_TARGET=local # Gemini CLI
|
|
223
|
+
GEMINI_TELEMETRY_OTLP_ENDPOINT=http://localhost:4318 # Gemini CLI
|
|
224
|
+
GEMINI_TELEMETRY_OTLP_PROTOCOL=http # Gemini CLI
|
|
225
|
+
GEMINI_TELEMETRY_LOG_PROMPTS=true # Gemini CLI
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Target-specific env vars are declared by each target adapter in `src/targets/`.
|
|
229
|
+
|
|
230
|
+
**Server configuration:**
|
|
231
|
+
|
|
232
|
+
| Env var | Default | Description |
|
|
233
|
+
|---|---|---|
|
|
234
|
+
| `PANOPTICON_DATA_DIR` | Platform-specific (see below) | Data directory |
|
|
235
|
+
| `PANOPTICON_PORT` | `4318` | Unified server port |
|
|
236
|
+
| `PANOPTICON_HOST` | `127.0.0.1` | Server bind address |
|
|
237
|
+
|
|
238
|
+
Data directory defaults:
|
|
239
|
+
|
|
240
|
+
| Platform | Path |
|
|
241
|
+
|----------|------|
|
|
242
|
+
| macOS | `~/Library/Application Support/panopticon/` |
|
|
243
|
+
| Linux | `~/.local/share/panopticon/` |
|
|
244
|
+
| Windows | `%APPDATA%/panopticon/` |
|
|
245
|
+
|
|
246
|
+
## Database
|
|
247
|
+
|
|
248
|
+
SQLite with WAL mode. Location depends on platform (see data directory above).
|
|
249
|
+
|
|
250
|
+
| Table | Description |
|
|
251
|
+
|-------|-------------|
|
|
252
|
+
| `sessions` | Unified session metadata — aggregated from hooks, OTel, and scanner |
|
|
253
|
+
| `otel_logs` | OTel log records (api_request, tool_result, user_prompt, etc.) |
|
|
254
|
+
| `otel_metrics` | OTel metric data points (token usage, cost, active time, etc.) |
|
|
255
|
+
| `hook_events` | Plugin hook events with full payloads (tool inputs/outputs, tool results) |
|
|
256
|
+
| `hook_events_fts` | FTS5 full-text search index on hook payloads |
|
|
257
|
+
| `scanner_turns` | Per-turn token usage from session files (input, output, cache, reasoning) |
|
|
258
|
+
| `scanner_events` | Tool calls, errors, reasoning, file snapshots from session files |
|
|
259
|
+
| `scanner_file_watermarks` | Byte offsets for incremental session file parsing |
|
|
260
|
+
| `session_repositories` | Maps sessions to GitHub repositories |
|
|
261
|
+
| `session_cwds` | Maps sessions to working directories |
|
|
262
|
+
| `model_pricing` | Cached model pricing from OpenRouter |
|
|
263
|
+
| `schema_meta` | Internal schema version tracking |
|
|
264
|
+
|
|
265
|
+
Query directly with `panopticon query` or via the `panopticon_query` MCP tool.
|
|
266
|
+
|
|
267
|
+
## Development
|
|
268
|
+
|
|
269
|
+
```bash
|
|
270
|
+
pnpm install # Install dependencies
|
|
271
|
+
pnpm dev # Watch mode (tsup)
|
|
272
|
+
pnpm check # Lint (Biome)
|
|
273
|
+
pnpm typecheck # Type check
|
|
274
|
+
pnpm test # Run tests (Vitest)
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
To test the full install flow:
|
|
278
|
+
|
|
279
|
+
```bash
|
|
280
|
+
pnpm build && npm pack
|
|
281
|
+
npm install -g ./fml-inc-panopticon-*.tgz
|
|
282
|
+
panopticon install --target claude
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
## Architecture
|
|
286
|
+
|
|
287
|
+
```
|
|
288
|
+
src/
|
|
289
|
+
├── cli.ts CLI entry point (install, uninstall, start/stop, query commands)
|
|
290
|
+
├── server.ts Unified HTTP server (hooks, OTLP, proxy — single port)
|
|
291
|
+
├── sdk.ts SDK shim (observe() wrapper)
|
|
292
|
+
├── config.ts Panopticon paths, ports, defaults
|
|
293
|
+
├── log.ts Log file paths (macOS/Linux/Windows)
|
|
294
|
+
├── repo.ts Git repository detection
|
|
295
|
+
├── toml.ts TOML read/write (for Codex config)
|
|
296
|
+
├── targets/
|
|
297
|
+
│ ├── types.ts TargetAdapter interface (config, hooks, events, detect, proxy)
|
|
298
|
+
│ ├── registry.ts Map-based target registry (register, get, all)
|
|
299
|
+
│ ├── index.ts Barrel — re-exports + registers all built-in targets
|
|
300
|
+
│ ├── claude.ts Claude Code adapter
|
|
301
|
+
│ ├── claude-desktop.ts Claude Desktop adapter
|
|
302
|
+
│ ├── gemini.ts Gemini CLI adapter
|
|
303
|
+
│ └── codex.ts Codex CLI adapter
|
|
304
|
+
├── db/
|
|
305
|
+
│ ├── schema.ts SQLite schema, migrations, WAL + auto-vacuum
|
|
306
|
+
│ ├── query.ts Query helpers for MCP tools and CLI
|
|
307
|
+
│ ├── store.ts Data storage (insert hooks, OTel, upsert sessions)
|
|
308
|
+
│ ├── prune.ts Data retention / pruning
|
|
309
|
+
│ └── pricing.ts Model pricing cache (OpenRouter)
|
|
310
|
+
├── scanner/
|
|
311
|
+
│ ├── index.ts Public API (createScannerLoop, scanOnce)
|
|
312
|
+
│ ├── loop.ts Poll loop — discovers files via target adapters, incremental parse
|
|
313
|
+
│ ├── reader.ts Byte-offset file reader (only reads new lines)
|
|
314
|
+
│ ├── store.ts Scanner DB operations (turns, events, watermarks, session upsert)
|
|
315
|
+
│ ├── reconcile.ts Compare scanner vs hooks/OTLP token data per session
|
|
316
|
+
│ └── types.ts ScannerHandle, ScannerOptions
|
|
317
|
+
├── hooks/
|
|
318
|
+
│ ├── handler.ts Hook event handler (stdin JSON → server)
|
|
319
|
+
│ ├── ingest.ts Hook processing — uses target adapters for normalization
|
|
320
|
+
│ └── permissions.ts PreToolUse permission enforcement
|
|
321
|
+
├── mcp/
|
|
322
|
+
│ ├── server.ts MCP server with query tools
|
|
323
|
+
│ └── permissions.ts Permission management MCP tools
|
|
324
|
+
├── otlp/
|
|
325
|
+
│ ├── server.ts HTTP OTLP receiver (protobuf + JSON)
|
|
326
|
+
│ ├── decode-logs.ts OTel log record decoding
|
|
327
|
+
│ ├── decode-metrics.ts OTel metric decoding
|
|
328
|
+
│ └── proto.ts Protocol buffer definitions
|
|
329
|
+
├── sync/
|
|
330
|
+
│ ├── index.ts Public API (createSyncLoop, resetWatermarks)
|
|
331
|
+
│ ├── types.ts Interfaces (SyncTarget, SyncOptions, MergedEvent, OTLP types)
|
|
332
|
+
│ ├── loop.ts Poll loop with debounced scheduling
|
|
333
|
+
│ ├── reader.ts Batch reads from SQLite + hook/OTLP dedup
|
|
334
|
+
│ ├── serialize.ts Convert rows → OTLP JSON (resourceLogs, resourceMetrics)
|
|
335
|
+
│ ├── watermark.ts Watermark persistence (sync-watermarks.db)
|
|
336
|
+
│ └── post.ts HTTP POST with retry + exponential backoff
|
|
337
|
+
└── proxy/
|
|
338
|
+
├── server.ts API proxy — routes built from target registry
|
|
339
|
+
├── emit.ts Event emission from proxy captures
|
|
340
|
+
├── streaming.ts SSE stream accumulation (Anthropic + OpenAI)
|
|
341
|
+
├── sessions.ts Proxy session tracking
|
|
342
|
+
└── formats/
|
|
343
|
+
├── types.ts Format parser interface
|
|
344
|
+
├── anthropic.ts Anthropic Messages API parser
|
|
345
|
+
├── openai.ts OpenAI Chat Completions parser
|
|
346
|
+
└── openai-responses.ts OpenAI Responses API parser
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### Target adapters
|
|
350
|
+
|
|
351
|
+
Each supported coding tool is a self-contained adapter in `src/targets/`. An adapter declares:
|
|
352
|
+
|
|
353
|
+
| Concern | What it specifies |
|
|
354
|
+
|---------|-------------------|
|
|
355
|
+
| **Config** | Directory, config file path, format (JSON/TOML) |
|
|
356
|
+
| **Hooks** | Event names, install-time config merge, uninstall cleanup |
|
|
357
|
+
| **Shell env** | Target-specific env vars for the shell profile |
|
|
358
|
+
| **Events** | Event name mapping to canonical types, payload normalization, permission response format |
|
|
359
|
+
| **Detection** | Display name, `isInstalled()`, `isConfigured()` for doctor |
|
|
360
|
+
| **Proxy** | Upstream host (static or dynamic), path rewriting, accumulator type |
|
|
361
|
+
| **Scanner** | `discover()` finds session files on disk, `parseFile()` extracts turns + events |
|
|
362
|
+
|
|
363
|
+
To add a new target, create `src/targets/<name>.ts`, implement `TargetAdapter`, call `registerTarget()`, and add the import to `src/targets/index.ts`. All consumers (install, uninstall, doctor, hooks, proxy, shell env, scanner) pick it up automatically.
|
package/bin/hook-handler
ADDED
package/bin/mcp-server
ADDED
package/bin/panopticon
ADDED
package/bin/proxy
ADDED
package/bin/server
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { ActivitySummaryResult, SpendingResult, SessionListResult, SearchResult, SessionTimelineResult } from '../types.js';
|
|
2
|
+
|
|
3
|
+
declare function callTool(name: string, params?: Record<string, unknown>): Promise<unknown>;
|
|
4
|
+
declare function listSessions(opts?: {
|
|
5
|
+
limit?: number;
|
|
6
|
+
since?: string;
|
|
7
|
+
}): Promise<SessionListResult>;
|
|
8
|
+
declare function sessionTimeline(opts: {
|
|
9
|
+
sessionId: string;
|
|
10
|
+
limit?: number;
|
|
11
|
+
offset?: number;
|
|
12
|
+
fullPayloads?: boolean;
|
|
13
|
+
}): Promise<SessionTimelineResult>;
|
|
14
|
+
declare function costBreakdown(opts?: {
|
|
15
|
+
since?: string;
|
|
16
|
+
groupBy?: "session" | "model" | "day";
|
|
17
|
+
}): Promise<SpendingResult>;
|
|
18
|
+
declare function activitySummary(opts?: {
|
|
19
|
+
since?: string;
|
|
20
|
+
}): Promise<ActivitySummaryResult>;
|
|
21
|
+
declare function listPlans(opts?: {
|
|
22
|
+
session_id?: string;
|
|
23
|
+
since?: string;
|
|
24
|
+
limit?: number;
|
|
25
|
+
}): Promise<unknown>;
|
|
26
|
+
declare function search(opts: {
|
|
27
|
+
query: string;
|
|
28
|
+
eventTypes?: string[];
|
|
29
|
+
since?: string;
|
|
30
|
+
limit?: number;
|
|
31
|
+
offset?: number;
|
|
32
|
+
fullPayloads?: boolean;
|
|
33
|
+
}): Promise<SearchResult>;
|
|
34
|
+
declare function print(opts: {
|
|
35
|
+
source: "hook" | "otel" | "message";
|
|
36
|
+
id: number;
|
|
37
|
+
}): Promise<unknown>;
|
|
38
|
+
declare function rawQuery(sql: string): Promise<unknown>;
|
|
39
|
+
declare function dbStats(): Promise<unknown>;
|
|
40
|
+
declare function callExec(command: string, params?: Record<string, unknown>): Promise<unknown>;
|
|
41
|
+
declare function pruneEstimate(cutoffMs: number): Promise<unknown>;
|
|
42
|
+
declare function pruneExecute(cutoffMs: number, opts?: {
|
|
43
|
+
vacuum?: boolean;
|
|
44
|
+
}): Promise<unknown>;
|
|
45
|
+
declare function refreshPricing(): Promise<unknown>;
|
|
46
|
+
declare function syncReset(target?: string): Promise<unknown>;
|
|
47
|
+
declare function syncWatermarkGet(target: string, table?: string): Promise<unknown>;
|
|
48
|
+
declare function syncWatermarkSet(target: string, table: string, value: number): Promise<unknown>;
|
|
49
|
+
declare function syncPending(target: string): Promise<{
|
|
50
|
+
target: string;
|
|
51
|
+
totalPending: number;
|
|
52
|
+
tables: Record<string, {
|
|
53
|
+
maxId: number;
|
|
54
|
+
watermark: number;
|
|
55
|
+
pending: number;
|
|
56
|
+
}>;
|
|
57
|
+
}>;
|
|
58
|
+
declare function syncTargetList(): Promise<unknown>;
|
|
59
|
+
declare function syncTargetAdd(target: {
|
|
60
|
+
name: string;
|
|
61
|
+
url: string;
|
|
62
|
+
token?: string;
|
|
63
|
+
tokenCommand?: string;
|
|
64
|
+
}): Promise<unknown>;
|
|
65
|
+
declare function syncTargetRemove(name: string): Promise<unknown>;
|
|
66
|
+
|
|
67
|
+
export { activitySummary, callExec, callTool, costBreakdown, dbStats, listPlans, listSessions, print, pruneEstimate, pruneExecute, rawQuery, refreshPricing, search, sessionTimeline, syncPending, syncReset, syncTargetAdd, syncTargetList, syncTargetRemove, syncWatermarkGet, syncWatermarkSet };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {
|
|
2
|
+
activitySummary,
|
|
3
|
+
callExec,
|
|
4
|
+
callTool,
|
|
5
|
+
costBreakdown,
|
|
6
|
+
dbStats,
|
|
7
|
+
listPlans,
|
|
8
|
+
listSessions,
|
|
9
|
+
print,
|
|
10
|
+
pruneEstimate,
|
|
11
|
+
pruneExecute,
|
|
12
|
+
rawQuery,
|
|
13
|
+
refreshPricing,
|
|
14
|
+
search,
|
|
15
|
+
sessionTimeline,
|
|
16
|
+
syncPending,
|
|
17
|
+
syncReset,
|
|
18
|
+
syncTargetAdd,
|
|
19
|
+
syncTargetList,
|
|
20
|
+
syncTargetRemove,
|
|
21
|
+
syncWatermarkGet,
|
|
22
|
+
syncWatermarkSet
|
|
23
|
+
} from "../chunk-4SM2H22C.js";
|
|
24
|
+
import "../chunk-K7YUPLES.js";
|
|
25
|
+
export {
|
|
26
|
+
activitySummary,
|
|
27
|
+
callExec,
|
|
28
|
+
callTool,
|
|
29
|
+
costBreakdown,
|
|
30
|
+
dbStats,
|
|
31
|
+
listPlans,
|
|
32
|
+
listSessions,
|
|
33
|
+
print,
|
|
34
|
+
pruneEstimate,
|
|
35
|
+
pruneExecute,
|
|
36
|
+
rawQuery,
|
|
37
|
+
refreshPricing,
|
|
38
|
+
search,
|
|
39
|
+
sessionTimeline,
|
|
40
|
+
syncPending,
|
|
41
|
+
syncReset,
|
|
42
|
+
syncTargetAdd,
|
|
43
|
+
syncTargetList,
|
|
44
|
+
syncTargetRemove,
|
|
45
|
+
syncWatermarkGet,
|
|
46
|
+
syncWatermarkSet
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|