Skip to content

Commit 48b6bdd

Browse files
committed
fix(gateway): skip diagnostic entries in session previews
1 parent 08c6548 commit 48b6bdd

3 files changed

Lines changed: 30 additions & 15 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Docs: https://docs.openclaw.ai
1212

1313
### Fixes
1414

15+
- Gateway/sessions: ignore diagnostic transcript entries when deriving Control UI/WebChat session selector previews, so background health or context records do not replace the latest user/assistant title text. (#66656) Thanks @Tianworld.
1516
- Control UI/WebChat: keep large attachment payloads out of Lit state and optimistic chat messages, using object URL previews plus send-time payload serialization so PDF/image uploads no longer trigger `RangeError: Maximum call stack size exceeded`. Fixes #73360; refs #54378 and #63432. Thanks @hejunhui-73, @Ansub, and @christianhernandez3-afk.
1617
- Agents/models: keep per-agent primary models strict when `fallbacks` is omitted, so probe-only custom providers are not tried as hidden fallback candidates unless the agent explicitly opts in. Fixes #73332. Thanks @haumanto.
1718
- Gateway/models: add `models.pricing.enabled` so offline or restricted-network installs can skip startup OpenRouter and LiteLLM pricing-catalog fetches while keeping explicit model costs working. Fixes #53639. Thanks @callebtc, @palewire, and @rjdjohnston.

src/gateway/session-utils.fs.test.ts

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -235,21 +235,27 @@ describe("readLastMessagePreviewFromTranscript", () => {
235235
expect(result).toBe("Real last");
236236
});
237237

238-
test("skips diagnostic heartbeat entries when deriving last message preview", () => {
239-
const sessionId = "test-last-skip-heartbeat";
240-
const transcriptPath = path.join(tmpDir, `${sessionId}.jsonl`);
241-
const lines = [
242-
JSON.stringify({ message: { role: "user", content: "Real last" } }),
243-
JSON.stringify({
244-
type: "diagnostic.heartbeat",
245-
message: { role: "assistant", content: "heartbeat: ok" },
246-
}),
247-
];
248-
fs.writeFileSync(transcriptPath, lines.join("\n"), "utf-8");
238+
test.each([
239+
["diagnostic.heartbeat", "heartbeat: ok"],
240+
["diagnostic.agentContext", "context refresh complete"],
241+
] as const)(
242+
"skips %s entries when deriving last message preview",
243+
(diagnosticType, diagnosticText) => {
244+
const sessionId = `test-last-skip-${diagnosticType.replace(".", "-")}`;
245+
const transcriptPath = path.join(tmpDir, `${sessionId}.jsonl`);
246+
const lines = [
247+
JSON.stringify({ message: { role: "user", content: "Real last" } }),
248+
JSON.stringify({
249+
type: diagnosticType,
250+
message: { role: "assistant", content: diagnosticText },
251+
}),
252+
];
253+
fs.writeFileSync(transcriptPath, lines.join("\n"), "utf-8");
249254

250-
const result = readLastMessagePreviewFromTranscript(sessionId, storePath);
251-
expect(result).toBe("Real last");
252-
});
255+
const result = readLastMessagePreviewFromTranscript(sessionId, storePath);
256+
expect(result).toBe("Real last");
257+
},
258+
);
253259

254260
test("returns null when no user/assistant messages exist", () => {
255261
const sessionId = "test-last-no-match";

src/gateway/session-utils.fs.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,14 @@ export function readFirstUserMessageFromTranscript(
415415
const LAST_MSG_MAX_BYTES = 16384;
416416
const LAST_MSG_MAX_LINES = 20;
417417

418+
function isDiagnosticTranscriptEntry(entry: unknown): boolean {
419+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
420+
return false;
421+
}
422+
const type = (entry as { type?: unknown }).type;
423+
return typeof type === "string" && type.startsWith("diagnostic.");
424+
}
425+
418426
function readLastMessagePreviewFromOpenTranscript(params: {
419427
fd: number;
420428
size: number;
@@ -434,7 +442,7 @@ function readLastMessagePreviewFromOpenTranscript(params: {
434442
const parsed = JSON.parse(line);
435443
// Keep session selectors usable: heartbeat/diagnostic lines are not
436444
// meaningful "last message" previews and can overwrite session titles.
437-
if (typeof parsed?.type === "string" && parsed.type === "diagnostic.heartbeat") {
445+
if (isDiagnosticTranscriptEntry(parsed)) {
438446
continue;
439447
}
440448
const msg = parsed?.message as TranscriptMessage | undefined;

0 commit comments

Comments
 (0)