recall-player 1.0.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 (108) hide show
  1. package/README.md +238 -0
  2. package/backend/dist/db/connection.d.ts +47 -0
  3. package/backend/dist/db/connection.d.ts.map +1 -0
  4. package/backend/dist/db/connection.js +88 -0
  5. package/backend/dist/db/connection.js.map +1 -0
  6. package/backend/dist/db/queries.d.ts +172 -0
  7. package/backend/dist/db/queries.d.ts.map +1 -0
  8. package/backend/dist/db/queries.js +436 -0
  9. package/backend/dist/db/queries.js.map +1 -0
  10. package/backend/dist/db/schema.d.ts +100 -0
  11. package/backend/dist/db/schema.d.ts.map +1 -0
  12. package/backend/dist/db/schema.js +6 -0
  13. package/backend/dist/db/schema.js.map +1 -0
  14. package/backend/dist/db/transcript-connection.d.ts +57 -0
  15. package/backend/dist/db/transcript-connection.d.ts.map +1 -0
  16. package/backend/dist/db/transcript-connection.js +112 -0
  17. package/backend/dist/db/transcript-connection.js.map +1 -0
  18. package/backend/dist/db/transcript-queries.d.ts +152 -0
  19. package/backend/dist/db/transcript-queries.d.ts.map +1 -0
  20. package/backend/dist/db/transcript-queries.js +706 -0
  21. package/backend/dist/db/transcript-queries.js.map +1 -0
  22. package/backend/dist/db/transcript-schema.d.ts +143 -0
  23. package/backend/dist/db/transcript-schema.d.ts.map +1 -0
  24. package/backend/dist/db/transcript-schema.js +10 -0
  25. package/backend/dist/db/transcript-schema.js.map +1 -0
  26. package/backend/dist/index.d.ts +2 -0
  27. package/backend/dist/index.d.ts.map +1 -0
  28. package/backend/dist/index.js +96 -0
  29. package/backend/dist/index.js.map +1 -0
  30. package/backend/dist/parser/agent-detector.d.ts +76 -0
  31. package/backend/dist/parser/agent-detector.d.ts.map +1 -0
  32. package/backend/dist/parser/agent-detector.js +281 -0
  33. package/backend/dist/parser/agent-detector.js.map +1 -0
  34. package/backend/dist/parser/base-parser.d.ts +123 -0
  35. package/backend/dist/parser/base-parser.d.ts.map +1 -0
  36. package/backend/dist/parser/base-parser.js +364 -0
  37. package/backend/dist/parser/base-parser.js.map +1 -0
  38. package/backend/dist/parser/claude-parser.d.ts +78 -0
  39. package/backend/dist/parser/claude-parser.d.ts.map +1 -0
  40. package/backend/dist/parser/claude-parser.js +247 -0
  41. package/backend/dist/parser/claude-parser.js.map +1 -0
  42. package/backend/dist/parser/codex-parser.d.ts +128 -0
  43. package/backend/dist/parser/codex-parser.d.ts.map +1 -0
  44. package/backend/dist/parser/codex-parser.js +371 -0
  45. package/backend/dist/parser/codex-parser.js.map +1 -0
  46. package/backend/dist/parser/gemini-parser.d.ts +107 -0
  47. package/backend/dist/parser/gemini-parser.d.ts.map +1 -0
  48. package/backend/dist/parser/gemini-parser.js +360 -0
  49. package/backend/dist/parser/gemini-parser.js.map +1 -0
  50. package/backend/dist/parser/parser-factory.d.ts +83 -0
  51. package/backend/dist/parser/parser-factory.d.ts.map +1 -0
  52. package/backend/dist/parser/parser-factory.js +163 -0
  53. package/backend/dist/parser/parser-factory.js.map +1 -0
  54. package/backend/dist/parser/session-indexer.d.ts +79 -0
  55. package/backend/dist/parser/session-indexer.d.ts.map +1 -0
  56. package/backend/dist/parser/session-indexer.js +558 -0
  57. package/backend/dist/parser/session-indexer.js.map +1 -0
  58. package/backend/dist/parser/timeline-builder.d.ts +7 -0
  59. package/backend/dist/parser/timeline-builder.d.ts.map +1 -0
  60. package/backend/dist/parser/timeline-builder.js +334 -0
  61. package/backend/dist/parser/timeline-builder.js.map +1 -0
  62. package/backend/dist/parser/transcript-parser.d.ts +25 -0
  63. package/backend/dist/parser/transcript-parser.d.ts.map +1 -0
  64. package/backend/dist/parser/transcript-parser.js +137 -0
  65. package/backend/dist/parser/transcript-parser.js.map +1 -0
  66. package/backend/dist/routes/commentary.d.ts +33 -0
  67. package/backend/dist/routes/commentary.d.ts.map +1 -0
  68. package/backend/dist/routes/commentary.js +153 -0
  69. package/backend/dist/routes/commentary.js.map +1 -0
  70. package/backend/dist/routes/import.d.ts +3 -0
  71. package/backend/dist/routes/import.d.ts.map +1 -0
  72. package/backend/dist/routes/import.js +220 -0
  73. package/backend/dist/routes/import.js.map +1 -0
  74. package/backend/dist/routes/sessions.d.ts +3 -0
  75. package/backend/dist/routes/sessions.d.ts.map +1 -0
  76. package/backend/dist/routes/sessions.js +393 -0
  77. package/backend/dist/routes/sessions.js.map +1 -0
  78. package/backend/dist/server.d.ts +25 -0
  79. package/backend/dist/server.d.ts.map +1 -0
  80. package/backend/dist/server.js +110 -0
  81. package/backend/dist/server.js.map +1 -0
  82. package/backend/dist/services/example-import.d.ts +20 -0
  83. package/backend/dist/services/example-import.d.ts.map +1 -0
  84. package/backend/dist/services/example-import.js +93 -0
  85. package/backend/dist/services/example-import.js.map +1 -0
  86. package/backend/dist/services/file-watcher.d.ts +22 -0
  87. package/backend/dist/services/file-watcher.d.ts.map +1 -0
  88. package/backend/dist/services/file-watcher.js +141 -0
  89. package/backend/dist/services/file-watcher.js.map +1 -0
  90. package/backend/dist/services/import-cli.d.ts +11 -0
  91. package/backend/dist/services/import-cli.d.ts.map +1 -0
  92. package/backend/dist/services/import-cli.js +171 -0
  93. package/backend/dist/services/import-cli.js.map +1 -0
  94. package/backend/dist/services/transcript-importer.d.ts +98 -0
  95. package/backend/dist/services/transcript-importer.d.ts.map +1 -0
  96. package/backend/dist/services/transcript-importer.js +342 -0
  97. package/backend/dist/services/transcript-importer.js.map +1 -0
  98. package/backend/dist/types/transcript.d.ts +174 -0
  99. package/backend/dist/types/transcript.d.ts.map +1 -0
  100. package/backend/dist/types/transcript.js +8 -0
  101. package/backend/dist/types/transcript.js.map +1 -0
  102. package/backend/package.json +40 -0
  103. package/backend/public/.gitkeep +0 -0
  104. package/backend/public/assets/index-D8IP1zNL.css +1 -0
  105. package/backend/public/assets/index-GtkMiMqE.js +69 -0
  106. package/backend/public/index.html +14 -0
  107. package/bin/recall.js +43 -0
  108. package/package.json +54 -0
