agentacta 2026.4.8 → 2026.4.10
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/README.md +13 -13
- package/dist/config.d.ts +4 -0
- package/dist/config.js +91 -0
- package/dist/config.js.map +1 -0
- package/dist/db.d.ts +5 -0
- package/dist/db.js +163 -0
- package/dist/db.js.map +1 -0
- package/dist/delta-attribution-context.d.ts +4 -0
- package/dist/delta-attribution-context.js +50 -0
- package/dist/delta-attribution-context.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +843 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer.d.ts +8 -0
- package/dist/indexer.js +879 -0
- package/dist/indexer.js.map +1 -0
- package/dist/insights.d.ts +5 -0
- package/dist/insights.js +224 -0
- package/dist/insights.js.map +1 -0
- package/dist/project-attribution.d.ts +6 -0
- package/dist/project-attribution.js +424 -0
- package/dist/project-attribution.js.map +1 -0
- package/dist/types.d.ts +361 -0
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -0
- package/index.js +1 -853
- package/package.json +18 -14
- package/config.js +0 -85
- package/db.js +0 -152
- package/delta-attribution-context.js +0 -57
- package/indexer.js +0 -865
- package/insights.js +0 -260
- package/project-attribution.js +0 -443
package/README.md
CHANGED
|
@@ -22,9 +22,9 @@ npx agentacta
|
|
|
22
22
|
|
|
23
23
|
## Why this exists
|
|
24
24
|
|
|
25
|
-
Agents move fast. Your memory of what happened doesn
|
|
25
|
+
Agents move fast. Your memory of what happened doesn't.
|
|
26
26
|
|
|
27
|
-
When you need to answer
|
|
27
|
+
When you need to answer "what changed, when, and why," you're usually scraping logs, scrolling transcripts, or asking the same assistant that forgot 20 minutes ago.
|
|
28
28
|
|
|
29
29
|
AgentActa gives you one place to inspect the full trail.
|
|
30
30
|
|
|
@@ -40,7 +40,7 @@ AgentActa gives you one place to inspect the full trail.
|
|
|
40
40
|
- 📊 Stats for sessions, messages, tools, and tokens
|
|
41
41
|
- ⚡ Live indexing via file watching
|
|
42
42
|
- 📱 Mobile-optimized UI with floating navigation
|
|
43
|
-
- 🏥 Session health scoring
|
|
43
|
+
- 🏥 Session health scoring - reliability scores, issue detection, and per-signal breakdowns
|
|
44
44
|
- 💡 Search suggestions based on real data
|
|
45
45
|
- ⌨️ Command palette (⌘K / Ctrl+K) for quick navigation
|
|
46
46
|
- 🎨 Theme settings (system, light, dark, OLED)
|
|
@@ -95,9 +95,9 @@ Pick a date, see everything that happened, newest first. Today's view updates li
|
|
|
95
95
|
|
|
96
96
|
The Insights tab surfaces session health across your entire history.
|
|
97
97
|
|
|
98
|
-
It tracks five issue signals
|
|
98
|
+
It tracks five issue signals - repeated tool loops, sessions that produced no output, high error rates, vague instructions, and incomplete sessions. Each signal is severity-scaled so scores reflect how bad the problem actually was, not just whether it occurred.
|
|
99
99
|
|
|
100
|
-
The reliability score (0
|
|
100
|
+
The reliability score (0-100) is the inverse of the confusion score: higher means the agent completed work cleanly. The issue rate shows what percentage of possible signal types were detected in a session.
|
|
101
101
|
|
|
102
102
|
### File Activity
|
|
103
103
|
|
|
@@ -131,7 +131,7 @@ On first run, AgentActa creates:
|
|
|
131
131
|
- `~/.config/agentacta/config.json`
|
|
132
132
|
- or `agentacta.config.json` in current directory (if present)
|
|
133
133
|
|
|
134
|
-
Default config (auto-generated on first run
|
|
134
|
+
Default config (auto-generated on first run - session directories are detected automatically):
|
|
135
135
|
|
|
136
136
|
```json
|
|
137
137
|
{
|
|
@@ -176,7 +176,7 @@ Default config (auto-generated on first run — session directories are detected
|
|
|
176
176
|
| `GET /api/timeline/stream?after=<ts>` | SSE stream for live timeline updates |
|
|
177
177
|
| `POST /api/maintenance` | VACUUM + WAL checkpoint (returns size before/after) |
|
|
178
178
|
| `GET /api/health` | Server status, version, uptime, session count |
|
|
179
|
-
| `GET /api/insights` | Session health summary
|
|
179
|
+
| `GET /api/insights` | Session health summary - reliability scores, issue counts, top flagged sessions |
|
|
180
180
|
| `GET /api/export/search?q=<query>&format=md` | Export search results |
|
|
181
181
|
|
|
182
182
|
### Context API
|
|
@@ -189,7 +189,7 @@ The Context API gives agents historical context before they start working. Inste
|
|
|
189
189
|
| `GET /api/context/repo?path=<repo-path>` | Aggregates for a repo/project |
|
|
190
190
|
| `GET /api/context/agent?name=<agent-name>` | Stats for a specific agent |
|
|
191
191
|
|
|
192
|
-
**File context**
|
|
192
|
+
**File context** - how many sessions touched this file, when it was last modified, recent change summaries, operation breakdown (reads vs edits), related files, and recent errors:
|
|
193
193
|
|
|
194
194
|
```bash
|
|
195
195
|
curl http://localhost:4003/api/context/file?path=/home/user/project/server.js
|
|
@@ -206,7 +206,7 @@ curl http://localhost:4003/api/context/file?path=/home/user/project/server.js
|
|
|
206
206
|
}
|
|
207
207
|
```
|
|
208
208
|
|
|
209
|
-
**Agent context**
|
|
209
|
+
**Agent context** - total sessions, cost, average duration, most-used tools, recent work:
|
|
210
210
|
|
|
211
211
|
```bash
|
|
212
212
|
curl http://localhost:4003/api/context/agent?name=claude-code
|
|
@@ -223,7 +223,7 @@ curl http://localhost:4003/api/context/agent?name=claude-code
|
|
|
223
223
|
}
|
|
224
224
|
```
|
|
225
225
|
|
|
226
|
-
**Repo context**
|
|
226
|
+
**Repo context** - aggregate cost, tokens, distinct agents, most-touched files, common tools:
|
|
227
227
|
|
|
228
228
|
```bash
|
|
229
229
|
curl http://localhost:4003/api/context/repo?path=agentacta
|
|
@@ -292,13 +292,13 @@ Your session history stays local.
|
|
|
292
292
|
|
|
293
293
|
PRs welcome.
|
|
294
294
|
|
|
295
|
-
See [CONTRIBUTING.md](CONTRIBUTING.md). If you
|
|
295
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md). If you're adding a new agent format, start in `src/indexer.ts`.
|
|
296
296
|
|
|
297
297
|
## Name
|
|
298
298
|
|
|
299
|
-
*Acta* is Latin for
|
|
299
|
+
*Acta* is Latin for "things done."
|
|
300
300
|
|
|
301
|
-
That
|
|
301
|
+
That's the job here: keep a readable record of what your agents actually did.
|
|
302
302
|
|
|
303
303
|
## License
|
|
304
304
|
|
package/dist/config.d.ts
ADDED
package/dist/config.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.CONFIG_FILE = void 0;
|
|
7
|
+
exports.loadConfig = loadConfig;
|
|
8
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
10
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
11
|
+
const CWD_CONFIG_FILE = node_path_1.default.join(process.cwd(), 'agentacta.config.json');
|
|
12
|
+
const XDG_CONFIG_DIR = node_path_1.default.join(process.env.XDG_CONFIG_HOME || node_path_1.default.join(node_os_1.default.homedir(), '.config'), 'agentacta');
|
|
13
|
+
const XDG_CONFIG_FILE = node_path_1.default.join(XDG_CONFIG_DIR, 'config.json');
|
|
14
|
+
// Resolve config file: CWD first (backward compat), then XDG default
|
|
15
|
+
function resolveConfigFile() {
|
|
16
|
+
if (node_fs_1.default.existsSync(CWD_CONFIG_FILE))
|
|
17
|
+
return CWD_CONFIG_FILE;
|
|
18
|
+
return XDG_CONFIG_FILE;
|
|
19
|
+
}
|
|
20
|
+
const CONFIG_FILE = resolveConfigFile();
|
|
21
|
+
exports.CONFIG_FILE = CONFIG_FILE;
|
|
22
|
+
const KNOWN_SESSION_DIRS = [
|
|
23
|
+
node_path_1.default.join(node_os_1.default.homedir(), '.claude', 'projects'), // Claude Code
|
|
24
|
+
node_path_1.default.join(node_os_1.default.homedir(), '.codex', 'sessions'), // Codex CLI
|
|
25
|
+
node_path_1.default.join(node_os_1.default.homedir(), '.openclaw', 'sessions'), // OpenClaw
|
|
26
|
+
];
|
|
27
|
+
const DEFAULTS = {
|
|
28
|
+
port: 4003,
|
|
29
|
+
storage: 'reference',
|
|
30
|
+
sessionsPath: null,
|
|
31
|
+
dbPath: './agentacta.db',
|
|
32
|
+
projectAliases: {}
|
|
33
|
+
};
|
|
34
|
+
function detectSessionDirs() {
|
|
35
|
+
const found = KNOWN_SESSION_DIRS.filter((d) => node_fs_1.default.existsSync(d));
|
|
36
|
+
return found.length > 0 ? found : null;
|
|
37
|
+
}
|
|
38
|
+
function loadConfig() {
|
|
39
|
+
let fileConfig = {};
|
|
40
|
+
if (node_fs_1.default.existsSync(CONFIG_FILE)) {
|
|
41
|
+
try {
|
|
42
|
+
fileConfig = JSON.parse(node_fs_1.default.readFileSync(CONFIG_FILE, 'utf8'));
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
console.error(`Warning: Could not parse ${CONFIG_FILE}:`, err.message);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
// First-run: create default config with auto-detected session dirs
|
|
50
|
+
const detected = detectSessionDirs();
|
|
51
|
+
const firstRunDefaults = { ...DEFAULTS, sessionsPath: detected };
|
|
52
|
+
const dir = node_path_1.default.dirname(CONFIG_FILE);
|
|
53
|
+
if (!node_fs_1.default.existsSync(dir))
|
|
54
|
+
node_fs_1.default.mkdirSync(dir, { recursive: true });
|
|
55
|
+
node_fs_1.default.writeFileSync(CONFIG_FILE, JSON.stringify(firstRunDefaults, null, 2) + '\n');
|
|
56
|
+
// Apply to in-memory config so this run also benefits
|
|
57
|
+
fileConfig = firstRunDefaults;
|
|
58
|
+
console.log(`Created default config: ${CONFIG_FILE}`);
|
|
59
|
+
if (detected) {
|
|
60
|
+
console.log(`Auto-detected session directories:\n${detected.map((d) => ` - ${d}`).join('\n')}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// In demo mode, ignore file-based sessionsPath so live data doesn't bleed in
|
|
64
|
+
if (process.env.AGENTACTA_DEMO_MODE)
|
|
65
|
+
delete fileConfig.sessionsPath;
|
|
66
|
+
const config = { ...DEFAULTS, ...fileConfig };
|
|
67
|
+
// Env var overrides (highest priority)
|
|
68
|
+
if (process.env.PORT)
|
|
69
|
+
config.port = parseInt(process.env.PORT);
|
|
70
|
+
if (process.env.AGENTACTA_STORAGE)
|
|
71
|
+
config.storage = process.env.AGENTACTA_STORAGE;
|
|
72
|
+
if (process.env.AGENTACTA_SESSIONS_PATH)
|
|
73
|
+
config.sessionsPath = process.env.AGENTACTA_SESSIONS_PATH;
|
|
74
|
+
if (process.env.AGENTACTA_DB_PATH)
|
|
75
|
+
config.dbPath = process.env.AGENTACTA_DB_PATH;
|
|
76
|
+
if (process.env.AGENTACTA_PROJECT_ALIASES_JSON) {
|
|
77
|
+
try {
|
|
78
|
+
config.projectAliases = JSON.parse(process.env.AGENTACTA_PROJECT_ALIASES_JSON);
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
console.error('Warning: Could not parse AGENTACTA_PROJECT_ALIASES_JSON:', err.message);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// Resolve dbPath relative to cwd
|
|
85
|
+
config.dbPath = node_path_1.default.resolve(config.dbPath);
|
|
86
|
+
if (!config.projectAliases || typeof config.projectAliases !== 'object')
|
|
87
|
+
config.projectAliases = {};
|
|
88
|
+
return config;
|
|
89
|
+
}
|
|
90
|
+
// v1.1.3
|
|
91
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/db.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
import type { PreparedStatements } from './types.js';
|
|
3
|
+
export declare function open(dbPath?: string): Database.Database;
|
|
4
|
+
export declare function init(dbPath?: string): void;
|
|
5
|
+
export declare function createStmts(db: Database.Database): PreparedStatements;
|
package/dist/db.js
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.open = open;
|
|
7
|
+
exports.init = init;
|
|
8
|
+
exports.createStmts = createStmts;
|
|
9
|
+
const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
|
|
10
|
+
const config_js_1 = require("./config.js");
|
|
11
|
+
let _config = null;
|
|
12
|
+
function getConfig() {
|
|
13
|
+
if (!_config)
|
|
14
|
+
_config = (0, config_js_1.loadConfig)();
|
|
15
|
+
return _config;
|
|
16
|
+
}
|
|
17
|
+
function open(dbPath) {
|
|
18
|
+
const p = dbPath || getConfig().dbPath;
|
|
19
|
+
const db = new better_sqlite3_1.default(p);
|
|
20
|
+
db.pragma('journal_mode = WAL');
|
|
21
|
+
db.pragma('foreign_keys = ON');
|
|
22
|
+
return db;
|
|
23
|
+
}
|
|
24
|
+
function init(dbPath) {
|
|
25
|
+
const db = open(dbPath);
|
|
26
|
+
db.exec(`
|
|
27
|
+
CREATE TABLE IF NOT EXISTS sessions (
|
|
28
|
+
id TEXT PRIMARY KEY,
|
|
29
|
+
start_time TEXT NOT NULL,
|
|
30
|
+
end_time TEXT,
|
|
31
|
+
message_count INTEGER DEFAULT 0,
|
|
32
|
+
tool_count INTEGER DEFAULT 0,
|
|
33
|
+
model TEXT,
|
|
34
|
+
summary TEXT,
|
|
35
|
+
agent TEXT,
|
|
36
|
+
session_type TEXT,
|
|
37
|
+
total_cost REAL DEFAULT 0,
|
|
38
|
+
total_tokens INTEGER DEFAULT 0,
|
|
39
|
+
input_tokens INTEGER DEFAULT 0,
|
|
40
|
+
output_tokens INTEGER DEFAULT 0,
|
|
41
|
+
cache_read_tokens INTEGER DEFAULT 0,
|
|
42
|
+
cache_write_tokens INTEGER DEFAULT 0,
|
|
43
|
+
initial_prompt TEXT,
|
|
44
|
+
first_message_id TEXT,
|
|
45
|
+
first_message_timestamp TEXT
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
CREATE TABLE IF NOT EXISTS events (
|
|
49
|
+
id TEXT PRIMARY KEY,
|
|
50
|
+
session_id TEXT NOT NULL,
|
|
51
|
+
timestamp TEXT NOT NULL,
|
|
52
|
+
type TEXT NOT NULL,
|
|
53
|
+
role TEXT,
|
|
54
|
+
content TEXT,
|
|
55
|
+
tool_name TEXT,
|
|
56
|
+
tool_args TEXT,
|
|
57
|
+
tool_result TEXT,
|
|
58
|
+
FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_start_time ON sessions(start_time DESC);
|
|
62
|
+
CREATE INDEX IF NOT EXISTS idx_events_session ON events(session_id);
|
|
63
|
+
CREATE INDEX IF NOT EXISTS idx_events_timestamp ON events(timestamp);
|
|
64
|
+
CREATE INDEX IF NOT EXISTS idx_events_type ON events(type);
|
|
65
|
+
CREATE INDEX IF NOT EXISTS idx_events_tool_name ON events(tool_name);
|
|
66
|
+
|
|
67
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS events_fts USING fts5(
|
|
68
|
+
content, tool_name, tool_args,
|
|
69
|
+
content='events',
|
|
70
|
+
content_rowid='rowid'
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
CREATE TRIGGER IF NOT EXISTS events_ai AFTER INSERT ON events BEGIN
|
|
74
|
+
INSERT INTO events_fts(rowid, content, tool_name, tool_args)
|
|
75
|
+
VALUES (new.rowid, new.content, new.tool_name, new.tool_args);
|
|
76
|
+
END;
|
|
77
|
+
|
|
78
|
+
CREATE TRIGGER IF NOT EXISTS events_ad AFTER DELETE ON events BEGIN
|
|
79
|
+
INSERT INTO events_fts(events_fts, rowid, content, tool_name, tool_args)
|
|
80
|
+
VALUES ('delete', old.rowid, old.content, old.tool_name, old.tool_args);
|
|
81
|
+
END;
|
|
82
|
+
|
|
83
|
+
CREATE TABLE IF NOT EXISTS index_state (
|
|
84
|
+
file_path TEXT PRIMARY KEY,
|
|
85
|
+
last_offset INTEGER DEFAULT 0,
|
|
86
|
+
last_modified TEXT
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
CREATE TABLE IF NOT EXISTS file_activity (
|
|
90
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
91
|
+
session_id TEXT NOT NULL,
|
|
92
|
+
file_path TEXT NOT NULL,
|
|
93
|
+
operation TEXT NOT NULL,
|
|
94
|
+
timestamp TEXT,
|
|
95
|
+
FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
CREATE INDEX IF NOT EXISTS idx_file_activity_path ON file_activity(file_path);
|
|
99
|
+
CREATE INDEX IF NOT EXISTS idx_file_activity_session ON file_activity(session_id);
|
|
100
|
+
|
|
101
|
+
CREATE TABLE IF NOT EXISTS archive (
|
|
102
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
103
|
+
session_id TEXT NOT NULL,
|
|
104
|
+
line_number INTEGER NOT NULL,
|
|
105
|
+
raw_json TEXT NOT NULL,
|
|
106
|
+
FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
CREATE INDEX IF NOT EXISTS idx_archive_session ON archive(session_id);
|
|
110
|
+
|
|
111
|
+
CREATE TABLE IF NOT EXISTS session_insights (
|
|
112
|
+
session_id TEXT PRIMARY KEY,
|
|
113
|
+
signals TEXT,
|
|
114
|
+
confusion_score INTEGER DEFAULT 0,
|
|
115
|
+
flagged INTEGER DEFAULT 0,
|
|
116
|
+
computed_at TEXT,
|
|
117
|
+
FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
CREATE INDEX IF NOT EXISTS idx_insights_flagged ON session_insights(flagged);
|
|
121
|
+
CREATE INDEX IF NOT EXISTS idx_insights_score ON session_insights(confusion_score DESC);
|
|
122
|
+
`);
|
|
123
|
+
// Add columns if missing (migration)
|
|
124
|
+
const cols = db.prepare("PRAGMA table_info(sessions)").all();
|
|
125
|
+
const colNames = cols.map((c) => c.name);
|
|
126
|
+
if (!colNames.includes('agent'))
|
|
127
|
+
db.exec("ALTER TABLE sessions ADD COLUMN agent TEXT");
|
|
128
|
+
if (!colNames.includes('session_type'))
|
|
129
|
+
db.exec("ALTER TABLE sessions ADD COLUMN session_type TEXT");
|
|
130
|
+
if (!colNames.includes('total_cost'))
|
|
131
|
+
db.exec("ALTER TABLE sessions ADD COLUMN total_cost REAL DEFAULT 0");
|
|
132
|
+
if (!colNames.includes('total_tokens'))
|
|
133
|
+
db.exec("ALTER TABLE sessions ADD COLUMN total_tokens INTEGER DEFAULT 0");
|
|
134
|
+
if (!colNames.includes('input_tokens'))
|
|
135
|
+
db.exec("ALTER TABLE sessions ADD COLUMN input_tokens INTEGER DEFAULT 0");
|
|
136
|
+
if (!colNames.includes('output_tokens'))
|
|
137
|
+
db.exec("ALTER TABLE sessions ADD COLUMN output_tokens INTEGER DEFAULT 0");
|
|
138
|
+
if (!colNames.includes('cache_read_tokens'))
|
|
139
|
+
db.exec("ALTER TABLE sessions ADD COLUMN cache_read_tokens INTEGER DEFAULT 0");
|
|
140
|
+
if (!colNames.includes('cache_write_tokens'))
|
|
141
|
+
db.exec("ALTER TABLE sessions ADD COLUMN cache_write_tokens INTEGER DEFAULT 0");
|
|
142
|
+
if (!colNames.includes('models'))
|
|
143
|
+
db.exec("ALTER TABLE sessions ADD COLUMN models TEXT");
|
|
144
|
+
if (!colNames.includes('projects'))
|
|
145
|
+
db.exec("ALTER TABLE sessions ADD COLUMN projects TEXT");
|
|
146
|
+
db.close();
|
|
147
|
+
}
|
|
148
|
+
function createStmts(db) {
|
|
149
|
+
return {
|
|
150
|
+
getState: db.prepare('SELECT * FROM index_state WHERE file_path = ?'),
|
|
151
|
+
getSession: db.prepare('SELECT id FROM sessions WHERE id = ?'),
|
|
152
|
+
deleteEvents: db.prepare('DELETE FROM events WHERE session_id = ?'),
|
|
153
|
+
deleteSession: db.prepare('DELETE FROM sessions WHERE id = ?'),
|
|
154
|
+
deleteFileActivity: db.prepare('DELETE FROM file_activity WHERE session_id = ?'),
|
|
155
|
+
insertEvent: db.prepare(`INSERT OR REPLACE INTO events (id, session_id, timestamp, type, role, content, tool_name, tool_args, tool_result) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`),
|
|
156
|
+
upsertSession: db.prepare(`INSERT OR REPLACE INTO sessions (id, start_time, end_time, message_count, tool_count, model, summary, agent, session_type, total_cost, total_tokens, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens, initial_prompt, first_message_id, first_message_timestamp, models, projects) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`),
|
|
157
|
+
upsertState: db.prepare(`INSERT OR REPLACE INTO index_state (file_path, last_offset, last_modified) VALUES (?, ?, ?)`),
|
|
158
|
+
insertFileActivity: db.prepare(`INSERT INTO file_activity (session_id, file_path, operation, timestamp) VALUES (?, ?, ?, ?)`),
|
|
159
|
+
deleteArchive: db.prepare('DELETE FROM archive WHERE session_id = ?'),
|
|
160
|
+
insertArchive: db.prepare('INSERT INTO archive (session_id, line_number, raw_json) VALUES (?, ?, ?)')
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=db.js.map
|
package/dist/db.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type Database from 'better-sqlite3';
|
|
2
|
+
import type { EventRow } from './types.js';
|
|
3
|
+
export declare function extractCallBaseId(id: string | null | undefined): string;
|
|
4
|
+
export declare function loadDeltaAttributionContext(db: Database.Database, sessionId: string, rows: EventRow[]): EventRow[];
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractCallBaseId = extractCallBaseId;
|
|
4
|
+
exports.loadDeltaAttributionContext = loadDeltaAttributionContext;
|
|
5
|
+
function extractCallBaseId(id) {
|
|
6
|
+
if (!id)
|
|
7
|
+
return '';
|
|
8
|
+
return String(id).replace(/:(call|result)$/, '');
|
|
9
|
+
}
|
|
10
|
+
function loadDeltaAttributionContext(db, sessionId, rows) {
|
|
11
|
+
if (!db || !Array.isArray(rows) || !rows.length)
|
|
12
|
+
return [];
|
|
13
|
+
const ordered = [...rows].sort((a, b) => {
|
|
14
|
+
const ta = Date.parse(a?.timestamp || '0') || 0;
|
|
15
|
+
const tb = Date.parse(b?.timestamp || '0') || 0;
|
|
16
|
+
if (ta !== tb)
|
|
17
|
+
return ta - tb;
|
|
18
|
+
return String(a?.id || '').localeCompare(String(b?.id || ''));
|
|
19
|
+
});
|
|
20
|
+
const first = ordered[0];
|
|
21
|
+
const firstTs = first?.timestamp || '1970-01-01T00:00:00.000Z';
|
|
22
|
+
const firstId = first?.id || '';
|
|
23
|
+
const neighborhoodRows = db.prepare(`SELECT * FROM events
|
|
24
|
+
WHERE session_id = ?
|
|
25
|
+
AND (timestamp < ? OR (timestamp = ? AND id < ?))
|
|
26
|
+
ORDER BY timestamp DESC, id DESC
|
|
27
|
+
LIMIT 12`).all(sessionId, firstTs, firstTs, firstId).reverse();
|
|
28
|
+
const callIds = [...new Set(rows
|
|
29
|
+
.filter((row) => row != null && row.type === 'tool_result')
|
|
30
|
+
.map((row) => extractCallBaseId(row.id))
|
|
31
|
+
.filter(Boolean)
|
|
32
|
+
.map((base) => `${base}:call`))];
|
|
33
|
+
if (!callIds.length)
|
|
34
|
+
return neighborhoodRows;
|
|
35
|
+
const placeholders = callIds.map(() => '?').join(',');
|
|
36
|
+
const linkedCallRows = db.prepare(`SELECT * FROM events
|
|
37
|
+
WHERE session_id = ?
|
|
38
|
+
AND type = 'tool_call'
|
|
39
|
+
AND id IN (${placeholders})`).all(sessionId, ...callIds);
|
|
40
|
+
const merged = [];
|
|
41
|
+
const seen = new Set();
|
|
42
|
+
for (const row of [...neighborhoodRows, ...linkedCallRows]) {
|
|
43
|
+
if (!row || !row.id || seen.has(row.id))
|
|
44
|
+
continue;
|
|
45
|
+
seen.add(row.id);
|
|
46
|
+
merged.push(row);
|
|
47
|
+
}
|
|
48
|
+
return merged;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=delta-attribution-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delta-attribution-context.js","sourceRoot":"","sources":["../src/delta-attribution-context.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|