copilot-tracer 1.0.4 → 1.0.5
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 +114 -158
- package/dist/cli.js +95 -76
- package/dist/db.js +166 -3
- package/dist/otlpReceiver.js +31 -12
- package/dist/setup.js +35 -12
- package/dist/webServer.js +39 -8
- package/package.json +1 -1
- package/web/index.html +296 -73
package/README.md
CHANGED
|
@@ -1,246 +1,196 @@
|
|
|
1
1
|
# copilot-tracer
|
|
2
2
|
|
|
3
|
-
Real-time tracing and prompt-refinement
|
|
3
|
+
Real-time tracing and prompt-refinement companion for **GitHub Copilot CLI** and **VS Code Copilot extension**.
|
|
4
4
|
|
|
5
|
-
Captures every prompt, response, token usage, AI credits, tool calls,
|
|
5
|
+
Captures every prompt, response, token usage, AI credits, tool calls, and duration — all in one place. Runs as a background daemon that collects data from all your projects automatically. Includes a web dashboard with project overview and per-project live tracing.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
11
|
-
- **
|
|
12
|
-
- **
|
|
13
|
-
- **
|
|
14
|
-
- **
|
|
15
|
-
- **
|
|
16
|
-
- **
|
|
11
|
+
- **Daemon mode** — install once, run forever. Collects traces from all projects automatically
|
|
12
|
+
- **Auto project detection** — detects project from `github.copilot.git.repository` in OTLP spans
|
|
13
|
+
- **Zero-intrusion capture** — uses Copilot's built-in OTel support. Set env vars, done.
|
|
14
|
+
- **Works everywhere** — captures both Copilot CLI and VS Code Copilot Chat
|
|
15
|
+
- **Dashboard** — overview of all projects with token usage, credits, and session counts
|
|
16
|
+
- **Live tracer** — real-time trace table per project with detail panel
|
|
17
|
+
- **Prompt refinement** — rewrites prompts with stronger instructions and less noise
|
|
17
18
|
- **AI Credits tracking** — matches exactly what Copilot terminal reports (e.g. `2.59 cr`)
|
|
18
|
-
- **Tool call visibility** — see every tool/skill/MCP invoked during a session
|
|
19
|
-
- **ACP proxy mode** — wrap the Copilot CLI to trace live JSON-RPC traffic when needed
|
|
20
19
|
- **Persistent storage** — SQLite at `~/.copilot-tracer/traces.db`, survives restarts
|
|
21
|
-
- **Console + Web UI** — CLI table view or browser dashboard, your choice
|
|
22
20
|
|
|
23
21
|
---
|
|
24
22
|
|
|
25
|
-
##
|
|
26
|
-
|
|
27
|
-
- Node.js v18+ (tested on v24)
|
|
28
|
-
- GitHub Copilot CLI (`copilot` command available in terminal)
|
|
29
|
-
- VS Code 1.99+ with built-in Copilot (no extension install needed)
|
|
30
|
-
|
|
31
|
-
---
|
|
32
|
-
|
|
33
|
-
## Install
|
|
23
|
+
## Quick Start (one-time setup)
|
|
34
24
|
|
|
35
25
|
```bash
|
|
36
26
|
npm install -g copilot-tracer
|
|
27
|
+
copilot-tracer --setup --daemon
|
|
37
28
|
```
|
|
38
29
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
> cd copilot-tracer && npm install && npx tsc
|
|
45
|
-
> npm link # registers global command from local build
|
|
46
|
-
> ```
|
|
30
|
+
This will:
|
|
31
|
+
1. Detect your Copilot CLI and VS Code installation
|
|
32
|
+
2. Patch `~/.zshrc` with OTEL env vars
|
|
33
|
+
3. Patch VS Code `settings.json` with terminal env vars
|
|
34
|
+
4. Start the daemon on port 4747
|
|
47
35
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
## Setup (one-time)
|
|
51
|
-
|
|
52
|
-
Run the auto-setup command. It detects your Copilot CLI and VS Code installation and injects the required config automatically:
|
|
36
|
+
Then apply env vars in your current shell:
|
|
53
37
|
|
|
54
38
|
```bash
|
|
55
|
-
|
|
39
|
+
source ~/.zshrc
|
|
56
40
|
```
|
|
57
41
|
|
|
58
|
-
|
|
59
|
-
- Detects `copilot` CLI path and version
|
|
60
|
-
- Detects VS Code version and confirms built-in Copilot
|
|
61
|
-
- Patches `~/.zshrc` (or `~/.bashrc`) with OTEL env vars
|
|
62
|
-
- Patches VS Code `settings.json` with `terminal.integrated.env.osx` block
|
|
42
|
+
Restart VS Code once. After that, the daemon collects traces from all your Copilot sessions automatically.
|
|
63
43
|
|
|
64
|
-
|
|
65
|
-
```
|
|
66
|
-
✅ GitHub Copilot CLI detected — /usr/bin/copilot v1.0.77
|
|
67
|
-
✅ Visual Studio Code detected — 1.131.0 (Built-in Copilot)
|
|
68
|
-
✅ Shell profile patched: .zshrc
|
|
69
|
-
✅ VS Code settings patched
|
|
70
|
-
```
|
|
44
|
+
Open **http://localhost:4747** to see the dashboard.
|
|
71
45
|
|
|
72
|
-
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## How It Works
|
|
73
49
|
|
|
74
|
-
```bash
|
|
75
|
-
source ~/.zshrc
|
|
76
50
|
```
|
|
51
|
+
┌─────────────────────────────────────────────────────────┐
|
|
52
|
+
│ copilot-tracer --daemon (runs once, stays running) │
|
|
53
|
+
│ │
|
|
54
|
+
│ OTLP Receiver ← Copilot CLI + VS Code │
|
|
55
|
+
│ (auto-detects project from github.copilot.git.repository)│
|
|
56
|
+
│ │
|
|
57
|
+
│ SQLite DB → Dashboard + Live Tracer (Socket.io) │
|
|
58
|
+
└─────────────────────────────────────────────────────────┘
|
|
77
59
|
|
|
78
|
-
|
|
60
|
+
Copilot CLI / VS Code Copilot Chat
|
|
61
|
+
│
|
|
62
|
+
│ OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4747
|
|
63
|
+
↓
|
|
64
|
+
POST /v1/traces (OpenTelemetry OTLP JSON)
|
|
65
|
+
│
|
|
66
|
+
↓
|
|
67
|
+
copilot-tracer parses spans → tokens, credits, tool calls
|
|
68
|
+
│
|
|
69
|
+
↓
|
|
70
|
+
SQLite DB (~/.copilot-tracer/traces.db)
|
|
71
|
+
│
|
|
72
|
+
├→ Dashboard: all projects overview
|
|
73
|
+
└→ Live Tracer: real-time per-project view
|
|
74
|
+
```
|
|
79
75
|
|
|
80
76
|
---
|
|
81
77
|
|
|
82
|
-
##
|
|
78
|
+
## Usage
|
|
83
79
|
|
|
84
|
-
|
|
80
|
+
### Daemon mode (recommended)
|
|
85
81
|
|
|
86
82
|
```bash
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
export COPILOT_OTEL_ENABLED=true
|
|
90
|
-
```
|
|
83
|
+
# First time: setup + start daemon
|
|
84
|
+
copilot-tracer --setup --daemon
|
|
91
85
|
|
|
92
|
-
|
|
86
|
+
# Subsequent starts
|
|
87
|
+
copilot-tracer --daemon
|
|
93
88
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4747",
|
|
97
|
-
"OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT": "true",
|
|
98
|
-
"COPILOT_OTEL_ENABLED": "true"
|
|
99
|
-
}
|
|
89
|
+
# Custom port
|
|
90
|
+
copilot-tracer --daemon --port 8080
|
|
100
91
|
```
|
|
101
92
|
|
|
102
|
-
|
|
93
|
+
### Normal mode (legacy)
|
|
103
94
|
|
|
104
|
-
|
|
95
|
+
Per-session mode with optional ACP proxy for live CLI tracing:
|
|
105
96
|
|
|
106
97
|
```bash
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
Open **http://localhost:4747** — shows "waiting for copilot CLI activity".
|
|
98
|
+
# Web UI only (read from DB)
|
|
99
|
+
copilot-tracer --ui web --no-proxy
|
|
111
100
|
|
|
112
|
-
|
|
101
|
+
# With project path
|
|
102
|
+
copilot-tracer --ui web --no-proxy --project-path /path/to/repo
|
|
113
103
|
|
|
114
|
-
|
|
104
|
+
# With ACP proxy (wraps copilot CLI)
|
|
105
|
+
copilot-tracer --ui web
|
|
106
|
+
```
|
|
115
107
|
|
|
116
|
-
|
|
108
|
+
### Setup only
|
|
117
109
|
|
|
118
110
|
```bash
|
|
119
|
-
#
|
|
120
|
-
copilot
|
|
121
|
-
|
|
122
|
-
# Or use Copilot Chat in VS Code
|
|
111
|
+
# Just patch env vars without starting
|
|
112
|
+
copilot-tracer --setup
|
|
123
113
|
```
|
|
124
114
|
|
|
125
|
-
Traces appear instantly in the web UI as each request completes.
|
|
126
|
-
|
|
127
115
|
---
|
|
128
116
|
|
|
129
|
-
##
|
|
117
|
+
## Dashboard
|
|
130
118
|
|
|
131
|
-
|
|
132
|
-
copilot CLI / VS Code Copilot Chat
|
|
133
|
-
|
|
|
134
|
-
| reads OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4747
|
|
135
|
-
|
|
|
136
|
-
↓ POST /v1/traces (OpenTelemetry OTLP JSON)
|
|
137
|
-
copilot-tracer OTLP receiver
|
|
138
|
-
|
|
|
139
|
-
↓
|
|
140
|
-
Parse spans → extract prompt, response, tokens, credits, tool calls
|
|
141
|
-
|
|
|
142
|
-
↓
|
|
143
|
-
SQLite DB (~/.copilot-tracer/traces.db)
|
|
144
|
-
|
|
|
145
|
-
↓
|
|
146
|
-
Web UI (Socket.io real-time) + Console table
|
|
147
|
-
```
|
|
119
|
+
Open http://localhost:4747 after starting the daemon.
|
|
148
120
|
|
|
149
|
-
|
|
121
|
+
- **Summary cards** — total projects, sessions, tokens, credits
|
|
122
|
+
- **Project cards** — each project shows path, session count, tokens, credits, last active
|
|
123
|
+
- **Click a project** → opens live tracer filtered to that project
|
|
150
124
|
|
|
151
125
|
---
|
|
152
126
|
|
|
153
|
-
##
|
|
127
|
+
## Live Tracer
|
|
154
128
|
|
|
155
|
-
|
|
129
|
+
Real-time trace table for a specific project.
|
|
156
130
|
|
|
157
131
|
**Table columns:**
|
|
158
132
|
| Date/Time | Prompt | AI Credits | Duration | Cached | Written | Reasoning | Skills | Agents | MCPs |
|
|
159
133
|
|
|
160
134
|
**Interactive features:**
|
|
161
|
-
- Click any row → detail panel: full prompt,
|
|
135
|
+
- Click any row → detail panel: full prompt, response, reasoning, call graph
|
|
162
136
|
- Click AI Credits → cost breakdown per token type
|
|
163
|
-
- Click Reasoning
|
|
164
|
-
- Click Skills / Agents / MCPs
|
|
165
|
-
- Real-time updates via Socket.io
|
|
166
|
-
- Dark theme
|
|
137
|
+
- Click Reasoning → full reasoning text
|
|
138
|
+
- Click Skills / Agents / MCPs → filtered call list
|
|
139
|
+
- Real-time updates via Socket.io
|
|
167
140
|
|
|
168
141
|
---
|
|
169
142
|
|
|
170
|
-
##
|
|
143
|
+
## Prompt Refinement
|
|
171
144
|
|
|
172
|
-
|
|
173
|
-
copilot-tracer --ui console --no-proxy
|
|
174
|
-
```
|
|
145
|
+
The web UI includes a prompt optimizer. Click "Refine Prompt" in the trace detail panel.
|
|
175
146
|
|
|
176
|
-
|
|
147
|
+
Techniques applied:
|
|
148
|
+
- Role grounding, imperative clarity, output format, chain-of-thought
|
|
149
|
+
- Noise removal, constraint injection, redundancy cleanup
|
|
177
150
|
|
|
178
151
|
---
|
|
179
152
|
|
|
180
|
-
##
|
|
153
|
+
## CLI Flags
|
|
181
154
|
|
|
182
|
-
|
|
155
|
+
| Flag | Description |
|
|
156
|
+
|------|-------------|
|
|
157
|
+
| `--daemon` | Run as background daemon (always-on OTLP receiver) |
|
|
158
|
+
| `--setup` | Auto-detect and configure env vars |
|
|
159
|
+
| `--port <port>` | Web UI port (default: 4747) |
|
|
160
|
+
| `--ui <mode>` | UI mode: console \| web \| both (normal mode only) |
|
|
161
|
+
| `--no-proxy` | Web/console only, no ACP proxy (normal mode only) |
|
|
162
|
+
| `--project-path <path>` | Project source path (normal mode only) |
|
|
163
|
+
| `--session <id>` | Custom session ID (normal mode only) |
|
|
164
|
+
| `--debug` | Verbose logging |
|
|
183
165
|
|
|
184
|
-
|
|
166
|
+
---
|
|
185
167
|
|
|
186
|
-
|
|
187
|
-
- **Imperative clarity** — turns soft phrasing into direct instructions
|
|
188
|
-
- **Output format** — asks for JSON, markdown, bullets, or steps when missing
|
|
189
|
-
- **Reasoning guidance** — adds step-by-step thinking for multi-step tasks
|
|
190
|
-
- **Noise removal** — strips filler like “please”, “could you”, and “I think”
|
|
191
|
-
- **Constraint injection** — adds language, tone, length, and audience constraints
|
|
192
|
-
- **Redundancy cleanup** — removes repeated or conflicting instructions
|
|
168
|
+
## Manual Setup (alternative)
|
|
193
169
|
|
|
194
|
-
|
|
170
|
+
Add to `~/.zshrc`:
|
|
195
171
|
|
|
196
172
|
```bash
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
173
|
+
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4747
|
|
174
|
+
export OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=true
|
|
175
|
+
export COPILOT_OTEL_ENABLED=true
|
|
200
176
|
```
|
|
201
177
|
|
|
202
|
-
|
|
178
|
+
For VS Code, add to `~/Library/Application Support/Code/User/settings.json`:
|
|
203
179
|
|
|
204
180
|
```json
|
|
205
|
-
{
|
|
206
|
-
"
|
|
207
|
-
"
|
|
208
|
-
"
|
|
209
|
-
"techniques": [],
|
|
210
|
-
"origTok": 10,
|
|
211
|
-
"newTok": 22,
|
|
212
|
-
"inputSavingPct": 0
|
|
181
|
+
"terminal.integrated.env.osx": {
|
|
182
|
+
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4747",
|
|
183
|
+
"OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT": "true",
|
|
184
|
+
"COPILOT_OTEL_ENABLED": "true"
|
|
213
185
|
}
|
|
214
186
|
```
|
|
215
187
|
|
|
216
188
|
---
|
|
217
189
|
|
|
218
|
-
## CLI Flags
|
|
219
|
-
|
|
220
|
-
| Flag | Description |
|
|
221
|
-
|------|-------------|
|
|
222
|
-
| `--ui web` | Start web UI (default) |
|
|
223
|
-
| `--ui console` | Start console table UI |
|
|
224
|
-
| `--ui both` | Both web + console |
|
|
225
|
-
| `--port 4747` | Web UI port (default: 4747) |
|
|
226
|
-
| `--no-proxy` | Web/console only, no ACP proxy |
|
|
227
|
-
| `--session <id>` | Custom session ID |
|
|
228
|
-
| `--setup` | Auto-detect and configure env vars |
|
|
229
|
-
| `--debug` | Verbose logging |
|
|
230
|
-
|
|
231
|
-
---
|
|
232
|
-
|
|
233
190
|
## Storage
|
|
234
191
|
|
|
235
192
|
Traces persist to `~/.copilot-tracer/traces.db` (SQLite). Safe to keep across sessions.
|
|
236
193
|
|
|
237
|
-
To test the web UI without running a live Copilot session:
|
|
238
|
-
|
|
239
|
-
```bash
|
|
240
|
-
node test-seed.mjs # seeds 4 sample traces (source build only)
|
|
241
|
-
copilot-tracer --ui web --no-proxy --session test-session-001
|
|
242
|
-
```
|
|
243
|
-
|
|
244
194
|
---
|
|
245
195
|
|
|
246
196
|
## Build & Publish
|
|
@@ -253,18 +203,24 @@ npx tsc # compile to dist/
|
|
|
253
203
|
To publish a new release to npm:
|
|
254
204
|
|
|
255
205
|
```bash
|
|
256
|
-
#
|
|
206
|
+
# Login first
|
|
207
|
+
npm login
|
|
208
|
+
|
|
209
|
+
# Patch version (1.0.4 → 1.0.5)
|
|
257
210
|
bash scripts/publish.sh
|
|
258
211
|
|
|
259
|
-
#
|
|
212
|
+
# Minor version
|
|
260
213
|
bash scripts/publish.sh minor
|
|
261
214
|
|
|
262
|
-
#
|
|
215
|
+
# Major version
|
|
216
|
+
bash scripts/publish.sh major
|
|
217
|
+
|
|
218
|
+
# Beta pre-release
|
|
263
219
|
bash scripts/publish.sh --tag beta --pre beta
|
|
264
220
|
```
|
|
265
221
|
|
|
266
222
|
The script will:
|
|
267
|
-
1. Check npm authentication
|
|
223
|
+
1. Check npm authentication
|
|
268
224
|
2. Verify git working tree is clean
|
|
269
225
|
3. Type-check + build
|
|
270
226
|
4. Verify `better-sqlite3` native module loads
|
package/dist/cli.js
CHANGED
|
@@ -4,7 +4,8 @@ import { spawn } from 'child_process';
|
|
|
4
4
|
import { randomUUID } from 'crypto';
|
|
5
5
|
import readline from 'readline';
|
|
6
6
|
import fs from 'fs';
|
|
7
|
-
import
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import { createSession, getTraces, getSessionSummary, ensureProject } from './db.js';
|
|
8
9
|
import { handleAcpMessage, traceEvents } from './proxy.js';
|
|
9
10
|
import { renderConsoleTable } from './consoleUi.js';
|
|
10
11
|
import { startWebServer } from './webServer.js';
|
|
@@ -20,91 +21,109 @@ program
|
|
|
20
21
|
.option('--session <id>', 'Filter by session ID')
|
|
21
22
|
.option('--debug', 'Dump ALL raw ACP messages to stderr (use to discover real method names)')
|
|
22
23
|
.option('--setup', 'Auto-detect copilot CLI + VS Code and configure OTLP env vars')
|
|
24
|
+
.option('--project-path <path>', 'Project source path (defaults to cwd)')
|
|
25
|
+
.option('--daemon', 'Run as background daemon — collects all OTLP data, no ACP proxy')
|
|
23
26
|
.allowUnknownOption()
|
|
24
27
|
.parse();
|
|
25
28
|
const opts = program.opts();
|
|
26
29
|
const port = parseInt(opts.port);
|
|
27
30
|
// Handle --setup: patch env files, apply to current process, then fall through to start web UI
|
|
28
31
|
if (opts.setup) {
|
|
29
|
-
runSetup(port);
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
const sessionId = opts.session || randomUUID();
|
|
35
|
-
createSession(sessionId);
|
|
36
|
-
console.log(`\n 🤖 Copilot Tracer | Session: ${sessionId}\n`);
|
|
37
|
-
// Start Web UI
|
|
38
|
-
if (opts.ui === 'web' || opts.ui === 'both') {
|
|
39
|
-
startWebServer(port, sessionId);
|
|
40
|
-
setTimeout(() => open(`http://localhost:${port}/`), 1500);
|
|
32
|
+
runSetup(port, opts.daemon);
|
|
33
|
+
if (!opts.daemon) {
|
|
34
|
+
opts.proxy = false;
|
|
35
|
+
opts.ui = 'web';
|
|
36
|
+
}
|
|
41
37
|
}
|
|
42
|
-
//
|
|
43
|
-
if (opts.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
refreshConsole();
|
|
38
|
+
// ── Daemon mode: run as always-on OTLP receiver ───────────────────────────
|
|
39
|
+
if (opts.daemon) {
|
|
40
|
+
console.log(`\n 🤖 Copilot Tracer — Daemon Mode`);
|
|
41
|
+
console.log(` 📡 Listening for OTLP traces on port ${port}`);
|
|
42
|
+
console.log(` 🌐 Dashboard: http://localhost:${port}/`);
|
|
43
|
+
console.log(` Press Ctrl+C to stop\n`);
|
|
44
|
+
startWebServer(port);
|
|
45
|
+
process.on('SIGINT', () => { process.exit(0); });
|
|
46
|
+
process.on('SIGTERM', () => { process.exit(0); });
|
|
52
47
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
48
|
+
else {
|
|
49
|
+
// ── Normal mode: per-session with optional ACP proxy ─────────────────────
|
|
50
|
+
const sessionId = opts.session || randomUUID();
|
|
51
|
+
// Resolve project path and create project record
|
|
52
|
+
const projectPath = opts.projectPath
|
|
53
|
+
? path.resolve(opts.projectPath)
|
|
54
|
+
: process.cwd();
|
|
55
|
+
const projectId = ensureProject(projectPath);
|
|
56
|
+
createSession(sessionId, projectId);
|
|
57
|
+
console.log(`\n 🤖 Copilot Tracer | Session: ${sessionId}`);
|
|
58
|
+
console.log(` 📁 Project: ${projectPath}\n`);
|
|
59
|
+
// Start Web UI
|
|
60
|
+
if (opts.ui === 'web' || opts.ui === 'both') {
|
|
61
|
+
startWebServer(port, sessionId, projectId);
|
|
62
|
+
setTimeout(() => open(`http://localhost:${port}/`), 1500);
|
|
63
63
|
}
|
|
64
|
-
//
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
logFile?.write(entry + '\n');
|
|
64
|
+
// Start Console UI refresh loop
|
|
65
|
+
if (opts.ui === 'console' || opts.ui === 'both') {
|
|
66
|
+
const refreshConsole = () => {
|
|
67
|
+
const entries = getTraces(sessionId, 50);
|
|
68
|
+
const summary = getSessionSummary(sessionId);
|
|
69
|
+
renderConsoleTable(entries, summary ?? undefined);
|
|
70
|
+
};
|
|
71
|
+
traceEvents.on('trace:update', refreshConsole);
|
|
72
|
+
traceEvents.on('trace:done', refreshConsole);
|
|
73
|
+
refreshConsole();
|
|
75
74
|
}
|
|
76
|
-
//
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
process.stderr.write(`[TRACER] stdin non-JSON: ${line}\n`);
|
|
75
|
+
// ACP Proxy — wrap copilot CLI
|
|
76
|
+
if (opts.proxy !== false) {
|
|
77
|
+
const copilotArgs = ['--acp', '--stdio', ...program.args];
|
|
78
|
+
const child = spawn(opts.cmd, copilotArgs, {
|
|
79
|
+
stdio: ['pipe', 'pipe', 'inherit'],
|
|
80
|
+
});
|
|
81
|
+
if (!child.pid) {
|
|
82
|
+
console.error(`\n ❌ Failed to start: ${opts.cmd} ${copilotArgs.join(' ')}`);
|
|
83
|
+
console.error(' Make sure GitHub Copilot CLI is installed: npm install -g @github/copilot-cli\n');
|
|
84
|
+
process.exit(1);
|
|
87
85
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
86
|
+
const stdinRl = readline.createInterface({ input: process.stdin });
|
|
87
|
+
const stdoutRl = readline.createInterface({ input: child.stdout });
|
|
88
|
+
const debug = opts.debug === true;
|
|
89
|
+
const logFile = debug ? fs.createWriteStream(`/tmp/copilot-tracer-${sessionId.slice(0, 8)}.ndjson`, { flags: 'a' }) : null;
|
|
90
|
+
function debugLog(direction, raw, parsed) {
|
|
91
|
+
if (!debug)
|
|
92
|
+
return;
|
|
93
|
+
const entry = JSON.stringify({ ts: new Date().toISOString(), dir: direction, raw, parsed });
|
|
94
|
+
process.stderr.write('[TRACER] ' + entry + '\n');
|
|
95
|
+
logFile?.write(entry + '\n');
|
|
97
96
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
97
|
+
stdinRl.on('line', (line) => {
|
|
98
|
+
let parsed;
|
|
99
|
+
try {
|
|
100
|
+
parsed = JSON.parse(line);
|
|
101
|
+
handleAcpMessage(sessionId, parsed, 'out');
|
|
102
|
+
}
|
|
103
|
+
catch (e) {
|
|
104
|
+
if (debug)
|
|
105
|
+
process.stderr.write(`[TRACER] stdin non-JSON: ${line}\n`);
|
|
106
|
+
}
|
|
107
|
+
debugLog('→ copilot', line, parsed);
|
|
108
|
+
child.stdin.write(line + '\n');
|
|
109
|
+
});
|
|
110
|
+
stdoutRl.on('line', (line) => {
|
|
111
|
+
let parsed;
|
|
112
|
+
try {
|
|
113
|
+
parsed = JSON.parse(line);
|
|
114
|
+
handleAcpMessage(sessionId, parsed, 'in');
|
|
115
|
+
}
|
|
116
|
+
catch (e) {
|
|
117
|
+
if (debug)
|
|
118
|
+
process.stderr.write(`[TRACER] stdout non-JSON: ${line}\n`);
|
|
119
|
+
}
|
|
120
|
+
debugLog('← copilot', line, parsed);
|
|
121
|
+
process.stdout.write(line + '\n');
|
|
122
|
+
});
|
|
123
|
+
child.on('exit', (code) => {
|
|
124
|
+
console.log(`\n Copilot CLI exited (code ${code})\n`);
|
|
125
|
+
process.exit(code ?? 0);
|
|
126
|
+
});
|
|
127
|
+
process.on('SIGINT', () => { child.kill(); process.exit(0); });
|
|
128
|
+
}
|
|
110
129
|
}
|