agentacta 1.3.4 → 1.5.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,95 +20,105 @@ npx agentacta
18
20
  <img src="screenshots/demo.gif" alt="AgentActa demo" width="800">
19
21
  </p>
20
22
 
21
- ---
22
-
23
- ## Why
24
-
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).
23
+ ## Why this exists
26
24
 
27
- AgentActa gives you a single, searchable view of everything.
25
+ Agents move fast. Your memory of what happened doesn’t.
28
26
 
29
- ## What You Get
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.
30
28
 
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
29
+ AgentActa gives you one place to inspect the full trail.
39
30
 
40
- ## Demo
31
+ ## What you get
41
32
 
42
- https://github.com/mirajchokshi/agentacta/raw/main/screenshots/demo-final.mp4
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
42
+ - ⌨️ Command palette (⌘K / Ctrl+K) for quick navigation
43
+ - 🎨 Theme settings (system, light, dark, OLED)
44
+ - 🏥 Health endpoint for monitoring (`/api/health`)
43
45
 
44
- ## Screenshots
45
46
 
46
- ![Search](screenshots/search.png)
47
- ![Sessions](screenshots/sessions.png)
48
- ![Session Detail](screenshots/session-detail.png)
49
- ![Timeline](screenshots/timeline.png)
50
- ![Files](screenshots/files.png)
51
- ![Stats](screenshots/stats.png)
52
- ![Search Results](screenshots/search-results.png)
53
-
54
- ## Quick Start
47
+ ## Quick start
55
48
 
56
49
  ```bash
57
- # Run directly (no install needed)
50
+ # run directly
58
51
  npx agentacta
59
52
 
60
- # Or install globally
53
+ # or install globally
61
54
  npm install -g agentacta
62
55
  agentacta
63
56
  ```
64
57
 
65
- Open `http://localhost:4003` in your browser.
58
+ Open: `http://localhost:4003`
66
59
 
67
- AgentActa automatically finds your sessions in:
60
+ Auto-detected session paths:
68
61
  - `~/.openclaw/agents/*/sessions/` (OpenClaw)
69
62
  - `~/.claude/projects/*/` (Claude Code)
70
63
  - `~/.codex/sessions/` (Codex CLI)
71
64
 
72
- Or point it at a custom path:
65
+ Custom path:
73
66
 
74
67
  ```bash
75
68
  AGENTACTA_SESSIONS_PATH=/path/to/sessions agentacta
76
69
  ```
77
70
 
78
- ## Features
71
+ ## Core features
79
72
 
80
73
  ### Search
81
- 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.
74
+
75
+ SQLite FTS5 full-text search with filters for message type (messages, tool calls, results) and role (user, assistant).
76
+
77
+ Suggestions come from your own dataset: top tools, common topics, frequently touched files.
82
78
 
83
79
  ### Sessions
84
- 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.
80
+
81
+ Browse indexed sessions with auto-generated summaries, token splits (input/output), and model details. Click into any session to see the full event history.
82
+
83
+ Session types get tagged so noisy categories are easier to spot (cron, sub-agent, heartbeat).
85
84
 
86
85
  ### Timeline
87
- Pick a date, see everything that happened. Messages, tool invocations, file changes — most recent first.
86
+
87
+ Pick a date, see everything that happened, newest first. Today's view updates live as new events come in.
88
88
 
89
89
  ### File Activity
90
- 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.
90
+
91
+ See what files were touched, how often, and by which sessions.
92
+
93
+ Sort by recency, frequency, or session count. Filter by extension. Group by directory. Click any file to see which sessions touched it.
91
94
 
92
95
  ### Export
93
- Download any session or search results as Markdown or JSON. Great for sharing, auditing, or archiving.
94
96
 
95
- ## How It Works
97
+ Export sessions or search results as Markdown or JSON.
96
98
 
97
- AgentActa reads JSONL session files (including OpenClaw, Claude Code, and Codex CLI formats), parses every message and tool call, and indexes them into a local SQLite database with FTS5 full-text search.
99
+ Useful for handoffs, incident writeups, and audit archives.
98
100
 
99
- 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`.
101
+ ## How it works
100
102
 
101
- ```
102
- Session JSONL files → SQLite + FTS5 index → HTTP API → Web UI
103
+ AgentActa parses JSONL session files (OpenClaw, Claude Code, Codex CLI), then indexes events into local SQLite with FTS5.
104
+
105
+ The UI is a single-page app served by a lightweight Node HTTP server.
106
+
107
+ No framework build pipeline. Minimal moving parts.
108
+
109
+ ```text
110
+ Session JSONL files -> SQLite + FTS5 index -> HTTP API -> Web UI
103
111
  ```
