From cb2f39ee790580c12bea07c6108de8399d1b9c3c Mon Sep 17 00:00:00 2001 From: Peter Kirkham Date: Mon, 13 Jul 2026 09:53:24 +0100 Subject: [PATCH] =?UTF-8?q?fix:=20compact=20boundary=20marker=20showing=20?= =?UTF-8?q?"undefined=20=C2=B7=20~NaNK=20tokens"=20on=20codex=20sessions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The codex adapter emitted _posthog/compact_boundary with only sessionId, while the UI assumed trigger/preTokens were always present. Make the UI render gracefully without them and have the codex adapter report trigger: "auto" plus preTokens from its usage tracker. Generated-By: PostHog Code Task-Id: 71484330-f52a-49bb-a528-5c708028bbf9 --- .../codex-app-server-agent.test.ts | 8 +++- .../codex-app-server-agent.ts | 4 ++ .../components/buildConversationItems.ts | 5 +- .../session-update/CompactBoundaryView.tsx | 48 +++++++++++-------- .../session-update/SessionUpdateView.tsx | 4 +- 5 files changed, 42 insertions(+), 27 deletions(-) diff --git a/packages/agent/src/adapters/codex-app-server/codex-app-server-agent.test.ts b/packages/agent/src/adapters/codex-app-server/codex-app-server-agent.test.ts index 6800a7cef0..11ede1c7df 100644 --- a/packages/agent/src/adapters/codex-app-server/codex-app-server-agent.test.ts +++ b/packages/agent/src/adapters/codex-app-server/codex-app-server-agent.test.ts @@ -1810,6 +1810,9 @@ describe("CodexAppServerAgent", () => { } as unknown as NewSessionRequest); // The compaction item brackets it: started → in progress, completed → boundary. + stub.emit("thread/tokenUsage/updated", { + tokenUsage: { last: { inputTokens: 90000, totalTokens: 120000 } }, + }); stub.emit("item/started", { item: { type: "contextCompaction", id: "c1" }, }); @@ -1817,11 +1820,12 @@ describe("CodexAppServerAgent", () => { item: { type: "contextCompaction", id: "c1", summary: "…" }, }); - // compact_boundary clears isCompacting + drains the host queue. + // compact_boundary clears isCompacting + drains the host queue; trigger/preTokens + // feed the renderer's boundary marker. expect( extNotifications.find((n) => n.method === "_posthog/compact_boundary") ?.params, - ).toMatchObject({ sessionId: "t" }); + ).toMatchObject({ sessionId: "t", trigger: "auto", preTokens: 120000 }); // ...and a user-visible marker lands in the transcript. expect(sessionUpdates).toContainEqual({ sessionId: "t", diff --git a/packages/agent/src/adapters/codex-app-server/codex-app-server-agent.ts b/packages/agent/src/adapters/codex-app-server/codex-app-server-agent.ts index e2209f5e05..3efde3ca58 100644 --- a/packages/agent/src/adapters/codex-app-server/codex-app-server-agent.ts +++ b/packages/agent/src/adapters/codex-app-server/codex-app-server-agent.ts @@ -1091,6 +1091,10 @@ export class CodexAppServerAgent extends BaseAcpAgent { void this.client .extNotification(POSTHOG_NOTIFICATIONS.COMPACT_BOUNDARY, { sessionId: this.sessionId, + // codex only compacts on its own (contextCompaction items); preTokens is the last + // context occupancy reading, omitted when no usage arrived yet. + trigger: "auto", + preTokens: this.usage.contextTokens(), }) .catch(() => undefined); void this.client diff --git a/packages/ui/src/features/sessions/components/buildConversationItems.ts b/packages/ui/src/features/sessions/components/buildConversationItems.ts index c46a2db492..339239f07c 100644 --- a/packages/ui/src/features/sessions/components/buildConversationItems.ts +++ b/packages/ui/src/features/sessions/components/buildConversationItems.ts @@ -541,9 +541,10 @@ function handleNotification( if (isNotification(msg.method, POSTHOG_NOTIFICATIONS.COMPACT_BOUNDARY)) { ensureImplicitTurn(b, ts); + // trigger/preTokens are adapter-dependent: the claude adapter sends both, codex sends neither. const params = msg.params as { - trigger: "manual" | "auto"; - preTokens: number; + trigger?: "manual" | "auto"; + preTokens?: number; contextSize?: number; }; markCompactingStatusComplete(b); diff --git a/packages/ui/src/features/sessions/components/session-update/CompactBoundaryView.tsx b/packages/ui/src/features/sessions/components/session-update/CompactBoundaryView.tsx index 6629be9134..40411ffb26 100644 --- a/packages/ui/src/features/sessions/components/session-update/CompactBoundaryView.tsx +++ b/packages/ui/src/features/sessions/components/session-update/CompactBoundaryView.tsx @@ -4,8 +4,9 @@ import { Badge, Box, Flex, Text } from "@radix-ui/themes"; import { useChatThreadChrome } from "../chat-thread/chatThreadChrome"; interface CompactBoundaryViewProps { - trigger: "manual" | "auto"; - preTokens: number; + // Both optional — the codex adapter reports a boundary without metadata. + trigger?: "manual" | "auto"; + preTokens?: number; contextSize?: number; } @@ -14,9 +15,10 @@ export function CompactBoundaryView({ preTokens, contextSize, }: CompactBoundaryViewProps) { - const tokensK = Math.round(preTokens / 1000); + const hasTokens = typeof preTokens === "number" && Number.isFinite(preTokens); + const tokensK = hasTokens ? Math.round(preTokens / 1000) : null; const percent = - contextSize && contextSize > 0 + hasTokens && contextSize && contextSize > 0 ? Math.round((preTokens / contextSize) * 100) : null; // New thread renders the boundary as a centered separator marker; the legacy thread keeps its @@ -24,13 +26,13 @@ export function CompactBoundaryView({ const chatChrome = useChatThreadChrome(); if (chatChrome) { + const markerParts = ["Conversation compacted"]; + if (trigger) markerParts.push(trigger); + if (percent !== null) markerParts.push(`${percent}% of context`); + else if (tokensK !== null) markerParts.push(`~${tokensK}K tokens`); return ( - - {`Conversation compacted · ${trigger} · ${ - percent !== null ? `${percent}% of context` : `~${tokensK}K tokens` - }`} - + {markerParts.join(" · ")} ); } @@ -40,18 +42,22 @@ export function CompactBoundaryView({ Conversation compacted - - {trigger} - - - {percent !== null - ? `(${percent}% of context · ~${tokensK}K tokens summarized)` - : `(~${tokensK}K tokens summarized)`} - + {trigger && ( + + {trigger} + + )} + {tokensK !== null && ( + + {percent !== null + ? `(${percent}% of context · ~${tokensK}K tokens summarized)` + : `(~${tokensK}K tokens summarized)`} + + )} ); diff --git a/packages/ui/src/features/sessions/components/session-update/SessionUpdateView.tsx b/packages/ui/src/features/sessions/components/session-update/SessionUpdateView.tsx index 1de866d66b..90b0774665 100644 --- a/packages/ui/src/features/sessions/components/session-update/SessionUpdateView.tsx +++ b/packages/ui/src/features/sessions/components/session-update/SessionUpdateView.tsx @@ -25,8 +25,8 @@ export type RenderItem = } | { sessionUpdate: "compact_boundary"; - trigger: "manual" | "auto"; - preTokens: number; + trigger?: "manual" | "auto"; + preTokens?: number; contextSize?: number; } | {