@myagentroam/agent 0.11.57 → 0.11.59
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/session/catalog.d.ts +3 -0
- package/dist/session/catalog.js +91 -8
- package/package.json +1 -1
|
@@ -25,6 +25,9 @@ export interface AgentSessionInputReceipt {
|
|
|
25
25
|
}
|
|
26
26
|
export interface AgentSessionContextUsage {
|
|
27
27
|
inputTokens: number;
|
|
28
|
+
gcCount: number;
|
|
29
|
+
/** Measured input decreases since Compact; undefined when GC usage is not yet paired. */
|
|
30
|
+
gcReclaimedTokens?: number;
|
|
28
31
|
}
|
|
29
32
|
export interface AgentSessionDeleteResult {
|
|
30
33
|
readonly deleted: boolean;
|
package/dist/session/catalog.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AgentError } from '../error.js';
|
|
2
2
|
import { publicHostedToolEvents } from '../runtime/event-projection.js';
|
|
3
3
|
import { appliedInputRecord } from './deferred-input.js';
|
|
4
|
+
import { compactSummaryFromCheckpoint } from './record-projection.js';
|
|
4
5
|
const MAX_INPUT_IMAGE_BYTES = 5 * 1024 * 1024;
|
|
5
6
|
const INPUT_IMAGE_MIME_TYPES = new Set(['image/png', 'image/jpeg', 'image/gif', 'image/webp']);
|
|
6
7
|
export function createSessionCatalog(store, borrowed) {
|
|
@@ -182,20 +183,102 @@ export function createSessionCatalog(store, borrowed) {
|
|
|
182
183
|
contextUsage: async (sessionId) => {
|
|
183
184
|
assertOpen();
|
|
184
185
|
const page = await store.readPage(sessionId, { limit: 1000 });
|
|
186
|
+
let inputTokens;
|
|
185
187
|
for (const record of page.records.toReversed()) {
|
|
186
188
|
if (!isAgentEvent(record.payload))
|
|
187
189
|
continue;
|
|
188
|
-
if (record.payload.type === 'context.compacted')
|
|
189
|
-
|
|
190
|
+
if (record.payload.type === 'context.compacted') {
|
|
191
|
+
if (record.payload.retainedContext === true)
|
|
192
|
+
return undefined;
|
|
193
|
+
inputTokens = 0;
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
190
196
|
if (record.payload.type === 'usage.updated' && record.payload.purpose !== 'compact') {
|
|
191
|
-
const
|
|
192
|
-
if (typeof
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
197
|
+
const tokens = record.payload.contextInputTokens ?? record.payload.inputTokens;
|
|
198
|
+
if (typeof tokens === 'number' && Number.isSafeInteger(tokens) && tokens >= 0) {
|
|
199
|
+
inputTokens = tokens;
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
196
202
|
}
|
|
197
203
|
}
|
|
198
|
-
|
|
204
|
+
if (inputTokens === undefined)
|
|
205
|
+
return undefined;
|
|
206
|
+
const usage = { inputTokens };
|
|
207
|
+
let gcCount = 0;
|
|
208
|
+
let gcReclaimedTokens = 0;
|
|
209
|
+
let tokensKnown = true;
|
|
210
|
+
let nextInputTokens;
|
|
211
|
+
let nextModelId;
|
|
212
|
+
let nextExecutionId;
|
|
213
|
+
let requestInputTokens;
|
|
214
|
+
const statistics = () => ({
|
|
215
|
+
...usage,
|
|
216
|
+
gcCount,
|
|
217
|
+
...(tokensKnown ? { gcReclaimedTokens } : {})
|
|
218
|
+
});
|
|
219
|
+
let countPage = page;
|
|
220
|
+
for (;;) {
|
|
221
|
+
for (const record of countPage.records.toReversed()) {
|
|
222
|
+
if (compactSummaryFromCheckpoint(record) !== undefined)
|
|
223
|
+
return statistics();
|
|
224
|
+
if (record.type === 'execution.header' &&
|
|
225
|
+
record.executionId === nextExecutionId &&
|
|
226
|
+
isRecord(record.payload))
|
|
227
|
+
nextModelId =
|
|
228
|
+
typeof record.payload.modelId === 'string' ? record.payload.modelId : undefined;
|
|
229
|
+
if (isAgentEvent(record.payload) &&
|
|
230
|
+
record.payload.type === 'usage.updated' &&
|
|
231
|
+
record.payload.purpose !== 'compact') {
|
|
232
|
+
const tokens = record.payload.contextInputTokens ?? record.payload.inputTokens;
|
|
233
|
+
if (typeof tokens === 'number' && Number.isSafeInteger(tokens) && tokens >= 0) {
|
|
234
|
+
requestInputTokens ??= tokens;
|
|
235
|
+
nextInputTokens = tokens;
|
|
236
|
+
nextModelId = undefined;
|
|
237
|
+
nextExecutionId = record.executionId;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
if (record.type === 'model.attempt' &&
|
|
241
|
+
isRecord(record.payload) &&
|
|
242
|
+
record.payload.state === 'STARTED' &&
|
|
243
|
+
record.payload.purpose === 'EXECUTION') {
|
|
244
|
+
// Reverse traversal preserves the last usage update within each request.
|
|
245
|
+
if (requestInputTokens !== undefined)
|
|
246
|
+
nextInputTokens = requestInputTokens;
|
|
247
|
+
requestInputTokens = undefined;
|
|
248
|
+
}
|
|
249
|
+
if (record.type === 'context.gc.completed' &&
|
|
250
|
+
isRecord(record.payload) &&
|
|
251
|
+
typeof record.payload.generation === 'number' &&
|
|
252
|
+
Number.isSafeInteger(record.payload.generation) &&
|
|
253
|
+
record.payload.generation > 0) {
|
|
254
|
+
gcCount ||= record.payload.generation;
|
|
255
|
+
const trigger = isRecord(record.payload.trigger) ? record.payload.trigger : undefined;
|
|
256
|
+
const before = trigger?.contextInputTokens;
|
|
257
|
+
if (typeof trigger?.usageSequence === 'number' &&
|
|
258
|
+
trigger.usageSequence > 0 &&
|
|
259
|
+
typeof before === 'number' &&
|
|
260
|
+
Number.isSafeInteger(before) &&
|
|
261
|
+
before >= 0 &&
|
|
262
|
+
nextInputTokens !== undefined &&
|
|
263
|
+
(nextModelId === undefined || nextModelId === trigger.modelId))
|
|
264
|
+
gcReclaimedTokens += Math.max(0, before - nextInputTokens);
|
|
265
|
+
else
|
|
266
|
+
tokensKnown = false;
|
|
267
|
+
nextInputTokens = undefined;
|
|
268
|
+
nextModelId = undefined;
|
|
269
|
+
nextExecutionId = undefined;
|
|
270
|
+
requestInputTokens = undefined;
|
|
271
|
+
if (record.payload.generation === 1)
|
|
272
|
+
return statistics();
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
if (countPage.previousBeforeSequence === undefined)
|
|
276
|
+
return statistics();
|
|
277
|
+
countPage = await store.readPage(sessionId, {
|
|
278
|
+
limit: 1000,
|
|
279
|
+
beforeSequence: countPage.previousBeforeSequence
|
|
280
|
+
});
|
|
281
|
+
}
|
|
199
282
|
},
|
|
200
283
|
fork: async (sessionId, options) => {
|
|
201
284
|
assertOpen();
|