104
112
 
105
- Data never leaves your machine.
113
+ Everything stays on your machine.
106
114
 
107
115
  ## Configuration
108
116
 
109
- 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):
117
+ On first run, AgentActa creates:
118
+ - `~/.config/agentacta/config.json`
119
+ - or `agentacta.config.json` in current directory (if present)
120
+
121
+ Default config:
110
122
 
111
123
  ```json
112
124
  {
@@ -118,85 +130,70 @@ On first run, AgentActa creates a config file with sensible defaults at `~/.conf
118
130
  }
119
131
  ```
120
132
 
121
- ### Storage Modes
133
+ ### Storage modes
122
134
 
123
- - **`reference`** (default) — Lightweight index. Stores parsed events in SQLite but not the raw JSONL. Source files must remain on disk.
124
- - **`archive`** Full JSONL stored in SQLite. Sessions survive even if the original files are deleted. Uses more disk space.
135
+ - `reference` (default): index parsed events in SQLite, keep source JSONL on disk. Lightweight.
136
+ - `archive`: store full JSONL in SQLite. Sessions survive even if original files are deleted. Uses more disk.
125
137
 
126
- ### Environment Variables
138
+ ### Environment variables
127
139
 
128
140
  | Variable | Default | Description |
129
141
  |---|---|---|
130
142
  | `PORT` | `4003` | Server port |
131
- | `AGENTACTA_HOST` | `127.0.0.1` | Bind address (see [Security](#security)) |
132
- | `AGENTACTA_SESSIONS_PATH` | Auto-detected | Custom sessions directory |
133
- | `AGENTACTA_DB_PATH` | `./agentacta.db` | Database file location |
134
- | `AGENTACTA_STORAGE` | `reference` | Storage mode (`reference` or `archive`) |
135
- | `AGENTACTA_PROJECT_ALIASES_JSON` | unset | JSON object mapping inferred project names (e.g. `{"old-name":"new-name"}`) |
143
+ | `AGENTACTA_HOST` | `127.0.0.1` | Bind address |
144
+ | `AGENTACTA_SESSIONS_PATH` | auto-detected | Custom sessions directory |
145
+ | `AGENTACTA_DB_PATH` | `./agentacta.db` | Database path |
146
+ | `AGENTACTA_STORAGE` | `reference` | `reference` or `archive` |
147
+ | `AGENTACTA_PROJECT_ALIASES_JSON` | unset | Rename inferred project labels |
136
148
 
137
149
  ## API
138
150
 
139
- AgentActa exposes a JSON API for programmatic access — useful for integrating search into your agent's workflow.
140
-
141
151
  | Endpoint | Description |
142
152
  |---|---|
143
- | `GET /api/stats` | Overview: session count, messages, tools, tokens |
144
- | `GET /api/sessions` | List sessions with metadata and token breakdowns |
145
- | `GET /api/sessions/:id` | Full session with all events |
146
- | `GET /api/search?q=<query>` | Full-text search with type/role/date filters |
147
- | `GET /api/suggestions` | Data-driven search suggestions |
148
- | `GET /api/timeline?date=YYYY-MM-DD` | All events for a given day |
149
- | `GET /api/files` | All files touched across sessions |
150
- | `GET /api/export/session/:id?format=md` | Export session as Markdown or JSON |
153
+ | `GET /api/stats` | Session/message/tool/token totals |
154
+ | `GET /api/sessions` | Session list with metadata |
155
+ | `GET /api/sessions/:id` | Full session events |
156
+ | `GET /api/search?q=<query>` | Full-text search + filters |
157
+ | `GET /api/suggestions` | Search suggestions |
158
+ | `GET /api/timeline?date=YYYY-MM-DD` | Events for one day |
159
+ | `GET /api/files` | Touched-file inventory |
160
+ | `GET /api/export/session/:id?format=md` | Export one session |
161
+ | `GET /api/timeline/stream?after=<ts>` | SSE stream for live timeline updates |
162
+ | `POST /api/maintenance` | VACUUM + WAL checkpoint (returns size before/after) |
163
+ | `GET /api/health` | Server status, version, uptime, session count |
151
164
  | `GET /api/export/search?q=<query>&format=md` | Export search results |
152
165
 
153
- ### Agent Integration
154
-
155
- Your AI agent can query AgentActa for better recall:
166
+ Agent integration example:
156
167
 
157
168
  ```javascript
