@adecore/agents 0.31.4 → 0.31.6
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/chat/acp-backend.d.ts +7 -0
- package/dist/chat/acp-backend.js +87 -6
- package/dist/chat/acp-protocol.d.ts +6 -0
- package/dist/chat/acp-protocol.js +34 -9
- package/dist/providers/accounts/acp-account.d.ts +1 -0
- package/dist/providers/accounts/acp-account.js +25 -3
- package/dist/providers/acp-agent-state.d.ts +35 -0
- package/dist/providers/acp-agent-state.js +170 -0
- package/dist/providers/acp-provider.d.ts +2 -0
- package/dist/providers/acp-provider.js +29 -33
- package/dist/providers/catalog.d.ts +2 -0
- package/dist/providers/catalog.js +14 -4
- package/dist/providers/index.d.ts +1 -0
- package/dist/providers/index.js +1 -0
- package/dist/providers/provider.d.ts +1 -0
- package/dist/providers/registry.d.ts +1 -0
- package/dist/providers/registry.js +9 -0
- package/dist/testing/fake-acp.d.ts +3 -0
- package/dist/testing/fake-acp.js +11 -4
- package/dist/usage/aggregate.js +1 -1
- package/dist/usage/index-file.d.ts +2 -0
- package/dist/usage/index-file.js +19 -10
- package/dist/usage/pricing.d.ts +3 -2
- package/dist/usage/pricing.js +42 -8
- package/dist/usage/readers/codex.d.ts +9 -0
- package/dist/usage/readers/codex.js +75 -14
- package/dist/usage/record.d.ts +1 -0
- package/dist/usage/scanner.js +32 -8
- package/package.json +3 -3
- package/src/chat/acp-backend.ts +93 -5
- package/src/chat/acp-protocol.ts +41 -9
- package/src/providers/accounts/acp-account.ts +34 -3
- package/src/providers/acp-agent-state.ts +206 -0
- package/src/providers/acp-provider.ts +33 -37
- package/src/providers/catalog.ts +19 -5
- package/src/providers/index.ts +1 -0
- package/src/providers/provider.ts +2 -0
- package/src/providers/registry.ts +10 -0
- package/src/testing/fake-acp.ts +17 -4
- package/src/usage/aggregate.ts +1 -1
- package/src/usage/index-file.ts +25 -18
- package/src/usage/pricing.ts +46 -8
- package/src/usage/readers/codex.ts +86 -14
- package/src/usage/record.ts +1 -0
- package/src/usage/scanner.ts +35 -8
package/src/usage/scanner.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash, type Hash } from 'node:crypto';
|
|
2
2
|
import { mkdir, open, readFile, readdir, stat } from 'node:fs/promises';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
|
+
import { zstdDecompressSync } from 'node:zlib';
|
|
4
5
|
import type { UsageProvider, UsageRoot } from '@adecore/agent-contracts';
|
|
5
6
|
import { errorText } from '../error-text.ts';
|
|
6
7
|
import { isNotFound, writeAtomic } from '../fs.ts';
|
|
@@ -13,6 +14,7 @@ import { cloneCodexState, codexMightCarryUsage, createCodexState, parseCodexLine
|
|
|
13
14
|
import { usageRoots, type UsageRootPath } from './roots.ts';
|
|
14
15
|
|
|
15
16
|
const HASH_CHUNK_BYTES = 65536;
|
|
17
|
+
const CODEX_PARSER_VERSION = 2;
|
|
16
18
|
|
|
17
19
|
interface HashedRead {
|
|
18
20
|
/* Everything from `from` to the end of the file, as it is at the read. */
|
|
@@ -82,7 +84,7 @@ function readsWhole(provider: UsageProvider): boolean {
|
|
|
82
84
|
}
|
|
83
85
|
|
|
84
86
|
function isUsageFile(provider: UsageProvider, name: string): boolean {
|
|
85
|
-
return readsWhole(provider) ? name === GROK_USAGE_FILE : name.endsWith('.jsonl');
|
|
87
|
+
return readsWhole(provider) ? name === GROK_USAGE_FILE : name.endsWith('.jsonl') || (provider === 'codex' && name.endsWith('.jsonl.zst'));
|
|
86
88
|
}
|
|
87
89
|
|
|
88
90
|
async function listUsageFiles(dir: string, provider: UsageProvider, out: string[] = []): Promise<string[]> {
|
|
@@ -255,7 +257,12 @@ export class UsageScanner {
|
|
|
255
257
|
}
|
|
256
258
|
let failure: string | null = null;
|
|
257
259
|
const accountOf = accountResolver(root, sessionAccounts);
|
|
258
|
-
|
|
260
|
+
const paths = await listUsageFiles(root.path, root.provider);
|
|
261
|
+
const plain = new Set(paths);
|
|
262
|
+
for (const path of paths) {
|
|
263
|
+
if (root.provider === 'codex' && path.endsWith('.jsonl.zst') && plain.has(path.slice(0, -4))) {
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
259
266
|
files += 1;
|
|
260
267
|
try {
|
|
261
268
|
if (await this.readFileInto(path, root.provider, accountOf)) {
|
|
@@ -288,15 +295,34 @@ export class UsageScanner {
|
|
|
288
295
|
|
|
289
296
|
private async readFileInto(path: string, provider: UsageProvider, accountOf: AccountOf): Promise<boolean> {
|
|
290
297
|
const info = await stat(path);
|
|
291
|
-
const
|
|
292
|
-
|
|
298
|
+
const compressed = provider === 'codex' && path.endsWith('.jsonl.zst');
|
|
299
|
+
const key = compressed ? path.slice(0, -4) : path;
|
|
300
|
+
const known = this.index.get(key);
|
|
301
|
+
const currentParser = provider !== 'codex' || known?.parserVersion === CODEX_PARSER_VERSION;
|
|
302
|
+
if (
|
|
303
|
+
currentParser &&
|
|
304
|
+
known !== undefined &&
|
|
305
|
+
known.provider === provider &&
|
|
306
|
+
(known.compressed ?? false) === compressed &&
|
|
307
|
+
known.size === info.size &&
|
|
308
|
+
known.mtimeMs === info.mtimeMs
|
|
309
|
+
) {
|
|
293
310
|
return false;
|
|
294
311
|
}
|
|
295
312
|
if (readsWhole(provider)) {
|
|
296
313
|
return this.readWholeInto(path, provider, accountOf, info);
|
|
297
314
|
}
|
|
298
|
-
const appended =
|
|
299
|
-
|
|
315
|
+
const appended =
|
|
316
|
+
!compressed &&
|
|
317
|
+
currentParser &&
|
|
318
|
+
known?.compressed !== true &&
|
|
319
|
+
known !== undefined &&
|
|
320
|
+
known.provider === provider &&
|
|
321
|
+
info.size > known.size &&
|
|
322
|
+
known.head?.startsWith('sha256:') === true;
|
|
323
|
+
let read = compressed
|
|
324
|
+
? { bytes: zstdDecompressSync(await readFile(path)), hash: createHash('sha256') }
|
|
325
|
+
: await readHashed(path, appended ? known.offset : 0);
|
|
300
326
|
// A file only counts as grown while it starts the way it did; one rewritten larger is read again from the start.
|
|
301
327
|
const grown = appended && headOf(read.hash) === known.head;
|
|
302
328
|
if (appended && !grown) {
|
|
@@ -315,9 +341,10 @@ export class UsageScanner {
|
|
|
315
341
|
records: foldByKey([...before, ...withAccount(parsed.records, accountOf)]),
|
|
316
342
|
tail: withAccount(parsed.tail, accountOf),
|
|
317
343
|
codex: parsed.codex,
|
|
318
|
-
head: headOf(read.hash)
|
|
344
|
+
head: headOf(read.hash),
|
|
345
|
+
...(provider === 'codex' ? { parserVersion: CODEX_PARSER_VERSION, compressed } : {})
|
|
319
346
|
};
|
|
320
|
-
this.index.set(
|
|
347
|
+
this.index.set(key, entry);
|
|
321
348
|
this.dirty = true;
|
|
322
349
|
return true;
|
|
323
350
|
}
|