sidekick-shared 0.27.2 → 0.27.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/CHANGELOG.md +26 -0
- package/README.md +24 -3
- package/dist/aggregation/EventAggregator.d.ts +12 -2
- package/dist/aggregation/EventAggregator.js +49 -19
- package/dist/browser.d.ts +2 -1
- package/dist/browser.js +9 -2
- package/dist/extractors/tokenUsage.js +1 -0
- package/dist/formatters/sessionDump.d.ts +10 -2
- package/dist/formatters/sessionDump.js +45 -23
- package/dist/index.d.ts +7 -3
- package/dist/index.js +31 -10
- package/dist/node.d.ts +2 -0
- package/dist/node.js +8 -2
- package/dist/parsers/codexParser.d.ts +22 -2
- package/dist/parsers/codexParser.js +64 -5
- package/dist/parsers/subagentScanner.d.ts +9 -0
- package/dist/parsers/subagentScanner.js +45 -12
- package/dist/parsers/subagentStatsCache.d.ts +17 -0
- package/dist/parsers/subagentStatsCache.js +82 -0
- package/dist/parsers/subagentTraceParser.js +19 -10
- package/dist/providers/claudeCode.js +8 -41
- package/dist/providers/codex.js +28 -14
- package/dist/providers/codexDatabase.d.ts +16 -1
- package/dist/providers/codexDatabase.js +49 -1
- package/dist/providers/openCode.js +30 -4
- package/dist/report/htmlReportGenerator.js +33 -11
- package/dist/report/sessionReportInputs.d.ts +3 -1
- package/dist/report/sessionReportInputs.js +2 -0
- package/dist/report/types.d.ts +5 -0
- package/dist/schemas/sessionEvent.d.ts +30 -6
- package/dist/schemas/sessionEvent.js +7 -1
- package/dist/schemas/stateFile.d.ts +2 -0
- package/dist/schemas/stateFile.js +1 -0
- package/dist/sessionTokenTotals.d.ts +46 -0
- package/dist/sessionTokenTotals.js +138 -0
- package/dist/stateFile.d.ts +7 -0
- package/dist/tokenSummary.d.ts +27 -1
- package/dist/tokenSummary.js +50 -3
- package/dist/types/codex.d.ts +4 -0
- package/dist/types/sessionEvent.d.ts +22 -0
- package/dist/usage/claudeUsageDedupe.d.ts +53 -0
- package/dist/usage/claudeUsageDedupe.js +195 -0
- package/dist/usage/subagentUsage.d.ts +13 -0
- package/dist/usage/subagentUsage.js +21 -0
- package/dist/usage/usageEvents.d.ts +11 -2
- package/dist/usage/usageEvents.js +79 -8
- package/dist/watchers/eventBridge.js +5 -0
- package/dist/watchers/jsonlWatcher.d.ts +5 -0
- package/dist/watchers/jsonlWatcher.js +40 -5
- package/dist/watchers/types.d.ts +5 -0
- package/package.json +1 -1
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Accumulate normalized usage into a subagent's token fields so every
|
|
3
|
+
* provider's `scanSubagents()` reports the same four buckets and the same
|
|
4
|
+
* cache-inclusive total as `summarizeTokens()`.
|
|
5
|
+
*
|
|
6
|
+
* Browser-safe: no Node imports.
|
|
7
|
+
*
|
|
8
|
+
* @module usage/subagentUsage
|
|
9
|
+
*/
|
|
10
|
+
import type { NormalizedUsage } from '../usageNormalization';
|
|
11
|
+
import type { SubagentStats } from '../types/sessionEvent';
|
|
12
|
+
/** Add one usage record (a call or a correction) to a subagent's token totals. */
|
|
13
|
+
export declare function addUsageToSubagent(stats: SubagentStats, usage: NormalizedUsage): void;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Accumulate normalized usage into a subagent's token fields so every
|
|
4
|
+
* provider's `scanSubagents()` reports the same four buckets and the same
|
|
5
|
+
* cache-inclusive total as `summarizeTokens()`.
|
|
6
|
+
*
|
|
7
|
+
* Browser-safe: no Node imports.
|
|
8
|
+
*
|
|
9
|
+
* @module usage/subagentUsage
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.addUsageToSubagent = addUsageToSubagent;
|
|
13
|
+
/** Add one usage record (a call or a correction) to a subagent's token totals. */
|
|
14
|
+
function addUsageToSubagent(stats, usage) {
|
|
15
|
+
stats.inputTokens += usage.uncachedInputTokens;
|
|
16
|
+
stats.outputTokens += usage.outputTokens;
|
|
17
|
+
stats.cacheReadTokens = (stats.cacheReadTokens ?? 0) + usage.cacheReadTokens;
|
|
18
|
+
stats.cacheWriteTokens = (stats.cacheWriteTokens ?? 0) + usage.cacheWriteTokens;
|
|
19
|
+
stats.reasoningTokens = (stats.reasoningTokens ?? 0) + usage.reasoningTokens;
|
|
20
|
+
stats.totalTokens = (stats.totalTokens ?? 0) + usage.totalTokens;
|
|
21
|
+
}
|
|
@@ -10,6 +10,11 @@
|
|
|
10
10
|
* catalog refresh never leaves stale costs behind. Cache files are touched on
|
|
11
11
|
* every hit and pruned least-recently-used, once per collection.
|
|
12
12
|
*
|
|
13
|
+
* A Claude Code session's subagents write their own transcripts under
|
|
14
|
+
* `<sessionId>/subagents/`; their usage is attributed to the parent session
|
|
15
|
+
* and their sizes and mtimes join the fingerprint. (Codex spawned subagents
|
|
16
|
+
* are top-level rollouts, already listed as sessions of their own.)
|
|
17
|
+
*
|
|
13
18
|
* Node-only: reads session files and the cache directory.
|
|
14
19
|
*
|
|
15
20
|
* @module usage/usageEvents
|
|
@@ -17,8 +22,12 @@
|
|
|
17
22
|
import type { ProviderId, SessionProviderBase, SessionProviderDiagnostic } from '../providers/types';
|
|
18
23
|
import type { TokenTotals } from '../types/historicalData';
|
|
19
24
|
import type { PricingProvenance } from '../usageNormalization';
|
|
20
|
-
/**
|
|
21
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Bump when the cached record shape or the counting rules change; older files
|
|
27
|
+
* are re-read. v2: Claude split lines and duplicate Codex `token_count` events
|
|
28
|
+
* are counted once, and Claude subagent transcripts are included.
|
|
29
|
+
*/
|
|
30
|
+
export declare const USAGE_CACHE_VERSION = 2;
|
|
22
31
|
/**
|
|
23
32
|
* Most-recently-used cache files kept on disk. Sized for a busy month of
|
|
24
33
|
* sessions (files are a few KB each); a collection larger than this still
|
|
@@ -11,6 +11,11 @@
|
|
|
11
11
|
* catalog refresh never leaves stale costs behind. Cache files are touched on
|
|
12
12
|
* every hit and pruned least-recently-used, once per collection.
|
|
13
13
|
*
|
|
14
|
+
* A Claude Code session's subagents write their own transcripts under
|
|
15
|
+
* `<sessionId>/subagents/`; their usage is attributed to the parent session
|
|
16
|
+
* and their sizes and mtimes join the fingerprint. (Codex spawned subagents
|
|
17
|
+
* are top-level rollouts, already listed as sessions of their own.)
|
|
18
|
+
*
|
|
14
19
|
* Node-only: reads session files and the cache directory.
|
|
15
20
|
*
|
|
16
21
|
* @module usage/usageEvents
|
|
@@ -59,8 +64,12 @@ const paths_1 = require("../paths");
|
|
|
59
64
|
const sessionPreviews_1 = require("../sessionPreviews");
|
|
60
65
|
const usageNormalization_1 = require("../usageNormalization");
|
|
61
66
|
const atomic_1 = require("../writers/atomic");
|
|
62
|
-
/**
|
|
63
|
-
|
|
67
|
+
/**
|
|
68
|
+
* Bump when the cached record shape or the counting rules change; older files
|
|
69
|
+
* are re-read. v2: Claude split lines and duplicate Codex `token_count` events
|
|
70
|
+
* are counted once, and Claude subagent transcripts are included.
|
|
71
|
+
*/
|
|
72
|
+
exports.USAGE_CACHE_VERSION = 2;
|
|
64
73
|
/**
|
|
65
74
|
* Most-recently-used cache files kept on disk. Sized for a busy month of
|
|
66
75
|
* sessions (files are a few KB each); a collection larger than this still
|
|
@@ -188,20 +197,81 @@ function priceCachedEvent(cached, provider, sessionId, project) {
|
|
|
188
197
|
costProvenance: priced.source,
|
|
189
198
|
};
|
|
190
199
|
}
|
|
191
|
-
|
|
192
|
-
|
|
200
|
+
const CLAUDE_AGENT_FILE = /^agent-.+\.jsonl$/;
|
|
201
|
+
/** Claude Code subagent transcripts of a session, sorted by name. */
|
|
202
|
+
function claudeSubagentFiles(preview) {
|
|
203
|
+
if (preview.provider !== 'claude-code')
|
|
204
|
+
return [];
|
|
205
|
+
const dir = path.join(path.dirname(preview.filePath), preview.sessionId, 'subagents');
|
|
206
|
+
let names;
|
|
207
|
+
try {
|
|
208
|
+
names = fs.readdirSync(dir).filter((name) => CLAUDE_AGENT_FILE.test(name));
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
return [];
|
|
212
|
+
}
|
|
213
|
+
const files = [];
|
|
214
|
+
for (const name of names.sort()) {
|
|
215
|
+
try {
|
|
216
|
+
const stat = fs.statSync(path.join(dir, name));
|
|
217
|
+
files.push({
|
|
218
|
+
path: path.join(dir, name),
|
|
219
|
+
name,
|
|
220
|
+
sizeBytes: stat.size,
|
|
221
|
+
modifiedAt: stat.mtimeMs,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
// Removed between listing and stat; the next collection re-reads.
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return files;
|
|
229
|
+
}
|
|
230
|
+
function sessionFingerprint(preview, subagents) {
|
|
231
|
+
const base = `${preview.sizeBytes}:${preview.modifiedAt}`;
|
|
232
|
+
if (subagents.length === 0)
|
|
233
|
+
return base;
|
|
234
|
+
return `${base}|${subagents.map((f) => `${f.name}:${f.sizeBytes}:${f.modifiedAt}`).join(',')}`;
|
|
235
|
+
}
|
|
236
|
+
function readTranscriptUsage(provider, filePath, cached) {
|
|
237
|
+
const reader = provider.createReader(filePath);
|
|
193
238
|
const events = reader.readAll();
|
|
194
239
|
reader.flush();
|
|
195
|
-
|
|
240
|
+
// A correction tops up the call its message already recorded, so it merges
|
|
241
|
+
// into that record instead of counting as another call.
|
|
242
|
+
const byMessageId = new Map();
|
|
196
243
|
for (const event of events) {
|
|
197
244
|
const usage = (0, usageNormalization_1.extractNormalizedUsage)(event);
|
|
198
245
|
if (!usage)
|
|
199
246
|
continue;
|
|
247
|
+
const messageId = event.message?.id;
|
|
248
|
+
const target = event.message?.usageKind === 'correction' && messageId
|
|
249
|
+
? byMessageId.get(messageId)
|
|
250
|
+
: undefined;
|
|
251
|
+
if (target) {
|
|
252
|
+
target.i += usage.uncachedInputTokens;
|
|
253
|
+
target.o += usage.outputTokens;
|
|
254
|
+
target.cw += usage.cacheWriteTokens;
|
|
255
|
+
target.cr += usage.cacheReadTokens;
|
|
256
|
+
target.bo += usage.billableOutputTokens;
|
|
257
|
+
target.tt += usage.totalTokens;
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
200
260
|
const timestamp = Date.parse(event.timestamp);
|
|
201
261
|
if (!Number.isFinite(timestamp))
|
|
202
262
|
continue;
|
|
203
|
-
|
|
263
|
+
const record = cachedEventFromUsage(usage, timestamp, event.message?.model ?? usage.model ?? 'unknown');
|
|
264
|
+
cached.push(record);
|
|
265
|
+
if (messageId)
|
|
266
|
+
byMessageId.set(messageId, record);
|
|
204
267
|
}
|
|
268
|
+
}
|
|
269
|
+
function readSessionUsage(provider, preview, subagents) {
|
|
270
|
+
const cached = [];
|
|
271
|
+
readTranscriptUsage(provider, preview.filePath, cached);
|
|
272
|
+
for (const file of subagents)
|
|
273
|
+
readTranscriptUsage(provider, file.path, cached);
|
|
274
|
+
cached.sort((a, b) => a.t - b.t);
|
|
205
275
|
return cached;
|
|
206
276
|
}
|
|
207
277
|
function yieldToEventLoop() {
|
|
@@ -239,7 +309,8 @@ async function collectUsageEvents(options) {
|
|
|
239
309
|
const provider = providerById.get(preview.provider);
|
|
240
310
|
if (!provider)
|
|
241
311
|
continue;
|
|
242
|
-
const
|
|
312
|
+
const subagentFiles = claudeSubagentFiles(preview);
|
|
313
|
+
const fingerprint = sessionFingerprint(preview, subagentFiles);
|
|
243
314
|
const filePath = cacheFilePath(cacheDir, preview.provider, preview.sessionId);
|
|
244
315
|
let cachedEvents = null;
|
|
245
316
|
let project = preview.workspacePath;
|
|
@@ -257,7 +328,7 @@ async function collectUsageEvents(options) {
|
|
|
257
328
|
if (!cachedEvents) {
|
|
258
329
|
cacheMisses += 1;
|
|
259
330
|
try {
|
|
260
|
-
cachedEvents = readSessionUsage(provider, preview);
|
|
331
|
+
cachedEvents = readSessionUsage(provider, preview, subagentFiles);
|
|
261
332
|
}
|
|
262
333
|
catch (error) {
|
|
263
334
|
const diagnostic = {
|
|
@@ -29,6 +29,7 @@ function toFollowEvents(event, providerId) {
|
|
|
29
29
|
? { read: usage.cache_read_input_tokens || 0, write: usage.cache_creation_input_tokens || 0 }
|
|
30
30
|
: undefined;
|
|
31
31
|
const cost = usage?.reported_cost;
|
|
32
|
+
const usageKind = usage ? event.message?.usageKind : undefined;
|
|
32
33
|
const model = event.message?.model;
|
|
33
34
|
const rateLimits = event.rateLimits;
|
|
34
35
|
switch (event.type) {
|
|
@@ -94,6 +95,7 @@ function toFollowEvents(event, providerId) {
|
|
|
94
95
|
summary: text || '(thinking...)',
|
|
95
96
|
tokens,
|
|
96
97
|
cacheTokens,
|
|
98
|
+
...(usageKind ? { usageKind } : {}),
|
|
97
99
|
cost,
|
|
98
100
|
model,
|
|
99
101
|
raw: event,
|
|
@@ -104,6 +106,8 @@ function toFollowEvents(event, providerId) {
|
|
|
104
106
|
const last = events[events.length - 1];
|
|
105
107
|
last.tokens = tokens;
|
|
106
108
|
last.cacheTokens = cacheTokens;
|
|
109
|
+
if (usageKind)
|
|
110
|
+
last.usageKind = usageKind;
|
|
107
111
|
last.cost = cost;
|
|
108
112
|
}
|
|
109
113
|
break;
|
|
@@ -158,6 +162,7 @@ function toFollowEvents(event, providerId) {
|
|
|
158
162
|
summary: label && text ? `${label}: ${text}` : summary,
|
|
159
163
|
tokens,
|
|
160
164
|
cacheTokens,
|
|
165
|
+
...(usageKind ? { usageKind } : {}),
|
|
161
166
|
cost,
|
|
162
167
|
model,
|
|
163
168
|
rateLimits,
|
|
@@ -11,6 +11,9 @@ export declare class JsonlSessionWatcher implements SessionWatcher {
|
|
|
11
11
|
private tail;
|
|
12
12
|
private startOffset;
|
|
13
13
|
private codexInPlanMode;
|
|
14
|
+
private readonly claudeUsageDeduper;
|
|
15
|
+
/** Last Codex cumulative usage seen; repeated `token_count` events carry the same value. */
|
|
16
|
+
private codexPrevTotal;
|
|
14
17
|
constructor(providerId: ProviderId, sessionPath: string, callbacks: SessionWatcherCallbacks);
|
|
15
18
|
get isActive(): boolean;
|
|
16
19
|
/** Seek to a committed byte offset before starting replay. */
|
|
@@ -20,5 +23,7 @@ export declare class JsonlSessionWatcher implements SessionWatcher {
|
|
|
20
23
|
start(replay: boolean): void;
|
|
21
24
|
stop(): void;
|
|
22
25
|
private handleRawEvent;
|
|
26
|
+
/** One call's usage from a token_count `info`, skipping duplicate events. */
|
|
27
|
+
private codexCallUsage;
|
|
23
28
|
private normalizeCodexEvent;
|
|
24
29
|
}
|
|
@@ -8,12 +8,29 @@ exports.JsonlSessionWatcher = void 0;
|
|
|
8
8
|
const jsonlTail_1 = require("./jsonlTail");
|
|
9
9
|
const codexParser_1 = require("../parsers/codexParser");
|
|
10
10
|
const toolSummary_1 = require("../formatters/toolSummary");
|
|
11
|
+
const claudeUsageDedupe_1 = require("../usage/claudeUsageDedupe");
|
|
11
12
|
// ── Normalizers ──
|
|
12
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Split lines of one Claude response repeat its usage; run the raw usage
|
|
15
|
+
* through the shared deduper so each response is counted once (last copy wins).
|
|
16
|
+
*/
|
|
17
|
+
function dedupedClaudeUsage(raw, deduper) {
|
|
18
|
+
if (!raw.message?.usage)
|
|
19
|
+
return { usage: undefined, usageKind: undefined };
|
|
20
|
+
const event = deduper.apply((0, claudeUsageDedupe_1.normalizeClaudeUsage)({
|
|
21
|
+
type: 'assistant',
|
|
22
|
+
timestamp: raw.timestamp || '',
|
|
23
|
+
message: raw.message,
|
|
24
|
+
}));
|
|
25
|
+
return { usage: event.message?.usage, usageKind: event.message?.usageKind };
|
|
26
|
+
}
|
|
27
|
+
function normalizeClaudeCodeEvent(raw, deduper) {
|
|
13
28
|
const events = [];
|
|
14
29
|
const ts = raw.timestamp || new Date().toISOString();
|
|
15
30
|
const permissionMode = raw.permissionMode;
|
|
16
|
-
const usage = raw.
|
|
31
|
+
const { usage, usageKind } = raw.type === 'assistant'
|
|
32
|
+
? dedupedClaudeUsage(raw, deduper)
|
|
33
|
+
: { usage: undefined, usageKind: undefined };
|
|
17
34
|
const tokens = usage
|
|
18
35
|
? { input: usage.input_tokens || 0, output: usage.output_tokens || 0 }
|
|
19
36
|
: undefined;
|
|
@@ -83,6 +100,7 @@ function normalizeClaudeCodeEvent(raw) {
|
|
|
83
100
|
summary: text || '(thinking...)',
|
|
84
101
|
tokens,
|
|
85
102
|
cacheTokens,
|
|
103
|
+
...(usageKind ? { usageKind } : {}),
|
|
86
104
|
cost,
|
|
87
105
|
model,
|
|
88
106
|
raw,
|
|
@@ -93,6 +111,8 @@ function normalizeClaudeCodeEvent(raw) {
|
|
|
93
111
|
const last = events[events.length - 1];
|
|
94
112
|
last.tokens = tokens;
|
|
95
113
|
last.cacheTokens = cacheTokens;
|
|
114
|
+
if (usageKind)
|
|
115
|
+
last.usageKind = usageKind;
|
|
96
116
|
last.cost = cost;
|
|
97
117
|
}
|
|
98
118
|
}
|
|
@@ -190,6 +210,9 @@ class JsonlSessionWatcher {
|
|
|
190
210
|
tail;
|
|
191
211
|
startOffset;
|
|
192
212
|
codexInPlanMode = false;
|
|
213
|
+
claudeUsageDeduper = new claudeUsageDedupe_1.ClaudeUsageDeduper();
|
|
214
|
+
/** Last Codex cumulative usage seen; repeated `token_count` events carry the same value. */
|
|
215
|
+
codexPrevTotal;
|
|
193
216
|
constructor(providerId, sessionPath, callbacks) {
|
|
194
217
|
this.providerId = providerId;
|
|
195
218
|
this.sessionPath = sessionPath;
|
|
@@ -223,17 +246,25 @@ class JsonlSessionWatcher {
|
|
|
223
246
|
stop() {
|
|
224
247
|
this.tail?.stop();
|
|
225
248
|
this.codexInPlanMode = false;
|
|
249
|
+
this.claudeUsageDeduper.reset();
|
|
250
|
+
this.codexPrevTotal = undefined;
|
|
226
251
|
}
|
|
227
252
|
handleRawEvent(event) {
|
|
228
253
|
// For codex, raw events don't match RawSessionEvent shape exactly, but
|
|
229
254
|
// JsonlParser parses any JSON object. Cast to Record for codex normalizer.
|
|
230
255
|
const followEvents = this.providerId === 'codex'
|
|
231
256
|
? this.normalizeCodexEvent(event)
|
|
232
|
-
: normalizeClaudeCodeEvent(event);
|
|
257
|
+
: normalizeClaudeCodeEvent(event, this.claudeUsageDeduper);
|
|
233
258
|
for (const fe of followEvents) {
|
|
234
259
|
this.callbacks.onEvent(fe);
|
|
235
260
|
}
|
|
236
261
|
}
|
|
262
|
+
/** One call's usage from a token_count `info`, skipping duplicate events. */
|
|
263
|
+
codexCallUsage(info) {
|
|
264
|
+
const resolved = (0, codexParser_1.resolveCodexCallUsage)(info, this.codexPrevTotal ?? null);
|
|
265
|
+
this.codexPrevTotal = resolved.total ?? undefined;
|
|
266
|
+
return resolved.usage;
|
|
267
|
+
}
|
|
237
268
|
normalizeCodexEvent(raw) {
|
|
238
269
|
const events = [];
|
|
239
270
|
const ts = raw.timestamp || new Date().toISOString();
|
|
@@ -332,7 +363,7 @@ class JsonlSessionWatcher {
|
|
|
332
363
|
const evtType = payload?.type;
|
|
333
364
|
if (evtType === 'token_count') {
|
|
334
365
|
const info = payload?.info;
|
|
335
|
-
const usage = (info
|
|
366
|
+
const usage = this.codexCallUsage(info);
|
|
336
367
|
const rl = payload?.rate_limits;
|
|
337
368
|
const rateLimits = rl ? extractRateLimits(rl) : undefined;
|
|
338
369
|
if (usage || rateLimits) {
|
|
@@ -343,12 +374,16 @@ class JsonlSessionWatcher {
|
|
|
343
374
|
summary: usage
|
|
344
375
|
? `Tokens: ${usage.input_tokens ?? 0} in / ${usage.output_tokens ?? 0} out`
|
|
345
376
|
: 'Rate limits updated',
|
|
377
|
+
// Codex input includes cached input; FollowEvent buckets are disjoint.
|
|
346
378
|
tokens: usage
|
|
347
379
|
? {
|
|
348
|
-
input: usage.input_tokens || 0,
|
|
380
|
+
input: Math.max(0, (usage.input_tokens || 0) - (usage.cached_input_tokens || 0)),
|
|
349
381
|
output: usage.output_tokens || 0,
|
|
350
382
|
}
|
|
351
383
|
: undefined,
|
|
384
|
+
cacheTokens: usage?.cached_input_tokens
|
|
385
|
+
? { read: usage.cached_input_tokens, write: 0 }
|
|
386
|
+
: undefined,
|
|
352
387
|
rateLimits,
|
|
353
388
|
raw,
|
|
354
389
|
});
|
package/dist/watchers/types.d.ts
CHANGED
|
@@ -18,6 +18,11 @@ export interface FollowEvent {
|
|
|
18
18
|
read: number;
|
|
19
19
|
write: number;
|
|
20
20
|
};
|
|
21
|
+
/**
|
|
22
|
+
* `'correction'` marks tokens that top up a response already counted (a later
|
|
23
|
+
* split line reported more). Absent means a regular call.
|
|
24
|
+
*/
|
|
25
|
+
usageKind?: 'call' | 'correction';
|
|
21
26
|
cost?: number;
|
|
22
27
|
toolName?: string;
|
|
23
28
|
toolInput?: string;
|