158
- const results = await fetch('http://localhost:4003/api/search?q=deployment+issue&limit=5');
159
- const data = await results.json();
160
- // Agent now has context from past sessions
161
- ```
162
-
163
- ### Demo Mode
164
-
165
- Want to see what AgentActa looks like with data? Run with demo sessions:
166
-
167
- ```bash
168
- # Generate demo data and start in demo mode
169
- npm run demo
170
-
171
- # Or separately:
172
- node scripts/seed-demo.js
173
- node index.js --demo
169
+ const res = await fetch('http://localhost:4003/api/search?q=deployment+issue&limit=5');
170
+ const data = await res.json();
174
171
  ```
175
172
 
176
- This creates 7 realistic sessions simulating a developer building a weather app — scaffolding, API integration, frontend, debugging, deployment, tests, and a sub-agent task.
177
-
178
173
  ## Security
179
174
 
180
- **AgentActa is a local tool.** It binds to `127.0.0.1` by default — only accessible from your machine.
175
+ AgentActa binds to `127.0.0.1` by default.
181
176
 
182
- To expose on your network (e.g., for Tailscale access):
177
+ If you expose it on a network, do it intentionally:
183
178
 
184
179
  ```bash
185
180
  AGENTACTA_HOST=0.0.0.0 agentacta
186
181
  ```
187
182
 
188
- ⚠️ **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.
183
+ **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.
189
184
 
190
- ## Tech Stack
185
+ ## Tech stack
191
186
 
192
- - **Node.js** — HTTP server (built-in `http`, no Express)
193
- - **better-sqlite3** Fast SQLite with FTS5 full-text search
194
- - **Vanilla HTML/CSS/JS** — No framework, no build step
195
- - **PWA** — Installable as a home screen app
187
+ - Node.js (built-in `http`)
188
+ - `better-sqlite3` + SQLite FTS5
189
+ - Vanilla HTML/CSS/JS
190
+ - PWA support
196
191
 
197
192
  ## Privacy
198
193
 
199
- All data stays local. AgentActa runs entirely on your machine — no cloud services, no telemetry, no external requests. Your agent history is yours.
194
+ No telemetry. No cloud sync. No external indexing service.
195
+
196
+ Your session history stays local.
200
197
 
201
198
  ## Compatibility
202
199
 
@@ -207,13 +204,15 @@ All data stays local. AgentActa runs entirely on your machine — no cloud servi
207
204
 
208
205
  ## Contributing
209
206
 
210
- 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.
207
+ PRs welcome.
208
+
209
+ See [CONTRIBUTING.md](CONTRIBUTING.md). If you’re adding a new agent format, start in `indexer.js`.
211
210
 
212
- ## Etymology
211
+ ## Name
213
212
 
214
- *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.
213
+ *Acta* is Latin for things done.”
215
214
 
216
- AgentActa is the same idea: a complete, searchable record of everything your AI agent did.
215
+ That’s the job here: keep a readable record of what your agents actually did.
217
216
 
218
217
  ## License
219
218
 
@@ -221,4 +220,4 @@ MIT
221
220
 
222
221
  ---
223
222
 
224
- Built in Chicago by humans and agents working together.
223
+ 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
@@ -1,9 +1,25 @@
1
1
  #!/usr/bin/env node
2
+
3
+ // Bridge release for users on ^1.x semver ranges
4
+ if (require('./package.json').version === '1.5.0') {
5
+ console.log('\n\x1b[33m⚠ AgentActa has moved to CalVer versioning (2026.x.x).\x1b[0m');
6
+ console.log('\x1b[33m You are running an old 1.x version.\x1b[0m\n');
7
+ console.log(' Update with: \x1b[36mnpx agentacta@latest\x1b[0m');
8
+ console.log(' Or install: \x1b[36mnpm install -g agentacta@latest\x1b[0m\n');
9
+ }
10
+
2
11
  const http = require('http');
3
12
  const fs = require('fs');
4
13
  const path = require('path');
5
14
  const { EventEmitter } = require('events');
6
15
 
16
+ // --version / -v flag: print version and exit
17
+ if (process.argv.includes('--version') || process.argv.includes('-v')) {
18
+ const pkg = require('./package.json');
19
+ console.log(`${pkg.name} v${pkg.version}`);
20
+ process.exit(0);
21
+ }
22
+
7
23
  // --demo flag: use demo session data (must run before config load)
8
24
  if (process.argv.includes('--demo')) {
9
25
  const demoDir = path.join(__dirname, 'demo');
@@ -193,6 +209,20 @@ const server = http.createServer((req, res) => {
193
209
  return json(res, { ok: true, sessions: result.sessions, events: result.events });
194
210
  }
195
211
 
212
+ else if (pathname === '/api/health') {
213
+ const pkg = require('./package.json');
214
+ const sessions = db.prepare('SELECT COUNT(*) as c FROM sessions').get().c;
215
+ const dbSize = getDbSize();
216
+ return json(res, {
217
+ status: 'ok',
218
+ version: pkg.version,
219
+ uptime: Math.round(process.uptime()),
220
+ sessions,
221
+ dbSizeBytes: dbSize.bytes,
222
+ node: process.version
223
+ });
224
+ }
225
+
196
226
  else if (pathname === '/api/config') {
197
227
  const dbSize = getDbSize();
198
228
  const archiveCount = db.prepare('SELECT COUNT(*) as c FROM archive').get().c;
@@ -428,13 +458,70 @@ const server = http.createServer((req, res) => {
428
458
  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
459
  const from = new Date(date + 'T00:00:00').toISOString();
430
460
  const to = new Date(date + 'T23:59:59.999').toISOString();
461
+ const limit = Math.min(parseInt(query.limit || '100', 10) || 100, 500);
462
+ const offset = Math.max(parseInt(query.offset || '0', 10) || 0, 0);
431
463
  const events = db.prepare(
432
464
  `SELECT e.*, s.summary as session_summary FROM events e