package/README.md ADDED
@@ -0,0 +1,238 @@
1
+ # Recall
2
+
3
+ A local-first web application that lets you **replay AI coding sessions** like a video player. Watch how features were built, decisions made, and problems solved across multiple AI coding agents.
4
+
5
+ **Supported Agents:**
6
+ - **Claude Code** - Anthropic's CLI coding assistant
7
+ - **Codex CLI** - OpenAI's command-line coding tool
8
+ - **Gemini CLI** - Google's terminal-based AI assistant
9
+
10
+ ---
11
+
12
+ ## Quick Start
13
+
14
+ ### Prerequisites
15
+
16
+ - **Node.js 18+** (check with `node --version`)
17
+ - At least one AI coding agent with session history:
18
+ - Claude Code sessions in `~/.claude/projects/`
19
+ - Codex CLI sessions in `~/.codex/sessions/`
20
+ - Gemini CLI sessions in `~/.gemini/tmp/`
21
+
22
+ ### Installation
23
+
24
+ ```bash
25
+ # Clone the repository
26
+ git clone https://github.com/anthropics/recall.git
27
+ cd recall
28
+
29
+ # Install backend dependencies
30
+ cd backend
31
+ npm install
32
+
33
+ # Install frontend dependencies
34
+ cd ../frontend
35
+ npm install
36
+ ```
37
+
38
+ ### Running the Application
39
+
40
+ You need to run both the backend and frontend servers:
41
+
42
+ **Terminal 1 - Backend:**
43
+ ```bash
44
+ cd backend
45
+ npm run dev
46
+ ```
47
+ Backend will start on http://localhost:3001
48
+
49
+ **Terminal 2 - Frontend:**
50
+ ```bash
51
+ cd frontend
52
+ npm run dev
53
+ ```
54
+ Frontend will start on http://localhost:5173 (or next available port)
55
+
56
+ ### Using Recall
57
+
58
+ 1. Open your browser to http://localhost:5173
59
+ 2. You'll see a list of all your AI coding sessions
60
+ 3. Use the filter tabs (All, Claude, Codex, Gemini) to filter by agent
61
+ 4. Click on any session to open the replay player
62
+ 5. Use the playback controls to step through the session
63
+
64
+ ---
65
+
66
+ ## Features
67
+
68
+ ### Session Browser
69
+ - View all sessions across Claude, Codex, and Gemini
70
+ - Filter by agent type, date range, and duration
71
+ - Search sessions by project name or content
72
+ - See session metadata (duration, event count, first message)
73
+
74
+ ### Session Player
75
+ - **Frame-by-frame playback** of coding sessions
76
+ - **Frame types:** User messages, AI responses, AI thinking, Tool executions
77
+ - **Filter controls** to show/hide specific frame types
78
+ - **Keyboard shortcuts** for navigation (arrow keys, space, etc.)
79
+ - **Search** within sessions to find specific content
80
+
81
+ ### Multi-Agent Support
82
+ - Automatically detects and parses sessions from all supported agents
83
+ - Agent-specific badges and colors in the UI
84
+ - Normalized frame format for consistent playback experience
85
+
86
+ ---
87
+
88
+ ## Project Structure
89
+
90
+ ```
91
+ recall/
92
+ ├── backend/ # Node.js + Express + TypeScript
93
+ │ ├── src/
94
+ │ │ ├── parser/ # Agent-specific parsers
95
+ │ │ │ ├── agent-detector.ts # Detects agent from file path
96
+ │ │ │ ├── base-parser.ts # Abstract parser base class
97
+ │ │ │ ├── claude-parser.ts # Claude Code parser
98
+ │ │ │ ├── codex-parser.ts # Codex CLI parser
99
+ │ │ │ ├── gemini-parser.ts # Gemini CLI parser
100
+ │ │ │ └── parser-factory.ts # Parser selection factory
101
+ │ │ ├── routes/ # API endpoints
102
+ │ │ ├── db/ # Database layer
103
+ │ │ └── types/ # TypeScript types
104
+ │ └── package.json
105
+
106
+ ├── frontend/ # React + Vite + TypeScript
107
+ │ ├── src/
108
+ │ │ ├── pages/ # Main pages (SessionList, SessionPlayer)
109
+ │ │ ├── components/ # Reusable components
110
+ │ │ ├── api/ # API client
111
+ │ │ └── types/ # TypeScript types
112
+ │ └── package.json
113
+
114
+ └── README.md
115
+ ```
116
+
117
+ ---
118
+
119
+ ## API Reference
120
+
121
+ ### List Sessions
122
+ ```bash
123
+ # Get all sessions
124
+ curl 'http://localhost:3001/api/sessions'
125
+
126
+ # Filter by agent
127
+ curl 'http://localhost:3001/api/sessions?agent=claude'
128
+ curl 'http://localhost:3001/api/sessions?agent=codex'
129
+ curl 'http://localhost:3001/api/sessions?agent=gemini'
130
+
131
+ # Pagination
132
+ curl 'http://localhost:3001/api/sessions?limit=10&offset=20'
133
+ ```
134
+
135
+ ### Get Available Agents
136
+ ```bash
137
+ curl 'http://localhost:3001/api/agents'
138
+ # Returns: { "agents": ["claude", "codex", "gemini"], "counts": {...} }
139
+ ```
140
+
141
+ ### Get Session Details
142
+ ```bash
143
+ curl 'http://localhost:3001/api/sessions/{sessionId}'
144
+ ```
145
+
146
+ ### Get Session Frames
147
+ ```bash
148
+ curl 'http://localhost:3001/api/sessions/{sessionId}/frames'
149
+ ```
150
+
151
+ ---
152
+
153
+ ## Keyboard Shortcuts (Session Player)
154
+
155
+ | Key | Action |
156
+ |-----|--------|
157
+ | `Space` | Play/Pause |
158
+ | `←` / `→` | Previous/Next frame |
159
+ | `Home` / `End` | First/Last frame |
160
+ | `n` / `p` | Next/Previous search match |
161
+ | `?` | Toggle help panel |
162
+
163
+ ---
164
+
165
+ ## Development
166
+
167
+ ### Backend Development
168
+ ```bash
169
+ cd backend
170
+ npm run dev # Development with hot reload
171
+ npm run build # Build for production
172
+ npm start # Run production build
173
+ npm test # Run tests
174
+ ```
175
+
176
+ ### Frontend Development
177
+ ```bash
178
+ cd frontend
179
+ npm run dev # Development with hot reload
180
+ npm run build # Build for production
181
+ npm run lint # Run ESLint
182
+ npm run preview # Preview production build
183
+ ```
184
+
185
+ ---
186
+
187
+ ## Session File Locations
188
+
189
+ Recall automatically scans these directories for sessions:
190
+
191
+ | Agent | Directory | File Format |
192
+ |-------|-----------|-------------|
193
+ | Claude Code | `~/.claude/projects/{project}/` | `*.jsonl` |
194
+ | Codex CLI | `~/.codex/sessions/` | `*.jsonl` (with date subdirs) |
195
+ | Gemini CLI | `~/.gemini/tmp/{hash}/chats/` | `session-*.json` |
196
+
197
+ ---
198
+
199
+ ## Troubleshooting
200
+
201
+ ### No sessions showing up?
202
+ 1. Make sure you have session files in one of the supported directories
203
+ 2. Check the backend console for any errors
204
+ 3. Try the API directly: `curl http://localhost:3001/api/agents`
205
+
206
+ ### Backend won't start?
207
+ 1. Make sure you're in the `backend` directory
208
+ 2. Run `npm install` to install dependencies
209
+ 3. Check that port 3001 is available
210
+
211
+ ### Frontend won't start?
212
+ 1. Make sure you're in the `frontend` directory
213
+ 2. Run `npm install` to install dependencies
214
+ 3. The frontend will automatically find an available port if 5173 is taken
215
+
216
+ ---
217
+
218
+ ## Security Notes
219
+
220
+ - **Local-only**: This app is designed for local use only
221
+ - **Read-only**: Session files are read but never modified
222
+ - **Sensitive data**: Session files may contain API keys, credentials, or sensitive code - do not expose this app to the internet
223
+
224
+ ---
225
+
226
+ ## License
227
+
228
+ MIT
229
+
230
+ ---
231
+
232
+ ## Credits
233
+
234
+ Built with:
235
+ - [Node.js](https://nodejs.org/) + [Express](https://expressjs.com/)
236
+ - [React](https://react.dev/) + [Vite](https://vitejs.dev/)
237
+ - [TypeScript](https://www.typescriptlang.org/)
238
+ - [Tailwind CSS](https://tailwindcss.com/)
@@ -0,0 +1,47 @@
1
+ import Database from 'better-sqlite3';
2
+ /**
3
+ * Creates and configures a new SQLite database connection
4
+ *
5
+ * Opens the claude-mem database in read-only mode for safety.
6
+ * This prevents accidental modifications to the user's session history.
7
+ *
8
+ * @returns {Database.Database} Configured SQLite database instance
9
+ * @throws {Error} If database file doesn't exist at DB_PATH
10
+ *
11
+ * @example
12
+ * const db = getDatabase();
13
+ * const result = db.prepare('SELECT COUNT(*) as count FROM sdk_sessions').get();
14
+ * console.log(`Found ${result.count} sessions`);
15
+ */
16
+ export declare function getDatabase(): Database.Database;
17
+ /**
18
+ * Get the singleton database instance
19
+ *
20
+ * Creates a new connection on first call, then reuses it for subsequent calls.
21
+ * This is safe because SQLite handles concurrent reads well in read-only mode.
22
+ *
23
+ * @returns {Database.Database} Singleton database instance
24
+ *
25
+ * @example
26
+ * import { getDbInstance } from './connection';
27
+ *
28
+ * const db = getDbInstance();
29
+ * const sessions = db.prepare('SELECT * FROM sdk_sessions LIMIT 10').all();
30
+ */
31
+ export declare function getDbInstance(): Database.Database;
32
+ /**
33
+ * Close the database connection and clear the singleton
34
+ *
35
+ * Should be called during graceful shutdown (SIGTERM, SIGINT).
36
+ * Ensures the database file is properly closed.
37
+ *
38
+ * @example
39
+ * process.on('SIGTERM', () => {
40
+ * server.close(() => {
41
+ * closeDatabase();
42
+ * process.exit(0);
43
+ * });
44
+ * });
45
+ */
46
+ export declare function closeDatabase(): void;
47
+ //# sourceMappingURL=connection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/db/connection.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAUtC;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,IAAI,QAAQ,CAAC,QAAQ,CAc/C;AAQD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,IAAI,QAAQ,CAAC,QAAQ,CAKjD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAKpC"}
@@ -0,0 +1,88 @@
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.getDatabase = getDatabase;
7
+ exports.getDbInstance = getDbInstance;
8
+ exports.closeDatabase = closeDatabase;
9
+ const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
10
+ const path_1 = __importDefault(require("path"));
11
+ const fs_1 = __importDefault(require("fs"));
12
+ /**
13
+ * Default path to the claude-mem database
14
+ * Located in user's home directory: ~/.claude-mem/claude-mem.db
15
+ */
16
+ const DB_PATH = path_1.default.join(process.env.HOME || '', '.claude-mem', 'claude-mem.db');
17
+ /**
18
+ * Creates and configures a new SQLite database connection
19
+ *
20
+ * Opens the claude-mem database in read-only mode for safety.
21
+ * This prevents accidental modifications to the user's session history.
22
+ *
23
+ * @returns {Database.Database} Configured SQLite database instance
24
+ * @throws {Error} If database file doesn't exist at DB_PATH
25
+ *
26
+ * @example
27
+ * const db = getDatabase();
28
+ * const result = db.prepare('SELECT COUNT(*) as count FROM sdk_sessions').get();
29
+ * console.log(`Found ${result.count} sessions`);
30
+ */
31
+ function getDatabase() {
32
+ if (!fs_1.default.existsSync(DB_PATH)) {
33
+ throw new Error(`Database not found at ${DB_PATH}. Make sure claude-mem is installed and has recorded sessions.`);
34
+ }
35
+ const db = new better_sqlite3_1.default(DB_PATH, {
36
+ readonly: true, // Prevent accidental writes
37
+ fileMustExist: true // Fail if file doesn't exist
38
+ });
39
+ // Enable better error messages for foreign key violations
40
+ db.pragma('foreign_keys = ON');
41
+ return db;
42
+ }
43
+ /**
44
+ * Global database instance (singleton)
45
+ * Reused across all requests to avoid connection overhead
46
+ */
47
+ let dbInstance = null;
48
+ /**
49
+ * Get the singleton database instance
50
+ *
51
+ * Creates a new connection on first call, then reuses it for subsequent calls.
52
+ * This is safe because SQLite handles concurrent reads well in read-only mode.
53
+ *
54
+ * @returns {Database.Database} Singleton database instance
55
+ *
56
+ * @example
57
+ * import { getDbInstance } from './connection';
58
+ *
59
+ * const db = getDbInstance();
60
+ * const sessions = db.prepare('SELECT * FROM sdk_sessions LIMIT 10').all();
61
+ */
62
+ function getDbInstance() {
63
+ if (!dbInstance) {
64
+ dbInstance = getDatabase();
65
+ }
66
+ return dbInstance;
67
+ }
68
+ /**
69
+ * Close the database connection and clear the singleton
70
+ *
71
+ * Should be called during graceful shutdown (SIGTERM, SIGINT).
72
+ * Ensures the database file is properly closed.
73
+ *
74
+ * @example
75
+ * process.on('SIGTERM', () => {
76
+ * server.close(() => {
77
+ * closeDatabase();
78
+ * process.exit(0);
79
+ * });
80
+ * });
81
+ */
82
+ function closeDatabase() {
83
+ if (dbInstance) {
84
+ dbInstance.close();
85
+ dbInstance = null;
86
+ }
87
+ }
88
+ //# sourceMappingURL=connection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/db/connection.ts"],"names":[],"mappings":";;;;;AAwBA,kCAcC;AAsBD,sCAKC;AAgBD,sCAKC;AAtFD,oEAAsC;AACtC,gDAAwB;AACxB,4CAAoB;AAEpB;;;GAGG;AACH,MAAM,OAAO,GAAG,cAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,EAAE,aAAa,EAAE,eAAe,CAAC,CAAC;AAElF;;;;;;;;;;;;;GAaG;AACH,SAAgB,WAAW;IACzB,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,yBAAyB,OAAO,gEAAgE,CAAC,CAAC;IACpH,CAAC;IAED,MAAM,EAAE,GAAG,IAAI,wBAAQ,CAAC,OAAO,EAAE;QAC/B,QAAQ,EAAE,IAAI,EAAO,4BAA4B;QACjD,aAAa,EAAE,IAAI,CAAE,6BAA6B;KACnD,CAAC,CAAC;IAEH,0DAA0D;IAC1D,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAE/B,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;GAGG;AACH,IAAI,UAAU,GAA6B,IAAI,CAAC;AAEhD;;;;;;;;;;;;;GAaG;AACH,SAAgB,aAAa;IAC3B,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,UAAU,GAAG,WAAW,EAAE,CAAC;IAC7B,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAgB,aAAa;IAC3B,IAAI,UAAU,EAAE,CAAC;QACf,UAAU,CAAC,KAAK,EAAE,CAAC;QACnB,UAAU,GAAG,IAAI,CAAC;IACpB,CAAC;AACH,CAAC"}
@@ -0,0 +1,172 @@
1
+ import type { Session, SessionEvent, SessionListQuery, SessionEventsQuery } from './schema';
2
+ /**
3
+ * Get all sessions with optional filtering and pagination
4
+ *
5
+ * Fetches sessions from the claude-mem database with support for:
6
+ * - Pagination (offset/limit)
7
+ * - Project filtering
8
+ * - Date range filtering
9
+ *
10
+ * Results are ordered by most recent first (started_at_epoch DESC).
11
+ *
12
+ * @param {SessionListQuery} query - Query parameters
13
+ * @param {number} [query.offset=0] - Number of sessions to skip
14
+ * @param {number} [query.limit=20] - Maximum number of sessions to return
15
+ * @param {string} [query.project] - Filter by project name (exact match)
16
+ * @param {string} [query.dateStart] - Filter sessions started after this date (ISO 8601)
17
+ * @param {string} [query.dateEnd] - Filter sessions started before this date (ISO 8601)
18
+ * @returns {{ sessions: Session[]; total: number }} Paginated sessions and total count
19
+ *
20
+ * @example
21
+ * // Get first 10 sessions
22
+ * const result = getSessions({ limit: 10, offset: 0 });
23
+ * console.log(`Found ${result.total} total sessions`);
24
+ * console.log(`Showing ${result.sessions.length} sessions`);
25
+ *
26
+ * @example
27
+ * // Filter by project and date
28
+ * const result = getSessions({
29
+ * project: 'my-project',
30
+ * dateStart: '2026-02-01T00:00:00.000Z',
31
+ * limit: 20
32
+ * });
33
+ */
34
+ export declare function getSessions(query: SessionListQuery): {
35
+ sessions: Session[];
36
+ total: number;
37
+ };
38
+ /**
39
+ * Get a single session by its UUID
40
+ *
41
+ * Fetches session metadata from the sdk_sessions table.
42
+ * Returns null if the session doesn't exist.
43
+ *
44
+ * @param {string} sessionId - Claude session UUID (claude_session_id)
45
+ * @returns {Session | null} Session object or null if not found
46
+ *
47
+ * @example
48
+ * const session = getSessionById('550e8400-e29b-41d4-a716-446655440000');
49
+ * if (session) {
50
+ * console.log(`Project: ${session.project}`);
51
+ * console.log(`Prompts: ${session.prompt_counter}`);
52
+ * }
53
+ */
54
+ export declare function getSessionById(sessionId: string): Session | null;
55
+ /**
56
+ * Get statistics for a session
57
+ *
58
+ * Calculates the total number of events, prompts, and observations
59
+ * for a given session. Useful for displaying session metadata.
60
+ *
61
+ * @param {string} sessionId - Claude session UUID
62
+ * @returns {{ eventCount: number; promptCount: number; observationCount: number } | null}
63
+ * Statistics object or null if session not found
64
+ *
65
+ * @example
66
+ * const stats = getSessionStats('550e8400-e29b-41d4-a716-446655440000');
67
+ * if (stats) {
68
+ * console.log(`Total events: ${stats.eventCount}`);
69
+ * console.log(`Prompts: ${stats.promptCount}`);
70
+ * console.log(`Observations: ${stats.observationCount}`);
71
+ * }
72
+ */
73
+ export declare function getSessionStats(sessionId: string): {
74
+ eventCount: number;
75
+ promptCount: number;
76
+ observationCount: number;
77
+ } | null;
78
+ /**
79
+ * Get session timeline events with TIME-FIRST ordering
80
+ *
81
+ * This is the core timeline reconstruction algorithm, validated in Phase 0.
82
+ * Events are ordered chronologically with prompts appearing before observations.
83
+ *
84
+ * **Ordering Algorithm:**
85
+ * 1. PRIMARY: Timestamp (ts ASC) - Chronological order
86
+ * 2. SECONDARY: Prompt number (COALESCE(prompt_number, 999999) ASC) - Group by prompt
87
+ * 3. TERTIARY: Kind rank (kind_rank ASC) - Prompts before observations
88
+ * 4. FINAL: Row ID (row_id ASC) - Stable tiebreaker
89
+ *
90
+ * **JSON Field Parsing:**
91
+ * The following fields are automatically parsed from JSON strings:
92
+ * - facts
93
+ * - concepts
94
+ * - files_read
95
+ * - files_modified
96
+ *
97
+ * **Validation:**
98
+ * This query has been validated on sessions with up to 902 events and passes
99
+ * all ordering checks (monotonic timestamps, prompt-before-observation, etc.)
100
+ *
101
+ * @param {string} sessionId - Claude session UUID
102
+ * @param {SessionEventsQuery} query - Filter and pagination options
103
+ * @param {number} [query.offset=0] - Number of events to skip
104
+ * @param {number} [query.limit=100] - Maximum number of events to return
105
+ * @param {string} [query.types] - Comma-separated observation types (e.g., "feature,bugfix")
106
+ * @param {number} [query.afterTs] - Only return events after this timestamp (epoch ms)
107
+ * @returns {{ events: SessionEvent[]; total: number }} Ordered events and total count
108
+ *
109
+ * @example
110
+ * // Get first 100 events
111
+ * const result = getSessionEvents(sessionId, { limit: 100, offset: 0 });
112
+ * console.log(`Total events: ${result.total}`);
113
+ * console.log(`Fetched: ${result.events.length}`);
114
+ *
115
+ * @example
116
+ * // Get only feature observations
117
+ * const result = getSessionEvents(sessionId, {
118
+ * types: 'feature',
119
+ * limit: 50
120
+ * });
121
+ *
122
+ * @example
123
+ * // Infinite scroll pagination
124
+ * const page1 = getSessionEvents(sessionId, { limit: 100, offset: 0 });
125
+ * const page2 = getSessionEvents(sessionId, { limit: 100, offset: 100 });
126
+ */
127
+ export declare function getSessionEvents(sessionId: string, query: SessionEventsQuery): {
128
+ events: SessionEvent[];
129
+ total: number;
130
+ };
131
+ /**
132
+ * Get a single event by its type and ID
133
+ *
134
+ * Fetches either a prompt or observation by its database row ID.
135
+ * For observations, JSON fields are automatically parsed.
136
+ *
137
+ * @param {('prompt' | 'observation')} eventType - Type of event to fetch
138
+ * @param {number} eventId - Database row ID of the event
139
+ * @returns {SessionEvent | null} Event object or null if not found
140
+ *
141
+ * @example
142
+ * // Get a prompt
143
+ * const prompt = getEventById('prompt', 123);
144
+ * if (prompt) {
145
+ * console.log(`Prompt: ${prompt.text}`);
146
+ * }
147
+ *
148
+ * @example
149
+ * // Get an observation
150
+ * const obs = getEventById('observation', 456);
151
+ * if (obs) {
152
+ * console.log(`Type: ${obs.obs_type}`);
153
+ * console.log(`Title: ${obs.title}`);
154
+ * console.log(`Files modified: ${obs.files_modified?.join(', ')}`);
155
+ * }
156
+ */
157
+ export declare function getEventById(eventType: 'prompt' | 'observation', eventId: number): SessionEvent | null;
158
+ /**
159
+ * Get a list of all unique project names
160
+ *
161
+ * Returns all distinct project names from the sessions table,
162
+ * sorted alphabetically. Useful for project filter dropdowns.
163
+ *
164
+ * @returns {string[]} Array of project names
165
+ *
166
+ * @example
167
+ * const projects = getProjects();
168
+ * console.log(`Found ${projects.length} projects:`);
169
+ * projects.forEach(p => console.log(` - ${p}`));
170
+ */
171
+ export declare function getProjects(): string[];
172
+ //# sourceMappingURL=queries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../src/db/queries.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,OAAO,EACP,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EACnB,MAAM,UAAU,CAAC;AAalB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG;IAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAuD3F;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAUhE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;CAC1B,GAAG,IAAI,CA8BP;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,kBAAkB,GACxB;IAAE,MAAM,EAAE,YAAY,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAmI3C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,QAAQ,GAAG,aAAa,EAAE,OAAO,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAoDtG;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,IAAI,MAAM,EAAE,CAUtC"}