sidekick-shared 0.18.4 → 0.19.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/README.md +23 -2
- package/dist/accounts.d.ts +1 -0
- package/dist/aggregation/EventAggregator.js +26 -11
- package/dist/browser.d.ts +2 -0
- package/dist/browser.js +5 -1
- package/dist/codexProfiles.d.ts +3 -2
- package/dist/codexProfiles.js +382 -52
- package/dist/context/sessionContext.d.ts +99 -0
- package/dist/context/sessionContext.js +523 -0
- package/dist/ensureDefaultAccounts.js +6 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +9 -3
- package/dist/modelContext.js +3 -1
- package/dist/modelInfo.js +69 -9
- package/dist/parsers/codexParser.d.ts +2 -0
- package/dist/parsers/codexParser.js +129 -63
- package/dist/providers/claudeCode.d.ts +2 -0
- package/dist/providers/claudeCode.js +4 -0
- package/dist/providers/codex.d.ts +2 -0
- package/dist/providers/codex.js +125 -91
- package/dist/providers/openCode.d.ts +2 -0
- package/dist/providers/openCode.js +4 -0
- package/dist/providers/types.d.ts +4 -0
- package/dist/report/htmlReportGenerator.js +3 -0
- package/dist/report/index.d.ts +1 -1
- package/dist/report/index.js +2 -1
- package/dist/report/transcriptParser.d.ts +3 -0
- package/dist/report/transcriptParser.js +25 -3
- package/dist/report/types.d.ts +2 -0
- package/dist/schemas/sessionEvent.d.ts +15 -0
- package/dist/schemas/sessionEvent.js +14 -1
- package/dist/types/sessionEvent.d.ts +16 -1
- package/dist/watchers/eventBridge.js +24 -0
- package/dist/watchers/factory.d.ts +2 -2
- package/dist/watchers/factory.js +7 -5
- package/dist/watchers/providerReaderWatcher.d.ts +27 -0
- package/dist/watchers/providerReaderWatcher.js +148 -0
- package/package.json +1 -1
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Provider-neutral session context evidence projection.
|
|
4
|
+
*
|
|
5
|
+
* Converts canonical SessionEvent streams into a compact manifest suitable for
|
|
6
|
+
* UI surfaces that need to explain what an assistant/provider has seen.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.calculateSessionContextPressure = calculateSessionContextPressure;
|
|
10
|
+
exports.buildSessionContextSnapshot = buildSessionContextSnapshot;
|
|
11
|
+
exports.createSessionContextProjector = createSessionContextProjector;
|
|
12
|
+
exports.readSessionContextSnapshot = readSessionContextSnapshot;
|
|
13
|
+
const EventAggregator_1 = require("../aggregation/EventAggregator");
|
|
14
|
+
const modelContext_1 = require("../modelContext");
|
|
15
|
+
const DEFAULT_CONTEXT_SOURCE_LIMIT = 200;
|
|
16
|
+
const DEFAULT_SNIPPET_MAX_CHARS = 240;
|
|
17
|
+
const DEFAULT_BODY_MAX_CHARS = 5000;
|
|
18
|
+
const MEDIUM_PRESSURE_RATIO = 0.6;
|
|
19
|
+
const HIGH_PRESSURE_RATIO = 0.8;
|
|
20
|
+
const EMPTY_ATTRIBUTION = {
|
|
21
|
+
systemPrompt: 0,
|
|
22
|
+
userMessages: 0,
|
|
23
|
+
assistantResponses: 0,
|
|
24
|
+
toolInputs: 0,
|
|
25
|
+
toolOutputs: 0,
|
|
26
|
+
thinking: 0,
|
|
27
|
+
other: 0,
|
|
28
|
+
};
|
|
29
|
+
function calculateSessionContextPressure(contextTokens, contextWindow) {
|
|
30
|
+
if (!Number.isFinite(contextTokens) || contextTokens <= 0) {
|
|
31
|
+
return { pressure: 'low', ratio: 0 };
|
|
32
|
+
}
|
|
33
|
+
if (!Number.isFinite(contextWindow) || contextWindow <= 0) {
|
|
34
|
+
return { pressure: 'low', ratio: 0 };
|
|
35
|
+
}
|
|
36
|
+
const ratio = Math.max(0, Math.min(1, contextTokens / contextWindow));
|
|
37
|
+
if (ratio >= HIGH_PRESSURE_RATIO)
|
|
38
|
+
return { pressure: 'high', ratio };
|
|
39
|
+
if (ratio >= MEDIUM_PRESSURE_RATIO)
|
|
40
|
+
return { pressure: 'medium', ratio };
|
|
41
|
+
return { pressure: 'low', ratio };
|
|
42
|
+
}
|
|
43
|
+
function buildSessionContextSnapshot(events, options = {}) {
|
|
44
|
+
const providerId = options.providerId;
|
|
45
|
+
const aggregator = new EventAggregator_1.EventAggregator({
|
|
46
|
+
providerId,
|
|
47
|
+
computeContextSize: options.computeContextSize,
|
|
48
|
+
});
|
|
49
|
+
const sourceState = createSourceExtractionState(options);
|
|
50
|
+
let lastPermissionMode;
|
|
51
|
+
let lastRateLimits;
|
|
52
|
+
for (const event of events) {
|
|
53
|
+
aggregator.processEvent(event);
|
|
54
|
+
extractSourcesFromEvent(event, sourceState);
|
|
55
|
+
if (event.permissionMode)
|
|
56
|
+
lastPermissionMode = event.permissionMode;
|
|
57
|
+
if (event.rateLimits)
|
|
58
|
+
lastRateLimits = event.rateLimits;
|
|
59
|
+
}
|
|
60
|
+
const metrics = aggregator.getMetrics();
|
|
61
|
+
const model = options.model ?? metrics.currentModel ?? metrics.modelStats[0]?.model;
|
|
62
|
+
const contextWindow = options.contextWindow ??
|
|
63
|
+
options.contextWindowForModel?.(model) ??
|
|
64
|
+
(0, modelContext_1.getModelContextWindowSize)(model);
|
|
65
|
+
const allSources = sourceState.sources;
|
|
66
|
+
const limitedSources = limitSources(allSources, options.sourceLimit ?? DEFAULT_CONTEXT_SOURCE_LIMIT);
|
|
67
|
+
const breakdown = buildLayerBreakdown(limitedSources);
|
|
68
|
+
const layers = breakdown.map(row => row.layer);
|
|
69
|
+
const sourceTokenTotal = allSources.reduce((sum, source) => sum + source.tokenEstimate, 0);
|
|
70
|
+
const contextTokens = metrics.currentContextSize > 0 ? metrics.currentContextSize : sourceTokenTotal;
|
|
71
|
+
const { pressure, ratio } = calculateSessionContextPressure(contextTokens, contextWindow);
|
|
72
|
+
return {
|
|
73
|
+
schemaVersion: 1,
|
|
74
|
+
providerId,
|
|
75
|
+
sessionId: options.sessionId,
|
|
76
|
+
sessionPath: options.sessionPath,
|
|
77
|
+
model,
|
|
78
|
+
contextWindow,
|
|
79
|
+
contextTokens,
|
|
80
|
+
pressure,
|
|
81
|
+
pressureRatio: ratio,
|
|
82
|
+
layers,
|
|
83
|
+
breakdown,
|
|
84
|
+
sources: limitedSources,
|
|
85
|
+
capabilities: {
|
|
86
|
+
providerId,
|
|
87
|
+
providerLabel: options.providerLabel ?? providerLabel(providerId),
|
|
88
|
+
model,
|
|
89
|
+
observedTools: [...sourceState.observedTools].sort((a, b) => a.localeCompare(b)),
|
|
90
|
+
mcpServers: [...sourceState.mcpServers].sort((a, b) => a.localeCompare(b)),
|
|
91
|
+
permissionMode: lastPermissionMode,
|
|
92
|
+
rateLimits: lastRateLimits,
|
|
93
|
+
},
|
|
94
|
+
attribution: metrics.contextAttribution ?? { ...EMPTY_ATTRIBUTION },
|
|
95
|
+
tokens: metrics.tokens,
|
|
96
|
+
compactionCount: metrics.compactionCount,
|
|
97
|
+
compactionEvents: metrics.compactionEvents,
|
|
98
|
+
truncationCount: metrics.truncationCount,
|
|
99
|
+
truncationEvents: metrics.truncationEvents,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function createSessionContextProjector(options = {}) {
|
|
103
|
+
let events = [];
|
|
104
|
+
return {
|
|
105
|
+
processEvent(event) {
|
|
106
|
+
events.push(event);
|
|
107
|
+
return buildSessionContextSnapshot(events, options);
|
|
108
|
+
},
|
|
109
|
+
processEvents(newEvents) {
|
|
110
|
+
events.push(...newEvents);
|
|
111
|
+
return buildSessionContextSnapshot(events, options);
|
|
112
|
+
},
|
|
113
|
+
getSnapshot() {
|
|
114
|
+
return buildSessionContextSnapshot(events, options);
|
|
115
|
+
},
|
|
116
|
+
reset() {
|
|
117
|
+
events = [];
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function readSessionContextSnapshot(provider, sessionPath, options = {}) {
|
|
122
|
+
const reader = provider.createReader(sessionPath);
|
|
123
|
+
const events = reader.readAll();
|
|
124
|
+
const model = options.model ?? latestModel(events);
|
|
125
|
+
return buildSessionContextSnapshot(events, {
|
|
126
|
+
...options,
|
|
127
|
+
providerId: provider.id,
|
|
128
|
+
providerLabel: provider.displayName,
|
|
129
|
+
sessionId: provider.getSessionId(sessionPath),
|
|
130
|
+
sessionPath,
|
|
131
|
+
model,
|
|
132
|
+
contextWindow: options.contextWindow ?? provider.getContextWindowLimit?.(model),
|
|
133
|
+
computeContextSize: provider.computeContextSize
|
|
134
|
+
? (usage) => provider.computeContextSize(usage)
|
|
135
|
+
: undefined,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
function createSourceExtractionState(options) {
|
|
139
|
+
return {
|
|
140
|
+
options,
|
|
141
|
+
sources: [],
|
|
142
|
+
observedTools: new Set(),
|
|
143
|
+
mcpServers: new Set(),
|
|
144
|
+
counter: 0,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
function extractSourcesFromEvent(event, state) {
|
|
148
|
+
switch (event.type) {
|
|
149
|
+
case 'system':
|
|
150
|
+
extractSystemSource(event, state);
|
|
151
|
+
break;
|
|
152
|
+
case 'user':
|
|
153
|
+
extractUserSources(event, state);
|
|
154
|
+
break;
|
|
155
|
+
case 'assistant':
|
|
156
|
+
extractAssistantSources(event, state);
|
|
157
|
+
break;
|
|
158
|
+
case 'tool_use':
|
|
159
|
+
if (event.tool) {
|
|
160
|
+
addToolInputSource(event, state, event.tool.name, event.tool.input, undefined);
|
|
161
|
+
}
|
|
162
|
+
break;
|
|
163
|
+
case 'tool_result':
|
|
164
|
+
addSource(state, {
|
|
165
|
+
event,
|
|
166
|
+
layer: 'tool outputs',
|
|
167
|
+
sourceType: event.result?.is_error ? 'error' : 'tool_output',
|
|
168
|
+
title: event.result?.is_error ? 'Tool error' : 'Tool result',
|
|
169
|
+
sourceRef: event.result?.tool_use_id,
|
|
170
|
+
text: stringifyValue(event.result?.output),
|
|
171
|
+
metadata: { toolUseId: event.result?.tool_use_id },
|
|
172
|
+
});
|
|
173
|
+
break;
|
|
174
|
+
case 'summary':
|
|
175
|
+
addSource(state, {
|
|
176
|
+
event,
|
|
177
|
+
layer: 'summary',
|
|
178
|
+
sourceType: 'summary',
|
|
179
|
+
title: 'Context summary',
|
|
180
|
+
text: extractText(event.message.content) || 'Context compacted',
|
|
181
|
+
});
|
|
182
|
+
break;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function extractSystemSource(event, state) {
|
|
186
|
+
const text = extractText(event.message.content);
|
|
187
|
+
const label = event.message.sourceLabel ?? event.message.role ?? 'system';
|
|
188
|
+
const usage = event.message.usage;
|
|
189
|
+
if (text) {
|
|
190
|
+
addSource(state, {
|
|
191
|
+
event,
|
|
192
|
+
layer: 'system',
|
|
193
|
+
sourceType: 'system',
|
|
194
|
+
title: label,
|
|
195
|
+
sourceRef: event.message.id,
|
|
196
|
+
text,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
if (usage || event.rateLimits) {
|
|
200
|
+
addSource(state, {
|
|
201
|
+
event,
|
|
202
|
+
layer: 'runtime',
|
|
203
|
+
sourceType: event.rateLimits ? 'rate_limit' : 'runtime',
|
|
204
|
+
title: event.rateLimits ? 'Runtime usage and rate limits' : 'Runtime usage',
|
|
205
|
+
sourceRef: event.message.id,
|
|
206
|
+
text: describeUsage(usage, event.rateLimits),
|
|
207
|
+
metadata: {
|
|
208
|
+
usage,
|
|
209
|
+
rateLimits: event.rateLimits,
|
|
210
|
+
},
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
function extractUserSources(event, state) {
|
|
215
|
+
const content = event.message.content;
|
|
216
|
+
if (Array.isArray(content)) {
|
|
217
|
+
for (const block of content) {
|
|
218
|
+
if (block.type === 'tool_result') {
|
|
219
|
+
const isError = block.is_error === true;
|
|
220
|
+
addSource(state, {
|
|
221
|
+
event,
|
|
222
|
+
layer: 'tool outputs',
|
|
223
|
+
sourceType: isError ? 'error' : 'tool_output',
|
|
224
|
+
title: isError ? 'Tool error' : 'Tool result',
|
|
225
|
+
sourceRef: stringValue(block.tool_use_id),
|
|
226
|
+
text: stringifyValue(block.content),
|
|
227
|
+
metadata: {
|
|
228
|
+
toolUseId: block.tool_use_id,
|
|
229
|
+
duration: block.duration,
|
|
230
|
+
},
|
|
231
|
+
});
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
const text = blockText(block);
|
|
235
|
+
if (text) {
|
|
236
|
+
addSource(state, {
|
|
237
|
+
event,
|
|
238
|
+
layer: 'user',
|
|
239
|
+
sourceType: 'user_prompt',
|
|
240
|
+
title: event.message.sourceLabel ?? 'User prompt',
|
|
241
|
+
sourceRef: event.message.id,
|
|
242
|
+
text,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
const text = extractText(content);
|
|
249
|
+
if (text) {
|
|
250
|
+
addSource(state, {
|
|
251
|
+
event,
|
|
252
|
+
layer: 'user',
|
|
253
|
+
sourceType: 'user_prompt',
|
|
254
|
+
title: event.message.sourceLabel ?? 'User prompt',
|
|
255
|
+
sourceRef: event.message.id,
|
|
256
|
+
text,
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
function extractAssistantSources(event, state) {
|
|
261
|
+
const content = event.message.content;
|
|
262
|
+
if (!Array.isArray(content)) {
|
|
263
|
+
const text = extractText(content);
|
|
264
|
+
if (text) {
|
|
265
|
+
addSource(state, {
|
|
266
|
+
event,
|
|
267
|
+
layer: 'assistant',
|
|
268
|
+
sourceType: 'assistant_response',
|
|
269
|
+
title: 'Assistant response',
|
|
270
|
+
sourceRef: event.message.id,
|
|
271
|
+
text,
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
for (const block of content) {
|
|
277
|
+
if (block.type === 'tool_use' && typeof block.name === 'string') {
|
|
278
|
+
addToolInputSource(event, state, block.name, isRecord(block.input) ? block.input : {}, stringValue(block.id));
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
if (block.type === 'thinking' || block.type === 'reasoning') {
|
|
282
|
+
const text = blockText(block);
|
|
283
|
+
if (text) {
|
|
284
|
+
addSource(state, {
|
|
285
|
+
event,
|
|
286
|
+
layer: 'thinking',
|
|
287
|
+
sourceType: 'thinking',
|
|
288
|
+
title: 'Reasoning',
|
|
289
|
+
sourceRef: event.message.id,
|
|
290
|
+
text,
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
const text = blockText(block);
|
|
296
|
+
if (text) {
|
|
297
|
+
addSource(state, {
|
|
298
|
+
event,
|
|
299
|
+
layer: 'assistant',
|
|
300
|
+
sourceType: 'assistant_response',
|
|
301
|
+
title: 'Assistant response',
|
|
302
|
+
sourceRef: event.message.id,
|
|
303
|
+
text,
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
function addToolInputSource(event, state, toolName, input, sourceRef) {
|
|
309
|
+
state.observedTools.add(toolName);
|
|
310
|
+
const mcpServer = inferMcpServer(toolName, input);
|
|
311
|
+
if (mcpServer)
|
|
312
|
+
state.mcpServers.add(mcpServer);
|
|
313
|
+
const sourceFile = inferSourceFile(input);
|
|
314
|
+
const command = inferCommand(input);
|
|
315
|
+
addSource(state, {
|
|
316
|
+
event,
|
|
317
|
+
layer: 'tool inputs',
|
|
318
|
+
sourceType: 'tool_input',
|
|
319
|
+
title: sourceFile ? `${toolName}: ${sourceFile}` : toolName,
|
|
320
|
+
sourceRef: sourceRef ?? command,
|
|
321
|
+
sourceFile,
|
|
322
|
+
toolName,
|
|
323
|
+
text: stringifyValue(input),
|
|
324
|
+
metadata: {
|
|
325
|
+
rawToolName: input._sidekickRawToolName,
|
|
326
|
+
mcpServer,
|
|
327
|
+
},
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
function addSource(state, seed) {
|
|
331
|
+
const cleanText = clean(seed.text);
|
|
332
|
+
if (!cleanText)
|
|
333
|
+
return;
|
|
334
|
+
const bodyText = seed.text.trim();
|
|
335
|
+
const snippetMaxChars = state.options.snippetMaxChars ?? DEFAULT_SNIPPET_MAX_CHARS;
|
|
336
|
+
const bodyMaxChars = state.options.bodyMaxChars ?? DEFAULT_BODY_MAX_CHARS;
|
|
337
|
+
const bodyInfo = state.options.includeBodies
|
|
338
|
+
? truncateWithInfo(bodyText, bodyMaxChars)
|
|
339
|
+
: undefined;
|
|
340
|
+
const tokenEstimate = estimateTokens(cleanText);
|
|
341
|
+
const metadata = {
|
|
342
|
+
...(seed.metadata ?? {}),
|
|
343
|
+
...(bodyInfo?.truncated ? { bodyTruncated: true, originalChars: bodyText.length } : {}),
|
|
344
|
+
};
|
|
345
|
+
state.sources.push({
|
|
346
|
+
id: `${state.options.sessionId ?? state.options.sessionPath ?? 'session'}:${state.counter++}`,
|
|
347
|
+
providerId: state.options.providerId,
|
|
348
|
+
sessionId: state.options.sessionId,
|
|
349
|
+
sessionPath: state.options.sessionPath,
|
|
350
|
+
eventType: seed.event.type,
|
|
351
|
+
timestamp: seed.event.timestamp,
|
|
352
|
+
layer: seed.layer,
|
|
353
|
+
sourceType: seed.sourceType,
|
|
354
|
+
title: seed.title,
|
|
355
|
+
sourceRef: seed.sourceRef,
|
|
356
|
+
sourceFile: seed.sourceFile,
|
|
357
|
+
toolName: seed.toolName,
|
|
358
|
+
score: seed.score,
|
|
359
|
+
tokenEstimate,
|
|
360
|
+
snippet: truncateClean(cleanText, snippetMaxChars),
|
|
361
|
+
body: bodyInfo?.text,
|
|
362
|
+
metadata: Object.keys(metadata).length > 0 ? metadata : undefined,
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
function buildLayerBreakdown(sources) {
|
|
366
|
+
const byLayer = new Map();
|
|
367
|
+
for (const source of sources) {
|
|
368
|
+
const row = byLayer.get(source.layer) ?? {
|
|
369
|
+
layer: source.layer,
|
|
370
|
+
tokenEstimate: 0,
|
|
371
|
+
sourceCount: 0,
|
|
372
|
+
};
|
|
373
|
+
row.tokenEstimate += source.tokenEstimate;
|
|
374
|
+
row.sourceCount++;
|
|
375
|
+
byLayer.set(source.layer, row);
|
|
376
|
+
}
|
|
377
|
+
return [...byLayer.values()].sort((a, b) => b.tokenEstimate - a.tokenEstimate);
|
|
378
|
+
}
|
|
379
|
+
function limitSources(sources, limit) {
|
|
380
|
+
if (!Number.isFinite(limit) || limit <= 0)
|
|
381
|
+
return [];
|
|
382
|
+
if (sources.length <= limit)
|
|
383
|
+
return [...sources];
|
|
384
|
+
const pinned = sources.filter(source => source.sourceType === 'system' ||
|
|
385
|
+
source.sourceType === 'runtime' ||
|
|
386
|
+
source.sourceType === 'rate_limit');
|
|
387
|
+
const pinnedLimit = Math.min(pinned.length, Math.max(1, Math.floor(limit / 4)));
|
|
388
|
+
const pinnedKept = pinned.slice(0, pinnedLimit);
|
|
389
|
+
const pinnedIds = new Set(pinnedKept.map(source => source.id));
|
|
390
|
+
const remaining = sources.filter(source => !pinnedIds.has(source.id));
|
|
391
|
+
const latest = remaining.slice(-(limit - pinnedKept.length));
|
|
392
|
+
const keepIds = new Set([...pinnedKept, ...latest].map(source => source.id));
|
|
393
|
+
return sources.filter(source => keepIds.has(source.id));
|
|
394
|
+
}
|
|
395
|
+
function latestModel(events) {
|
|
396
|
+
for (let i = events.length - 1; i >= 0; i--) {
|
|
397
|
+
const model = events[i].message.model;
|
|
398
|
+
if (model)
|
|
399
|
+
return model;
|
|
400
|
+
}
|
|
401
|
+
return undefined;
|
|
402
|
+
}
|
|
403
|
+
function providerLabel(providerId) {
|
|
404
|
+
switch (providerId) {
|
|
405
|
+
case 'claude-code':
|
|
406
|
+
return 'Claude Code';
|
|
407
|
+
case 'codex':
|
|
408
|
+
return 'Codex';
|
|
409
|
+
case 'opencode':
|
|
410
|
+
return 'OpenCode';
|
|
411
|
+
default:
|
|
412
|
+
return undefined;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
function describeUsage(usage, rateLimits) {
|
|
416
|
+
const parts = [];
|
|
417
|
+
if (usage) {
|
|
418
|
+
parts.push(`Input tokens: ${usage.input_tokens || 0}`);
|
|
419
|
+
parts.push(`Output tokens: ${usage.output_tokens || 0}`);
|
|
420
|
+
if (usage.cache_read_input_tokens)
|
|
421
|
+
parts.push(`Cache read: ${usage.cache_read_input_tokens}`);
|
|
422
|
+
if (usage.cache_creation_input_tokens)
|
|
423
|
+
parts.push(`Cache write: ${usage.cache_creation_input_tokens}`);
|
|
424
|
+
if (usage.reasoning_tokens)
|
|
425
|
+
parts.push(`Reasoning tokens: ${usage.reasoning_tokens}`);
|
|
426
|
+
}
|
|
427
|
+
if (rateLimits?.primary) {
|
|
428
|
+
parts.push(`Primary limit: ${rateLimits.primary.usedPercent}% used`);
|
|
429
|
+
}
|
|
430
|
+
if (rateLimits?.secondary) {
|
|
431
|
+
parts.push(`Secondary limit: ${rateLimits.secondary.usedPercent}% used`);
|
|
432
|
+
}
|
|
433
|
+
return parts.join('\n') || 'Runtime metadata';
|
|
434
|
+
}
|
|
435
|
+
function inferSourceFile(input) {
|
|
436
|
+
for (const key of ['file_path', 'path', 'filename', 'notebook_path', 'target_file']) {
|
|
437
|
+
const value = input[key];
|
|
438
|
+
if (typeof value === 'string' && value.trim())
|
|
439
|
+
return value.trim();
|
|
440
|
+
}
|
|
441
|
+
const files = input.files;
|
|
442
|
+
if (Array.isArray(files)) {
|
|
443
|
+
const first = files.find(value => typeof value === 'string' && value.trim());
|
|
444
|
+
if (typeof first === 'string')
|
|
445
|
+
return first.trim();
|
|
446
|
+
}
|
|
447
|
+
return undefined;
|
|
448
|
+
}
|
|
449
|
+
function inferCommand(input) {
|
|
450
|
+
const command = input.command ?? input.cmd;
|
|
451
|
+
if (typeof command === 'string' && command.trim())
|
|
452
|
+
return command.trim();
|
|
453
|
+
if (Array.isArray(command)) {
|
|
454
|
+
return command.map(part => String(part)).join(' ').trim() || undefined;
|
|
455
|
+
}
|
|
456
|
+
return undefined;
|
|
457
|
+
}
|
|
458
|
+
function inferMcpServer(toolName, input) {
|
|
459
|
+
const explicit = input._sidekickMcpServerName ?? input.server_name ?? input.serverName;
|
|
460
|
+
if (typeof explicit === 'string' && explicit.trim())
|
|
461
|
+
return explicit.trim();
|
|
462
|
+
const match = /^mcp__([^_]+(?:_[^_]+)*)__/.exec(toolName);
|
|
463
|
+
if (match)
|
|
464
|
+
return match[1];
|
|
465
|
+
return undefined;
|
|
466
|
+
}
|
|
467
|
+
function extractText(content) {
|
|
468
|
+
if (typeof content === 'string')
|
|
469
|
+
return content;
|
|
470
|
+
if (Array.isArray(content)) {
|
|
471
|
+
return content
|
|
472
|
+
.map(block => isRecord(block) ? blockText(block) : '')
|
|
473
|
+
.filter(Boolean)
|
|
474
|
+
.join('\n');
|
|
475
|
+
}
|
|
476
|
+
if (content == null)
|
|
477
|
+
return '';
|
|
478
|
+
return stringifyValue(content);
|
|
479
|
+
}
|
|
480
|
+
function blockText(block) {
|
|
481
|
+
for (const key of ['text', 'thinking', 'content']) {
|
|
482
|
+
const value = block[key];
|
|
483
|
+
if (typeof value === 'string')
|
|
484
|
+
return value;
|
|
485
|
+
}
|
|
486
|
+
return '';
|
|
487
|
+
}
|
|
488
|
+
function stringifyValue(value) {
|
|
489
|
+
if (value == null)
|
|
490
|
+
return '';
|
|
491
|
+
if (typeof value === 'string')
|
|
492
|
+
return value;
|
|
493
|
+
try {
|
|
494
|
+
return JSON.stringify(value, null, 2);
|
|
495
|
+
}
|
|
496
|
+
catch {
|
|
497
|
+
return String(value);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
function stringValue(value) {
|
|
501
|
+
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
502
|
+
}
|
|
503
|
+
function clean(text) {
|
|
504
|
+
return text.replace(/\s+/g, ' ').trim();
|
|
505
|
+
}
|
|
506
|
+
function truncateClean(text, maxChars) {
|
|
507
|
+
return truncateWithInfo(text, maxChars).text;
|
|
508
|
+
}
|
|
509
|
+
function truncateWithInfo(text, maxChars) {
|
|
510
|
+
if (!Number.isFinite(maxChars) || maxChars <= 0)
|
|
511
|
+
return { text: '', truncated: text.length > 0 };
|
|
512
|
+
if (text.length <= maxChars)
|
|
513
|
+
return { text, truncated: false };
|
|
514
|
+
if (maxChars <= 3)
|
|
515
|
+
return { text: text.slice(0, maxChars), truncated: true };
|
|
516
|
+
return { text: `${text.slice(0, maxChars - 3)}...`, truncated: true };
|
|
517
|
+
}
|
|
518
|
+
function estimateTokens(text) {
|
|
519
|
+
return Math.max(1, Math.ceil(text.length / 4));
|
|
520
|
+
}
|
|
521
|
+
function isRecord(value) {
|
|
522
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
523
|
+
}
|
|
@@ -96,5 +96,11 @@ function ensureDefaultCodexAccount(options) {
|
|
|
96
96
|
async function ensureDefaultAccounts(options) {
|
|
97
97
|
const claude = await ensureDefaultClaudeAccount(options);
|
|
98
98
|
const codex = ensureDefaultCodexAccount(options);
|
|
99
|
+
try {
|
|
100
|
+
(0, codexProfiles_1.reconcileCodexAuthState)();
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
logFailure(options, 'Codex auth reconciliation failed.', error);
|
|
104
|
+
}
|
|
99
105
|
return { claude, codex };
|
|
100
106
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -50,6 +50,8 @@ export { FilterEngine } from './search/advancedFilter';
|
|
|
50
50
|
export type { FilterMode, FilterState, HighlightFormat as FilterHighlightFormat } from './search/advancedFilter';
|
|
51
51
|
export { composeContext } from './context/composer';
|
|
52
52
|
export type { Fidelity, ContextResult } from './context/composer';
|
|
53
|
+
export { buildSessionContextSnapshot, calculateSessionContextPressure, createSessionContextProjector, readSessionContextSnapshot, } from './context/sessionContext';
|
|
54
|
+
export type { BuildSessionContextSnapshotOptions, ReadSessionContextSnapshotOptions, SessionContextCapabilities, SessionContextLayerBreakdown, SessionContextPressure, SessionContextProjector, SessionContextSnapshot, SessionContextSource, SessionContextSourceType, } from './context/sessionContext';
|
|
53
55
|
export { PlanExtractor, parsePlanMarkdown as parsePlanMarkdownShared, extractProposedPlan as extractProposedPlanShared } from './parsers/planExtractor';
|
|
54
56
|
export type { ExtractedPlan, ExtractedPlanStep } from './parsers/planExtractor';
|
|
55
57
|
export { parseChangelog } from './parsers/changelogParser';
|
|
@@ -82,7 +84,7 @@ export { HeatmapTracker } from './aggregation/HeatmapTracker';
|
|
|
82
84
|
export type { HeatmapBucket, SerializedHeatmapState } from './aggregation/HeatmapTracker';
|
|
83
85
|
export { PatternExtractor } from './aggregation/PatternExtractor';
|
|
84
86
|
export type { PatternCluster, SerializedPatternState } from './aggregation/PatternExtractor';
|
|
85
|
-
export { generateHtmlReport, parseTranscript, openInBrowser } from './report';
|
|
87
|
+
export { generateHtmlReport, parseTranscript, parseTranscriptFromEvents, openInBrowser } from './report';
|
|
86
88
|
export type { TranscriptContentBlock, TranscriptEntry, HtmlReportOptions } from './report';
|
|
87
89
|
export { readActiveCredentials, writeActiveCredentials } from './credentialIO';
|
|
88
90
|
export { readClaudeMaxCredentials, readClaudeMaxAccessTokenSync } from './credentials';
|
package/dist/index.js
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.findActiveClaudeSession = exports.discoverSessionDirectory = exports.getClaudeSessionDirectory = exports.encodeClaudeWorkspacePath = exports.detectSessionActivity = exports.extractTaskInfo = exports.scanSubagentDir = exports.normalizeCodexToolInput = exports.normalizeCodexToolName = exports.extractPatchFilePaths = exports.CodexRolloutParser = exports.parseDbPartData = exports.parseDbMessageData = exports.convertOpenCodeMessage = exports.detectPlanModeFromText = exports.normalizeToolInput = exports.normalizeToolName = exports.TRUNCATION_PATTERNS = exports.JsonlParser = exports.CodexProvider = exports.OpenCodeProvider = exports.ClaudeCodeProvider = exports.getAllDetectedProviders = exports.detectProvider = exports.readClaudeCodePlanFiles = exports.getPlanAnalytics = exports.writePlans = exports.getLatestPlan = exports.readPlans = exports.readLatestHandoff = exports.readHistory = exports.readNotes = exports.readDecisions = exports.readTasks = exports.getProjectSlugRaw = exports.getProjectSlug = exports.encodeWorkspacePath = exports.getGlobalDataPath = exports.getProjectDataPath = exports.getConfigDir = exports.MAX_PLANS_PER_PROJECT = exports.PLAN_SCHEMA_VERSION = exports.createEmptyTokenTotals = exports.HISTORICAL_DATA_SCHEMA_VERSION = exports.STALENESS_THRESHOLDS = exports.IMPORTANCE_DECAY_FACTORS = exports.KNOWLEDGE_NOTE_SCHEMA_VERSION = exports.DECISION_LOG_SCHEMA_VERSION = exports.normalizeTaskStatus = exports.TASK_PERSISTENCE_SCHEMA_VERSION = void 0;
|
|
7
|
-
exports.
|
|
8
|
-
exports.
|
|
9
|
-
exports.scopePeakHoursToSessionProvider = exports.isClaudeCodeSessionProvider = exports.fetchPeakHoursStatus = exports.createPeakHoursNotApplicableState = exports.fetchOpenAIStatus = exports.fetchProviderStatus = exports.permissionModeSchema = exports.sessionEventSchema = exports.sessionMessageSchema = exports.messageUsageSchema = exports.extractToolCalls = exports.extractToolCall = exports.extractTokenUsage = exports.LITELLM_CATALOG_URL = exports.normalizeLiteLlmCatalog = exports.hydratePricingCatalog = exports.formatCost = exports.sortModelIds = exports.compareModelIds = exports.getModelDisplayInfo = exports.shortModelName = exports.mergeCostSources = exports.calculateCostWithProvenance = exports.calculateCostWithPricing = exports.calculateCost = exports.getModelInfo = exports.getModelPricing = exports.parseModelId = exports.DEFAULT_CONTEXT_WINDOW = exports.getModelContextWindowSize = exports.MultiProviderQuotaService = exports.CodexQuotaWatcher = exports.resolveCodexQuotaFromLocalSources = exports.resolveCodexQuota = exports.readLatestCodexQuotaFromRollouts = exports.quotaFromCodexRateLimits = exports.fetchCodexQuotaFromApi = exports.getWorkspaceIdFromPath = exports.pruneQuotaHistory = exports.readQuotaHistoryDailyBuckets = exports.readQuotaHistoryRange = void 0;
|
|
7
|
+
exports.EventAggregator = exports.getRandomPhrase = exports.PHRASE_CATEGORIES = exports.ALL_PHRASES = exports.HIGHLIGHT_CSS = exports.clearHighlightCache = exports.highlightEvent = exports.formatSessionJson = exports.formatSessionMarkdown = exports.formatSessionText = exports.classifyNoise = exports.shouldMergeWithPrevious = exports.classifyFollowEvent = exports.classifyMessage = exports.getSoftNoiseReason = exports.isHardNoiseFollowEvent = exports.isHardNoise = exports.formatToolSummary = exports.formatTokenCount = exports.formatDurationMs = exports.createJsonlTail = exports.toFollowEvents = exports.createWatcher = exports.parseChangelog = exports.extractProposedPlanShared = exports.parsePlanMarkdownShared = exports.PlanExtractor = exports.readSessionContextSnapshot = exports.createSessionContextProjector = exports.calculateSessionContextPressure = exports.buildSessionContextSnapshot = exports.composeContext = exports.FilterEngine = exports.searchSessions = exports.CodexDatabase = exports.OpenCodeDatabase = exports.discoverDebugLogs = exports.collapseDuplicates = exports.filterByLevel = exports.parseDebugLog = exports.scanSubagentTraces = exports.findAllSessionsWithWorktrees = exports.discoverWorktreeSiblings = exports.resolveWorktreeMainRepo = exports.getAllClaudeProjectFolders = exports.decodeEncodedPath = exports.getMostRecentlyActiveSessionDir = exports.findSubdirectorySessionDirs = exports.findSessionsInDirectory = exports.findAllClaudeSessions = void 0;
|
|
8
|
+
exports.fetchQuota = exports.removeCodexAccount = exports.switchToCodexAccount = exports.finalizeCodexAccount = exports.prepareCodexAccount = exports.getCodexExecutionEnv = exports.resolveSidekickCodexHome = exports.getActiveCodexAccount = exports.listCodexAccounts = exports.getSystemCodexHome = exports.getCodexMonitoringHomes = exports.getCodexProfileHome = exports.getCodexProfilesDir = exports.getActiveAccountStatus = exports.removeSavedAccountProfile = exports.replaceSavedAccountProfiles = exports.setActiveSavedAccount = exports.upsertSavedAccountProfile = exports.getActiveSavedAccount = exports.listSavedAccountProfiles = exports.writeSavedAccountRegistry = exports.readSavedAccountRegistry = exports.getAccountsDir = exports.isMultiAccountEnabled = exports.getActiveAccount = exports.listAccounts = exports.removeAccount = exports.switchToAccount = exports.addCurrentAccount = exports.readActiveClaudeAccount = exports.writeAccountRegistry = exports.readAccountRegistry = exports.ensureDefaultAccounts = exports.readClaudeMaxAccessTokenSync = exports.readClaudeMaxCredentials = exports.writeActiveCredentials = exports.readActiveCredentials = exports.openInBrowser = exports.parseTranscriptFromEvents = exports.parseTranscript = exports.generateHtmlReport = exports.PatternExtractor = exports.HeatmapTracker = exports.FrequencyTracker = exports.getSnapshotPath = exports.isSnapshotValid = exports.deleteSnapshot = exports.loadSnapshot = exports.saveSnapshot = exports.parseTodoDependencies = void 0;
|
|
9
|
+
exports.scopePeakHoursToSessionProvider = exports.isClaudeCodeSessionProvider = exports.fetchPeakHoursStatus = exports.createPeakHoursNotApplicableState = exports.fetchOpenAIStatus = exports.fetchProviderStatus = exports.permissionModeSchema = exports.sessionEventSchema = exports.sessionMessageSchema = exports.messageUsageSchema = exports.extractToolCalls = exports.extractToolCall = exports.extractTokenUsage = exports.LITELLM_CATALOG_URL = exports.normalizeLiteLlmCatalog = exports.hydratePricingCatalog = exports.formatCost = exports.sortModelIds = exports.compareModelIds = exports.getModelDisplayInfo = exports.shortModelName = exports.mergeCostSources = exports.calculateCostWithProvenance = exports.calculateCostWithPricing = exports.calculateCost = exports.getModelInfo = exports.getModelPricing = exports.parseModelId = exports.DEFAULT_CONTEXT_WINDOW = exports.getModelContextWindowSize = exports.MultiProviderQuotaService = exports.CodexQuotaWatcher = exports.resolveCodexQuotaFromLocalSources = exports.resolveCodexQuota = exports.readLatestCodexQuotaFromRollouts = exports.quotaFromCodexRateLimits = exports.fetchCodexQuotaFromApi = exports.getWorkspaceIdFromPath = exports.pruneQuotaHistory = exports.readQuotaHistoryDailyBuckets = exports.readQuotaHistoryRange = exports.appendQuotaHistorySample = exports.writeQuotaSnapshot = exports.readQuotaSnapshot = exports.QuotaPoller = exports.describeQuotaFailure = void 0;
|
|
10
10
|
var taskPersistence_1 = require("./types/taskPersistence");
|
|
11
11
|
Object.defineProperty(exports, "TASK_PERSISTENCE_SCHEMA_VERSION", { enumerable: true, get: function () { return taskPersistence_1.TASK_PERSISTENCE_SCHEMA_VERSION; } });
|
|
12
12
|
Object.defineProperty(exports, "normalizeTaskStatus", { enumerable: true, get: function () { return taskPersistence_1.normalizeTaskStatus; } });
|
|
@@ -118,6 +118,11 @@ Object.defineProperty(exports, "FilterEngine", { enumerable: true, get: function
|
|
|
118
118
|
// Context
|
|
119
119
|
var composer_1 = require("./context/composer");
|
|
120
120
|
Object.defineProperty(exports, "composeContext", { enumerable: true, get: function () { return composer_1.composeContext; } });
|
|
121
|
+
var sessionContext_1 = require("./context/sessionContext");
|
|
122
|
+
Object.defineProperty(exports, "buildSessionContextSnapshot", { enumerable: true, get: function () { return sessionContext_1.buildSessionContextSnapshot; } });
|
|
123
|
+
Object.defineProperty(exports, "calculateSessionContextPressure", { enumerable: true, get: function () { return sessionContext_1.calculateSessionContextPressure; } });
|
|
124
|
+
Object.defineProperty(exports, "createSessionContextProjector", { enumerable: true, get: function () { return sessionContext_1.createSessionContextProjector; } });
|
|
125
|
+
Object.defineProperty(exports, "readSessionContextSnapshot", { enumerable: true, get: function () { return sessionContext_1.readSessionContextSnapshot; } });
|
|
121
126
|
// Plan Extraction
|
|
122
127
|
var planExtractor_1 = require("./parsers/planExtractor");
|
|
123
128
|
Object.defineProperty(exports, "PlanExtractor", { enumerable: true, get: function () { return planExtractor_1.PlanExtractor; } });
|
|
@@ -180,6 +185,7 @@ Object.defineProperty(exports, "PatternExtractor", { enumerable: true, get: func
|
|
|
180
185
|
var report_1 = require("./report");
|
|
181
186
|
Object.defineProperty(exports, "generateHtmlReport", { enumerable: true, get: function () { return report_1.generateHtmlReport; } });
|
|
182
187
|
Object.defineProperty(exports, "parseTranscript", { enumerable: true, get: function () { return report_1.parseTranscript; } });
|
|
188
|
+
Object.defineProperty(exports, "parseTranscriptFromEvents", { enumerable: true, get: function () { return report_1.parseTranscriptFromEvents; } });
|
|
183
189
|
Object.defineProperty(exports, "openInBrowser", { enumerable: true, get: function () { return report_1.openInBrowser; } });
|
|
184
190
|
// Credential I/O (platform-aware: Keychain on macOS, file on Linux/Windows)
|
|
185
191
|
var credentialIO_1 = require("./credentialIO");
|
package/dist/modelContext.js
CHANGED
|
@@ -8,7 +8,9 @@ exports.DEFAULT_CONTEXT_WINDOW = void 0;
|
|
|
8
8
|
exports.getModelContextWindowSize = getModelContextWindowSize;
|
|
9
9
|
/** Known model context window sizes (in tokens). */
|
|
10
10
|
const MODEL_CONTEXT_SIZES = {
|
|
11
|
-
// Claude — native 1M context (Opus 4.6+, Sonnet 4.6+)
|
|
11
|
+
// Claude — native 1M context (Fable 5, Opus 4.6+, Sonnet 4.6+)
|
|
12
|
+
'claude-fable-5': 1_000_000,
|
|
13
|
+
'claude-opus-4-8': 1_000_000,
|
|
12
14
|
'claude-opus-4-7': 1_000_000,
|
|
13
15
|
'claude-opus-4-6': 1_000_000,
|
|
14
16
|
'claude-sonnet-4-7': 1_000_000,
|