clawprobe 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.
Files changed (82) hide show
  1. package/README.md +301 -0
  2. package/dist/cli/commands/compacts.d.ts +11 -0
  3. package/dist/cli/commands/compacts.d.ts.map +1 -0
  4. package/dist/cli/commands/compacts.js +68 -0
  5. package/dist/cli/commands/compacts.js.map +1 -0
  6. package/dist/cli/commands/context.d.ts +8 -0
  7. package/dist/cli/commands/context.d.ts.map +1 -0
  8. package/dist/cli/commands/context.js +78 -0
  9. package/dist/cli/commands/context.js.map +1 -0
  10. package/dist/cli/commands/cost.d.ts +12 -0
  11. package/dist/cli/commands/cost.d.ts.map +1 -0
  12. package/dist/cli/commands/cost.js +52 -0
  13. package/dist/cli/commands/cost.js.map +1 -0
  14. package/dist/cli/commands/memory.d.ts +36 -0
  15. package/dist/cli/commands/memory.d.ts.map +1 -0
  16. package/dist/cli/commands/memory.js +139 -0
  17. package/dist/cli/commands/memory.js.map +1 -0
  18. package/dist/cli/commands/session.d.ts +10 -0
  19. package/dist/cli/commands/session.d.ts.map +1 -0
  20. package/dist/cli/commands/session.js +95 -0
  21. package/dist/cli/commands/session.js.map +1 -0
  22. package/dist/cli/commands/status.d.ts +9 -0
  23. package/dist/cli/commands/status.d.ts.map +1 -0
  24. package/dist/cli/commands/status.js +68 -0
  25. package/dist/cli/commands/status.js.map +1 -0
  26. package/dist/cli/commands/suggest.d.ts +11 -0
  27. package/dist/cli/commands/suggest.d.ts.map +1 -0
  28. package/dist/cli/commands/suggest.js +68 -0
  29. package/dist/cli/commands/suggest.js.map +1 -0
  30. package/dist/cli/format.d.ts +29 -0
  31. package/dist/cli/format.d.ts.map +1 -0
  32. package/dist/cli/format.js +125 -0
  33. package/dist/cli/format.js.map +1 -0
  34. package/dist/core/config.d.ts +63 -0
  35. package/dist/core/config.d.ts.map +1 -0
  36. package/dist/core/config.js +92 -0
  37. package/dist/core/config.js.map +1 -0
  38. package/dist/core/db.d.ts +87 -0
  39. package/dist/core/db.d.ts.map +1 -0
  40. package/dist/core/db.js +263 -0
  41. package/dist/core/db.js.map +1 -0
  42. package/dist/core/jsonl-parser.d.ts +55 -0
  43. package/dist/core/jsonl-parser.d.ts.map +1 -0
  44. package/dist/core/jsonl-parser.js +79 -0
  45. package/dist/core/jsonl-parser.js.map +1 -0
  46. package/dist/core/memory-editor.d.ts +18 -0
  47. package/dist/core/memory-editor.d.ts.map +1 -0
  48. package/dist/core/memory-editor.js +125 -0
  49. package/dist/core/memory-editor.js.map +1 -0
  50. package/dist/core/session-store.d.ts +35 -0
  51. package/dist/core/session-store.d.ts.map +1 -0
  52. package/dist/core/session-store.js +66 -0
  53. package/dist/core/session-store.js.map +1 -0
  54. package/dist/core/watcher.d.ts +19 -0
  55. package/dist/core/watcher.d.ts.map +1 -0
  56. package/dist/core/watcher.js +83 -0
  57. package/dist/core/watcher.js.map +1 -0
  58. package/dist/daemon.d.ts +3 -0
  59. package/dist/daemon.d.ts.map +1 -0
  60. package/dist/daemon.js +147 -0
  61. package/dist/daemon.js.map +1 -0
  62. package/dist/engines/compact-diff.d.ts +19 -0
  63. package/dist/engines/compact-diff.d.ts.map +1 -0
  64. package/dist/engines/compact-diff.js +124 -0
  65. package/dist/engines/compact-diff.js.map +1 -0
  66. package/dist/engines/cost.d.ts +73 -0
  67. package/dist/engines/cost.d.ts.map +1 -0
  68. package/dist/engines/cost.js +149 -0
  69. package/dist/engines/cost.js.map +1 -0
  70. package/dist/engines/file-analyzer.d.ts +28 -0
  71. package/dist/engines/file-analyzer.d.ts.map +1 -0
  72. package/dist/engines/file-analyzer.js +139 -0
  73. package/dist/engines/file-analyzer.js.map +1 -0
  74. package/dist/engines/rule-engine.d.ts +25 -0
  75. package/dist/engines/rule-engine.d.ts.map +1 -0
  76. package/dist/engines/rule-engine.js +209 -0
  77. package/dist/engines/rule-engine.js.map +1 -0
  78. package/dist/index.d.ts +3 -0
  79. package/dist/index.d.ts.map +1 -0
  80. package/dist/index.js +207 -0
  81. package/dist/index.js.map +1 -0
  82. package/package.json +35 -0
