@qiaolei81/copilot-session-viewer 0.3.1 → 0.3.3
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/AGENTS.md +109 -0
- package/CHANGELOG.md +33 -0
- package/CONTRIBUTING.md +104 -0
- package/RELEASE.md +146 -0
- package/docs/API.md +471 -0
- package/docs/DEVELOPMENT.md +556 -0
- package/docs/INSTALLATION.md +329 -0
- package/docs/README.md +102 -0
- package/docs/TROUBLESHOOTING.md +630 -0
- package/docs/images/homepage.png +0 -0
- package/docs/images/session-detail.png +0 -0
- package/docs/images/time-analysis.png +0 -0
- package/docs/unified-event-format-design.md +844 -0
- package/docs/unified-event-format-implementation.md +350 -0
- package/eslint.config.mjs +133 -0
- package/package.json +10 -4
- package/public/js/homepage.min.js +35 -0
- package/public/js/session-detail.min.js +461 -0
- package/public/js/telemetry-browser.min.js +1 -0
- package/public/js/time-analyze.min.js +518 -0
- package/scripts/release.sh +43 -0
- package/server.js +3 -0
- package/src/app.js +2 -1
- package/src/controllers/insightController.js +31 -0
- package/src/controllers/sessionController.js +56 -0
- package/src/controllers/tagController.js +8 -0
- package/src/controllers/uploadController.js +32 -1
- package/src/middleware/common.js +20 -1
- package/src/models/Session.js +12 -2
- package/src/services/sessionRepository.js +98 -108
- package/src/telemetry.js +152 -0
- package/src/utils/fileUtils.js +2 -1
- package/views/index.ejs +9 -494
- package/views/session-vue.ejs +166 -1869
- package/views/telemetry-snippet.ejs +26 -0
- package/views/time-analyze.ejs +2 -2217
- package/.env.example +0 -14
package/docs/API.md
ADDED
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
# 🔌 API Documentation
|
|
2
|
+
|
|
3
|
+
REST API endpoints for Copilot Session Viewer.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Base URL
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
http://localhost:3838
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Authentication
|
|
16
|
+
|
|
17
|
+
**None required** - This is a local development tool with no authentication.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Endpoints
|
|
22
|
+
|
|
23
|
+
### Sessions
|
|
24
|
+
|
|
25
|
+
#### List Sessions
|
|
26
|
+
|
|
27
|
+
Get all sessions with optional pagination.
|
|
28
|
+
|
|
29
|
+
```http
|
|
30
|
+
GET /api/sessions
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Query Parameters:**
|
|
34
|
+
- `page` (number, optional) - Page number for pagination
|
|
35
|
+
- `limit` (number, optional) - Items per page
|
|
36
|
+
|
|
37
|
+
**Response:**
|
|
38
|
+
```json
|
|
39
|
+
[
|
|
40
|
+
{
|
|
41
|
+
"id": "f9db650c-1f87-491f-8e4f-52d45538d677",
|
|
42
|
+
"summary": "Analyze this codebase structure",
|
|
43
|
+
"createdAt": "2026-02-15T02:30:00.000Z",
|
|
44
|
+
"duration": 17936000,
|
|
45
|
+
"eventCount": 1044,
|
|
46
|
+
"type": "directory",
|
|
47
|
+
"workspace": {
|
|
48
|
+
"cwd": "/Users/dev/my-project"
|
|
49
|
+
},
|
|
50
|
+
"selectedModel": "claude-sonnet-4.5",
|
|
51
|
+
"copilotVersion": "0.0.410",
|
|
52
|
+
"isImported": false,
|
|
53
|
+
"hasInsight": true
|
|
54
|
+
}
|
|
55
|
+
]
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Example:**
|
|
59
|
+
```bash
|
|
60
|
+
curl http://localhost:3838/api/sessions
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
#### Load More Sessions
|
|
66
|
+
|
|
67
|
+
Get additional sessions with offset-based pagination (for infinite scroll).
|
|
68
|
+
|
|
69
|
+
```http
|
|
70
|
+
GET /api/sessions/load-more
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Query Parameters:**
|
|
74
|
+
- `offset` (number, required) - Number of sessions to skip
|
|
75
|
+
- `limit` (number, optional, default: 20) - Number of sessions to return
|
|
76
|
+
|
|
77
|
+
**Response:**
|
|
78
|
+
```json
|
|
79
|
+
{
|
|
80
|
+
"sessions": [
|
|
81
|
+
{
|
|
82
|
+
"id": "session-id",
|
|
83
|
+
"summary": "Session summary",
|
|
84
|
+
// ... same structure as /api/sessions
|
|
85
|
+
}
|
|
86
|
+
],
|
|
87
|
+
"hasMore": true,
|
|
88
|
+
"totalSessions": 237
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**Example:**
|
|
93
|
+
```bash
|
|
94
|
+
curl "http://localhost:3838/api/sessions/load-more?offset=20&limit=20"
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
#### Get Session Events
|
|
100
|
+
|
|
101
|
+
Retrieve all events for a specific session.
|
|
102
|
+
|
|
103
|
+
```http
|
|
104
|
+
GET /api/sessions/:sessionId/events
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**Path Parameters:**
|
|
108
|
+
- `sessionId` (string, required) - UUID of the session
|
|
109
|
+
|
|
110
|
+
**Response:** JSONL stream (one JSON object per line)
|
|
111
|
+
```
|
|
112
|
+
{"type":"session.start","timestamp":"2026-02-15T02:30:00.000Z","sessionId":"f9db650c..."}
|
|
113
|
+
{"type":"user.message","timestamp":"2026-02-15T02:30:01.000Z","message":"Analyze this code","turnId":0}
|
|
114
|
+
{"type":"assistant.message","timestamp":"2026-02-15T02:30:05.000Z","message":"I'll help you analyze...","turnId":0}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Example:**
|
|
118
|
+
```bash
|
|
119
|
+
curl http://localhost:3838/api/sessions/f9db650c-1f87-491f-8e4f-52d45538d677/events
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
### Session Management
|
|
125
|
+
|
|
126
|
+
#### Get Session Details
|
|
127
|
+
|
|
128
|
+
Get detailed information about a specific session.
|
|
129
|
+
|
|
130
|
+
```http
|
|
131
|
+
GET /session/:sessionId
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Response:** HTML page with session viewer interface
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
#### Export Session
|
|
139
|
+
|
|
140
|
+
Download a session as a ZIP archive.
|
|
141
|
+
|
|
142
|
+
```http
|
|
143
|
+
GET /session/:sessionId/download
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**Response:**
|
|
147
|
+
- **Content-Type:** `application/zip`
|
|
148
|
+
- **Content-Disposition:** `attachment; filename="session-{sessionId}.zip"`
|
|
149
|
+
|
|
150
|
+
**ZIP Contents:**
|
|
151
|
+
- `events.jsonl` - Event stream data
|
|
152
|
+
- `workspace.yaml` - Session metadata
|
|
153
|
+
- `copilot-insight.md` - AI analysis (if available)
|
|
154
|
+
|
|
155
|
+
**Example:**
|
|
156
|
+
```bash
|
|
157
|
+
curl -O http://localhost:3838/session/f9db650c-1f87-491f-8e4f-52d45538d677/download
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
#### Import Session
|
|
163
|
+
|
|
164
|
+
Upload and import a session ZIP file.
|
|
165
|
+
|
|
166
|
+
```http
|
|
167
|
+
POST /session/import
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
**Content-Type:** `multipart/form-data`
|
|
171
|
+
|
|
172
|
+
**Form Fields:**
|
|
173
|
+
- `sessionZip` (file, required) - ZIP file containing session data
|
|
174
|
+
|
|
175
|
+
**Response:**
|
|
176
|
+
```json
|
|
177
|
+
{
|
|
178
|
+
"success": true,
|
|
179
|
+
"sessionId": "imported-session-uuid",
|
|
180
|
+
"message": "Session imported successfully"
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Error Response:**
|
|
185
|
+
```json
|
|
186
|
+
{
|
|
187
|
+
"success": false,
|
|
188
|
+
"error": "Invalid ZIP file format"
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
**Example:**
|
|
193
|
+
```bash
|
|
194
|
+
curl -X POST \
|
|
195
|
+
-F "sessionZip=@session-export.zip" \
|
|
196
|
+
http://localhost:3838/session/import
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
### AI Insights
|
|
202
|
+
|
|
203
|
+
#### Generate Insight
|
|
204
|
+
|
|
205
|
+
Generate an AI-powered analysis of a session.
|
|
206
|
+
|
|
207
|
+
```http
|
|
208
|
+
POST /session/:sessionId/insight
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**Request Body:**
|
|
212
|
+
```json
|
|
213
|
+
{}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
**Response:** Server-Sent Events (SSE) stream
|
|
217
|
+
|
|
218
|
+
**SSE Event Types:**
|
|
219
|
+
```
|
|
220
|
+
data: {"type":"start","message":"Starting analysis..."}
|
|
221
|
+
data: {"type":"progress","message":"Analyzing events...","percent":25}
|
|
222
|
+
data: {"type":"content","content":"## Session Analysis\n\nThis session shows..."}
|
|
223
|
+
data: {"type":"complete","message":"Analysis complete"}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**Example:**
|
|
227
|
+
```bash
|
|
228
|
+
curl -X POST \
|
|
229
|
+
-H "Accept: text/event-stream" \
|
|
230
|
+
http://localhost:3838/session/f9db650c-1f87-491f-8e4f-52d45538d677/insight
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
#### Get Insight Status
|
|
236
|
+
|
|
237
|
+
Check if an insight exists for a session.
|
|
238
|
+
|
|
239
|
+
```http
|
|
240
|
+
GET /session/:sessionId/insight
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
**Response:**
|
|
244
|
+
```json
|
|
245
|
+
{
|
|
246
|
+
"exists": true,
|
|
247
|
+
"path": "/path/to/copilot-insight.md",
|
|
248
|
+
"size": 15420,
|
|
249
|
+
"lastModified": "2026-02-15T02:35:00.000Z"
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
#### Delete Insight
|
|
256
|
+
|
|
257
|
+
Remove the generated insight for a session.
|
|
258
|
+
|
|
259
|
+
```http
|
|
260
|
+
DELETE /session/:sessionId/insight
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
**Response:**
|
|
264
|
+
```json
|
|
265
|
+
{
|
|
266
|
+
"success": true,
|
|
267
|
+
"message": "Insight deleted successfully"
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## Data Types
|
|
274
|
+
|
|
275
|
+
### Session Object
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
interface Session {
|
|
279
|
+
id: string; // UUID
|
|
280
|
+
summary: string; // Human-readable description
|
|
281
|
+
createdAt: string; // ISO timestamp
|
|
282
|
+
duration?: number; // Duration in milliseconds
|
|
283
|
+
eventCount: number; // Number of events in session
|
|
284
|
+
type: "directory" | "file"; // Session format type
|
|
285
|
+
workspace?: {
|
|
286
|
+
cwd: string; // Working directory
|
|
287
|
+
};
|
|
288
|
+
selectedModel?: string; // AI model used
|
|
289
|
+
copilotVersion?: string; // Copilot CLI version
|
|
290
|
+
isImported: boolean; // Whether session was imported
|
|
291
|
+
hasInsight: boolean; // Whether AI insight exists
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### Event Object
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
interface Event {
|
|
299
|
+
type: string; // Event type (e.g., "user.message")
|
|
300
|
+
timestamp: string; // ISO timestamp
|
|
301
|
+
[key: string]: any; // Additional event-specific fields
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Common Event Types
|
|
306
|
+
|
|
307
|
+
| Category | Event Types | Description |
|
|
308
|
+
|----------|-------------|-------------|
|
|
309
|
+
| **Session** | `session.start`, `session.model_change` | Session lifecycle |
|
|
310
|
+
| **User** | `user.message`, `user.confirmation` | User interactions |
|
|
311
|
+
| **Assistant** | `assistant.message`, `assistant.turn_start`, `assistant.turn_end` | AI responses |
|
|
312
|
+
| **Tool** | `tool.execution_start`, `tool.execution_complete` | Tool invocations |
|
|
313
|
+
| **Sub-Agent** | `subagent.started`, `subagent.completed` | Sub-agent lifecycle |
|
|
314
|
+
| **System** | `client.log`, `error` | System diagnostics |
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## Error Responses
|
|
319
|
+
|
|
320
|
+
### Standard Error Format
|
|
321
|
+
|
|
322
|
+
```json
|
|
323
|
+
{
|
|
324
|
+
"error": "Error message",
|
|
325
|
+
"code": "ERROR_CODE",
|
|
326
|
+
"details": "Additional details"
|
|
327
|
+
}
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### HTTP Status Codes
|
|
331
|
+
|
|
332
|
+
| Code | Description | Common Causes |
|
|
333
|
+
|------|-------------|---------------|
|
|
334
|
+
| `200` | OK | Request successful |
|
|
335
|
+
| `400` | Bad Request | Invalid session ID, malformed request |
|
|
336
|
+
| `404` | Not Found | Session not found, endpoint not found |
|
|
337
|
+
| `500` | Internal Server Error | File system errors, processing errors |
|
|
338
|
+
|
|
339
|
+
### Example Error Responses
|
|
340
|
+
|
|
341
|
+
**Invalid Session ID:**
|
|
342
|
+
```json
|
|
343
|
+
{
|
|
344
|
+
"error": "Invalid session ID format",
|
|
345
|
+
"code": "INVALID_SESSION_ID"
|
|
346
|
+
}
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
**Session Not Found:**
|
|
350
|
+
```json
|
|
351
|
+
{
|
|
352
|
+
"error": "Session not found",
|
|
353
|
+
"code": "SESSION_NOT_FOUND"
|
|
354
|
+
}
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
**File System Error:**
|
|
358
|
+
```json
|
|
359
|
+
{
|
|
360
|
+
"error": "Unable to read session directory",
|
|
361
|
+
"code": "FILE_SYSTEM_ERROR",
|
|
362
|
+
"details": "ENOENT: no such file or directory"
|
|
363
|
+
}
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
## Rate Limiting
|
|
369
|
+
|
|
370
|
+
### Current Limits
|
|
371
|
+
|
|
372
|
+
- **General requests**: 100 requests per minute
|
|
373
|
+
- **Insight generation**: 5 requests per minute
|
|
374
|
+
- **File uploads**: 10 requests per minute
|
|
375
|
+
|
|
376
|
+
### Rate Limit Headers
|
|
377
|
+
|
|
378
|
+
```http
|
|
379
|
+
X-RateLimit-Limit: 100
|
|
380
|
+
X-RateLimit-Remaining: 95
|
|
381
|
+
X-RateLimit-Reset: 1640995200
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
---
|
|
385
|
+
|
|
386
|
+
## WebSocket Support
|
|
387
|
+
|
|
388
|
+
**Not currently implemented** - All communication is via REST API and SSE.
|
|
389
|
+
|
|
390
|
+
Future versions may include WebSocket support for:
|
|
391
|
+
- Real-time session updates
|
|
392
|
+
- Live event streaming
|
|
393
|
+
- Multi-user collaboration
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
397
|
+
## SDK / Client Libraries
|
|
398
|
+
|
|
399
|
+
### JavaScript/Node.js
|
|
400
|
+
|
|
401
|
+
```javascript
|
|
402
|
+
// Basic API client example
|
|
403
|
+
class CopilotSessionViewer {
|
|
404
|
+
constructor(baseURL = 'http://localhost:3838') {
|
|
405
|
+
this.baseURL = baseURL;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
async getSessions() {
|
|
409
|
+
const response = await fetch(`${this.baseURL}/api/sessions`);
|
|
410
|
+
return response.json();
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
async getSessionEvents(sessionId) {
|
|
414
|
+
const response = await fetch(`${this.baseURL}/api/sessions/${sessionId}/events`);
|
|
415
|
+
const text = await response.text();
|
|
416
|
+
return text.split('\n').filter(Boolean).map(line => JSON.parse(line));
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
async exportSession(sessionId) {
|
|
420
|
+
const response = await fetch(`${this.baseURL}/session/${sessionId}/download`);
|
|
421
|
+
return response.blob();
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// Usage
|
|
426
|
+
const viewer = new CopilotSessionViewer();
|
|
427
|
+
const sessions = await viewer.getSessions();
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
### Python
|
|
431
|
+
|
|
432
|
+
```python
|
|
433
|
+
import requests
|
|
434
|
+
import json
|
|
435
|
+
|
|
436
|
+
class CopilotSessionViewer:
|
|
437
|
+
def __init__(self, base_url="http://localhost:3838"):
|
|
438
|
+
self.base_url = base_url
|
|
439
|
+
|
|
440
|
+
def get_sessions(self):
|
|
441
|
+
response = requests.get(f"{self.base_url}/api/sessions")
|
|
442
|
+
return response.json()
|
|
443
|
+
|
|
444
|
+
def get_session_events(self, session_id):
|
|
445
|
+
response = requests.get(f"{self.base_url}/api/sessions/{session_id}/events")
|
|
446
|
+
return [json.loads(line) for line in response.text.strip().split('\n')]
|
|
447
|
+
|
|
448
|
+
def export_session(self, session_id, filename):
|
|
449
|
+
response = requests.get(f"{self.base_url}/session/{session_id}/download")
|
|
450
|
+
with open(filename, 'wb') as f:
|
|
451
|
+
f.write(response.content)
|
|
452
|
+
|
|
453
|
+
# Usage
|
|
454
|
+
viewer = CopilotSessionViewer()
|
|
455
|
+
sessions = viewer.get_sessions()
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
---
|
|
459
|
+
|
|
460
|
+
## OpenAPI Specification
|
|
461
|
+
|
|
462
|
+
A complete OpenAPI 3.0 specification is available at:
|
|
463
|
+
```
|
|
464
|
+
http://localhost:3838/api/openapi.json
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
You can use this with tools like Swagger UI, Postman, or code generators.
|
|
468
|
+
|
|
469
|
+
---
|
|
470
|
+
|
|
471
|
+
**Need help?** Check the [Troubleshooting Guide](TROUBLESHOOTING.md) or [open an issue](https://github.com/qiaolei81/copilot-session-viewer/issues).
|