@codexhost/cli-darwin-x64 0.13.0 → 0.13.1
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 +1 -1
- package/THIRD_PARTY_NOTICES.txt +1 -1
- package/app/codexhost-distribution.json +1 -1
- package/app/console-server.mjs +88 -44
- package/app/console-web.js +3681 -3948
- package/app/desktop-controller.mjs +8 -1
- package/app/host-runtime.mjs +457 -156
- package/app/plugins/antigravity/plugin.mjs +8 -1
- package/app/plugins/claude-code/plugin.mjs +34469 -23777
- package/app/plugins/codebuddy/plugin.mjs +47 -4
- package/app/plugins/codex-usage/plugin.mjs +639 -18
- package/app/plugins/cursor-cli/plugin.mjs +8 -1
- package/app/plugins/deepseek-harness/plugin.mjs +28 -3
- package/app/plugins/grok/plugin.mjs +43 -8
- package/app/plugins/hermes/plugin.mjs +8 -1
- package/app/plugins/kimi-code/plugin.mjs +8 -1
- package/app/plugins/kiro-cli/plugin.mjs +8 -1
- package/app/plugins/omp/plugin.mjs +31 -7
- package/app/plugins/opencode/plugin.mjs +34 -4
- package/app/plugins/pi/plugin.mjs +84 -43
- package/app/plugins/qoder/plugin.mjs +54 -4
- package/app/plugins/qoder-cn/plugin.mjs +54 -4
- package/app/plugins/workbuddy/plugin.mjs +47 -4
- package/app/plugins/zcode/plugin.mjs +37 -4
- package/app/renderer-extension.js +11568 -7287
- package/bin/codexhost +0 -0
- package/libexec/codexhost-shim +0 -0
- package/libexec/codexhost-updater +0 -0
- package/package.json +1 -1
|
@@ -14676,6 +14676,8 @@ var usageStatisticsSessionSchema = external_exports.strictObject({
|
|
|
14676
14676
|
harness,
|
|
14677
14677
|
sessionId: external_exports.string().min(1).max(512),
|
|
14678
14678
|
project: project.nullable(),
|
|
14679
|
+
/** Persisted Desktop title for a mapped Session, otherwise its native name; may be absent. */
|
|
14680
|
+
title: external_exports.string().min(1).max(200).optional(),
|
|
14679
14681
|
/** Models the session used, most requests first. */
|
|
14680
14682
|
models: external_exports.array(model).max(16),
|
|
14681
14683
|
firstAtMs: count,
|
|
@@ -14742,7 +14744,12 @@ var usageStatisticsResultSchema = external_exports.strictObject({
|
|
|
14742
14744
|
* The sessions that spent the most, by cost and by tokens without cache, all filters applied;
|
|
14743
14745
|
* requests without a native session are not listed here but count everywhere else.
|
|
14744
14746
|
*/
|
|
14745
|
-
sessions: external_exports.array(usageStatisticsSessionSchema).max(100)
|
|
14747
|
+
sessions: external_exports.array(usageStatisticsSessionSchema).max(100),
|
|
14748
|
+
/**
|
|
14749
|
+
* The sessions last active in the range, newest first, all filters applied. Optional for older
|
|
14750
|
+
* Hosts; missing is treated as no list rather than no sessions.
|
|
14751
|
+
*/
|
|
14752
|
+
recentSessions: external_exports.array(usageStatisticsSessionSchema).max(100).optional()
|
|
14746
14753
|
});
|
|
14747
14754
|
|
|
14748
14755
|
// ../../shared-contracts/dist/ids.js
|
|
@@ -15862,8 +15869,24 @@ import path from "node:path";
|
|
|
15862
15869
|
import { setImmediate as yieldToEventLoop } from "node:timers/promises";
|
|
15863
15870
|
|
|
15864
15871
|
// ../../harness-adapter/dist/usage-statistics.js
|
|
15872
|
+
import { createReadStream } from "node:fs";
|
|
15873
|
+
import { createInterface } from "node:readline";
|
|
15865
15874
|
var MAX_SESSION_ID_LENGTH = 512;
|
|
15866
15875
|
var MAX_CWD_LENGTH = 4096;
|
|
15876
|
+
var MAX_SESSION_TITLE_LENGTH = 200;
|
|
15877
|
+
function usageSessionTitle(value) {
|
|
15878
|
+
if (typeof value !== "string")
|
|
15879
|
+
return void 0;
|
|
15880
|
+
const normalized = value.replaceAll("\0", "").replaceAll(/\s+/gu, " ").trim();
|
|
15881
|
+
if (!normalized)
|
|
15882
|
+
return void 0;
|
|
15883
|
+
if (normalized.length <= MAX_SESSION_TITLE_LENGTH)
|
|
15884
|
+
return normalized;
|
|
15885
|
+
const characters = [...normalized];
|
|
15886
|
+
if (characters.length <= MAX_SESSION_TITLE_LENGTH)
|
|
15887
|
+
return normalized;
|
|
15888
|
+
return `${characters.slice(0, MAX_SESSION_TITLE_LENGTH - 1).join("").trimEnd()}…`;
|
|
15889
|
+
}
|
|
15867
15890
|
function sessionIdOk(value) {
|
|
15868
15891
|
return typeof value === "string" && value.length > 0 && value.length <= MAX_SESSION_ID_LENGTH;
|
|
15869
15892
|
}
|
|
@@ -15873,12 +15896,14 @@ function cwdOk(value) {
|
|
|
15873
15896
|
function withUsageSession(entry, session) {
|
|
15874
15897
|
const sessionId = sessionIdOk(session.sessionId) ? session.sessionId : void 0;
|
|
15875
15898
|
const cwd = cwdOk(session.cwd) ? session.cwd : void 0;
|
|
15899
|
+
const sessionTitle = sessionId !== void 0 ? usageSessionTitle(session.title) : void 0;
|
|
15876
15900
|
if (sessionId === void 0 && cwd === void 0)
|
|
15877
15901
|
return entry;
|
|
15878
15902
|
return {
|
|
15879
15903
|
...entry,
|
|
15880
15904
|
...sessionId !== void 0 ? { sessionId } : {},
|
|
15881
|
-
...cwd !== void 0 ? { cwd } : {}
|
|
15905
|
+
...cwd !== void 0 ? { cwd } : {},
|
|
15906
|
+
...sessionTitle !== void 0 ? { sessionTitle } : {}
|
|
15882
15907
|
};
|
|
15883
15908
|
}
|
|
15884
15909
|
function tokenCount(value) {
|
|
@@ -15918,6 +15943,12 @@ function parseHarnessUsageEntry(value) {
|
|
|
15918
15943
|
return null;
|
|
15919
15944
|
if (entry.cwd !== void 0 && !cwdOk(entry.cwd))
|
|
15920
15945
|
return null;
|
|
15946
|
+
if (entry.sessionTitle !== void 0) {
|
|
15947
|
+
const sessionTitle = usageSessionTitle(entry.sessionTitle);
|
|
15948
|
+
if (sessionTitle === void 0)
|
|
15949
|
+
return null;
|
|
15950
|
+
entry.sessionTitle = sessionTitle;
|
|
15951
|
+
}
|
|
15921
15952
|
if (entry.tokensUnknown !== void 0 && entry.tokensUnknown !== true)
|
|
15922
15953
|
return null;
|
|
15923
15954
|
if (entry.costUsd !== void 0 && (typeof entry.costUsd !== "number" || !Number.isFinite(entry.costUsd) || entry.costUsd < 0)) {
|
|
@@ -15928,6 +15959,25 @@ function parseHarnessUsageEntry(value) {
|
|
|
15928
15959
|
}
|
|
15929
15960
|
return entry;
|
|
15930
15961
|
}
|
|
15962
|
+
async function* jsonlRecords(file2, marker, signal) {
|
|
15963
|
+
const lines = createInterface({
|
|
15964
|
+
input: createReadStream(file2, { encoding: "utf8", signal }),
|
|
15965
|
+
crlfDelay: Infinity
|
|
15966
|
+
});
|
|
15967
|
+
for await (const line of lines) {
|
|
15968
|
+
if (!line.includes(marker))
|
|
15969
|
+
continue;
|
|
15970
|
+
let value;
|
|
15971
|
+
try {
|
|
15972
|
+
value = JSON.parse(line);
|
|
15973
|
+
} catch {
|
|
15974
|
+
continue;
|
|
15975
|
+
}
|
|
15976
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
15977
|
+
yield value;
|
|
15978
|
+
}
|
|
15979
|
+
}
|
|
15980
|
+
}
|
|
15931
15981
|
function nativeTimeMs(value) {
|
|
15932
15982
|
const time3 = typeof value === "number" ? value : typeof value === "string" ? Date.parse(value) : Number.NaN;
|
|
15933
15983
|
return Number.isFinite(time3) && time3 > 0 ? Math.floor(time3) : null;
|
|
@@ -16336,7 +16386,7 @@ var CodexCounters = class {
|
|
|
16336
16386
|
};
|
|
16337
16387
|
|
|
16338
16388
|
// dist/rollout-io.js
|
|
16339
|
-
import { createReadStream } from "node:fs";
|
|
16389
|
+
import { createReadStream as createReadStream2 } from "node:fs";
|
|
16340
16390
|
import { StringDecoder } from "node:string_decoder";
|
|
16341
16391
|
import { promisify } from "node:util";
|
|
16342
16392
|
import { zstdDecompress } from "node:zlib";
|
|
@@ -16401,7 +16451,7 @@ function frameSize(data) {
|
|
|
16401
16451
|
}
|
|
16402
16452
|
async function* rolloutBytes(file2, signal) {
|
|
16403
16453
|
signal.throwIfAborted();
|
|
16404
|
-
const stream =
|
|
16454
|
+
const stream = createReadStream2(file2, { signal });
|
|
16405
16455
|
let pending = Buffer.alloc(0);
|
|
16406
16456
|
try {
|
|
16407
16457
|
for await (const value of stream) {
|
|
@@ -16499,18 +16549,61 @@ async function stamp(file2) {
|
|
|
16499
16549
|
throw new Error("Codex rollout is not a regular file");
|
|
16500
16550
|
return `${s.dev}:${s.ino}:${s.size}:${s.mtimeNs}:${s.ctimeNs}`;
|
|
16501
16551
|
}
|
|
16502
|
-
function fingerprint(files) {
|
|
16503
|
-
return createHash("sha256").update(JSON.stringify(files)).digest("hex");
|
|
16552
|
+
function fingerprint(files, extra = "") {
|
|
16553
|
+
return createHash("sha256").update(JSON.stringify(files)).update(extra).digest("hex");
|
|
16554
|
+
}
|
|
16555
|
+
function typedPrompt(value) {
|
|
16556
|
+
if (typeof value !== "string")
|
|
16557
|
+
return void 0;
|
|
16558
|
+
const text2 = value.trim();
|
|
16559
|
+
if (!text2 || text2.startsWith("<") || text2.startsWith("# AGENTS.md") || text2.startsWith("<!--")) {
|
|
16560
|
+
return void 0;
|
|
16561
|
+
}
|
|
16562
|
+
return usageSessionTitle(text2);
|
|
16563
|
+
}
|
|
16564
|
+
function userItemPrompt(payload) {
|
|
16565
|
+
if (!payload || payload.type !== "message" || payload.role !== "user")
|
|
16566
|
+
return void 0;
|
|
16567
|
+
if (!Array.isArray(payload.content))
|
|
16568
|
+
return typedPrompt(payload.content);
|
|
16569
|
+
for (const part of payload.content) {
|
|
16570
|
+
if (typeof part !== "object" || part === null)
|
|
16571
|
+
continue;
|
|
16572
|
+
const block = part;
|
|
16573
|
+
if (block.type === "input_text" || block.type === "text") {
|
|
16574
|
+
const prompt = typedPrompt(block.text);
|
|
16575
|
+
if (prompt)
|
|
16576
|
+
return prompt;
|
|
16577
|
+
}
|
|
16578
|
+
}
|
|
16579
|
+
return void 0;
|
|
16580
|
+
}
|
|
16581
|
+
async function readThreadNames(home, signal) {
|
|
16582
|
+
const names = /* @__PURE__ */ new Map();
|
|
16583
|
+
try {
|
|
16584
|
+
for await (const line of jsonlRecords(path.join(home, "session_index.jsonl"), '"thread_name"', signal)) {
|
|
16585
|
+
const id = text(line.id);
|
|
16586
|
+
const name = usageSessionTitle(line.thread_name);
|
|
16587
|
+
if (id && name)
|
|
16588
|
+
names.set(id, name);
|
|
16589
|
+
}
|
|
16590
|
+
} catch (error51) {
|
|
16591
|
+
if (error51.code !== "ENOENT")
|
|
16592
|
+
throw error51;
|
|
16593
|
+
}
|
|
16594
|
+
return names;
|
|
16504
16595
|
}
|
|
16505
|
-
async function readCodexRollouts(files, thread, signal) {
|
|
16596
|
+
async function readCodexRollouts(files, thread, signal, options = {}) {
|
|
16506
16597
|
const counters = new CodexCounters();
|
|
16507
|
-
let model2 = "", cwd = "", ownFrom = null, firstMeta = false, forkAt = 0, seen = 0;
|
|
16598
|
+
let model2 = "", cwd = "", ownFrom = null, firstMeta = false, forkAt = 0, seen = 0, firstPrompt;
|
|
16508
16599
|
for (const file2 of files) {
|
|
16509
16600
|
for await (const line of rolloutLines(file2, signal)) {
|
|
16510
16601
|
signal.throwIfAborted();
|
|
16511
16602
|
if (++seen % 128 === 0)
|
|
16512
16603
|
await yieldToEventLoop(void 0, { signal });
|
|
16513
16604
|
const kind = /"type"\s*:\s*"([^"]+)"/u.exec(line.slice(0, 1024))?.[1];
|
|
16605
|
+
if (!kind && line.trim())
|
|
16606
|
+
options.onIncomplete?.();
|
|
16514
16607
|
if (!kind || ![
|
|
16515
16608
|
"session_meta",
|
|
16516
16609
|
"turn_context",
|
|
@@ -16528,19 +16621,24 @@ async function readCodexRollouts(files, thread, signal) {
|
|
|
16528
16621
|
try {
|
|
16529
16622
|
row = object2(JSON.parse(line));
|
|
16530
16623
|
} catch {
|
|
16624
|
+
options.onIncomplete?.();
|
|
16531
16625
|
continue;
|
|
16532
16626
|
}
|
|
16533
16627
|
const p = object2(row?.payload);
|
|
16534
16628
|
const at = nativeTimeMs(row?.timestamp);
|
|
16535
|
-
if (!row || !p || at === null)
|
|
16629
|
+
if (!row || !p || at === null) {
|
|
16630
|
+
options.onIncomplete?.();
|
|
16536
16631
|
continue;
|
|
16632
|
+
}
|
|
16537
16633
|
switch (row.type) {
|
|
16538
16634
|
case "session_meta": {
|
|
16539
16635
|
if (!firstMeta) {
|
|
16540
16636
|
if (text(p.id) !== thread)
|
|
16541
16637
|
throw new Error("Codex rollout identity does not match its source");
|
|
16542
|
-
if (p.forked_from_id || p.parent_thread_id || p.subagent_history_start_ordinal)
|
|
16638
|
+
if (p.forked_from_id || p.parent_thread_id || p.subagent_history_start_ordinal) {
|
|
16543
16639
|
forkAt = nativeTimeMs(p.timestamp) ?? at;
|
|
16640
|
+
options.onIncomplete?.();
|
|
16641
|
+
}
|
|
16544
16642
|
cwd = text(p.cwd);
|
|
16545
16643
|
firstMeta = true;
|
|
16546
16644
|
}
|
|
@@ -16554,30 +16652,41 @@ async function readCodexRollouts(files, thread, signal) {
|
|
|
16554
16652
|
counters.context("", text(p.turn_id), model2);
|
|
16555
16653
|
break;
|
|
16556
16654
|
case "token_usage_record":
|
|
16655
|
+
if (!usage(p.usage) || !text(p.response_id))
|
|
16656
|
+
options.onIncomplete?.();
|
|
16557
16657
|
counters.record(at, model2, p);
|
|
16558
16658
|
break;
|
|
16559
16659
|
case "compacted": {
|
|
16560
16660
|
const record2 = object2(p.latest_token_usage_record);
|
|
16561
|
-
if (record2 && p.compaction_response_id && record2.response_id === p.compaction_response_id)
|
|
16661
|
+
if (record2 && p.compaction_response_id && record2.response_id === p.compaction_response_id) {
|
|
16662
|
+
if (!usage(record2.usage))
|
|
16663
|
+
options.onIncomplete?.();
|
|
16562
16664
|
counters.record(at, model2, record2, true);
|
|
16665
|
+
}
|
|
16563
16666
|
break;
|
|
16564
16667
|
}
|
|
16565
16668
|
case "response_item":
|
|
16566
16669
|
counters.boundary();
|
|
16670
|
+
firstPrompt ??= userItemPrompt(p);
|
|
16567
16671
|
break;
|
|
16568
16672
|
case "event_msg":
|
|
16569
16673
|
if (p.type === "task_started") {
|
|
16570
16674
|
counters.context("", text(p.turn_id), "");
|
|
16571
16675
|
counters.boundary();
|
|
16572
16676
|
}
|
|
16573
|
-
if (p.type === "user_message")
|
|
16677
|
+
if (p.type === "user_message") {
|
|
16574
16678
|
counters.boundary();
|
|
16679
|
+
firstPrompt ??= typedPrompt(p.message);
|
|
16680
|
+
}
|
|
16575
16681
|
if (p.type === "thread_settings_applied") {
|
|
16576
16682
|
model2 = text(object2(p.thread_settings)?.model) || model2;
|
|
16577
16683
|
counters.context("", "", model2);
|
|
16578
16684
|
}
|
|
16579
16685
|
if (p.type === "token_count") {
|
|
16580
16686
|
const info = object2(p.info);
|
|
16687
|
+
options.onTokenCount?.(info);
|
|
16688
|
+
if (info && !usage(info.total_token_usage))
|
|
16689
|
+
options.onIncomplete?.();
|
|
16581
16690
|
if (info)
|
|
16582
16691
|
counters.count(at, model2, usage(info.total_token_usage), usage(info.last_token_usage));
|
|
16583
16692
|
}
|
|
@@ -16604,12 +16713,22 @@ async function readCodexRollouts(files, thread, signal) {
|
|
|
16604
16713
|
...v.usage.known & 8 ? { cacheWriteInputTokens: written } : {},
|
|
16605
16714
|
...v.usage.known & 16 ? { reasoningOutputTokens: reasoning } : {}
|
|
16606
16715
|
});
|
|
16607
|
-
return entry ? [withUsageSession(entry, { sessionId: thread, cwd })] : [];
|
|
16716
|
+
return entry ? [withUsageSession(entry, { sessionId: thread, cwd, title: firstPrompt })] : [];
|
|
16608
16717
|
});
|
|
16609
16718
|
}
|
|
16610
|
-
function createCodexUsageStatistics(environment) {
|
|
16719
|
+
function createCodexUsageStatistics(environment, options = {}) {
|
|
16611
16720
|
const home = path.resolve(environment.CODEX_HOME || path.join(environment.HOME || environment.USERPROFILE || os.homedir(), ".codex"));
|
|
16612
16721
|
const groups = /* @__PURE__ */ new Map();
|
|
16722
|
+
let names = /* @__PURE__ */ new Map();
|
|
16723
|
+
let namesStamp = "";
|
|
16724
|
+
async function threadNames(signal) {
|
|
16725
|
+
const current = await stamp(path.join(home, "session_index.jsonl")).catch(() => "-");
|
|
16726
|
+
if (namesStamp === current)
|
|
16727
|
+
return names;
|
|
16728
|
+
names = await readThreadNames(home, signal);
|
|
16729
|
+
namesStamp = current;
|
|
16730
|
+
return names;
|
|
16731
|
+
}
|
|
16613
16732
|
return {
|
|
16614
16733
|
async listSources(signal) {
|
|
16615
16734
|
const found = /* @__PURE__ */ new Map();
|
|
@@ -16628,7 +16747,7 @@ function createCodexUsageStatistics(environment) {
|
|
|
16628
16747
|
if (!entry.isFile())
|
|
16629
16748
|
continue;
|
|
16630
16749
|
const thread = ROLLOUT.exec(entry.name)?.[1];
|
|
16631
|
-
if (!thread)
|
|
16750
|
+
if (!thread || options.sessionId && thread !== options.sessionId)
|
|
16632
16751
|
continue;
|
|
16633
16752
|
const list = found.get(thread) ?? [];
|
|
16634
16753
|
list.push({ file: file2, fingerprint: await stamp(file2) });
|
|
@@ -16637,13 +16756,14 @@ function createCodexUsageStatistics(environment) {
|
|
|
16637
16756
|
}
|
|
16638
16757
|
await visit(path.join(home, "sessions"), 0);
|
|
16639
16758
|
await visit(path.join(home, "archived_sessions"), 0);
|
|
16759
|
+
const indexStamp = options.sessionId ? "" : await stamp(path.join(home, "session_index.jsonl")).catch(() => "-");
|
|
16640
16760
|
const result = [];
|
|
16641
16761
|
groups.clear();
|
|
16642
16762
|
for (const [thread, files] of found) {
|
|
16643
16763
|
files.sort((a, b) => path.basename(a.file).localeCompare(path.basename(b.file)) || a.file.localeCompare(b.file));
|
|
16644
16764
|
const id = path.join(home, `usage-thread-${thread}`);
|
|
16645
16765
|
groups.set(id, { thread, files });
|
|
16646
|
-
result.push({ id, fingerprint: fingerprint(files) });
|
|
16766
|
+
result.push({ id, fingerprint: fingerprint(files, indexStamp) });
|
|
16647
16767
|
}
|
|
16648
16768
|
return result;
|
|
16649
16769
|
},
|
|
@@ -16674,11 +16794,511 @@ function createCodexUsageStatistics(environment) {
|
|
|
16674
16794
|
if (!duplicate)
|
|
16675
16795
|
kept.push(candidate);
|
|
16676
16796
|
}
|
|
16677
|
-
const entries = await readCodexRollouts(kept.map(({ file: file2 }) => file2), group.thread, signal);
|
|
16797
|
+
const entries = await readCodexRollouts(kept.map(({ file: file2 }) => file2), group.thread, signal, options);
|
|
16678
16798
|
for (const file2 of group.files)
|
|
16679
16799
|
if (await stamp(file2.file) !== file2.fingerprint)
|
|
16680
16800
|
throw new Error("Codex rollout changed while reading; refresh to retry");
|
|
16681
|
-
|
|
16801
|
+
const named = options.sessionId ? void 0 : (await threadNames(signal)).get(group.thread);
|
|
16802
|
+
return named ? entries.map((entry) => withUsageSession(entry, {
|
|
16803
|
+
sessionId: entry.sessionId,
|
|
16804
|
+
cwd: entry.cwd,
|
|
16805
|
+
title: named
|
|
16806
|
+
})) : entries;
|
|
16807
|
+
}
|
|
16808
|
+
};
|
|
16809
|
+
}
|
|
16810
|
+
|
|
16811
|
+
// dist/session-usage.js
|
|
16812
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
16813
|
+
|
|
16814
|
+
// ../../harness-adapter/dist/usage.js
|
|
16815
|
+
var tokenFields = [
|
|
16816
|
+
"inputTokens",
|
|
16817
|
+
"cachedInputTokens",
|
|
16818
|
+
"cacheWriteInputTokens",
|
|
16819
|
+
"outputTokens",
|
|
16820
|
+
"reasoningOutputTokens",
|
|
16821
|
+
"totalTokens",
|
|
16822
|
+
"contextWindowTokens",
|
|
16823
|
+
"contextUsedTokens"
|
|
16824
|
+
];
|
|
16825
|
+
var safeIntegerFields = [
|
|
16826
|
+
"planFiveHourResetsAtUnix",
|
|
16827
|
+
"planSevenDayResetsAtUnix",
|
|
16828
|
+
"timeToFirstOutputMs"
|
|
16829
|
+
];
|
|
16830
|
+
var percentFields = [
|
|
16831
|
+
"cacheHitRatePercent",
|
|
16832
|
+
"sessionCacheHitRatePercent",
|
|
16833
|
+
"planFiveHourUsedPercent",
|
|
16834
|
+
"planSevenDayUsedPercent"
|
|
16835
|
+
];
|
|
16836
|
+
var usageFields = /* @__PURE__ */ new Set([
|
|
16837
|
+
...tokenFields,
|
|
16838
|
+
...safeIntegerFields,
|
|
16839
|
+
...percentFields,
|
|
16840
|
+
"sessionCacheUsage",
|
|
16841
|
+
"totalCostUsd",
|
|
16842
|
+
"totalCredits",
|
|
16843
|
+
"contextUsagePercent",
|
|
16844
|
+
"outputTokensPerSecond",
|
|
16845
|
+
"apiOutputTokensPerSecond",
|
|
16846
|
+
"costSource",
|
|
16847
|
+
"unpricedModels"
|
|
16848
|
+
]);
|
|
16849
|
+
function isRecord(value) {
|
|
16850
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16851
|
+
}
|
|
16852
|
+
function parseHostUsage(value) {
|
|
16853
|
+
if (!isRecord(value))
|
|
16854
|
+
throw new Error("Harness Usage must be an object");
|
|
16855
|
+
const keys = Object.keys(value);
|
|
16856
|
+
if (keys.length === 0)
|
|
16857
|
+
throw new Error("Harness Usage must contain a reliable field");
|
|
16858
|
+
for (const key2 of keys) {
|
|
16859
|
+
if (!usageFields.has(key2)) {
|
|
16860
|
+
throw new Error(`Harness Usage contains unknown field '${key2}'`);
|
|
16861
|
+
}
|
|
16862
|
+
}
|
|
16863
|
+
for (const field of [
|
|
16864
|
+
"totalCredits",
|
|
16865
|
+
"contextUsagePercent",
|
|
16866
|
+
"apiOutputTokensPerSecond"
|
|
16867
|
+
]) {
|
|
16868
|
+
const candidate = value[field];
|
|
16869
|
+
if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate < 0)) {
|
|
16870
|
+
throw new Error(`Harness Usage '${field}' must be a finite non-negative number`);
|
|
16871
|
+
}
|
|
16872
|
+
}
|
|
16873
|
+
for (const field of tokenFields) {
|
|
16874
|
+
const candidate = value[field];
|
|
16875
|
+
if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isSafeInteger(candidate) || candidate < 0)) {
|
|
16876
|
+
throw new Error(`Harness Usage '${field}' must be a non-negative safe integer`);
|
|
16877
|
+
}
|
|
16878
|
+
}
|
|
16879
|
+
for (const field of safeIntegerFields) {
|
|
16880
|
+
const candidate = value[field];
|
|
16881
|
+
if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isSafeInteger(candidate) || candidate < 0)) {
|
|
16882
|
+
throw new Error(`Harness Usage '${field}' must be a non-negative safe integer`);
|
|
16883
|
+
}
|
|
16884
|
+
}
|
|
16885
|
+
if (value.outputTokensPerSecond !== void 0 && (typeof value.outputTokensPerSecond !== "number" || !Number.isFinite(value.outputTokensPerSecond) || value.outputTokensPerSecond < 0)) {
|
|
16886
|
+
throw new Error("Harness Usage 'outputTokensPerSecond' must be a finite non-negative number");
|
|
16887
|
+
}
|
|
16888
|
+
if (value.totalCostUsd !== void 0 && (typeof value.totalCostUsd !== "number" || !Number.isFinite(value.totalCostUsd) || value.totalCostUsd < 0)) {
|
|
16889
|
+
throw new Error("Harness Usage 'totalCostUsd' must be a finite non-negative number");
|
|
16890
|
+
}
|
|
16891
|
+
for (const field of percentFields) {
|
|
16892
|
+
const candidate = value[field];
|
|
16893
|
+
if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate < 0 || candidate > 100)) {
|
|
16894
|
+
throw new Error(`Harness Usage '${field}' must be between 0 and 100`);
|
|
16895
|
+
}
|
|
16896
|
+
}
|
|
16897
|
+
if (value.sessionCacheUsage !== void 0) {
|
|
16898
|
+
const totals2 = value.sessionCacheUsage;
|
|
16899
|
+
if (!isRecord(totals2) || Object.keys(totals2).some((key2) => key2 !== "inputTokens" && key2 !== "cachedInputTokens") || typeof totals2.inputTokens !== "number" || !Number.isSafeInteger(totals2.inputTokens) || totals2.inputTokens < 0 || typeof totals2.cachedInputTokens !== "number" || !Number.isSafeInteger(totals2.cachedInputTokens) || totals2.cachedInputTokens < 0 || totals2.cachedInputTokens > totals2.inputTokens) {
|
|
16900
|
+
throw new Error("Harness Usage 'sessionCacheUsage' must contain complete bounded token totals");
|
|
16901
|
+
}
|
|
16902
|
+
}
|
|
16903
|
+
const hasContextUsed = value.contextUsedTokens !== void 0;
|
|
16904
|
+
const hasContextWindow = value.contextWindowTokens !== void 0;
|
|
16905
|
+
if (hasContextUsed !== hasContextWindow) {
|
|
16906
|
+
throw new Error("Harness Usage context fields must be provided together");
|
|
16907
|
+
}
|
|
16908
|
+
if (hasContextWindow && value.contextWindowTokens === 0) {
|
|
16909
|
+
throw new Error("Harness Usage 'contextWindowTokens' must be greater than zero");
|
|
16910
|
+
}
|
|
16911
|
+
if (value.planFiveHourResetsAtUnix !== void 0 && value.planFiveHourUsedPercent === void 0) {
|
|
16912
|
+
throw new Error("Harness Usage 'planFiveHourResetsAtUnix' must be provided with 'planFiveHourUsedPercent'");
|
|
16913
|
+
}
|
|
16914
|
+
if (value.planSevenDayResetsAtUnix !== void 0 && value.planSevenDayUsedPercent === void 0) {
|
|
16915
|
+
throw new Error("Harness Usage 'planSevenDayResetsAtUnix' must be provided with 'planSevenDayUsedPercent'");
|
|
16916
|
+
}
|
|
16917
|
+
if (value.costSource !== void 0) {
|
|
16918
|
+
if (value.costSource !== "publicPrice" && value.costSource !== "native") {
|
|
16919
|
+
throw new Error("Harness Usage 'costSource' must be 'publicPrice' or 'native'");
|
|
16920
|
+
}
|
|
16921
|
+
if (value.totalCostUsd === void 0) {
|
|
16922
|
+
throw new Error("Harness Usage 'costSource' must be provided with 'totalCostUsd'");
|
|
16923
|
+
}
|
|
16924
|
+
}
|
|
16925
|
+
if (value.unpricedModels !== void 0) {
|
|
16926
|
+
const models = value.unpricedModels;
|
|
16927
|
+
if (!Array.isArray(models) || models.length === 0 || !models.every((model2) => typeof model2 === "string" && model2.length > 0)) {
|
|
16928
|
+
throw new Error("Harness Usage 'unpricedModels' must be a non-empty list of Model IDs");
|
|
16929
|
+
}
|
|
16930
|
+
if (value.costSource !== "publicPrice") {
|
|
16931
|
+
throw new Error("Harness Usage 'unpricedModels' must be provided with a 'publicPrice' cost");
|
|
16932
|
+
}
|
|
16933
|
+
return { ...value, unpricedModels: [...models] };
|
|
16934
|
+
}
|
|
16935
|
+
return { ...value };
|
|
16936
|
+
}
|
|
16937
|
+
var requestTokenFields = [
|
|
16938
|
+
"inputTokens",
|
|
16939
|
+
"cachedInputTokens",
|
|
16940
|
+
"cacheWriteInputTokens",
|
|
16941
|
+
"cacheWrite1hInputTokens",
|
|
16942
|
+
"outputTokens",
|
|
16943
|
+
"reasoningOutputTokens",
|
|
16944
|
+
"startedAtMs",
|
|
16945
|
+
"completedAtMs"
|
|
16946
|
+
];
|
|
16947
|
+
var requestFields = /* @__PURE__ */ new Set([
|
|
16948
|
+
...requestTokenFields,
|
|
16949
|
+
"requestId",
|
|
16950
|
+
"historical",
|
|
16951
|
+
"model",
|
|
16952
|
+
"provider"
|
|
16953
|
+
]);
|
|
16954
|
+
function parseHostUsageRequest(value) {
|
|
16955
|
+
if (!isRecord(value))
|
|
16956
|
+
throw new Error("Harness Usage request must be an object");
|
|
16957
|
+
for (const key2 of Object.keys(value)) {
|
|
16958
|
+
if (!requestFields.has(key2)) {
|
|
16959
|
+
throw new Error(`Harness Usage request contains unknown field '${key2}'`);
|
|
16960
|
+
}
|
|
16961
|
+
}
|
|
16962
|
+
if (typeof value.requestId !== "string" || value.requestId.length === 0) {
|
|
16963
|
+
throw new Error("Harness Usage request 'requestId' must be a non-empty string");
|
|
16964
|
+
}
|
|
16965
|
+
for (const field of ["model", "provider"]) {
|
|
16966
|
+
const candidate = value[field];
|
|
16967
|
+
if (candidate !== void 0 && (typeof candidate !== "string" || candidate.length === 0)) {
|
|
16968
|
+
throw new Error(`Harness Usage request '${field}' must be a non-empty string`);
|
|
16969
|
+
}
|
|
16970
|
+
}
|
|
16971
|
+
if (value.historical !== void 0 && typeof value.historical !== "boolean") {
|
|
16972
|
+
throw new Error("Harness Usage request 'historical' must be a boolean");
|
|
16973
|
+
}
|
|
16974
|
+
for (const field of requestTokenFields) {
|
|
16975
|
+
const candidate = value[field];
|
|
16976
|
+
if (candidate !== void 0 && (typeof candidate !== "number" || !Number.isSafeInteger(candidate) || candidate < 0)) {
|
|
16977
|
+
throw new Error(`Harness Usage request '${field}' must be a non-negative safe integer`);
|
|
16978
|
+
}
|
|
16979
|
+
}
|
|
16980
|
+
if (value.inputTokens === void 0 || value.outputTokens === void 0) {
|
|
16981
|
+
throw new Error("Harness Usage request must contain 'inputTokens' and 'outputTokens'");
|
|
16982
|
+
}
|
|
16983
|
+
const request = value;
|
|
16984
|
+
if ((request.cachedInputTokens ?? 0) + (request.cacheWriteInputTokens ?? 0) > request.inputTokens) {
|
|
16985
|
+
throw new Error("Harness Usage request cache Tokens must not exceed 'inputTokens'");
|
|
16986
|
+
}
|
|
16987
|
+
if ((request.reasoningOutputTokens ?? 0) > request.outputTokens) {
|
|
16988
|
+
throw new Error("Harness Usage request 'reasoningOutputTokens' must not exceed 'outputTokens'");
|
|
16989
|
+
}
|
|
16990
|
+
if (request.cacheWrite1hInputTokens !== void 0 && request.cacheWrite1hInputTokens > (request.cacheWriteInputTokens ?? -1)) {
|
|
16991
|
+
throw new Error("Harness Usage request 'cacheWrite1hInputTokens' must not exceed 'cacheWriteInputTokens'");
|
|
16992
|
+
}
|
|
16993
|
+
if (request.startedAtMs === void 0 !== (request.completedAtMs === void 0)) {
|
|
16994
|
+
throw new Error("Harness Usage request timing fields must be provided together");
|
|
16995
|
+
}
|
|
16996
|
+
if (request.startedAtMs !== void 0 && request.completedAtMs !== void 0 && request.completedAtMs < request.startedAtMs) {
|
|
16997
|
+
throw new Error("Harness Usage request 'completedAtMs' must not precede 'startedAtMs'");
|
|
16998
|
+
}
|
|
16999
|
+
return { ...request };
|
|
17000
|
+
}
|
|
17001
|
+
|
|
17002
|
+
// dist/session-observation.js
|
|
17003
|
+
var integer2 = (value) => typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
|
|
17004
|
+
function tokenSnapshot(value) {
|
|
17005
|
+
const token = object2(value);
|
|
17006
|
+
if (!token)
|
|
17007
|
+
return null;
|
|
17008
|
+
const total = object2(token.total);
|
|
17009
|
+
const last = object2(token.last);
|
|
17010
|
+
const result = {};
|
|
17011
|
+
for (const field of [
|
|
17012
|
+
"totalTokens",
|
|
17013
|
+
"inputTokens",
|
|
17014
|
+
"cachedInputTokens",
|
|
17015
|
+
"cacheWriteInputTokens",
|
|
17016
|
+
"outputTokens",
|
|
17017
|
+
"reasoningOutputTokens"
|
|
17018
|
+
]) {
|
|
17019
|
+
const n = integer2(total?.[field]);
|
|
17020
|
+
if (n !== void 0)
|
|
17021
|
+
result[field] = n;
|
|
17022
|
+
}
|
|
17023
|
+
const used = integer2(last?.totalTokens);
|
|
17024
|
+
const window = integer2(token.modelContextWindow);
|
|
17025
|
+
if (used !== void 0 && window !== void 0 && window > 0) {
|
|
17026
|
+
result.contextUsedTokens = used;
|
|
17027
|
+
result.contextWindowTokens = window;
|
|
17028
|
+
}
|
|
17029
|
+
const input = integer2(last?.inputTokens);
|
|
17030
|
+
const cached2 = integer2(last?.cachedInputTokens);
|
|
17031
|
+
if (input && cached2 !== void 0 && cached2 <= input)
|
|
17032
|
+
result.cacheHitRatePercent = cached2 / input * 100;
|
|
17033
|
+
if (result.inputTokens && result.cachedInputTokens !== void 0) {
|
|
17034
|
+
result.sessionCacheUsage = {
|
|
17035
|
+
inputTokens: result.inputTokens,
|
|
17036
|
+
cachedInputTokens: result.cachedInputTokens
|
|
17037
|
+
};
|
|
17038
|
+
}
|
|
17039
|
+
try {
|
|
17040
|
+
return Object.keys(result).length ? parseHostUsage(result) : null;
|
|
17041
|
+
} catch {
|
|
17042
|
+
return null;
|
|
17043
|
+
}
|
|
17044
|
+
}
|
|
17045
|
+
function observeSessionUsage(message) {
|
|
17046
|
+
const frame = object2(message);
|
|
17047
|
+
const params = object2(frame?.params);
|
|
17048
|
+
if (!params || typeof params.threadId !== "string" || !params.threadId)
|
|
17049
|
+
return null;
|
|
17050
|
+
const sessionId = params.threadId;
|
|
17051
|
+
if (frame?.method === "thread/tokenUsage/updated") {
|
|
17052
|
+
const usage2 = tokenSnapshot(params.tokenUsage);
|
|
17053
|
+
return usage2 ? { sessionId, usage: usage2 } : null;
|
|
17054
|
+
}
|
|
17055
|
+
if (frame?.method === "turn/started" || frame?.method === "turn/completed") {
|
|
17056
|
+
const turn = object2(params.turn);
|
|
17057
|
+
return typeof turn?.id === "string" && turn.id ? {
|
|
17058
|
+
sessionId,
|
|
17059
|
+
turn: { id: turn.id, phase: frame.method === "turn/started" ? "started" : "completed" }
|
|
17060
|
+
} : null;
|
|
17061
|
+
}
|
|
17062
|
+
if (typeof params.turnId !== "string" || !params.turnId)
|
|
17063
|
+
return null;
|
|
17064
|
+
if ([
|
|
17065
|
+
"item/agentMessage/delta",
|
|
17066
|
+
"item/reasoning/textDelta",
|
|
17067
|
+
"item/reasoning/summaryTextDelta"
|
|
17068
|
+
].includes(String(frame?.method)) && typeof params.delta === "string" && params.delta.length > 0) {
|
|
17069
|
+
return { sessionId, turn: { id: params.turnId, phase: "output" } };
|
|
17070
|
+
}
|
|
17071
|
+
return null;
|
|
17072
|
+
}
|
|
17073
|
+
function rolloutTokenSnapshot(info) {
|
|
17074
|
+
const record2 = object2(info);
|
|
17075
|
+
if (!record2)
|
|
17076
|
+
return null;
|
|
17077
|
+
const convert = (value) => {
|
|
17078
|
+
const u = object2(value);
|
|
17079
|
+
return u && {
|
|
17080
|
+
totalTokens: u.total_tokens,
|
|
17081
|
+
inputTokens: u.input_tokens,
|
|
17082
|
+
cachedInputTokens: u.cached_input_tokens,
|
|
17083
|
+
cacheWriteInputTokens: u.cache_write_input_tokens,
|
|
17084
|
+
outputTokens: u.output_tokens,
|
|
17085
|
+
reasoningOutputTokens: u.reasoning_output_tokens
|
|
17086
|
+
};
|
|
17087
|
+
};
|
|
17088
|
+
return tokenSnapshot({
|
|
17089
|
+
total: convert(record2.total_token_usage),
|
|
17090
|
+
last: convert(record2.last_token_usage),
|
|
17091
|
+
modelContextWindow: record2.model_context_window
|
|
17092
|
+
});
|
|
17093
|
+
}
|
|
17094
|
+
|
|
17095
|
+
// dist/response-timing.js
|
|
17096
|
+
var nonNegativeInteger = (value) => typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
17097
|
+
var CodexResponseTiming = class {
|
|
17098
|
+
#turns = /* @__PURE__ */ new Map();
|
|
17099
|
+
reset() {
|
|
17100
|
+
this.#turns.clear();
|
|
17101
|
+
}
|
|
17102
|
+
observe(message, now) {
|
|
17103
|
+
const frame = object2(message);
|
|
17104
|
+
const params = object2(frame?.params);
|
|
17105
|
+
if (!params || typeof params.threadId !== "string")
|
|
17106
|
+
return null;
|
|
17107
|
+
const sessionId = params.threadId;
|
|
17108
|
+
const turn = object2(params.turn);
|
|
17109
|
+
if (frame?.method === "turn/started" && typeof turn?.id === "string") {
|
|
17110
|
+
if (this.#turns.get(sessionId)?.id !== turn.id) {
|
|
17111
|
+
this.#turns.set(sessionId, {
|
|
17112
|
+
id: turn.id,
|
|
17113
|
+
pending: false,
|
|
17114
|
+
unavailable: false,
|
|
17115
|
+
seen: /* @__PURE__ */ new Set()
|
|
17116
|
+
});
|
|
17117
|
+
}
|
|
17118
|
+
return null;
|
|
17119
|
+
}
|
|
17120
|
+
const state = this.#turns.get(sessionId);
|
|
17121
|
+
if (!state)
|
|
17122
|
+
return null;
|
|
17123
|
+
const unavailable = () => {
|
|
17124
|
+
state.unavailable = true;
|
|
17125
|
+
return { sessionId, timingUnavailable: { turnId: state.id } };
|
|
17126
|
+
};
|
|
17127
|
+
if (frame?.method === "thread/closed") {
|
|
17128
|
+
this.#turns.delete(sessionId);
|
|
17129
|
+
return unavailable();
|
|
17130
|
+
}
|
|
17131
|
+
if (frame?.method === "turn/completed" && turn?.id === state.id) {
|
|
17132
|
+
this.#turns.delete(sessionId);
|
|
17133
|
+
return state.pending || state.unavailable ? unavailable() : null;
|
|
17134
|
+
}
|
|
17135
|
+
if (params.turnId !== state.id)
|
|
17136
|
+
return null;
|
|
17137
|
+
if (frame?.method === "error")
|
|
17138
|
+
return unavailable();
|
|
17139
|
+
if (frame?.method === "rawResponse/completed") {
|
|
17140
|
+
const id = params.responseId;
|
|
17141
|
+
if (typeof id !== "string" || !id)
|
|
17142
|
+
return unavailable();
|
|
17143
|
+
if (state.seen.has(id))
|
|
17144
|
+
return null;
|
|
17145
|
+
state.seen.add(id);
|
|
17146
|
+
const usage2 = object2(params.usage);
|
|
17147
|
+
const startedAtMs = state.firstOutputAtMs;
|
|
17148
|
+
state.firstOutputAtMs = void 0;
|
|
17149
|
+
state.pending = false;
|
|
17150
|
+
if (state.unavailable || startedAtMs === void 0 || !nonNegativeInteger(now) || now <= startedAtMs || !nonNegativeInteger(usage2?.outputTokens) || usage2.reasoningOutputTokens != null && (!nonNegativeInteger(usage2.reasoningOutputTokens) || usage2.reasoningOutputTokens > usage2.outputTokens)) {
|
|
17151
|
+
return unavailable();
|
|
17152
|
+
}
|
|
17153
|
+
return {
|
|
17154
|
+
sessionId,
|
|
17155
|
+
requestTiming: {
|
|
17156
|
+
requestId: id,
|
|
17157
|
+
turnId: state.id,
|
|
17158
|
+
outputTokens: usage2.outputTokens,
|
|
17159
|
+
startedAtMs,
|
|
17160
|
+
completedAtMs: now
|
|
17161
|
+
}
|
|
17162
|
+
};
|
|
17163
|
+
}
|
|
17164
|
+
if (frame?.method === "rawResponseItem/completed") {
|
|
17165
|
+
const item = object2(params.item);
|
|
17166
|
+
if (item?.type === "message" && item.role === "assistant" || [
|
|
17167
|
+
"reasoning",
|
|
17168
|
+
"function_call",
|
|
17169
|
+
"custom_tool_call",
|
|
17170
|
+
"local_shell_call",
|
|
17171
|
+
"web_search_call",
|
|
17172
|
+
"image_generation_call",
|
|
17173
|
+
"tool_search_call"
|
|
17174
|
+
].includes(String(item?.type)))
|
|
17175
|
+
state.pending = true;
|
|
17176
|
+
return null;
|
|
17177
|
+
}
|
|
17178
|
+
if (frame?.method === "item/started") {
|
|
17179
|
+
const item = object2(params.item);
|
|
17180
|
+
if (item?.type === "agentMessage" || item?.type === "reasoning" || item?.type === "plan") {
|
|
17181
|
+
state.pending = true;
|
|
17182
|
+
state.firstOutputAtMs ??= now;
|
|
17183
|
+
}
|
|
17184
|
+
return null;
|
|
17185
|
+
}
|
|
17186
|
+
const reasoning = frame?.method === "item/reasoning/textDelta" || frame?.method === "item/reasoning/summaryTextDelta";
|
|
17187
|
+
if ((reasoning || frame?.method === "item/agentMessage/delta" || frame?.method === "item/plan/delta") && typeof params.delta === "string" && params.delta.length > 0) {
|
|
17188
|
+
state.pending = true;
|
|
17189
|
+
state.firstOutputAtMs ??= now;
|
|
17190
|
+
}
|
|
17191
|
+
return null;
|
|
17192
|
+
}
|
|
17193
|
+
};
|
|
17194
|
+
|
|
17195
|
+
// dist/session-usage.js
|
|
17196
|
+
function createCodexSessionUsage(environment, closed) {
|
|
17197
|
+
const timing = new CodexResponseTiming();
|
|
17198
|
+
const rawCompleted = "rawResponse/completed";
|
|
17199
|
+
let hideRawCompleted = false;
|
|
17200
|
+
const live = /* @__PURE__ */ new Map();
|
|
17201
|
+
const cache = /* @__PURE__ */ new Map();
|
|
17202
|
+
return {
|
|
17203
|
+
requestOptions({ method, params, initializeParams }) {
|
|
17204
|
+
if (closed.aborted)
|
|
17205
|
+
return null;
|
|
17206
|
+
if (method === "initialize") {
|
|
17207
|
+
const capabilities2 = object2(params.capabilities);
|
|
17208
|
+
const excluded2 = capabilities2?.optOutNotificationMethods;
|
|
17209
|
+
hideRawCompleted = false;
|
|
17210
|
+
if (capabilities2?.experimentalApi !== true || !Array.isArray(excluded2))
|
|
17211
|
+
return null;
|
|
17212
|
+
if (!excluded2.includes(rawCompleted))
|
|
17213
|
+
return null;
|
|
17214
|
+
hideRawCompleted = true;
|
|
17215
|
+
return {
|
|
17216
|
+
capabilities: {
|
|
17217
|
+
...capabilities2,
|
|
17218
|
+
optOutNotificationMethods: excluded2.filter((method2) => method2 !== rawCompleted)
|
|
17219
|
+
}
|
|
17220
|
+
};
|
|
17221
|
+
}
|
|
17222
|
+
const capabilities = object2(initializeParams?.capabilities);
|
|
17223
|
+
const excluded = capabilities?.optOutNotificationMethods;
|
|
17224
|
+
return method === "thread/start" && capabilities?.experimentalApi === true && !(Array.isArray(excluded) && excluded.includes(rawCompleted)) && (params.experimentalRawEvents === void 0 || params.experimentalRawEvents === false) ? { experimentalRawEvents: true } : null;
|
|
17225
|
+
},
|
|
17226
|
+
shouldForwardNotification(message) {
|
|
17227
|
+
return closed.aborted || !hideRawCompleted || object2(message)?.method !== rawCompleted;
|
|
17228
|
+
},
|
|
17229
|
+
reset() {
|
|
17230
|
+
timing.reset();
|
|
17231
|
+
},
|
|
17232
|
+
observe(message, observedAtMs = Date.now()) {
|
|
17233
|
+
if (closed.aborted)
|
|
17234
|
+
return null;
|
|
17235
|
+
const observation = observeSessionUsage(message);
|
|
17236
|
+
const measured = timing.observe(message, observedAtMs);
|
|
17237
|
+
if (observation?.usage)
|
|
17238
|
+
live.set(observation.sessionId, observation.usage);
|
|
17239
|
+
return measured ? { ...observation, ...measured } : observation;
|
|
17240
|
+
},
|
|
17241
|
+
async read(sessionId, signal) {
|
|
17242
|
+
signal = AbortSignal.any([signal, closed]);
|
|
17243
|
+
signal.throwIfAborted();
|
|
17244
|
+
for (let attempt = 0; ; attempt++) {
|
|
17245
|
+
let snapshot = null;
|
|
17246
|
+
let complete = true;
|
|
17247
|
+
const reader = createCodexUsageStatistics(environment, {
|
|
17248
|
+
sessionId,
|
|
17249
|
+
onTokenCount: (info) => {
|
|
17250
|
+
snapshot = rolloutTokenSnapshot(info) ?? snapshot;
|
|
17251
|
+
},
|
|
17252
|
+
onIncomplete: () => {
|
|
17253
|
+
complete = false;
|
|
17254
|
+
}
|
|
17255
|
+
});
|
|
17256
|
+
const sources = await reader.listSources(signal);
|
|
17257
|
+
const source = sources[0];
|
|
17258
|
+
if (!source)
|
|
17259
|
+
return null;
|
|
17260
|
+
let history = cache.get(sessionId);
|
|
17261
|
+
if (history?.fingerprint !== source.fingerprint) {
|
|
17262
|
+
const entries = await reader.readSource(source.id, signal);
|
|
17263
|
+
const requests = entries.map((entry) => parseHostUsageRequest({
|
|
17264
|
+
requestId: entry.id,
|
|
17265
|
+
historical: true,
|
|
17266
|
+
...entry.model ? { model: entry.model } : {},
|
|
17267
|
+
inputTokens: entry.inputTokens,
|
|
17268
|
+
outputTokens: entry.outputTokens,
|
|
17269
|
+
...entry.cachedInputTokens !== void 0 ? { cachedInputTokens: entry.cachedInputTokens } : {},
|
|
17270
|
+
// Codex/OpenAI cache has no separately billed cache creation bucket.
|
|
17271
|
+
cacheWriteInputTokens: entry.cacheWriteInputTokens ?? 0,
|
|
17272
|
+
...entry.reasoningOutputTokens !== void 0 ? { reasoningOutputTokens: entry.reasoningOutputTokens } : {}
|
|
17273
|
+
}));
|
|
17274
|
+
const inputTokens = requests.reduce((sum, r) => sum + r.inputTokens, 0);
|
|
17275
|
+
const outputTokens = requests.reduce((sum, r) => sum + r.outputTokens, 0);
|
|
17276
|
+
const cachedInputTokens = requests.every((r) => r.cachedInputTokens !== void 0) ? requests.reduce((sum, r) => sum + (r.cachedInputTokens ?? 0), 0) : void 0;
|
|
17277
|
+
const last = requests.at(-1);
|
|
17278
|
+
const usage2 = requests.length ? parseHostUsage({
|
|
17279
|
+
...snapshot ?? {},
|
|
17280
|
+
inputTokens,
|
|
17281
|
+
outputTokens,
|
|
17282
|
+
totalTokens: inputTokens + outputTokens,
|
|
17283
|
+
...cachedInputTokens !== void 0 ? { cachedInputTokens } : {},
|
|
17284
|
+
...complete && cachedInputTokens !== void 0 ? { sessionCacheUsage: { inputTokens, cachedInputTokens } } : {},
|
|
17285
|
+
...last?.inputTokens && last.cachedInputTokens !== void 0 ? { cacheHitRatePercent: last.cachedInputTokens / last.inputTokens * 100 } : {}
|
|
17286
|
+
}) : snapshot;
|
|
17287
|
+
history = {
|
|
17288
|
+
fingerprint: source.fingerprint,
|
|
17289
|
+
history: { usage: usage2, requests, complete: complete && requests.length > 0 }
|
|
17290
|
+
};
|
|
17291
|
+
cache.set(sessionId, history);
|
|
17292
|
+
}
|
|
17293
|
+
const result = history.history;
|
|
17294
|
+
const latest = live.get(sessionId);
|
|
17295
|
+
const caughtUp = !latest || (latest.inputTokens ?? 0) <= (result.usage?.inputTokens ?? 0) && (latest.outputTokens ?? 0) <= (result.usage?.outputTokens ?? 0);
|
|
17296
|
+
if (!caughtUp && attempt < 2) {
|
|
17297
|
+
await delay(50 * (attempt + 1), void 0, { signal });
|
|
17298
|
+
continue;
|
|
17299
|
+
}
|
|
17300
|
+
return { ...result, complete: result.complete && caughtUp };
|
|
17301
|
+
}
|
|
16682
17302
|
}
|
|
16683
17303
|
};
|
|
16684
17304
|
}
|
|
@@ -16689,6 +17309,7 @@ function createUsageStatisticsAdapter(context) {
|
|
|
16689
17309
|
const reader = createCodexUsageStatistics(context.environment);
|
|
16690
17310
|
return {
|
|
16691
17311
|
harnessId: harnessIdSchema.parse("codex-usage"),
|
|
17312
|
+
sessionUsage: createCodexSessionUsage(context.environment, abort.signal),
|
|
16692
17313
|
usageStatistics: {
|
|
16693
17314
|
listSources: (signal) => reader.listSources(AbortSignal.any([signal, abort.signal])),
|
|
16694
17315
|
readSource: (id, signal) => reader.readSource(id, AbortSignal.any([signal, abort.signal]))
|