agentacta 1.3.3 → 1.4.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/README.md CHANGED
@@ -4,9 +4,11 @@
4
4
  [![npm](https://img.shields.io/npm/v/agentacta)](https://www.npmjs.com/package/agentacta)
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
6
6
 
7
- **Your AI agent does hundreds of things. Can you find them?**
7
+ **Your agent did 1000s of things today. Can you find the 1 that broke prod?**
8
8
 
9
- AgentActa is an audit trail and search engine for AI agent sessions. It indexes everything your agent did — every message, tool call, file edit, web search, and decision — into a fast, searchable local interface.
9
+ AgentActa is a local audit trail and search engine for AI agent sessions.
10
+
11
+ It indexes messages, tool calls, file edits, searches, and decisions into a fast UI you can query in seconds.
10
12
 
11
13
  One command. Zero config. Full visibility.
12
14
 
@@ -18,24 +20,25 @@ npx agentacta
18
20
  <img src="screenshots/demo.gif" alt="AgentActa demo" width="800">
19
21
  </p>
20
22
 
21
- ---
23
+ ## Why this exists
22
24
 
23
- ## Why
25
+ Agents move fast. Your memory of what happened doesn’t.
24
26
 
25
- AI agents are powerful. They write code, send emails, manage infrastructure, make decisions on your behalf. But when you need to know *what happened* — what was changed, when, and why you're digging through scattered logs or asking the agent to remember (it won't).
27
+ When you need to answer what changed, when, and why,” youre usually scraping logs, scrolling transcripts, or asking the same assistant that forgot 20 minutes ago.
26
28
 
27
- AgentActa gives you a single, searchable view of everything.
29
+ AgentActa gives you one place to inspect the full trail.
28
30
 
29
- ## What You Get
31
+ ## What you get
30
32
 
31
- 🔍 **Full-text search** across all messages, tool calls, and results
32
- 📋 **Session browser** with summaries, token breakdowns (input/output), and model info
33
- 📅 **Timeline view** everything that happened on any given day
34
- 📁 **File activity** — every file your agent touched, across all sessions
35
- 📊 **Stats** sessions, messages, tool usage, token counts
36
- **Live indexing** new sessions appear automatically via file watching
37
- 📱 **Mobile-friendly** responsive UI with bottom tab navigation
38
- 💡 **Smart suggestions** — quick search chips derived from your actual session data
33
+ - 🔍 Full-text search across messages, tool calls, and results
34
+ - 📋 Session browser with summaries, token breakdowns, and model info
35
+ - 📅 Timeline view with live updates for today
36
+ - 📁 File activity across all indexed sessions
37
+ - 🌗 Light and dark themes
38
+ - 📊 Stats for sessions, messages, tools, and tokens
39
+ - Live indexing via file watching
40
+ - 📱 Mobile-friendly UI
41
+ - 💡 Search suggestions based on real data
39
42
 
40
43
  ## Demo
41
44
 
@@ -51,61 +54,81 @@ https://github.com/mirajchokshi/agentacta/raw/main/screenshots/demo-final.mp4
51
54
  ![Stats](screenshots/stats.png)
52
55
  ![Search Results](screenshots/search-results.png)
53
56
 
54
- ## Quick Start
57
+ ## Quick start
55
58
 
56
59
  ```bash
57
- # Run directly (no install needed)
60
+ # run directly
58
61
  npx agentacta
59
62
 
60
- # Or install globally
63
+ # or install globally
61
64
  npm install -g agentacta
62
65
  agentacta
63
66
  ```
64
67
 
65
- Open `http://localhost:4003` in your browser.
68
+ Open: `http://localhost:4003`
66
69
 
67
- AgentActa automatically finds your sessions in:
70
+ Auto-detected session paths:
68
71
  - `~/.openclaw/agents/*/sessions/` (OpenClaw)
69
72
  - `~/.claude/projects/*/` (Claude Code)
73
+ - `~/.codex/sessions/` (Codex CLI)
70
74
 
71
- Or point it at a custom path:
75
+ Custom path:
72
76
 
73
77
  ```bash
74
78
  AGENTACTA_SESSIONS_PATH=/path/to/sessions agentacta
75
79
  ```
76
80
 
77
- ## Features
81
+ ## Core features
78
82
 
79
83
  ### Search
80
- Full-text search powered by SQLite FTS5. Filter by message type (messages, tool calls, results) and role (user, assistant). Quick search suggestions are generated from your actual data — most-used tools, common topics, frequently touched files.
84
+
85
+ SQLite FTS5 full-text search with filters for message type (messages, tool calls, results) and role (user, assistant).
86
+
87
+ Suggestions come from your own dataset: top tools, common topics, frequently touched files.
81
88
 
82
89
  ### Sessions
83
- Browse all indexed sessions with auto-generated summaries, token breakdowns (output vs input), and model info. Sessions are automatically tagged by type — cron jobs, sub-agent tasks, and heartbeat sessions get distinct badges. Click into any session to see the full event history, most recent first.
90
+
91
+ Browse indexed sessions with auto-generated summaries, token splits (input/output), and model details. Click into any session to see the full event history.
92
+
93
+ Session types get tagged so noisy categories are easier to spot (cron, sub-agent, heartbeat).
84
94
 
85
95
  ### Timeline
86
- Pick a date, see everything that happened. Messages, tool invocations, file changes — most recent first.
96
+
97
+ Pick a date, see everything that happened, newest first. Today's view updates live as new events come in.
87
98
 
88
99
  ### File Activity
89
- See every file your agent read, wrote, or edited. Sort by most touched, most recent, or most sessions. Filter by extension, group by directory. Click any file to see which sessions touched it and what was done.
100
+
101
+ See what files were touched, how often, and by which sessions.
102
+
103
+ Sort by recency, frequency, or session count. Filter by extension. Group by directory. Click any file to see which sessions touched it.
90
104
 
91
105
  ### Export
92
- Download any session or search results as Markdown or JSON. Great for sharing, auditing, or archiving.
93
106
 
94
- ## How It Works
107
+ Export sessions or search results as Markdown or JSON.
95
108
 
96
- AgentActa reads JSONL session files (the standard format used by OpenClaw and Claude Code), parses every message and tool call, and indexes them into a local SQLite database with FTS5 full-text search.
109
+ Useful for handoffs, incident writeups, and audit archives.
97
110
 
98
- The web UI is a single-page app served by a lightweight Node.js HTTP server. No frameworks, no build step, no external dependencies beyond `better-sqlite3`.
111
+ ## How it works
99
112
 
100
- ```
101
- Session JSONL files → SQLite + FTS5 index → HTTP API → Web UI
113
+ AgentActa parses JSONL session files (OpenClaw, Claude Code, Codex CLI), then indexes events into local SQLite with FTS5.
114
+
115
+ The UI is a single-page app served by a lightweight Node HTTP server.
116
+
117
+ No framework build pipeline. Minimal moving parts.
118
+
119
+ ```text
120
+ Session JSONL files -> SQLite + FTS5 index -> HTTP API -> Web UI
102
121
  ```
103
122
 
104
- Data never leaves your machine.
123
+ Everything stays on your machine.
105
124
 
106
125
  ## Configuration
107
126
 
108
- On first run, AgentActa creates a config file with sensible defaults at `~/.config/agentacta/config.json` (or `agentacta.config.json` in the current directory if it exists):
127
+ On first run, AgentActa creates:
128
+ - `~/.config/agentacta/config.json`
129
+ - or `agentacta.config.json` in current directory (if present)
130
+
131
+ Default config:
109
132
 
110
133
  ```json
111
134
  {
@@ -117,102 +140,101 @@ On first run, AgentActa creates a config file with sensible defaults at `~/.conf
117
140
  }
118
141
  ```
119
142
 
120
- ### Storage Modes
143
+ ### Storage modes
121
144
 
122
- - **`reference`** (default) — Lightweight index. Stores parsed events in SQLite but not the raw JSONL. Source files must remain on disk.
123
- - **`archive`** Full JSONL stored in SQLite. Sessions survive even if the original files are deleted. Uses more disk space.
145
+ - `reference` (default): index parsed events in SQLite, keep source JSONL on disk. Lightweight.
146
+ - `archive`: store full JSONL in SQLite. Sessions survive even if original files are deleted. Uses more disk.
124
147
 
125
- ### Environment Variables
148
+ ### Environment variables
126
149
 
127
150
  | Variable | Default | Description |
128
151
  |---|---|---|
129
152
  | `PORT` | `4003` | Server port |
130
- | `AGENTACTA_HOST` | `127.0.0.1` | Bind address (see [Security](#security)) |
131
- | `AGENTACTA_SESSIONS_PATH` | Auto-detected | Custom sessions directory |
132
- | `AGENTACTA_DB_PATH` | `./agentacta.db` | Database file location |
133
- | `AGENTACTA_STORAGE` | `reference` | Storage mode (`reference` or `archive`) |
134
- | `AGENTACTA_PROJECT_ALIASES_JSON` | unset | JSON object mapping inferred project names (e.g. `{"old-name":"new-name"}`) |
153
+ | `AGENTACTA_HOST` | `127.0.0.1` | Bind address |
154
+ | `AGENTACTA_SESSIONS_PATH` | auto-detected | Custom sessions directory |
155
+ | `AGENTACTA_DB_PATH` | `./agentacta.db` | Database path |
156
+ | `AGENTACTA_STORAGE` | `reference` | `reference` or `archive` |
157
+ | `AGENTACTA_PROJECT_ALIASES_JSON` | unset | Rename inferred project labels |
135
158
 
136
159
  ## API
137
160
 
138
- AgentActa exposes a JSON API for programmatic access — useful for integrating search into your agent's workflow.
139
-
140
161
  | Endpoint | Description |
141
162
  |---|---|
142
- | `GET /api/stats` | Overview: session count, messages, tools, tokens |
143
- | `GET /api/sessions` | List sessions with metadata and token breakdowns |
144
- | `GET /api/sessions/:id` | Full session with all events |
145
- | `GET /api/search?q=<query>` | Full-text search with type/role/date filters |
146
- | `GET /api/suggestions` | Data-driven search suggestions |
147
- | `GET /api/timeline?date=YYYY-MM-DD` | All events for a given day |
148
- | `GET /api/files` | All files touched across sessions |
149
- | `GET /api/export/session/:id?format=md` | Export session as Markdown or JSON |
163
+ | `GET /api/stats` | Session/message/tool/token totals |
164
+ | `GET /api/sessions` | Session list with metadata |
165
+ | `GET /api/sessions/:id` | Full session events |
166
+ | `GET /api/search?q=<query>` | Full-text search + filters |
167
+ | `GET /api/suggestions` | Search suggestions |
168
+ | `GET /api/timeline?date=YYYY-MM-DD` | Events for one day |
169
+ | `GET /api/files` | Touched-file inventory |
170
+ | `GET /api/export/session/:id?format=md` | Export one session |
171
+ | `GET /api/timeline/stream?after=<ts>` | SSE stream for live timeline updates |
172
+ | `POST /api/maintenance` | VACUUM + WAL checkpoint (returns size before/after) |
150
173
  | `GET /api/export/search?q=<query>&format=md` | Export search results |
151
174
 
152
- ### Agent Integration
153
-
154
- Your AI agent can query AgentActa for better recall:
175
+ Agent integration example:
155
176
 
156
177
  ```javascript
157
- const results = await fetch('http://localhost:4003/api/search?q=deployment+issue&limit=5');
158
- const data = await results.json();
159
- // Agent now has context from past sessions
178
+ const res = await fetch('http://localhost:4003/api/search?q=deployment+issue&limit=5');
179
+ const data = await res.json();
160
180
  ```
161
181
 
162
- ### Demo Mode
163
-
164
- Want to see what AgentActa looks like with data? Run with demo sessions:
182
+ ## Demo mode
165
183
 
166
184
  ```bash
167
- # Generate demo data and start in demo mode
185
+ # seed demo data + run
168
186
  npm run demo
169
187
 
170
- # Or separately:
188
+ # or split steps
171
189
  node scripts/seed-demo.js
172
190
  node index.js --demo
173
191
  ```
174
192
 
175
- This creates 7 realistic sessions simulating a developer building a weather app scaffolding, API integration, frontend, debugging, deployment, tests, and a sub-agent task.
193
+ Demo mode creates 7 realistic sessions (weather app build path: scaffolding, API, frontend, debugging, deployment, tests, sub-agent task).
176
194
 
177
195
  ## Security
178
196
 
179
- **AgentActa is a local tool.** It binds to `127.0.0.1` by default — only accessible from your machine.
197
+ AgentActa binds to `127.0.0.1` by default.
180
198
 
181
- To expose on your network (e.g., for Tailscale access):
199
+ If you expose it on a network, do it intentionally:
182
200
 
183
201
  ```bash
184
202
  AGENTACTA_HOST=0.0.0.0 agentacta
185
203
  ```
186
204
 
187
- ⚠️ **Important:** Agent session data can contain sensitive information file contents, API responses, personal messages, tool call arguments. If you expose AgentActa on a network, ensure it's a trusted one. There is no built-in authentication.
205
+ **Important:** Session data can contain sensitive content (file snippets, API payloads, personal messages, tool args). There is no built-in auth yet, so only expose on trusted networks.
188
206
 
189
- ## Tech Stack
207
+ ## Tech stack
190
208
 
191
- - **Node.js** — HTTP server (built-in `http`, no Express)
192
- - **better-sqlite3** Fast SQLite with FTS5 full-text search
193
- - **Vanilla HTML/CSS/JS** — No framework, no build step
194
- - **PWA** — Installable as a home screen app
209
+ - Node.js (built-in `http`)
210
+ - `better-sqlite3` + SQLite FTS5
211
+ - Vanilla HTML/CSS/JS
212
+ - PWA support
195
213
 
196
214
  ## Privacy
197
215
 
198
- All data stays local. AgentActa runs entirely on your machine — no cloud services, no telemetry, no external requests. Your agent history is yours.
216
+ No telemetry. No cloud sync. No external indexing service.
217
+
218
+ Your session history stays local.
199
219
 
200
220
  ## Compatibility
201
221
 
202
222
  - ✅ [OpenClaw](https://github.com/openclaw/openclaw)
203
223
  - ✅ Claude Code
204
- - 🔜 Codex CLI
224
+ - Codex CLI
205
225
  - 🔜 Custom JSONL formats
206
226
 
207
227
  ## Contributing
208
228
 
209
- PRs welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for dev setup and guidelines. If you're adding support for a new agent format, add a parser in `indexer.js` and open a PR.
229
+ PRs welcome.
230
+
231
+ See [CONTRIBUTING.md](CONTRIBUTING.md). If you’re adding a new agent format, start in `indexer.js`.
210
232
 
211
- ## Etymology
233
+ ## Name
212
234
 
213
- *Acta* (Latin) "things done." In ancient Rome, the *acta diurna* were daily public records of official proceedings — senate decisions, military victories, births and deaths — posted in public spaces for all citizens to read.
235
+ *Acta* is Latin for things done.”
214
236
 
215
- AgentActa is the same idea: a complete, searchable record of everything your AI agent did.
237
+ That’s the job here: keep a readable record of what your agents actually did.
216
238
 
217
239
  ## License
218
240
 
@@ -220,4 +242,4 @@ MIT
220
242
 
221
243
  ---
222
244
 
223
- Built in Chicago by humans and agents working together.
245
+ Built in Chicago by humans and agents.
package/db.js CHANGED
@@ -54,6 +54,7 @@ function init(dbPath) {
54
54
  FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
55
55
  );
56
56
 
57
+ CREATE INDEX IF NOT EXISTS idx_sessions_start_time ON sessions(start_time DESC);
57
58
  CREATE INDEX IF NOT EXISTS idx_events_session ON events(session_id);
58
59
  CREATE INDEX IF NOT EXISTS idx_events_timestamp ON events(timestamp);
59
60
  CREATE INDEX IF NOT EXISTS idx_events_type ON events(type);
package/index.js CHANGED
@@ -428,13 +428,67 @@ const server = http.createServer((req, res) => {
428
428
  const date = query.date || (() => { const n = new Date(); return `${n.getFullYear()}-${String(n.getMonth()+1).padStart(2,'0')}-${String(n.getDate()).padStart(2,'0')}`; })();
429
429
  const from = new Date(date + 'T00:00:00').toISOString();
430
430
  const to = new Date(date + 'T23:59:59.999').toISOString();
431
+ const limit = Math.min(parseInt(query.limit || '100', 10) || 100, 500);
432
+ const offset = Math.max(parseInt(query.offset || '0', 10) || 0, 0);
431
433
  const events = db.prepare(
432
434
  `SELECT e.*, s.summary as session_summary FROM events e
433
435
  JOIN sessions s ON s.id = e.session_id
434
436
  WHERE e.timestamp >= ? AND e.timestamp <= ?
435
- ORDER BY e.timestamp DESC`
436
- ).all(from, to);
437
- json(res, { date, events, total: events.length });
437
+ ORDER BY e.timestamp DESC
438
+ LIMIT ? OFFSET ?`
439
+ ).all(from, to, limit, offset);
440
+ const total = db.prepare(
441
+ `SELECT COUNT(*) as c FROM events e
442
+ WHERE e.timestamp >= ? AND e.timestamp <= ?`
443
+ ).get(from, to).c;
444
+ json(res, { date, events, total, limit, offset, hasMore: offset + events.length < total });
445
+ }
446
+ else if (pathname === '/api/timeline/stream') {
447
+ res.writeHead(200, {
448
+ 'Content-Type': 'text/event-stream',
449
+ 'Cache-Control': 'no-cache',
450
+ 'Connection': 'keep-alive',
451
+ 'X-Accel-Buffering': 'no'
452
+ });
453
+ res.write(': connected\n\n');
454
+
455
+ let lastTs = query.after || new Date().toISOString();
456
+
457
+ const onUpdate = () => {
458
+ try {
459
+ const rows = db.prepare(
460
+ `SELECT e.*, s.summary as session_summary FROM events e
461
+ JOIN sessions s ON s.id = e.session_id
462
+ WHERE e.timestamp > ?
463
+ ORDER BY e.timestamp ASC`
464
+ ).all(lastTs);
465
+ if (rows.length) {
466
+ lastTs = rows[rows.length - 1].timestamp;
467
+ res.write(`id: ${lastTs}\ndata: ${JSON.stringify(rows)}\n\n`);
468
+ }
469
+ } catch (err) {
470
+ console.error('Timeline SSE error:', err.message);
471
+ }
472
+ };
473
+
474
+ sseEmitter.on('session-update', onUpdate);
475
+
476
+ const ping = setInterval(() => {
477
+ try { res.write(': ping\n\n'); } catch {}
478
+ }, 30000);
479
+
480
+ req.on('close', () => {
481
+ sseEmitter.off('session-update', onUpdate);
482
+ clearInterval(ping);
483
+ });
484
+ }
485
+ else if (pathname === '/api/maintenance') {
486
+ if (req.method !== 'POST') return json(res, { error: 'Method not allowed' }, 405);
487
+ const sizeBefore = getDbSize();
488
+ db.pragma('wal_checkpoint(TRUNCATE)');
489
+ db.exec('VACUUM');
490
+ const sizeAfter = getDbSize();
491
+ json(res, { ok: true, sizeBefore, sizeAfter });
438
492
  }
439
493
  else if (pathname === '/api/files') {
440
494
  const limit = parseInt(query.limit) || 100;