@@ -0,0 +1,63 @@
1
+ export interface OpenClawCompactionConfig {
2
+ reserveTokens?: number;
3
+ keepRecentTokens?: number;
4
+ }
5
+ export interface OpenClawConfig {
6
+ agents?: {
7
+ defaults?: {
8
+ workspace?: string;
9
+ bootstrapMaxChars?: number;
10
+ compaction?: OpenClawCompactionConfig;
11
+ };
12
+ };
13
+ plugins?: {
14
+ slots?: {
15
+ contextEngine?: string;
16
+ memory?: string;
17
+ };
18
+ };
19
+ models?: {
20
+ default?: string;
21
+ provider?: string;
22
+ };
23
+ }
24
+ export interface ProbeConfig {
25
+ openclaw: {
26
+ dir: string;
27
+ agent: string;
28
+ };
29
+ server: {
30
+ port: number;
31
+ host: string;
32
+ };
33
+ cost: {
34
+ customPrices: Record<string, {
35
+ input: number;
36
+ output: number;
37
+ }>;
38
+ };
39
+ alerts: {
40
+ dailyBudgetUsd?: number;
41
+ weeklyBudgetUsd?: number;
42
+ };
43
+ memory: {
44
+ defaultFile: string;
45
+ };
46
+ rules: {
47
+ disabled: string[];
48
+ compactionFreqThresholdMin: number;
49
+ memoryBloatThresholdChars: number;
50
+ };
51
+ }
52
+ export interface ResolvedConfig {
53
+ probe: ProbeConfig;
54
+ openclaw: OpenClawConfig;
55
+ openclawDir: string;
56
+ workspaceDir: string;
57
+ sessionsDir: string;
58
+ bootstrapMaxChars: number;
59
+ probeDir: string;
60
+ }
61
+ export declare function resolveConfig(overrides?: Partial<ProbeConfig>): ResolvedConfig;
62
+ export declare function assertOpenClawExists(cfg: ResolvedConfig): void;
63
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,wBAAwB;IACvC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE;QACP,QAAQ,CAAC,EAAE;YACT,SAAS,CAAC,EAAE,MAAM,CAAC;YACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;YAC3B,UAAU,CAAC,EAAE,wBAAwB,CAAC;SACvC,CAAC;KACH,CAAC;IACF,OAAO,CAAC,EAAE;QACR,KAAK,CAAC,EAAE;YACN,aAAa,CAAC,EAAE,MAAM,CAAC;YACvB,MAAM,CAAC,EAAE,MAAM,CAAC;SACjB,CAAC;KACH,CAAC;IACF,MAAM,CAAC,EAAE;QACP,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE;QACR,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,MAAM,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,IAAI,EAAE;QACJ,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACjE,CAAC;IACF,MAAM,EAAE;QACN,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;IACF,MAAM,EAAE;QACN,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;IACF,KAAK,EAAE;QACL,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,0BAA0B,EAAE,MAAM,CAAC;QACnC,yBAAyB,EAAE,MAAM,CAAC;KACnC,CAAC;CACH;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,EAAE,cAAc,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAyBD,wBAAgB,aAAa,CAAC,SAAS,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,cAAc,CAuDlF;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI,CAQ9D"}
@@ -0,0 +1,92 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import os from "os";
4
+ const DEFAULT_PROBE_CONFIG = {
5
+ openclaw: {
6
+ dir: path.join(os.homedir(), ".openclaw"),
7
+ agent: "main",
8
+ },
9
+ server: {
10
+ port: 4747,
11
+ host: "127.0.0.1",
12
+ },
13
+ cost: {
14
+ customPrices: {},
15
+ },
16
+ alerts: {},
17
+ memory: {
18
+ defaultFile: "MEMORY.md",
19
+ },
20
+ rules: {
21
+ disabled: [],
22
+ compactionFreqThresholdMin: 30,
23
+ memoryBloatThresholdChars: 50000,
24
+ },
25
+ };
26
+ export function resolveConfig(overrides = {}) {
27
+ const probeDir = path.join(os.homedir(), ".clawprobe");
28
+ const probeConfigPath = path.join(probeDir, "config.json");
29
+ let fileConfig = {};
30
+ if (fs.existsSync(probeConfigPath)) {
31
+ try {
32
+ fileConfig = JSON.parse(fs.readFileSync(probeConfigPath, "utf-8"));
33
+ }
34
+ catch {
35
+ // ignore malformed config
36
+ }
37
+ }
38
+ const probe = deepMerge(DEFAULT_PROBE_CONFIG, fileConfig, overrides);
39
+ // OPENCLAW_DIR env var takes priority
40
+ const openclawDir = process.env["OPENCLAW_DIR"] ?? probe.openclaw.dir;
41
+ const openclawConfigPath = path.join(openclawDir, "openclaw.json");
42
+ let openclawConfig = {};
43
+ if (fs.existsSync(openclawConfigPath)) {
44
+ try {
45
+ openclawConfig = JSON.parse(fs.readFileSync(openclawConfigPath, "utf-8"));
46
+ }
47
+ catch {
48
+ // ignore malformed config
49
+ }
50
+ }
51
+ const workspaceDir = openclawConfig.agents?.defaults?.workspace ??
52
+ path.join(openclawDir, "workspace");
53
+ const sessionsDir = path.join(openclawDir, "agents", probe.openclaw.agent, "sessions");
54
+ const bootstrapMaxChars = openclawConfig.agents?.defaults?.bootstrapMaxChars ?? 20000;
55
+ return {
56
+ probe,
57
+ openclaw: openclawConfig,
58
+ openclawDir,
59
+ workspaceDir,
60
+ sessionsDir,
61
+ bootstrapMaxChars,
62
+ probeDir,
63
+ };
64
+ }
65
+ export function assertOpenClawExists(cfg) {
66
+ if (!fs.existsSync(cfg.openclawDir)) {
67
+ console.error(`Error: OpenClaw directory not found at ${cfg.openclawDir}\n` +
68
+ `Set OPENCLAW_DIR environment variable or add "openclaw.dir" to ~/.clawprobe/config.json`);
69
+ process.exit(1);
70
+ }
71
+ }
72
+ function deepMerge(...objects) {
73
+ const result = {};
74
+ for (const obj of objects) {
75
+ for (const [key, value] of Object.entries(obj)) {
76
+ if (value !== undefined &&
77
+ value !== null &&
78
+ typeof value === "object" &&
79
+ !Array.isArray(value) &&
80
+ typeof result[key] === "object" &&
81
+ result[key] !== null &&
82
+ !Array.isArray(result[key])) {
83
+ result[key] = deepMerge(result[key], value);
84
+ }
85
+ else if (value !== undefined) {
86
+ result[key] = value;
87
+ }
88
+ }
89
+ }
90
+ return result;
91
+ }
92
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ import { DatabaseSync } from "node:sqlite";
2
+ export interface SessionSnapshotRow {
3
+ id: number;
4
+ agent: string;
5
+ session_key: string;
6
+ session_id: string;
7
+ model: string | null;
8
+ provider: string | null;
9
+ input_tokens: number;
10
+ output_tokens: number;
11
+ total_tokens: number;
12
+ context_tokens: number;
13
+ compaction_count: number;
14
+ sampled_at: number;
15
+ }
16
+ export interface CostRecordRow {
17
+ id: number;
18
+ agent: string;
19
+ session_key: string;
20
+ date: string;
21
+ input_tokens: number;
22
+ output_tokens: number;
23
+ model: string | null;
24
+ estimated_usd: number;
25
+ recorded_at: number;
26
+ }
27
+ export interface CompactEventRow {
28
+ id: number;
29
+ agent: string;
30
+ session_key: string;
31
+ compaction_entry_id: string;
32
+ first_kept_entry_id: string;
33
+ tokens_before: number | null;
34
+ summary_text: string | null;
35
+ compacted_at: number | null;
36
+ compacted_message_count: number | null;
37
+ compacted_messages: string | null;
38
+ }
39
+ export interface FileSnapshotRow {
40
+ id: number;
41
+ agent: string;
42
+ file_path: string;
43
+ raw_chars: number;
44
+ injected_chars: number;
45
+ was_truncated: number;
46
+ sampled_at: number;
47
+ }
48
+ export interface SuggestionRow {
49
+ id: number;
50
+ agent: string;
51
+ rule_id: string;
52
+ severity: string;
53
+ title: string;
54
+ detail: string;
55
+ action: string | null;
56
+ created_at: number;
57
+ dismissed: number;
58
+ }
59
+ export declare function openDb(probeDir: string): DatabaseSync;
60
+ export declare function getDb(): DatabaseSync;
61
+ export declare function resetDb(): void;
62
+ export declare function insertSessionSnapshot(db: DatabaseSync, row: Omit<SessionSnapshotRow, "id">): void;
63
+ export declare function getFirstSnapshot(db: DatabaseSync, agent: string, sessionKey: string): SessionSnapshotRow | undefined;
64
+ export declare function getLatestSnapshot(db: DatabaseSync, agent: string, sessionKey: string): SessionSnapshotRow | undefined;
65
+ export declare function getAllSnapshots(db: DatabaseSync, agent: string, sessionKey: string): SessionSnapshotRow[];
66
+ export declare function getAllSessionKeys(db: DatabaseSync, agent: string): {
67
+ session_key: string;
68
+ last_sampled_at: number;
69
+ }[];
70
+ export declare function upsertCostRecord(db: DatabaseSync, row: Omit<CostRecordRow, "id">): void;
71
+ export declare function getDailyCostSummary(db: DatabaseSync, agent: string, days: number): {
72
+ date: string;
73
+ total_usd: number;
74
+ input_tokens: number;
75
+ output_tokens: number;
76
+ }[];
77
+ export declare function upsertCompactEvent(db: DatabaseSync, row: Omit<CompactEventRow, "id">): void;
78
+ export declare function getCompactEvents(db: DatabaseSync, agent: string, limit: number, sessionKey?: string): CompactEventRow[];
79
+ export declare function getCompactEventById(db: DatabaseSync, id: number): CompactEventRow | undefined;
80
+ export declare function insertFileSnapshot(db: DatabaseSync, row: Omit<FileSnapshotRow, "id">): void;
81
+ export declare function getLatestFileSnapshots(db: DatabaseSync, agent: string): FileSnapshotRow[];
82
+ export declare function upsertSuggestion(db: DatabaseSync, row: Omit<SuggestionRow, "id" | "dismissed">): void;
83
+ export declare function getSuggestions(db: DatabaseSync, agent: string, severity?: string): SuggestionRow[];
84
+ export declare function dismissSuggestion(db: DatabaseSync, agent: string, ruleId: string): void;
85
+ export declare function resetDismissed(db: DatabaseSync, agent: string): void;
86
+ export declare function removeSuggestion(db: DatabaseSync, agent: string, ruleId: string): void;
87
+ //# sourceMappingURL=db.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/core/db.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,263 @@
1
+ import { DatabaseSync } from "node:sqlite";
2
+ import fs from "fs";
3
+ import path from "path";
4
+ const SCHEMA = `
5
+ PRAGMA journal_mode = WAL;
6
+ PRAGMA foreign_keys = ON;
7
+
8
+ CREATE TABLE IF NOT EXISTS session_snapshots (
9
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
10
+ agent TEXT NOT NULL,
11
+ session_key TEXT NOT NULL,
12
+ session_id TEXT NOT NULL,
13
+ model TEXT,
14
+ provider TEXT,
15
+ input_tokens INTEGER NOT NULL DEFAULT 0,
16
+ output_tokens INTEGER NOT NULL DEFAULT 0,
17
+ total_tokens INTEGER NOT NULL DEFAULT 0,
18
+ context_tokens INTEGER NOT NULL DEFAULT 0,
19
+ compaction_count INTEGER NOT NULL DEFAULT 0,
20
+ sampled_at INTEGER NOT NULL
21
+ );
22
+
23
+ CREATE INDEX IF NOT EXISTS idx_ss_agent_session ON session_snapshots(agent, session_key, sampled_at);
24
+
25
+ CREATE TABLE IF NOT EXISTS cost_records (
26
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
27
+ agent TEXT NOT NULL,
28
+ session_key TEXT NOT NULL,
29
+ date TEXT NOT NULL,
30
+ input_tokens INTEGER NOT NULL DEFAULT 0,
31
+ output_tokens INTEGER NOT NULL DEFAULT 0,
32
+ model TEXT,
33
+ estimated_usd REAL NOT NULL DEFAULT 0,
34
+ recorded_at INTEGER NOT NULL
35
+ );
36
+
37
+ CREATE INDEX IF NOT EXISTS idx_cr_agent_date ON cost_records(agent, date);
38
+
39
+ CREATE TABLE IF NOT EXISTS compact_events (
40
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
41
+ agent TEXT NOT NULL,
42
+ session_key TEXT NOT NULL,
43
+ compaction_entry_id TEXT NOT NULL UNIQUE,
44
+ first_kept_entry_id TEXT NOT NULL,
45
+ tokens_before INTEGER,
46
+ summary_text TEXT,
47
+ compacted_at INTEGER,
48
+ compacted_message_count INTEGER,
49
+ compacted_messages TEXT
50
+ );
51
+
52
+ CREATE INDEX IF NOT EXISTS idx_ce_agent_session ON compact_events(agent, session_key);
53
+
54
+ CREATE TABLE IF NOT EXISTS file_snapshots (
55
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
56
+ agent TEXT NOT NULL,
57
+ file_path TEXT NOT NULL,
58
+ raw_chars INTEGER NOT NULL DEFAULT 0,
59
+ injected_chars INTEGER NOT NULL DEFAULT 0,
60
+ was_truncated INTEGER NOT NULL DEFAULT 0,
61
+ sampled_at INTEGER NOT NULL
62
+ );
63
+
64
+ CREATE INDEX IF NOT EXISTS idx_fs_agent_path ON file_snapshots(agent, file_path, sampled_at);
65
+
66
+ CREATE TABLE IF NOT EXISTS suggestions (
67
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
68
+ agent TEXT NOT NULL,
69
+ rule_id TEXT NOT NULL,
70
+ severity TEXT NOT NULL,
71
+ title TEXT NOT NULL,
72
+ detail TEXT NOT NULL,
73
+ action TEXT,
74
+ created_at INTEGER NOT NULL,
75
+ dismissed INTEGER NOT NULL DEFAULT 0
76
+ );
77
+
78
+ CREATE INDEX IF NOT EXISTS idx_sg_agent_rule ON suggestions(agent, rule_id, dismissed);
79
+ `;
80
+ let _db = null;
81
+ export function openDb(probeDir) {
82
+ if (_db)
83
+ return _db;
84
+ fs.mkdirSync(probeDir, { recursive: true });
85
+ const dbPath = path.join(probeDir, "probe.db");
86
+ _db = new DatabaseSync(dbPath);
87
+ _db.exec(SCHEMA);
88
+ return _db;
89
+ }
90
+ export function getDb() {
91
+ if (!_db)
92
+ throw new Error("Database not initialized. Call openDb() first.");
93
+ return _db;
94
+ }
95
+ export function resetDb() {
96
+ if (_db) {
97
+ _db.close();
98
+ _db = null;
99
+ }
100
+ }
101
+ // --- Session Snapshots ---
102
+ export function insertSessionSnapshot(db, row) {
103
+ db.prepare(`
104
+ INSERT INTO session_snapshots
105
+ (agent, session_key, session_id, model, provider,
106
+ input_tokens, output_tokens, total_tokens, context_tokens,
107
+ compaction_count, sampled_at)
108
+ VALUES
109
+ (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
110
+ `).run(row.agent, row.session_key, row.session_id, row.model, row.provider, row.input_tokens, row.output_tokens, row.total_tokens, row.context_tokens, row.compaction_count, row.sampled_at);
111
+ }
112
+ export function getFirstSnapshot(db, agent, sessionKey) {
113
+ return db.prepare(`
114
+ SELECT * FROM session_snapshots
115
+ WHERE agent = ? AND session_key = ?
116
+ ORDER BY sampled_at ASC
117
+ LIMIT 1
118
+ `).get(agent, sessionKey);
119
+ }
120
+ export function getLatestSnapshot(db, agent, sessionKey) {
121
+ return db.prepare(`
122
+ SELECT * FROM session_snapshots
123
+ WHERE agent = ? AND session_key = ?
124
+ ORDER BY sampled_at DESC
125
+ LIMIT 1
126
+ `).get(agent, sessionKey);
127
+ }
128
+ export function getAllSnapshots(db, agent, sessionKey) {
129
+ return db.prepare(`
130
+ SELECT * FROM session_snapshots
131
+ WHERE agent = ? AND session_key = ?
132
+ ORDER BY sampled_at ASC
133
+ `).all(agent, sessionKey);
134
+ }
135
+ export function getAllSessionKeys(db, agent) {
136
+ return db.prepare(`
137
+ SELECT session_key, MAX(sampled_at) as last_sampled_at
138
+ FROM session_snapshots
139
+ WHERE agent = ?
140
+ GROUP BY session_key
141
+ ORDER BY last_sampled_at DESC
142
+ `).all(agent);
143
+ }
144
+ // --- Cost Records ---
145
+ export function upsertCostRecord(db, row) {
146
+ db.prepare(`
147
+ INSERT INTO cost_records
148
+ (agent, session_key, date, input_tokens, output_tokens, model, estimated_usd, recorded_at)
149
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
150
+ `).run(row.agent, row.session_key, row.date, row.input_tokens, row.output_tokens, row.model, row.estimated_usd, row.recorded_at);
151
+ }
152
+ export function getDailyCostSummary(db, agent, days) {
153
+ const cutoff = new Date(Date.now() - days * 86400_000).toISOString().slice(0, 10);
154
+ return db.prepare(`
155
+ SELECT
156
+ date,
157
+ SUM(estimated_usd) AS total_usd,
158
+ SUM(input_tokens) AS input_tokens,
159
+ SUM(output_tokens) AS output_tokens
160
+ FROM cost_records
161
+ WHERE agent = ? AND date >= ?
162
+ GROUP BY date
163
+ ORDER BY date ASC
164
+ `).all(agent, cutoff);
165
+ }
166
+ // --- Compact Events ---
167
+ export function upsertCompactEvent(db, row) {
168
+ db.prepare(`
169
+ INSERT OR REPLACE INTO compact_events
170
+ (agent, session_key, compaction_entry_id, first_kept_entry_id,
171
+ tokens_before, summary_text, compacted_at,
172
+ compacted_message_count, compacted_messages)
173
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
174
+ `).run(row.agent, row.session_key, row.compaction_entry_id, row.first_kept_entry_id, row.tokens_before, row.summary_text, row.compacted_at, row.compacted_message_count, row.compacted_messages);
175
+ }
176
+ export function getCompactEvents(db, agent, limit, sessionKey) {
177
+ if (sessionKey) {
178
+ return db.prepare(`
179
+ SELECT * FROM compact_events
180
+ WHERE agent = ? AND session_key = ?
181
+ ORDER BY compacted_at DESC
182
+ LIMIT ?
183
+ `).all(agent, sessionKey, limit);
184
+ }
185
+ return db.prepare(`
186
+ SELECT * FROM compact_events
187
+ WHERE agent = ?
188
+ ORDER BY compacted_at DESC
189
+ LIMIT ?
190
+ `).all(agent, limit);
191
+ }
192
+ export function getCompactEventById(db, id) {
193
+ return db.prepare(`SELECT * FROM compact_events WHERE id = ?`).get(id);
194
+ }
195
+ // --- File Snapshots ---
196
+ export function insertFileSnapshot(db, row) {
197
+ db.prepare(`
198
+ INSERT INTO file_snapshots
199
+ (agent, file_path, raw_chars, injected_chars, was_truncated, sampled_at)
200
+ VALUES (?, ?, ?, ?, ?, ?)
201
+ `).run(row.agent, row.file_path, row.raw_chars, row.injected_chars, row.was_truncated, row.sampled_at);
202
+ }
203
+ export function getLatestFileSnapshots(db, agent) {
204
+ return db.prepare(`
205
+ SELECT fs.*
206
+ FROM file_snapshots fs
207
+ INNER JOIN (
208
+ SELECT file_path, MAX(sampled_at) AS max_at
209
+ FROM file_snapshots
210
+ WHERE agent = ?
211
+ GROUP BY file_path
212
+ ) latest ON fs.file_path = latest.file_path AND fs.sampled_at = latest.max_at
213
+ WHERE fs.agent = ?
214
+ ORDER BY fs.raw_chars DESC
215
+ `).all(agent, agent);
216
+ }
217
+ // --- Suggestions ---
218
+ export function upsertSuggestion(db, row) {
219
+ const existing = db.prepare(`
220
+ SELECT id, dismissed FROM suggestions
221
+ WHERE agent = ? AND rule_id = ?
222
+ `).get(row.agent, row.rule_id);
223
+ if (existing) {
224
+ if (existing.dismissed)
225
+ return;
226
+ db.prepare(`
227
+ UPDATE suggestions
228
+ SET severity = ?, title = ?, detail = ?, action = ?, created_at = ?
229
+ WHERE id = ?
230
+ `).run(row.severity, row.title, row.detail, row.action, row.created_at, existing.id);
231
+ }
232
+ else {
233
+ db.prepare(`
234
+ INSERT INTO suggestions
235
+ (agent, rule_id, severity, title, detail, action, created_at, dismissed)
236
+ VALUES (?, ?, ?, ?, ?, ?, ?, 0)
237
+ `).run(row.agent, row.rule_id, row.severity, row.title, row.detail, row.action, row.created_at);
238
+ }
239
+ }
240
+ export function getSuggestions(db, agent, severity) {
241
+ if (severity) {
242
+ return db.prepare(`
243
+ SELECT * FROM suggestions
244
+ WHERE agent = ? AND dismissed = 0 AND severity = ?
245
+ ORDER BY CASE severity WHEN 'critical' THEN 0 WHEN 'warning' THEN 1 ELSE 2 END, created_at DESC
246
+ `).all(agent, severity);
247
+ }
248
+ return db.prepare(`
249
+ SELECT * FROM suggestions
250
+ WHERE agent = ? AND dismissed = 0
251
+ ORDER BY CASE severity WHEN 'critical' THEN 0 WHEN 'warning' THEN 1 ELSE 2 END, created_at DESC
252
+ `).all(agent);
253
+ }
254
+ export function dismissSuggestion(db, agent, ruleId) {
255
+ db.prepare(`UPDATE suggestions SET dismissed = 1 WHERE agent = ? AND rule_id = ?`).run(agent, ruleId);
256
+ }
257
+ export function resetDismissed(db, agent) {
258
+ db.prepare(`UPDATE suggestions SET dismissed = 0 WHERE agent = ?`).run(agent);
259
+ }
260
+ export function removeSuggestion(db, agent, ruleId) {
261
+ db.prepare(`DELETE FROM suggestions WHERE agent = ? AND rule_id = ?`).run(agent, ruleId);
262
+ }
263
+ //# sourceMappingURL=db.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/core/db.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ export interface SessionHeader {
2
+ type: "session";
3
+ id: string;
4
+ cwd: string;
5
+ timestamp: number;
6
+ parentSession?: string;
7
+ }
8
+ export interface MessageEntry {
9
+ type: "message";
10
+ id: string;
11
+ parentId: string;
12
+ role: "user" | "assistant" | "tool";
13
+ content: string;
14
+ timestamp?: number;
15
+ }
16
+ export interface CompactionEntry {
17
+ type: "compaction";
18
+ id: string;
19
+ parentId: string;
20
+ firstKeptEntryId: string;
21
+ tokensBefore: number;
22
+ content: string;
23
+ timestamp?: number;
24
+ }
25
+ export interface CustomMessageEntry {
26
+ type: "custom_message";
27
+ id: string;
28
+ parentId: string;
29
+ role: string;
30
+ content: string;
31
+ hidden?: boolean;
32
+ }
33
+ export type JournalEntry = SessionHeader | MessageEntry | CompactionEntry | CustomMessageEntry | {
34
+ type: string;
35
+ [key: string]: unknown;
36
+ };
37
+ export interface CompactEvent {
38
+ entryId: string;
39
+ parentId: string;
40
+ firstKeptEntryId: string;
41
+ tokensBefore: number;
42
+ summaryText: string;
43
+ timestamp?: number;
44
+ lineIndex: number;
45
+ }
46
+ export interface ParseResult {
47
+ entries: JournalEntry[];
48
+ compactEvents: CompactEvent[];
49
+ }
50
+ export declare function parseAll(filePath: string): ParseResult;
51
+ export declare function parseIncremental(filePath: string): ParseResult;
52
+ export declare function resetCursor(filePath: string): void;
53
+ export declare function getCompactedMessages(allEntries: JournalEntry[], compactEvent: CompactEvent, previousFirstKeptId?: string): MessageEntry[];
54
+ export declare function buildConversationTree(entries: JournalEntry[]): MessageEntry[];
55
+ //# sourceMappingURL=jsonl-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonl-parser.d.ts","sourceRoot":"","sources":["../../src/core/jsonl-parser.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,SAAS,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,SAAS,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,YAAY,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,gBAAgB,CAAC;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,MAAM,YAAY,GACpB,aAAa,GACb,YAAY,GACZ,eAAe,GACf,kBAAkB,GAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC;AAI7C,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,aAAa,EAAE,YAAY,EAAE,CAAC;CAC/B;AAMD,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAGtD;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAqD9D;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAElD;AAID,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,YAAY,EAAE,EAC1B,YAAY,EAAE,YAAY,EAC1B,mBAAmB,CAAC,EAAE,MAAM,GAC3B,YAAY,EAAE,CAmBhB;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,YAAY,EAAE,CAG7E"}
@@ -0,0 +1,79 @@
1
+ import fs from "fs";
2
+ // --- Incremental cursor state ---
3
+ const fileCursors = new Map();
4
+ export function parseAll(filePath) {
5
+ fileCursors.delete(filePath);
6
+ return parseIncremental(filePath);
7
+ }
8
+ export function parseIncremental(filePath) {
9
+ if (!fs.existsSync(filePath)) {
10
+ return { entries: [], compactEvents: [] };
11
+ }
12
+ const fd = fs.openSync(filePath, "r");
13
+ const stat = fs.fstatSync(fd);
14
+ const fileSize = stat.size;
15
+ const cursor = fileCursors.get(filePath) ?? 0;
16
+ if (cursor >= fileSize) {
17
+ fs.closeSync(fd);
18
+ return { entries: [], compactEvents: [] };
19
+ }
20
+ const chunkSize = fileSize - cursor;
21
+ const buf = Buffer.allocUnsafe(chunkSize);
22
+ fs.readSync(fd, buf, 0, chunkSize, cursor);
23
+ fs.closeSync(fd);
24
+ fileCursors.set(filePath, fileSize);
25
+ const newText = buf.toString("utf-8");
26
+ const lines = newText.split("\n").filter((l) => l.trim().length > 0);
27
+ const entries = [];
28
+ const compactEvents = [];
29
+ let lineIndex = 0;
30
+ for (const line of lines) {
31
+ try {
32
+ const entry = JSON.parse(line);
33
+ entries.push(entry);
34
+ if (entry.type === "compaction") {
35
+ const ce = entry;
36
+ compactEvents.push({
37
+ entryId: ce.id,
38
+ parentId: ce.parentId,
39
+ firstKeptEntryId: ce.firstKeptEntryId,
40
+ tokensBefore: ce.tokensBefore,
41
+ summaryText: ce.content,
42
+ timestamp: ce.timestamp,
43
+ lineIndex,
44
+ });
45
+ }
46
+ lineIndex++;
47
+ }
48
+ catch {
49
+ // skip malformed lines
50
+ }
51
+ }
52
+ return { entries, compactEvents };
53
+ }
54
+ export function resetCursor(filePath) {
55
+ fileCursors.delete(filePath);
56
+ }
57
+ // --- Full analysis helpers ---
58
+ export function getCompactedMessages(allEntries, compactEvent, previousFirstKeptId) {
59
+ const messages = allEntries.filter((e) => e.type === "message");
60
+ // Entries after the previous compact boundary, before this compact's firstKeptEntryId
61
+ let started = previousFirstKeptId === undefined;
62
+ const result = [];
63
+ for (const msg of messages) {
64
+ if (!started) {
65
+ if (msg.id === previousFirstKeptId)
66
+ started = true;
67
+ continue;
68
+ }
69
+ if (msg.id === compactEvent.firstKeptEntryId)
70
+ break;
71
+ result.push(msg);
72
+ }
73
+ return result;
74
+ }
75
+ export function buildConversationTree(entries) {
76
+ // Return messages in insertion order (they form a linear chain via parentId)
77
+ return entries.filter((e) => e.type === "message");
78
+ }
79
+ //# sourceMappingURL=jsonl-parser.js.map