Skip to content
This repository was archived by the owner on Aug 6, 2026. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2818,6 +2818,14 @@ describe("CodexAppServerAgent", () => {
_meta: {},
} as unknown as NewSessionRequest);

// The last usage reading before compaction feeds the boundary's preTokens/contextSize.
stub.emit("thread/tokenUsage/updated", {
tokenUsage: {
last: { inputTokens: 180000, outputTokens: 5000, totalTokens: 185000 },
modelContextWindow: 200000,
},
});

// The compaction item brackets it: started → in progress, completed → boundary.
stub.emit("item/started", {
item: { type: "contextCompaction", id: "c1" },
Expand All @@ -2830,7 +2838,12 @@ describe("CodexAppServerAgent", () => {
expect(
extNotifications.find((n) => n.method === "_posthog/compact_boundary")
?.params,
).toMatchObject({ sessionId: "t" });
).toMatchObject({
sessionId: "t",
trigger: "auto",
preTokens: 185000,
contextSize: 200000,
});
// ...and a user-visible marker lands in the transcript.
expect(sessionUpdates).toContainEqual({
sessionId: "t",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1747,6 +1747,10 @@ export class CodexAppServerAgent extends BaseAcpAgent {
void this.client
.extNotification(POSTHOG_NOTIFICATIONS.COMPACT_BOUNDARY, {
sessionId: this.sessionId,
// codex only auto-compacts; there's no manual /compact.
trigger: "auto",
preTokens: this.usage.contextTokens(),
contextSize: this.usage.contextSize(),
})
.catch(() => undefined);
void this.client
Expand Down
8 changes: 8 additions & 0 deletions packages/agent/src/adapters/codex-app-server/usage-tracker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ export class UsageTracker {
private baseline: ContextBreakdownBaseline = emptyBaseline();
private lastTurn?: Usage;
private contextUsed?: number;
// Model context window is a constant, so it survives resetForTurn.
private contextWindow?: number;

setBaseline(baseline: ContextBreakdownBaseline): void {
this.baseline = baseline;
Expand All @@ -48,6 +50,7 @@ export class UsageTracker {
const { context, used, size } = reading;
// Drives the per-source breakdown's "conversation" bucket on turn complete.
this.contextUsed = used;
if (size != null) this.contextWindow = size;
const inputTokens = context.inputTokens ?? 0;
const outputTokens = context.outputTokens ?? 0;
const cachedReadTokens = context.cachedInputTokens ?? 0;
Expand Down Expand Up @@ -81,4 +84,9 @@ export class UsageTracker {
contextTokens(): number | undefined {
return this.contextUsed;
}

/** Model context window last reported by codex, or undefined pre-usage. */
contextSize(): number | undefined {
return this.contextWindow;
}
}
Loading