@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/dist/setup.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {
|
|
2
|
+
configureShellEnv,
|
|
3
|
+
fetchPricing,
|
|
4
|
+
initDb
|
|
5
|
+
} from "./chunk-L7G27XWF.js";
|
|
6
|
+
import "./chunk-3TZAKV3M.js";
|
|
7
|
+
import "./chunk-ZEC4LRKS.js";
|
|
8
|
+
import "./chunk-QVK6VGCV.js";
|
|
9
|
+
import "./chunk-DZ5HJFB4.js";
|
|
10
|
+
import {
|
|
11
|
+
config
|
|
12
|
+
} from "./chunk-K7YUPLES.js";
|
|
13
|
+
export {
|
|
14
|
+
config,
|
|
15
|
+
configureShellEnv,
|
|
16
|
+
fetchPricing,
|
|
17
|
+
initDb
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { S as SyncTarget, a as SyncFilter, b as SyncOptions, c as SyncHandle, T as TableSyncDescriptor } from '../types-D-MYCBol.js';
|
|
2
|
+
export { R as RepoConfigSnapshotRecord, d as SessionSyncRecord, U as UserConfigSnapshotRecord } from '../types-D-MYCBol.js';
|
|
3
|
+
|
|
4
|
+
interface SyncConfig {
|
|
5
|
+
targets: SyncTarget[];
|
|
6
|
+
filter?: SyncFilter;
|
|
7
|
+
}
|
|
8
|
+
declare function loadSyncConfig(): SyncConfig;
|
|
9
|
+
declare function saveSyncConfig(syncCfg: SyncConfig): void;
|
|
10
|
+
declare function addTarget(target: SyncTarget): void;
|
|
11
|
+
declare function removeTarget(name: string): boolean;
|
|
12
|
+
declare function listTargets(): SyncTarget[];
|
|
13
|
+
|
|
14
|
+
declare function createSyncLoop(opts: SyncOptions): SyncHandle;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Ordered list of table sync descriptors. The order matches the
|
|
18
|
+
* round-robin execution order in the sync loop.
|
|
19
|
+
*
|
|
20
|
+
* All tables sync via POST /v1/sync with {table, rows} payload.
|
|
21
|
+
* Session-linked tables are filtered by repo attribution in the sync loop.
|
|
22
|
+
*/
|
|
23
|
+
declare const TABLE_SYNC_REGISTRY: TableSyncDescriptor<any>[];
|
|
24
|
+
|
|
25
|
+
declare function watermarkKey(table: string, targetName: string): string;
|
|
26
|
+
declare function readWatermark(key: string): number;
|
|
27
|
+
declare function resetWatermarks(targetName?: string): void;
|
|
28
|
+
|
|
29
|
+
export { SyncFilter, SyncHandle, SyncOptions, SyncTarget, TABLE_SYNC_REGISTRY, TableSyncDescriptor, addTarget, createSyncLoop, listTargets, loadSyncConfig, readWatermark, removeTarget, resetWatermarks, saveSyncConfig, watermarkKey };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {
|
|
2
|
+
addTarget,
|
|
3
|
+
createSyncLoop,
|
|
4
|
+
listTargets,
|
|
5
|
+
loadSyncConfig,
|
|
6
|
+
removeTarget,
|
|
7
|
+
saveSyncConfig
|
|
8
|
+
} from "../chunk-HQCY722C.js";
|
|
9
|
+
import "../chunk-CF4GPWLI.js";
|
|
10
|
+
import "../chunk-7Q3BJMLG.js";
|
|
11
|
+
import {
|
|
12
|
+
TABLE_SYNC_REGISTRY,
|
|
13
|
+
readWatermark,
|
|
14
|
+
resetWatermarks,
|
|
15
|
+
watermarkKey
|
|
16
|
+
} from "../chunk-SEXU2WYG.js";
|
|
17
|
+
import "../chunk-QK5442ZP.js";
|
|
18
|
+
import "../chunk-DZ5HJFB4.js";
|
|
19
|
+
import "../chunk-K7YUPLES.js";
|
|
20
|
+
export {
|
|
21
|
+
TABLE_SYNC_REGISTRY,
|
|
22
|
+
addTarget,
|
|
23
|
+
createSyncLoop,
|
|
24
|
+
listTargets,
|
|
25
|
+
loadSyncConfig,
|
|
26
|
+
readWatermark,
|
|
27
|
+
removeTarget,
|
|
28
|
+
resetWatermarks,
|
|
29
|
+
saveSyncConfig,
|
|
30
|
+
watermarkKey
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
interface HookInput {
|
|
2
|
+
session_id: string;
|
|
3
|
+
hook_event_name: string;
|
|
4
|
+
cwd?: string;
|
|
5
|
+
repository?: string;
|
|
6
|
+
tool_name?: string;
|
|
7
|
+
tool_input?: Record<string, unknown>;
|
|
8
|
+
source?: string;
|
|
9
|
+
target?: string;
|
|
10
|
+
prompt?: string;
|
|
11
|
+
[key: string]: unknown;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Target adapter types — each supported coding tool declares its specifics
|
|
16
|
+
* via this interface so consumers can iterate over the registry instead of
|
|
17
|
+
* hardcoding target-specific branches.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* All hook event names panopticon registers for.
|
|
22
|
+
*
|
|
23
|
+
* Claude Code fires these as shell commands via hooks.json — each invocation
|
|
24
|
+
* pipes a JSON payload to stdin with session_id, hook_event_name, and
|
|
25
|
+
* event-specific fields. Panopticon's hook-handler POSTs the payload to
|
|
26
|
+
* the local server, which calls processHookEvent() in ingest.ts.
|
|
27
|
+
*
|
|
28
|
+
* Non-Claude targets (Gemini, Codex) map their native event names to these
|
|
29
|
+
* canonical names via their adapter's eventMap.
|
|
30
|
+
*/
|
|
31
|
+
declare const ALL_EVENTS: readonly ["SessionStart", "SessionEnd", "Setup", "UserPromptSubmit", "PreToolUse", "PostToolUse", "PostToolUseFailure", "PermissionRequest", "PermissionDenied", "Stop", "StopFailure", "SubagentStart", "SubagentStop", "PreCompact", "PostCompact", "Notification", "TeammateIdle", "TaskCreated", "TaskCompleted", "Elicitation", "ElicitationResult", "ConfigChange", "InstructionsLoaded", "CwdChanged", "FileChanged", "WorktreeCreate", "WorktreeRemove"];
|
|
32
|
+
/** Union type of all supported event names. */
|
|
33
|
+
type CanonicalEvent = (typeof ALL_EVENTS)[number];
|
|
34
|
+
interface TargetConfigSpec {
|
|
35
|
+
/** Directory where this target stores its config, e.g. ~/.claude */
|
|
36
|
+
dir: string;
|
|
37
|
+
/** Path to the main config file */
|
|
38
|
+
configPath: string;
|
|
39
|
+
/** Format of the config file */
|
|
40
|
+
configFormat: "json" | "toml";
|
|
41
|
+
}
|
|
42
|
+
interface TargetInstallOpts {
|
|
43
|
+
pluginRoot: string;
|
|
44
|
+
port: number;
|
|
45
|
+
proxy?: boolean;
|
|
46
|
+
}
|
|
47
|
+
interface TargetHookSpec {
|
|
48
|
+
/** Event names this target uses, in the target's own convention */
|
|
49
|
+
events: string[];
|
|
50
|
+
/**
|
|
51
|
+
* Apply panopticon hook registration (and related config like MCP servers,
|
|
52
|
+
* telemetry) to this target's existing config. Each target handles its own
|
|
53
|
+
* deduplication/merge logic. Returns the modified config.
|
|
54
|
+
*/
|
|
55
|
+
applyInstallConfig(existingConfig: Record<string, unknown>, opts: TargetInstallOpts): Record<string, unknown>;
|
|
56
|
+
/**
|
|
57
|
+
* Remove panopticon hook registration (and related config like MCP servers,
|
|
58
|
+
* telemetry) from this target's existing config. Returns the modified config.
|
|
59
|
+
*/
|
|
60
|
+
removeInstallConfig(existingConfig: Record<string, unknown>): Record<string, unknown>;
|
|
61
|
+
}
|
|
62
|
+
interface TargetShellEnvSpec {
|
|
63
|
+
/**
|
|
64
|
+
* Env vars to export as [varName, value] tuples.
|
|
65
|
+
* These are target-specific; shared OTEL_* vars are handled separately.
|
|
66
|
+
*/
|
|
67
|
+
envVars(port: number, proxy: boolean): Array<[string, string]>;
|
|
68
|
+
}
|
|
69
|
+
interface TargetEventSpec {
|
|
70
|
+
/** Map from target's event name to canonical panopticon event name. */
|
|
71
|
+
eventMap: Record<string, CanonicalEvent>;
|
|
72
|
+
/**
|
|
73
|
+
* Transform the raw hook payload before storage.
|
|
74
|
+
* Used e.g. by Gemini to extract user_prompt from llm_request.messages.
|
|
75
|
+
*/
|
|
76
|
+
normalizePayload?(data: HookInput): HookInput;
|
|
77
|
+
/**
|
|
78
|
+
* Format a permission response for this target's expected shape.
|
|
79
|
+
*/
|
|
80
|
+
formatPermissionResponse(decision: {
|
|
81
|
+
allow: boolean;
|
|
82
|
+
reason: string;
|
|
83
|
+
}): Record<string, unknown>;
|
|
84
|
+
}
|
|
85
|
+
interface TargetDetectSpec {
|
|
86
|
+
/** Human-readable name for display, e.g. "Claude Code" */
|
|
87
|
+
displayName: string;
|
|
88
|
+
/** Check whether this target is installed on the system */
|
|
89
|
+
isInstalled(): boolean;
|
|
90
|
+
/** Check whether panopticon is configured within this target */
|
|
91
|
+
isConfigured(): boolean;
|
|
92
|
+
}
|
|
93
|
+
interface MetricSpec {
|
|
94
|
+
/** OTel metric name(s) this target emits for token usage */
|
|
95
|
+
metricNames: string[];
|
|
96
|
+
/** Aggregation function: 'SUM' for per-request deltas, 'MAX' for cumulative counters */
|
|
97
|
+
aggregation: "SUM" | "MAX";
|
|
98
|
+
/** JSON paths to extract token type from metric attributes (first non-null wins) */
|
|
99
|
+
tokenTypeAttrs: string[];
|
|
100
|
+
/** JSON paths to extract model name from metric attributes (first non-null wins) */
|
|
101
|
+
modelAttrs: string[];
|
|
102
|
+
/** Remap token_type values before aggregation, e.g. { cached_input: 'cacheRead' } */
|
|
103
|
+
tokenTypeMap?: Record<string, string>;
|
|
104
|
+
/** Token type values to exclude (e.g. 'total' to avoid double-counting) */
|
|
105
|
+
excludeTokenTypes?: string[];
|
|
106
|
+
}
|
|
107
|
+
interface OtelLogFieldSpec {
|
|
108
|
+
/** SQL expressions to extract event type from otel_logs (COALESCEd). Default: ['body'] */
|
|
109
|
+
eventTypeExprs?: string[];
|
|
110
|
+
/** SQL expressions to extract timestamp in ms from otel_logs. Default: ['CAST(timestamp_ns / 1000000 AS INTEGER)'] */
|
|
111
|
+
timestampMsExprs?: string[];
|
|
112
|
+
}
|
|
113
|
+
interface TargetOtelSpec {
|
|
114
|
+
/** OTel service.name this target emits. Used for session inference when metrics lack session_id. */
|
|
115
|
+
serviceName?: string;
|
|
116
|
+
/** Token usage metric declaration. Undefined means no token metrics. */
|
|
117
|
+
metrics?: MetricSpec;
|
|
118
|
+
/** How to extract event type and timestamp from otel_logs rows. */
|
|
119
|
+
logFields?: OtelLogFieldSpec;
|
|
120
|
+
}
|
|
121
|
+
interface TargetIdentSpec {
|
|
122
|
+
/** Model-name regex patterns for last-resort target identification from hook payloads */
|
|
123
|
+
modelPatterns?: RegExp[];
|
|
124
|
+
}
|
|
125
|
+
interface TargetProxySpec {
|
|
126
|
+
/**
|
|
127
|
+
* Upstream host for API proxying.
|
|
128
|
+
* String for simple mapping; function for dynamic routing (e.g. Codex JWT).
|
|
129
|
+
*/
|
|
130
|
+
upstreamHost: string | ((headers: Record<string, string>) => string);
|
|
131
|
+
/** Path rewrite rule, if needed. Default: pass through. */
|
|
132
|
+
rewritePath?(path: string, headers: Record<string, string>): string;
|
|
133
|
+
/** Which stream accumulator to use */
|
|
134
|
+
accumulatorType: "anthropic" | "openai";
|
|
135
|
+
}
|
|
136
|
+
interface DiscoveredFile {
|
|
137
|
+
filePath: string;
|
|
138
|
+
}
|
|
139
|
+
interface ParsedTurn {
|
|
140
|
+
sessionId: string;
|
|
141
|
+
turnIndex: number;
|
|
142
|
+
timestampMs: number;
|
|
143
|
+
model?: string;
|
|
144
|
+
role: "user" | "assistant";
|
|
145
|
+
contentPreview?: string;
|
|
146
|
+
inputTokens: number;
|
|
147
|
+
outputTokens: number;
|
|
148
|
+
cacheReadTokens: number;
|
|
149
|
+
cacheCreationTokens: number;
|
|
150
|
+
reasoningTokens: number;
|
|
151
|
+
}
|
|
152
|
+
type RelationshipType = "subagent" | "continuation" | "fork";
|
|
153
|
+
interface ParsedSession {
|
|
154
|
+
sessionId: string;
|
|
155
|
+
parentSessionId?: string;
|
|
156
|
+
relationshipType?: RelationshipType;
|
|
157
|
+
model?: string;
|
|
158
|
+
cwd?: string;
|
|
159
|
+
cliVersion?: string;
|
|
160
|
+
startedAtMs?: number;
|
|
161
|
+
firstPrompt?: string;
|
|
162
|
+
}
|
|
163
|
+
interface ParsedEvent {
|
|
164
|
+
sessionId: string;
|
|
165
|
+
eventType: string;
|
|
166
|
+
timestampMs: number;
|
|
167
|
+
toolName?: string;
|
|
168
|
+
toolInput?: string;
|
|
169
|
+
toolOutput?: string;
|
|
170
|
+
content?: string;
|
|
171
|
+
metadata?: Record<string, unknown>;
|
|
172
|
+
}
|
|
173
|
+
interface ParsedToolCall {
|
|
174
|
+
toolUseId: string;
|
|
175
|
+
toolName: string;
|
|
176
|
+
category: string;
|
|
177
|
+
inputJson?: string;
|
|
178
|
+
skillName?: string;
|
|
179
|
+
resultContentLength?: number;
|
|
180
|
+
resultContent?: string;
|
|
181
|
+
subagentSessionId?: string;
|
|
182
|
+
/** Timestamp (ms) when the tool was invoked (from the assistant message). */
|
|
183
|
+
timestampMs?: number;
|
|
184
|
+
}
|
|
185
|
+
interface ParsedMessage {
|
|
186
|
+
sessionId: string;
|
|
187
|
+
ordinal: number;
|
|
188
|
+
role: "user" | "assistant";
|
|
189
|
+
content: string;
|
|
190
|
+
timestampMs?: number;
|
|
191
|
+
hasThinking: boolean;
|
|
192
|
+
hasToolUse: boolean;
|
|
193
|
+
isSystem: boolean;
|
|
194
|
+
contentLength: number;
|
|
195
|
+
model?: string;
|
|
196
|
+
tokenUsage?: string;
|
|
197
|
+
contextTokens?: number;
|
|
198
|
+
outputTokens?: number;
|
|
199
|
+
hasContextTokens: boolean;
|
|
200
|
+
hasOutputTokens: boolean;
|
|
201
|
+
/** DAG node UUID from the JSONL line that produced this message. */
|
|
202
|
+
uuid?: string;
|
|
203
|
+
/** Parent DAG node UUID (the line this message is a reply to). */
|
|
204
|
+
parentUuid?: string;
|
|
205
|
+
toolCalls: ParsedToolCall[];
|
|
206
|
+
/** tool_use_id → raw result content (from tool_result blocks in user messages) */
|
|
207
|
+
toolResults: Map<string, {
|
|
208
|
+
contentLength: number;
|
|
209
|
+
contentRaw: string;
|
|
210
|
+
timestampMs?: number;
|
|
211
|
+
}>;
|
|
212
|
+
}
|
|
213
|
+
interface ParseResult {
|
|
214
|
+
meta?: ParsedSession;
|
|
215
|
+
turns: ParsedTurn[];
|
|
216
|
+
events: ParsedEvent[];
|
|
217
|
+
messages: ParsedMessage[];
|
|
218
|
+
newByteOffset: number;
|
|
219
|
+
/**
|
|
220
|
+
* When true, turn indices are absolute (0-based from start of session)
|
|
221
|
+
* and the caller should NOT re-index them. Used by parsers that re-read
|
|
222
|
+
* the full file (e.g. Gemini JSON) rather than reading incrementally.
|
|
223
|
+
* INSERT OR IGNORE handles dedup via the UNIQUE constraint.
|
|
224
|
+
*/
|
|
225
|
+
absoluteIndices?: boolean;
|
|
226
|
+
/** Additional sessions from DAG fork detection (branched conversations). */
|
|
227
|
+
forks?: ParseResult[];
|
|
228
|
+
/**
|
|
229
|
+
* When true, the parser detected a DAG fork during incremental reading.
|
|
230
|
+
* The caller should reset the file watermark and reparse from byte 0
|
|
231
|
+
* so fork detection can run on the full file.
|
|
232
|
+
*/
|
|
233
|
+
needsFullReparse?: boolean;
|
|
234
|
+
/**
|
|
235
|
+
* Tool results from filtered-out messages (e.g. tool-result-only user
|
|
236
|
+
* messages) that still need to be backfilled into tool_calls.
|
|
237
|
+
*/
|
|
238
|
+
orphanedToolResults?: Map<string, {
|
|
239
|
+
contentLength: number;
|
|
240
|
+
contentRaw: string;
|
|
241
|
+
timestampMs?: number;
|
|
242
|
+
}>;
|
|
243
|
+
}
|
|
244
|
+
interface TargetScannerSpec {
|
|
245
|
+
/** Discover session files on disk for this target. */
|
|
246
|
+
discover(): DiscoveredFile[];
|
|
247
|
+
/**
|
|
248
|
+
* Parse a session file. Receives the file path and current byte offset.
|
|
249
|
+
* Returns parsed data and new byte offset, or null if no new data.
|
|
250
|
+
*/
|
|
251
|
+
parseFile(filePath: string, fromByteOffset: number): ParseResult | null;
|
|
252
|
+
/** Normalize a tool name to a standard category for analytics grouping. */
|
|
253
|
+
normalizeToolCategory(toolName: string): string;
|
|
254
|
+
}
|
|
255
|
+
interface TargetAdapter {
|
|
256
|
+
/** Machine identifier: "claude", "gemini", "codex", etc. */
|
|
257
|
+
id: string;
|
|
258
|
+
config: TargetConfigSpec;
|
|
259
|
+
hooks: TargetHookSpec;
|
|
260
|
+
shellEnv: TargetShellEnvSpec;
|
|
261
|
+
events: TargetEventSpec;
|
|
262
|
+
detect: TargetDetectSpec;
|
|
263
|
+
/** Proxy spec is optional — not every target routes through the proxy */
|
|
264
|
+
proxy?: TargetProxySpec;
|
|
265
|
+
/** OTel telemetry schema — how this target emits metrics and logs */
|
|
266
|
+
otel?: TargetOtelSpec;
|
|
267
|
+
/** How to identify this target from hook payloads when no explicit source field is present */
|
|
268
|
+
ident?: TargetIdentSpec;
|
|
269
|
+
/** Session file scanner — reads local transcript files for token usage */
|
|
270
|
+
scanner?: TargetScannerSpec;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
declare function registerTarget(adapter: TargetAdapter): void;
|
|
274
|
+
declare function getTarget(id: string): TargetAdapter | undefined;
|
|
275
|
+
declare function getTargetOrThrow(id: string): TargetAdapter;
|
|
276
|
+
declare function allTargets(): TargetAdapter[];
|
|
277
|
+
declare function targetIds(): string[];
|
|
278
|
+
|
|
279
|
+
export { ALL_EVENTS, type CanonicalEvent, type TargetAdapter, type TargetConfigSpec, type TargetDetectSpec, type TargetEventSpec, type TargetHookSpec, type TargetInstallOpts, type TargetProxySpec, type TargetShellEnvSpec, allTargets, getTarget, getTargetOrThrow, registerTarget, targetIds };
|
package/dist/targets.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ALL_EVENTS
|
|
3
|
+
} from "./chunk-ZEC4LRKS.js";
|
|
4
|
+
import {
|
|
5
|
+
allTargets,
|
|
6
|
+
getTarget,
|
|
7
|
+
getTargetOrThrow,
|
|
8
|
+
registerTarget,
|
|
9
|
+
targetIds
|
|
10
|
+
} from "./chunk-QVK6VGCV.js";
|
|
11
|
+
import "./chunk-K7YUPLES.js";
|
|
12
|
+
export {
|
|
13
|
+
ALL_EVENTS,
|
|
14
|
+
allTargets,
|
|
15
|
+
getTarget,
|
|
16
|
+
getTargetOrThrow,
|
|
17
|
+
registerTarget,
|
|
18
|
+
targetIds
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=targets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
interface SyncTarget {
|
|
2
|
+
/** Unique name for this target, used as watermark namespace */
|
|
3
|
+
name: string;
|
|
4
|
+
/** Sync endpoint base URL (e.g. "https://example.com") */
|
|
5
|
+
url: string;
|
|
6
|
+
/** Bearer token — sent as Authorization: Bearer <token> */
|
|
7
|
+
token?: string;
|
|
8
|
+
/** Shell command that returns a Bearer token on stdout (e.g. "gh auth token"). Cached for 5 minutes. */
|
|
9
|
+
tokenCommand?: string;
|
|
10
|
+
/** Additional headers (merged with token auth if both provided) */
|
|
11
|
+
headers?: Record<string, string>;
|
|
12
|
+
}
|
|
13
|
+
interface SyncFilter {
|
|
14
|
+
/** Only sync events matching these repo patterns (glob, e.g. "fml-inc/*") */
|
|
15
|
+
includeRepos?: string[];
|
|
16
|
+
/** Exclude repos matching these patterns (takes precedence over include) */
|
|
17
|
+
excludeRepos?: string[];
|
|
18
|
+
/** Only sync sessions with associated repo attribution (default true) */
|
|
19
|
+
requireRepo?: boolean;
|
|
20
|
+
}
|
|
21
|
+
interface SyncOptions {
|
|
22
|
+
targets: SyncTarget[];
|
|
23
|
+
filter?: SyncFilter;
|
|
24
|
+
/** Max rows read from SQLite per batch (default 2000) */
|
|
25
|
+
batchSize?: number;
|
|
26
|
+
/** Max records per HTTP POST (default 25) */
|
|
27
|
+
postBatchSize?: number;
|
|
28
|
+
/** If true, timer keeps Node alive (default false) */
|
|
29
|
+
keepAlive?: boolean;
|
|
30
|
+
/** Idle poll interval in ms (default 30000) */
|
|
31
|
+
idleIntervalMs?: number;
|
|
32
|
+
/** Catch-up poll interval in ms (default 1000) */
|
|
33
|
+
catchUpIntervalMs?: number;
|
|
34
|
+
}
|
|
35
|
+
interface SyncHandle {
|
|
36
|
+
start: () => void;
|
|
37
|
+
stop: () => void;
|
|
38
|
+
}
|
|
39
|
+
interface UserConfigSnapshotRecord {
|
|
40
|
+
id: number;
|
|
41
|
+
deviceName: string;
|
|
42
|
+
snapshotAtMs: number;
|
|
43
|
+
contentHash: string;
|
|
44
|
+
permissions: Record<string, unknown>;
|
|
45
|
+
enabledPlugins: unknown[];
|
|
46
|
+
hooks: unknown[];
|
|
47
|
+
commands: unknown[];
|
|
48
|
+
rules: unknown[];
|
|
49
|
+
skills: unknown[];
|
|
50
|
+
}
|
|
51
|
+
interface RepoConfigSnapshotRecord {
|
|
52
|
+
id: number;
|
|
53
|
+
repository: string;
|
|
54
|
+
cwd: string;
|
|
55
|
+
sessionId: string | null;
|
|
56
|
+
snapshotAtMs: number;
|
|
57
|
+
contentHash: string;
|
|
58
|
+
hooks: unknown[];
|
|
59
|
+
mcpServers: unknown[];
|
|
60
|
+
commands: unknown[];
|
|
61
|
+
agents: unknown[];
|
|
62
|
+
rules: unknown[];
|
|
63
|
+
localHooks: unknown[];
|
|
64
|
+
localMcpServers: unknown[];
|
|
65
|
+
localPermissions: Record<string, unknown>;
|
|
66
|
+
localIsGitignored: boolean;
|
|
67
|
+
instructions: unknown[];
|
|
68
|
+
}
|
|
69
|
+
interface SessionSyncRecord {
|
|
70
|
+
sessionId: string;
|
|
71
|
+
target: string | null;
|
|
72
|
+
startedAtMs: number | null;
|
|
73
|
+
endedAtMs: number | null;
|
|
74
|
+
cwd: string | null;
|
|
75
|
+
firstPrompt: string | null;
|
|
76
|
+
permissionMode: string | null;
|
|
77
|
+
agentVersion: string | null;
|
|
78
|
+
totalInputTokens: number | null;
|
|
79
|
+
totalOutputTokens: number | null;
|
|
80
|
+
totalCacheReadTokens: number | null;
|
|
81
|
+
totalCacheCreationTokens: number | null;
|
|
82
|
+
totalReasoningTokens: number | null;
|
|
83
|
+
turnCount: number | null;
|
|
84
|
+
models: string | null;
|
|
85
|
+
summary: string | null;
|
|
86
|
+
toolCounts: Record<string, number>;
|
|
87
|
+
hookToolCounts: Record<string, number>;
|
|
88
|
+
eventTypeCounts: Record<string, number>;
|
|
89
|
+
hookEventTypeCounts: Record<string, number>;
|
|
90
|
+
project: string | null;
|
|
91
|
+
machine: string;
|
|
92
|
+
messageCount: number;
|
|
93
|
+
userMessageCount: number;
|
|
94
|
+
parentSessionId: string | null;
|
|
95
|
+
relationshipType: string;
|
|
96
|
+
isAutomated: boolean;
|
|
97
|
+
createdAt: number | null;
|
|
98
|
+
repositories: Array<{
|
|
99
|
+
repository: string;
|
|
100
|
+
firstSeenMs: number;
|
|
101
|
+
gitUserName: string | null;
|
|
102
|
+
gitUserEmail: string | null;
|
|
103
|
+
branch: string | null;
|
|
104
|
+
}>;
|
|
105
|
+
cwds: Array<{
|
|
106
|
+
cwd: string;
|
|
107
|
+
firstSeenMs: number;
|
|
108
|
+
}>;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Descriptor for a single table that participates in the sync loop.
|
|
112
|
+
* All tables POST to /v1/sync with {table, rows} payload.
|
|
113
|
+
*/
|
|
114
|
+
interface TableSyncDescriptor<TRow = unknown> {
|
|
115
|
+
/** Table name, used as watermark key and sent in the POST body. */
|
|
116
|
+
table: string;
|
|
117
|
+
/** Noun for log messages (e.g. "events", "logs"). */
|
|
118
|
+
logNoun: string;
|
|
119
|
+
/** Read rows from SQLite starting after the given watermark. */
|
|
120
|
+
read: (afterId: number, limit: number) => {
|
|
121
|
+
rows: TRow[];
|
|
122
|
+
maxId: number;
|
|
123
|
+
};
|
|
124
|
+
/** Whether this table's rows are linked to sessions (filtered by repo). */
|
|
125
|
+
sessionLinked: boolean;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export type { RepoConfigSnapshotRecord as R, SyncTarget as S, TableSyncDescriptor as T, UserConfigSnapshotRecord as U, SyncFilter as a, SyncOptions as b, SyncHandle as c, SessionSyncRecord as d };
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified response types for panopticon query functions.
|
|
3
|
+
*
|
|
4
|
+
* These types define the canonical shapes returned by both local queries
|
|
5
|
+
* (panopticon SQLite) and remote queries (FML backend). Both sources
|
|
6
|
+
* populate the same fields — the data originates from panopticon either way.
|
|
7
|
+
*
|
|
8
|
+
* Conventions:
|
|
9
|
+
* - camelCase field names
|
|
10
|
+
* - ISO 8601 strings for timestamps
|
|
11
|
+
* - null for genuinely absent data, never for source-dependent gaps
|
|
12
|
+
*/
|
|
13
|
+
interface Repository {
|
|
14
|
+
name: string;
|
|
15
|
+
gitUserName: string | null;
|
|
16
|
+
gitUserEmail: string | null;
|
|
17
|
+
}
|
|
18
|
+
interface Session {
|
|
19
|
+
sessionId: string;
|
|
20
|
+
target: string | null;
|
|
21
|
+
model: string | null;
|
|
22
|
+
project: string | null;
|
|
23
|
+
startedAt: string | null;
|
|
24
|
+
endedAt: string | null;
|
|
25
|
+
firstPrompt: string | null;
|
|
26
|
+
turnCount: number;
|
|
27
|
+
messageCount: number;
|
|
28
|
+
totalInputTokens: number;
|
|
29
|
+
totalOutputTokens: number;
|
|
30
|
+
totalCost: number;
|
|
31
|
+
repositories: Repository[];
|
|
32
|
+
parentSessionId: string | null;
|
|
33
|
+
relationshipType: string | null;
|
|
34
|
+
summary: string | null;
|
|
35
|
+
}
|
|
36
|
+
interface SessionListResult {
|
|
37
|
+
sessions: Session[];
|
|
38
|
+
totalCount: number;
|
|
39
|
+
source: "local" | "remote";
|
|
40
|
+
}
|
|
41
|
+
interface TimelineToolCall {
|
|
42
|
+
toolName: string;
|
|
43
|
+
category: string;
|
|
44
|
+
toolUseId: string | null;
|
|
45
|
+
inputJson: string | null;
|
|
46
|
+
skillName: string | null;
|
|
47
|
+
resultContentLength: number | null;
|
|
48
|
+
durationMs: number | null;
|
|
49
|
+
subagentSessionId: string | null;
|
|
50
|
+
/** Subagent session metadata, present when subagentSessionId is set */
|
|
51
|
+
subagent: {
|
|
52
|
+
sessionId: string;
|
|
53
|
+
model: string | null;
|
|
54
|
+
turnCount: number;
|
|
55
|
+
firstPrompt: string | null;
|
|
56
|
+
} | null;
|
|
57
|
+
}
|
|
58
|
+
interface TimelineMessage {
|
|
59
|
+
id: number;
|
|
60
|
+
ordinal: number;
|
|
61
|
+
role: string;
|
|
62
|
+
content: string;
|
|
63
|
+
timestampMs: number | null;
|
|
64
|
+
model: string | null;
|
|
65
|
+
isSystem: boolean;
|
|
66
|
+
hasThinking: boolean;
|
|
67
|
+
hasToolUse: boolean;
|
|
68
|
+
contentLength: number;
|
|
69
|
+
uuid: string | null;
|
|
70
|
+
parentUuid: string | null;
|
|
71
|
+
tokenUsage: string | null;
|
|
72
|
+
contextTokens: number;
|
|
73
|
+
outputTokens: number;
|
|
74
|
+
toolCalls: TimelineToolCall[];
|
|
75
|
+
}
|
|
76
|
+
interface ChildSession {
|
|
77
|
+
sessionId: string;
|
|
78
|
+
relationshipType: string;
|
|
79
|
+
model: string | null;
|
|
80
|
+
turnCount: number;
|
|
81
|
+
firstPrompt: string | null;
|
|
82
|
+
startedAtMs: number | null;
|
|
83
|
+
}
|
|
84
|
+
interface SessionTimelineResult {
|
|
85
|
+
session: {
|
|
86
|
+
sessionId: string;
|
|
87
|
+
target: string | null;
|
|
88
|
+
model: string | null;
|
|
89
|
+
project: string | null;
|
|
90
|
+
parentSessionId: string | null;
|
|
91
|
+
relationshipType: string | null;
|
|
92
|
+
repositories: Repository[];
|
|
93
|
+
childSessions: ChildSession[];
|
|
94
|
+
} | null;
|
|
95
|
+
messages: TimelineMessage[];
|
|
96
|
+
totalMessages: number;
|
|
97
|
+
hasMore: boolean;
|
|
98
|
+
source: "local" | "remote";
|
|
99
|
+
}
|
|
100
|
+
interface SpendingGroup {
|
|
101
|
+
key: string;
|
|
102
|
+
inputTokens: number;
|
|
103
|
+
outputTokens: number;
|
|
104
|
+
totalTokens: number;
|
|
105
|
+
totalCost: number;
|
|
106
|
+
sessionCount: number;
|
|
107
|
+
}
|
|
108
|
+
interface SpendingResult {
|
|
109
|
+
groups: SpendingGroup[];
|
|
110
|
+
totals: {
|
|
111
|
+
inputTokens: number;
|
|
112
|
+
outputTokens: number;
|
|
113
|
+
totalTokens: number;
|
|
114
|
+
totalCost: number;
|
|
115
|
+
};
|
|
116
|
+
groupBy: "session" | "model" | "day";
|
|
117
|
+
source: "local" | "remote";
|
|
118
|
+
}
|
|
119
|
+
interface ActivitySessionDetail {
|
|
120
|
+
sessionId: string;
|
|
121
|
+
startedAt: string | null;
|
|
122
|
+
durationMinutes: number;
|
|
123
|
+
model: string | null;
|
|
124
|
+
project: string | null;
|
|
125
|
+
repositories: Repository[];
|
|
126
|
+
userPrompts: string[];
|
|
127
|
+
toolsUsed: Array<{
|
|
128
|
+
tool: string;
|
|
129
|
+
count: number;
|
|
130
|
+
}>;
|
|
131
|
+
filesModified: string[];
|
|
132
|
+
totalCost: number;
|
|
133
|
+
}
|
|
134
|
+
interface ActivitySummaryResult {
|
|
135
|
+
period: {
|
|
136
|
+
since: string;
|
|
137
|
+
until: string;
|
|
138
|
+
};
|
|
139
|
+
totalSessions: number;
|
|
140
|
+
totalTokens: number;
|
|
141
|
+
totalCost: number;
|
|
142
|
+
topTools: Array<{
|
|
143
|
+
tool: string;
|
|
144
|
+
count: number;
|
|
145
|
+
}>;
|
|
146
|
+
sessions: ActivitySessionDetail[];
|
|
147
|
+
source: "local" | "remote";
|
|
148
|
+
}
|
|
149
|
+
interface SearchMatch {
|
|
150
|
+
sessionId: string;
|
|
151
|
+
timestamp: string;
|
|
152
|
+
matchType: string;
|
|
153
|
+
matchSnippet: string;
|
|
154
|
+
eventType: string | null;
|
|
155
|
+
toolName: string | null;
|
|
156
|
+
}
|
|
157
|
+
interface SearchResult {
|
|
158
|
+
results: SearchMatch[];
|
|
159
|
+
totalMatches: number;
|
|
160
|
+
query: string;
|
|
161
|
+
source: "local" | "remote";
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export type { ActivitySessionDetail, ActivitySummaryResult, ChildSession, Repository, SearchMatch, SearchResult, Session, SessionListResult, SessionTimelineResult, SpendingGroup, SpendingResult, TimelineMessage, TimelineToolCall };
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|