@newrelic/preflight 1.15.6 → 1.16.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/dist/config.d.ts +3 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -0
- package/dist/config.js.map +1 -1
- package/dist/dashboard/dashboard-server.d.ts.map +1 -1
- package/dist/dashboard/dashboard-server.js +15 -0
- package/dist/dashboard/dashboard-server.js.map +1 -1
- package/dist/dashboard/routes/api-handler.d.ts +26 -18
- package/dist/dashboard/routes/api-handler.d.ts.map +1 -1
- package/dist/dashboard/routes/api-handler.js +23 -15
- package/dist/dashboard/routes/api-handler.js.map +1 -1
- package/dist/data/copilot-pricing/README.md +42 -0
- package/dist/data/copilot-pricing/pricing.json +54 -0
- package/dist/data/copilot-sdk-extension/extension.mjs +123 -0
- package/dist/deploy/data-paths.d.ts +6 -4
- package/dist/deploy/data-paths.d.ts.map +1 -1
- package/dist/deploy/data-paths.js +5 -3
- package/dist/deploy/data-paths.js.map +1 -1
- package/dist/hooks/collector-script.d.ts +12 -3
- package/dist/hooks/collector-script.d.ts.map +1 -1
- package/dist/hooks/collector-script.js +70 -18
- package/dist/hooks/collector-script.js.map +1 -1
- package/dist/hooks/copilot-sdk-usage-mapper.d.ts +45 -0
- package/dist/hooks/copilot-sdk-usage-mapper.d.ts.map +1 -0
- package/dist/hooks/copilot-sdk-usage-mapper.js +73 -0
- package/dist/hooks/copilot-sdk-usage-mapper.js.map +1 -0
- package/dist/hooks/copilot-usage-watcher.d.ts +109 -0
- package/dist/hooks/copilot-usage-watcher.d.ts.map +1 -0
- package/dist/hooks/copilot-usage-watcher.js +436 -0
- package/dist/hooks/copilot-usage-watcher.js.map +1 -0
- package/dist/index.d.ts +11 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +162 -70
- package/dist/index.js.map +1 -1
- package/dist/metrics/copilot-pricing-overlay.d.ts +42 -0
- package/dist/metrics/copilot-pricing-overlay.d.ts.map +1 -0
- package/dist/metrics/copilot-pricing-overlay.js +97 -0
- package/dist/metrics/copilot-pricing-overlay.js.map +1 -0
- package/dist/metrics/git-efficiency-tracker.d.ts +12 -1
- package/dist/metrics/git-efficiency-tracker.d.ts.map +1 -1
- package/dist/metrics/git-efficiency-tracker.js +18 -3
- package/dist/metrics/git-efficiency-tracker.js.map +1 -1
- package/dist/metrics/local-session-aggregator.d.ts +164 -0
- package/dist/metrics/local-session-aggregator.d.ts.map +1 -0
- package/dist/metrics/local-session-aggregator.js +444 -0
- package/dist/metrics/local-session-aggregator.js.map +1 -0
- package/dist/platforms/copilot-adapter.d.ts +1 -1
- package/dist/platforms/copilot-adapter.d.ts.map +1 -1
- package/dist/platforms/copilot-adapter.js +64 -10
- package/dist/platforms/copilot-adapter.js.map +1 -1
- package/dist/platforms/copilot-sdk-adapter.d.ts +24 -0
- package/dist/platforms/copilot-sdk-adapter.d.ts.map +1 -0
- package/dist/platforms/copilot-sdk-adapter.js +173 -0
- package/dist/platforms/copilot-sdk-adapter.js.map +1 -0
- package/dist/platforms/index.d.ts +1 -0
- package/dist/platforms/index.d.ts.map +1 -1
- package/dist/platforms/index.js +1 -0
- package/dist/platforms/index.js.map +1 -1
- package/dist/platforms/platform-registry.d.ts.map +1 -1
- package/dist/platforms/platform-registry.js +13 -11
- package/dist/platforms/platform-registry.js.map +1 -1
- package/dist/storage/session-store.d.ts +9 -0
- package/dist/storage/session-store.d.ts.map +1 -1
- package/dist/storage/session-store.js +213 -20
- package/dist/storage/session-store.js.map +1 -1
- package/dist/web/assets/{index-BasTEtUs.js → index-Bwc4qaqj.js} +1 -1
- package/dist/web/assets/index-DwdSz9gz.css +2 -0
- package/dist/web/index.html +2 -2
- package/package.json +2 -2
- package/dist/web/assets/index-BI-2ELf2.css +0 -2
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copilot Usage Watcher — polls VS Code Copilot agent debug logs and emits
|
|
3
|
+
* one `mode: 'token'` line per LLM request into the session's hook buffer,
|
|
4
|
+
* giving Copilot sessions token-exact cost (the same fidelity
|
|
5
|
+
* ParentTranscriptWatcher gives Claude Code sessions) instead of
|
|
6
|
+
* content-size estimation.
|
|
7
|
+
*
|
|
8
|
+
* Source of truth: VS Code writes per-request records to
|
|
9
|
+
* `<userDataDir>/workspaceStorage/<hash>/GitHub.copilot-chat/debug-logs/<sessionId>/main.jsonl`,
|
|
10
|
+
* where `<sessionId>` is the same chat session id VS Code sends as
|
|
11
|
+
* `session_id` in agent hook payloads — so events emitted here land in the
|
|
12
|
+
* same `buffer-<sessionId>.jsonl` the hook collector writes to. Each usage
|
|
13
|
+
* record is `{ type: 'llm_request', sid, ts, attrs: { model, inputTokens,
|
|
14
|
+
* outputTokens, cachedTokens, responseId, copilotUsageNanoAiu, ... } }`.
|
|
15
|
+
* This path + schema are produced by VS Code's `chatDebugFileLoggerService.ts`
|
|
16
|
+
* (formerly `microsoft/vscode-copilot-chat`, now merged into
|
|
17
|
+
* `microsoft/vscode` under `extensions/copilot/` and archived); the record
|
|
18
|
+
* shape is documented in its `otel-data-flow.html` and cross-checked against a
|
|
19
|
+
* real main.jsonl (VS Code 1.109 / Copilot Chat).
|
|
20
|
+
* The hooks doc notes transcript/debug-log formats are not a stable API
|
|
21
|
+
* (code.visualstudio.com/docs/copilot/customization/hooks) — same stability
|
|
22
|
+
* tier as the Claude Code transcript format the parent/subagent watchers
|
|
23
|
+
* already depend on; schema drift degrades to zero emissions, never a crash.
|
|
24
|
+
*
|
|
25
|
+
* Tailing/cursor mechanics mirror `ParentTranscriptWatcher`: durable byte
|
|
26
|
+
* cursor per session (`.copilot-usage-pos-<sessionId>`), bounded reads per
|
|
27
|
+
* poll, bounded partial-line carry, duplicate emissions after a crash are
|
|
28
|
+
* deduped downstream by (sessionId, messageId) in
|
|
29
|
+
* `HookEventProcessor.handleTokenEvent()` — `responseId` serves as the
|
|
30
|
+
* message id.
|
|
31
|
+
*/
|
|
32
|
+
import { appendFileSync, closeSync, existsSync, mkdirSync, openSync, readdirSync, readFileSync, readSync, statSync, writeFileSync, } from 'node:fs';
|
|
33
|
+
import { homedir } from 'node:os';
|
|
34
|
+
import { join } from 'node:path';
|
|
35
|
+
import { StringDecoder } from 'node:string_decoder';
|
|
36
|
+
import { createLogger } from '../shared/index.js';
|
|
37
|
+
const logger = createLogger('copilot-usage-watcher');
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// Constants
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
const DEFAULT_POLL_INTERVAL_MS = 2_000;
|
|
42
|
+
const DEFAULT_DISCOVERY_HOURS = 24;
|
|
43
|
+
// Copilot debug-log lines embed full inputMessages payloads and routinely run
|
|
44
|
+
// hundreds of KiB — far larger than transcript lines. A bigger window keeps a
|
|
45
|
+
// single record from spanning many polls (each carry-over persists the whole
|
|
46
|
+
// partial line into the cursor file).
|
|
47
|
+
const MAX_BYTES_PER_POLL = 1024 * 1024;
|
|
48
|
+
/** See SubagentWatcher's identical constant for the OOM-bug rationale this guards against. */
|
|
49
|
+
const MAX_PARTIAL_LINE_BYTES = 4 * 1024 * 1024; // 4 MiB — sized to the larger log lines
|
|
50
|
+
const SESSION_ID_RE = /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/;
|
|
51
|
+
const COPILOT_LOG_SUBPATH = join('GitHub.copilot-chat', 'debug-logs');
|
|
52
|
+
/**
|
|
53
|
+
* VS Code Remote (WSL, SSH, dev containers, Codespaces) `workspaceStorage`
|
|
54
|
+
* roots. When the Copilot Chat extension runs in a remote extension host, it
|
|
55
|
+
* writes debug logs under the server's user-data dir rather than the desktop
|
|
56
|
+
* one, so these must be searched alongside the local roots or remote sessions
|
|
57
|
+
* silently yield zero token events (and therefore $0.00 cost).
|
|
58
|
+
*/
|
|
59
|
+
function remoteWorkspaceStorageRoots(home) {
|
|
60
|
+
return ['.vscode-server', '.vscode-server-insiders', '.vscode-remote'].map((dir) => join(home, dir, 'data', 'User', 'workspaceStorage'));
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Default VS Code `workspaceStorage` roots per OS (stable + Insiders), plus
|
|
64
|
+
* the remote-server roots used by WSL/SSH/dev-container sessions.
|
|
65
|
+
* Sourced from VS Code's documented user-data locations
|
|
66
|
+
* (code.visualstudio.com/docs/configure/command-line#_advanced-cli-options).
|
|
67
|
+
*/
|
|
68
|
+
export function defaultWorkspaceStorageRoots() {
|
|
69
|
+
const home = homedir();
|
|
70
|
+
const variants = ['Code', 'Code - Insiders'];
|
|
71
|
+
const remote = remoteWorkspaceStorageRoots(home);
|
|
72
|
+
if (process.platform === 'darwin') {
|
|
73
|
+
return [
|
|
74
|
+
...variants.map((v) => join(home, 'Library', 'Application Support', v, 'User', 'workspaceStorage')),
|
|
75
|
+
...remote,
|
|
76
|
+
];
|
|
77
|
+
}
|
|
78
|
+
if (process.platform === 'win32') {
|
|
79
|
+
const appData = process.env.APPDATA ?? join(home, 'AppData', 'Roaming');
|
|
80
|
+
return [...variants.map((v) => join(appData, v, 'User', 'workspaceStorage')), ...remote];
|
|
81
|
+
}
|
|
82
|
+
return [...variants.map((v) => join(home, '.config', v, 'User', 'workspaceStorage')), ...remote];
|
|
83
|
+
}
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
// CopilotUsageWatcher
|
|
86
|
+
// ---------------------------------------------------------------------------
|
|
87
|
+
export class CopilotUsageWatcher {
|
|
88
|
+
storagePath;
|
|
89
|
+
workspaceStorageRoots;
|
|
90
|
+
pollIntervalMs;
|
|
91
|
+
discoveryHours;
|
|
92
|
+
parentSessionFilter;
|
|
93
|
+
localStore;
|
|
94
|
+
intervalId = null;
|
|
95
|
+
partialByPath = new Map();
|
|
96
|
+
decoderByPath = new Map();
|
|
97
|
+
filesWatched = 0;
|
|
98
|
+
linesRead = 0;
|
|
99
|
+
bytesRead = 0;
|
|
100
|
+
parseErrors = 0;
|
|
101
|
+
debugLoggingLikelyDisabled = false;
|
|
102
|
+
warnedDebugLoggingDisabled = false;
|
|
103
|
+
constructor(options = {}) {
|
|
104
|
+
this.storagePath = options.storagePath ?? join(homedir(), '.newrelic-preflight');
|
|
105
|
+
this.workspaceStorageRoots = options.workspaceStorageRoots ?? defaultWorkspaceStorageRoots();
|
|
106
|
+
this.pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
107
|
+
this.discoveryHours = options.discoveryHours ?? DEFAULT_DISCOVERY_HOURS;
|
|
108
|
+
this.parentSessionFilter = options.parentSessionId ?? null;
|
|
109
|
+
this.localStore = options.localStore;
|
|
110
|
+
}
|
|
111
|
+
start() {
|
|
112
|
+
if (this.intervalId !== null)
|
|
113
|
+
return;
|
|
114
|
+
this.intervalId = setInterval(() => {
|
|
115
|
+
try {
|
|
116
|
+
this.poll();
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
this.recordError(err);
|
|
120
|
+
}
|
|
121
|
+
}, this.pollIntervalMs);
|
|
122
|
+
this.intervalId.unref?.();
|
|
123
|
+
}
|
|
124
|
+
stop() {
|
|
125
|
+
if (this.intervalId !== null) {
|
|
126
|
+
clearInterval(this.intervalId);
|
|
127
|
+
this.intervalId = null;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
getHealth() {
|
|
131
|
+
return {
|
|
132
|
+
filesWatched: this.filesWatched,
|
|
133
|
+
linesRead: this.linesRead,
|
|
134
|
+
bytesRead: this.bytesRead,
|
|
135
|
+
parseErrors: this.parseErrors,
|
|
136
|
+
debugLoggingLikelyDisabled: this.debugLoggingLikelyDisabled,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
/** One discovery + tail pass. Exported for direct testing. */
|
|
140
|
+
poll() {
|
|
141
|
+
const files = this.discoverFiles();
|
|
142
|
+
this.filesWatched = files.length;
|
|
143
|
+
this.evictStalePartials(files);
|
|
144
|
+
for (const file of files) {
|
|
145
|
+
try {
|
|
146
|
+
this.tailFile(file.path, file.sessionId);
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
this.recordError(err);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// -------------------------------------------------------------------------
|
|
154
|
+
// Discovery
|
|
155
|
+
// -------------------------------------------------------------------------
|
|
156
|
+
discoverFiles() {
|
|
157
|
+
const out = [];
|
|
158
|
+
const cutoffMs = Date.now() - this.discoveryHours * 3_600_000;
|
|
159
|
+
// Unscoped (--local) mode: skip sessions a live --stdio process already
|
|
160
|
+
// tails, so two processes never race on the same cursor file — identical
|
|
161
|
+
// to ParentTranscriptWatcher's unfiltered discovery.
|
|
162
|
+
const liveOwnedSessionIds = this.parentSessionFilter === null
|
|
163
|
+
? (this.localStore?.getActiveSessionIdsFromHeartbeats() ?? null)
|
|
164
|
+
: null;
|
|
165
|
+
let anyRootExists = false;
|
|
166
|
+
let anyDebugLogDir = false;
|
|
167
|
+
for (const root of this.workspaceStorageRoots) {
|
|
168
|
+
if (!existsSync(root))
|
|
169
|
+
continue;
|
|
170
|
+
anyRootExists = true;
|
|
171
|
+
let workspaceHashes;
|
|
172
|
+
try {
|
|
173
|
+
workspaceHashes = readdirSync(root);
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
for (const hash of workspaceHashes) {
|
|
179
|
+
const logsDir = join(root, hash, COPILOT_LOG_SUBPATH);
|
|
180
|
+
if (!existsSync(logsDir))
|
|
181
|
+
continue;
|
|
182
|
+
anyDebugLogDir = true;
|
|
183
|
+
let sessionDirs;
|
|
184
|
+
try {
|
|
185
|
+
sessionDirs = readdirSync(logsDir);
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
for (const sessionId of sessionDirs) {
|
|
191
|
+
if (!SESSION_ID_RE.test(sessionId))
|
|
192
|
+
continue;
|
|
193
|
+
if (this.parentSessionFilter !== null && sessionId !== this.parentSessionFilter) {
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
if (liveOwnedSessionIds?.has(sessionId))
|
|
197
|
+
continue;
|
|
198
|
+
const logPath = join(logsDir, sessionId, 'main.jsonl');
|
|
199
|
+
try {
|
|
200
|
+
const st = statSync(logPath);
|
|
201
|
+
if (!st.isFile())
|
|
202
|
+
continue;
|
|
203
|
+
// Scoped mode always tails its own session; unscoped applies the
|
|
204
|
+
// recency window so old logs don't trigger unbounded cold scans.
|
|
205
|
+
if (this.parentSessionFilter === null && st.mtimeMs < cutoffMs)
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
out.push({ path: logPath, sessionId });
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
// A VS Code install is present (root exists) yet no Copilot debug-logs
|
|
216
|
+
// directory anywhere ⇒ the off-by-default fileLogging setting is almost
|
|
217
|
+
// certainly not enabled. Warn once so a zero-cost session reads as a
|
|
218
|
+
// missing prerequisite rather than a broken integration.
|
|
219
|
+
this.debugLoggingLikelyDisabled = anyRootExists && !anyDebugLogDir;
|
|
220
|
+
if (this.debugLoggingLikelyDisabled && !this.warnedDebugLoggingDisabled) {
|
|
221
|
+
this.warnedDebugLoggingDisabled = true;
|
|
222
|
+
logger.warn('No Copilot debug-logs directory found; token-exact cost is unavailable. ' +
|
|
223
|
+
'Enable "github.copilot.chat.agentDebugLog.fileLogging.enabled" in VS Code ' +
|
|
224
|
+
'settings.json and reload the window.');
|
|
225
|
+
}
|
|
226
|
+
return out;
|
|
227
|
+
}
|
|
228
|
+
// -------------------------------------------------------------------------
|
|
229
|
+
// Tailing
|
|
230
|
+
// -------------------------------------------------------------------------
|
|
231
|
+
tailFile(path, dirSessionId) {
|
|
232
|
+
const cursorPath = this.cursorPath(dirSessionId);
|
|
233
|
+
const persisted = this.readCursor(cursorPath);
|
|
234
|
+
const memPartial = this.partialByPath.get(path);
|
|
235
|
+
const startCursor = memPartial !== undefined
|
|
236
|
+
? { bytePos: persisted.bytePos, partialLine: memPartial }
|
|
237
|
+
: persisted;
|
|
238
|
+
let size;
|
|
239
|
+
try {
|
|
240
|
+
size = statSync(path).size;
|
|
241
|
+
}
|
|
242
|
+
catch {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
// Truncated/rotated file: restart from 0.
|
|
246
|
+
const fromPos = startCursor.bytePos > size ? 0 : startCursor.bytePos;
|
|
247
|
+
if (fromPos >= size)
|
|
248
|
+
return;
|
|
249
|
+
const toRead = Math.min(size - fromPos, MAX_BYTES_PER_POLL);
|
|
250
|
+
const buf = Buffer.alloc(toRead);
|
|
251
|
+
let actuallyRead = 0;
|
|
252
|
+
let fd = null;
|
|
253
|
+
try {
|
|
254
|
+
fd = openSync(path, 'r');
|
|
255
|
+
actuallyRead = readSync(fd, buf, 0, toRead, fromPos);
|
|
256
|
+
}
|
|
257
|
+
catch (err) {
|
|
258
|
+
this.recordError(err);
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
finally {
|
|
262
|
+
if (fd !== null)
|
|
263
|
+
closeSync(fd);
|
|
264
|
+
}
|
|
265
|
+
if (actuallyRead <= 0)
|
|
266
|
+
return;
|
|
267
|
+
this.bytesRead += actuallyRead;
|
|
268
|
+
let decoder = this.decoderByPath.get(path);
|
|
269
|
+
if (!decoder) {
|
|
270
|
+
decoder = new StringDecoder('utf8');
|
|
271
|
+
this.decoderByPath.set(path, decoder);
|
|
272
|
+
}
|
|
273
|
+
const combined = startCursor.partialLine + decoder.write(buf.subarray(0, actuallyRead));
|
|
274
|
+
const nextBytePos = fromPos + actuallyRead;
|
|
275
|
+
const lastNewline = combined.lastIndexOf('\n');
|
|
276
|
+
let lines = [];
|
|
277
|
+
let newPartial = combined;
|
|
278
|
+
if (lastNewline >= 0) {
|
|
279
|
+
lines = combined.slice(0, lastNewline).split('\n');
|
|
280
|
+
newPartial = combined.slice(lastNewline + 1);
|
|
281
|
+
}
|
|
282
|
+
if (newPartial.length > MAX_PARTIAL_LINE_BYTES) {
|
|
283
|
+
newPartial = '';
|
|
284
|
+
this.parseErrors += 1;
|
|
285
|
+
}
|
|
286
|
+
for (const line of lines) {
|
|
287
|
+
if (!line)
|
|
288
|
+
continue;
|
|
289
|
+
this.linesRead += 1;
|
|
290
|
+
const parsed = this.tryParseLine(line);
|
|
291
|
+
if (parsed === null)
|
|
292
|
+
continue;
|
|
293
|
+
const sessionId = parsed.sessionId ?? dirSessionId;
|
|
294
|
+
this.appendToBuffer(sessionId, {
|
|
295
|
+
mode: 'token',
|
|
296
|
+
tool: 'copilot-usage',
|
|
297
|
+
timestamp: parsed.timestampMs,
|
|
298
|
+
sessionId,
|
|
299
|
+
messageId: parsed.responseId,
|
|
300
|
+
model: parsed.model,
|
|
301
|
+
// VS Code's inputTokens is cache-INCLUSIVE (verified against a real
|
|
302
|
+
// main.jsonl: each request's cachedTokens ≈ the previous request's
|
|
303
|
+
// inputTokens). CostTracker follows the Anthropic convention where
|
|
304
|
+
// input excludes cache reads, so emit only the uncached remainder —
|
|
305
|
+
// otherwise cached tokens are double-billed at full input rate.
|
|
306
|
+
inputTokens: Math.max(0, parsed.inputTokens - parsed.cachedTokens),
|
|
307
|
+
outputTokens: parsed.outputTokens,
|
|
308
|
+
// `cachedTokens` is the only cache figure the debug-log schema exposes,
|
|
309
|
+
// and it is cache-READ (confirmed against a real main.jsonl: it tracks
|
|
310
|
+
// the previous request's input). KNOWN ESTIMATION GAP: VS Code does not
|
|
311
|
+
// surface cache-CREATION (cache-write) tokens separately, so any turn
|
|
312
|
+
// with a fresh cache write has those tokens folded into `inputTokens`
|
|
313
|
+
// above and billed at the base input rate instead of the premium
|
|
314
|
+
// `cacheCreationPerMTok` rate (src/shared/pricing.ts). This causes a
|
|
315
|
+
// small, consistent UNDER-billing on cache-write turns. We report 0
|
|
316
|
+
// rather than guess a split the source doesn't provide; revisit if VS
|
|
317
|
+
// Code adds a cache-creation field to the schema.
|
|
318
|
+
cacheReadTokens: parsed.cachedTokens,
|
|
319
|
+
cacheCreationTokens: 0,
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
this.writeCursor(cursorPath, nextBytePos, newPartial);
|
|
323
|
+
if (newPartial.length > 0)
|
|
324
|
+
this.partialByPath.set(path, newPartial);
|
|
325
|
+
else
|
|
326
|
+
this.partialByPath.delete(path);
|
|
327
|
+
}
|
|
328
|
+
evictStalePartials(files) {
|
|
329
|
+
if (this.partialByPath.size === 0 && this.decoderByPath.size === 0)
|
|
330
|
+
return;
|
|
331
|
+
const live = new Set(files.map((f) => f.path));
|
|
332
|
+
for (const path of this.partialByPath.keys()) {
|
|
333
|
+
if (!live.has(path))
|
|
334
|
+
this.partialByPath.delete(path);
|
|
335
|
+
}
|
|
336
|
+
for (const path of this.decoderByPath.keys()) {
|
|
337
|
+
if (!live.has(path))
|
|
338
|
+
this.decoderByPath.delete(path);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Parse a debug-log JSONL line, returning non-null only for an
|
|
343
|
+
* `llm_request` record carrying a model, responseId, and token counts.
|
|
344
|
+
*/
|
|
345
|
+
tryParseLine(line) {
|
|
346
|
+
let parsed;
|
|
347
|
+
try {
|
|
348
|
+
parsed = JSON.parse(line);
|
|
349
|
+
}
|
|
350
|
+
catch {
|
|
351
|
+
this.parseErrors += 1;
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
if (!parsed || typeof parsed !== 'object')
|
|
355
|
+
return null;
|
|
356
|
+
const obj = parsed;
|
|
357
|
+
if (obj.type !== 'llm_request')
|
|
358
|
+
return null;
|
|
359
|
+
const attrs = obj.attrs;
|
|
360
|
+
if (!attrs || typeof attrs !== 'object')
|
|
361
|
+
return null;
|
|
362
|
+
const a = attrs;
|
|
363
|
+
const model = typeof a.model === 'string' && a.model.length > 0 ? a.model : null;
|
|
364
|
+
if (!model)
|
|
365
|
+
return null;
|
|
366
|
+
const responseId = typeof a.responseId === 'string' && a.responseId.length > 0 ? a.responseId : null;
|
|
367
|
+
if (!responseId)
|
|
368
|
+
return null;
|
|
369
|
+
const timestampMs = typeof obj.ts === 'number' && Number.isFinite(obj.ts) && obj.ts > 0 ? obj.ts : Date.now();
|
|
370
|
+
const sid = typeof obj.sid === 'string' && SESSION_ID_RE.test(obj.sid) ? obj.sid : null;
|
|
371
|
+
return {
|
|
372
|
+
timestampMs,
|
|
373
|
+
sessionId: sid,
|
|
374
|
+
responseId,
|
|
375
|
+
model,
|
|
376
|
+
inputTokens: num(a.inputTokens),
|
|
377
|
+
outputTokens: num(a.outputTokens),
|
|
378
|
+
cachedTokens: num(a.cachedTokens),
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
// -------------------------------------------------------------------------
|
|
382
|
+
// Buffer + cursor I/O
|
|
383
|
+
// -------------------------------------------------------------------------
|
|
384
|
+
cursorPath(sessionId) {
|
|
385
|
+
return join(this.storagePath, `.copilot-usage-pos-${sessionId}`);
|
|
386
|
+
}
|
|
387
|
+
readCursor(cursorPath) {
|
|
388
|
+
if (!existsSync(cursorPath))
|
|
389
|
+
return { bytePos: 0, partialLine: '' };
|
|
390
|
+
try {
|
|
391
|
+
const parsed = JSON.parse(readFileSync(cursorPath, 'utf-8').trim());
|
|
392
|
+
const bytePos = typeof parsed.bytePos === 'number' && parsed.bytePos >= 0 ? parsed.bytePos : 0;
|
|
393
|
+
const partialLine = typeof parsed.partialLine === 'string' ? parsed.partialLine : '';
|
|
394
|
+
return { bytePos, partialLine };
|
|
395
|
+
}
|
|
396
|
+
catch {
|
|
397
|
+
return { bytePos: 0, partialLine: '' };
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
writeCursor(cursorPath, bytePos, partialLine) {
|
|
401
|
+
try {
|
|
402
|
+
if (!existsSync(this.storagePath)) {
|
|
403
|
+
mkdirSync(this.storagePath, { recursive: true, mode: 0o700 });
|
|
404
|
+
}
|
|
405
|
+
writeFileSync(cursorPath, JSON.stringify({ bytePos, partialLine }), { mode: 0o600 });
|
|
406
|
+
}
|
|
407
|
+
catch (err) {
|
|
408
|
+
this.recordError(err);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
/** Append into the session's hook buffer, same path convention as the collector. */
|
|
412
|
+
appendToBuffer(sessionId, event) {
|
|
413
|
+
try {
|
|
414
|
+
if (!existsSync(this.storagePath)) {
|
|
415
|
+
mkdirSync(this.storagePath, { recursive: true, mode: 0o700 });
|
|
416
|
+
}
|
|
417
|
+
appendFileSync(join(this.storagePath, `buffer-${sessionId}.jsonl`), JSON.stringify(event) + '\n', {
|
|
418
|
+
mode: 0o600,
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
catch (err) {
|
|
422
|
+
this.recordError(err);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
recordError(err) {
|
|
426
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
427
|
+
logger.warn('CopilotUsageWatcher error', { message: message.slice(0, 200) });
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
// ---------------------------------------------------------------------------
|
|
431
|
+
// Helpers
|
|
432
|
+
// ---------------------------------------------------------------------------
|
|
433
|
+
function num(v) {
|
|
434
|
+
return typeof v === 'number' && Number.isFinite(v) && v >= 0 ? v : 0;
|
|
435
|
+
}
|
|
436
|
+
//# sourceMappingURL=copilot-usage-watcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copilot-usage-watcher.js","sourceRoot":"","sources":["../../src/hooks/copilot-usage-watcher.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import 'dotenv/config';
|
|
3
|
-
import {
|
|
4
|
-
import type { ProxyToolCallRecord, ProxyRequestRecord } from './proxy/index.js';
|
|
5
|
-
import { LocalStore } from './storage/index.js';
|
|
3
|
+
import { DashboardServer } from './dashboard/dashboard-server.js';
|
|
6
4
|
import { LiveSessionRegistry } from './metrics/live-session-registry.js';
|
|
5
|
+
import type { ProxyRequestRecord, ProxyToolCallRecord } from './proxy/index.js';
|
|
6
|
+
import { LocalStore } from './storage/index.js';
|
|
7
7
|
import { NrIngestManager } from './transport/nr-ingest.js';
|
|
8
|
-
import { DashboardServer } from './dashboard/dashboard-server.js';
|
|
9
8
|
import type { CliOptions } from './types.js';
|
|
10
|
-
|
|
11
|
-
export { NrMcpServer, createServer } from './server.js';
|
|
9
|
+
import { VERSION } from './version.js';
|
|
12
10
|
export { loadMcpConfig, redactSensitive } from './config.js';
|
|
13
11
|
export type { McpServerConfig } from './config.js';
|
|
12
|
+
export { AmazonQAdapter, ClaudeCodeAdapter, ContinueAdapter, CopilotAdapter, createDefaultRegistry, CursorAdapter, GenericMcpAdapter, parseCopilotUsageResponse, PlatformRegistry, REPORT_SESSION_END_TOOL, REPORT_SESSION_START_TOOL, REPORT_TOOL_CALL_TOOL, validateReportToolCallInput, WindsurfAdapter, ZedAdapter, } from './platforms/index.js';
|
|
13
|
+
export type { NormalizedToolCall, PlatformAdapter, PlatformConfig, PlatformSessionMetadata, ReportSessionEndInput, ReportSessionStartInput, ReportToolCallInput, } from './platforms/index.js';
|
|
14
|
+
export { ProxyManager } from './proxy/index.js';
|
|
15
|
+
export type { ProxyRequestRecord, ProxyToolCallRecord, UpstreamConfig } from './proxy/index.js';
|
|
16
|
+
export { createServer, NrMcpServer } from './server.js';
|
|
14
17
|
export { LocalStore } from './storage/index.js';
|
|
15
|
-
export type { HookEvent, SessionSummary
|
|
18
|
+
export type { AuditEntry, HookEvent, SessionSummary } from './storage/index.js';
|
|
16
19
|
export type { CliOptions, ServerOptions } from './types.js';
|
|
17
|
-
export {
|
|
18
|
-
export type { ProxyToolCallRecord, ProxyRequestRecord, UpstreamConfig } from './proxy/index.js';
|
|
19
|
-
export { ClaudeCodeAdapter, CursorAdapter, WindsurfAdapter, CopilotAdapter, ZedAdapter, ContinueAdapter, AmazonQAdapter, parseCopilotUsageResponse, GenericMcpAdapter, validateReportToolCallInput, REPORT_TOOL_CALL_TOOL, REPORT_SESSION_START_TOOL, REPORT_SESSION_END_TOOL, PlatformRegistry, createDefaultRegistry, } from './platforms/index.js';
|
|
20
|
-
export type { NormalizedToolCall, PlatformConfig, PlatformSessionMetadata, PlatformAdapter, ReportToolCallInput, ReportSessionStartInput, ReportSessionEndInput, } from './platforms/index.js';
|
|
20
|
+
export { VERSION };
|
|
21
21
|
export declare function maskCredential(key: string): string;
|
|
22
22
|
/**
|
|
23
23
|
* Structural subset of NrIngestManager consumed by the proxy-mode telemetry
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|