433
465
  JOIN sessions s ON s.id = e.session_id
434
466
  WHERE e.timestamp >= ? AND e.timestamp <= ?
435
- ORDER BY e.timestamp DESC`
436
- ).all(from, to);
437
- json(res, { date, events, total: events.length });
467
+ ORDER BY e.timestamp DESC
468
+ LIMIT ? OFFSET ?`
469
+ ).all(from, to, limit, offset);
470
+ const total = db.prepare(
471
+ `SELECT COUNT(*) as c FROM events e
472
+ WHERE e.timestamp >= ? AND e.timestamp <= ?`
473
+ ).get(from, to).c;
474
+ json(res, { date, events, total, limit, offset, hasMore: offset + events.length < total });
475
+ }
476
+ else if (pathname === '/api/timeline/stream') {
477
+ res.writeHead(200, {
478
+ 'Content-Type': 'text/event-stream',
479
+ 'Cache-Control': 'no-cache',
480
+ 'Connection': 'keep-alive',
481
+ 'X-Accel-Buffering': 'no'
482
+ });
483
+ res.write(': connected\n\n');
484
+
485
+ let lastTs = query.after || new Date().toISOString();
486
+ let lastId = query.afterId || '';
487
+
488
+ const onUpdate = () => {
489
+ try {
490
+ const rows = db.prepare(
491
+ `SELECT e.*, s.summary as session_summary FROM events e
492
+ JOIN sessions s ON s.id = e.session_id
493
+ WHERE (e.timestamp > ?) OR (e.timestamp = ? AND e.id > ?)
494
+ ORDER BY e.timestamp ASC, e.id ASC`
495
+ ).all(lastTs, lastTs, lastId);
496
+ if (rows.length) {
497
+ const tail = rows[rows.length - 1];
498
+ lastTs = tail.timestamp || lastTs;
499
+ lastId = tail.id || lastId;
500
+ res.write(`id: ${lastTs}:${lastId}\ndata: ${JSON.stringify(rows)}\n\n`);
501
+ }
502
+ } catch (err) {
503
+ console.error('Timeline SSE error:', err.message);
504
+ }
505
+ };
506
+
507
+ sseEmitter.on('session-update', onUpdate);
508
+
509
+ const ping = setInterval(() => {
510
+ try { res.write(': ping\n\n'); } catch {}
511
+ }, 30000);
512
+
513
+ req.on('close', () => {
514
+ sseEmitter.off('session-update', onUpdate);
515
+ clearInterval(ping);
516
+ });
517
+ }
518
+ else if (pathname === '/api/maintenance') {
519
+ if (req.method !== 'POST') return json(res, { error: 'Method not allowed' }, 405);
520
+ const sizeBefore = getDbSize();
521
+ db.pragma('wal_checkpoint(TRUNCATE)');
522
+ db.exec('VACUUM');
523
+ const sizeAfter = getDbSize();
524
+ json(res, { ok: true, sizeBefore, sizeAfter });
438
525
  }
439
526
  else if (pathname === '/api/files') {
440
527
  const limit = parseInt(query.limit) || 100;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentacta",
3
- "version": "1.3.4",
3
+ "version": "1.5.0",
4
4
  "description": "Audit trail and search engine for AI agent sessions",
5
5
  "main": "index.js",
6
6
  "bin": {