diff --git a/src/logging/diagnostic-stability.test.ts b/src/logging/diagnostic-stability.test.ts index 6610157a390..ba2e4d22e8b 100644 --- a/src/logging/diagnostic-stability.test.ts +++ b/src/logging/diagnostic-stability.test.ts @@ -97,6 +97,45 @@ describe("diagnostic stability recorder", () => { expect(snapshot.events[1]).not.toHaveProperty("reason"); }); + it("summarizes assembled context diagnostics without prompt text", async () => { + startDiagnosticStabilityRecorder(); + + emitDiagnosticEvent({ + type: "context.assembled", + runId: "run-secret", + sessionId: "session-secret", + provider: "openai", + model: "gpt-5.4", + channel: "telegram", + trigger: "user-message", + messageCount: 4, + historyTextChars: 1200, + historyImageBlocks: 1, + maxMessageTextChars: 800, + systemPromptChars: 300, + promptChars: 100, + promptImages: 1, + contextTokenBudget: 200_000, + reserveTokens: 20_000, + }); + await new Promise((resolve) => setImmediate(resolve)); + + const snapshot = getDiagnosticStabilitySnapshot({ limit: 10 }); + + expect(snapshot.events[0]).toMatchObject({ + type: "context.assembled", + provider: "openai", + model: "gpt-5.4", + channel: "telegram", + count: 4, + context: { limit: 200_000 }, + }); + expect(snapshot.events[0]).not.toHaveProperty("runId"); + expect(snapshot.events[0]).not.toHaveProperty("sessionId"); + expect(snapshot.events[0]).not.toHaveProperty("promptChars"); + expect(snapshot.events[0]).not.toHaveProperty("systemPromptChars"); + }); + it("sanitizes tool and model diagnostic error categories", async () => { startDiagnosticStabilityRecorder(); diff --git a/src/logging/diagnostic-stability.ts b/src/logging/diagnostic-stability.ts index ea209f62261..50b0357a3e9 100644 --- a/src/logging/diagnostic-stability.ts +++ b/src/logging/diagnostic-stability.ts @@ -246,6 +246,14 @@ function sanitizeDiagnosticEvent(event: DiagnosticEventPayload): DiagnosticStabi case "run.attempt": record.count = event.attempt; break; + case "context.assembled": + record.channel = event.channel; + record.provider = event.provider; + record.model = event.model; + record.count = event.messageCount; + record.context = + event.contextTokenBudget !== undefined ? { limit: event.contextTokenBudget } : undefined; + break; case "diagnostic.heartbeat": record.webhooks = { ...event.webhooks }; record.active = event.active;