fix(coding-agent): handle empty session titles and session info metadata (#2304)

* fix(coding-agent): handle empty session titles in tree

* fix(coding-agent): ignore session info in summaries

* docs: update changelog for PR #2304
This commit is contained in:
Aliou Diallo
2026-03-17 16:22:04 +01:00
committed by GitHub
parent 2d05e87281
commit 18d90b5c48
5 changed files with 25 additions and 8 deletions

View File

@@ -162,6 +162,7 @@ function getMessageFromEntry(entry: SessionEntry): AgentMessage | undefined {
case "model_change":
case "custom":
case "label":
case "session_info":
return undefined;
}
}

View File

@@ -317,7 +317,10 @@ function findValidCutPoints(entries: SessionEntry[], startIndex: number, endInde
case "custom":
case "custom_message":
case "label":
case "session_info":
break;
}
// branch_summary and custom_message are user-role messages, valid cut points
if (entry.type === "branch_summary" || entry.type === "custom_message") {
cutPoints.push(i);

View File

@@ -565,12 +565,10 @@ async function buildSessionInfo(filePath: string): Promise<SessionInfo | null> {
let name: string | undefined;
for (const entry of entries) {
// Extract session name (use latest)
// Extract session name (use latest, including explicit clears)
if (entry.type === "session_info") {
const infoEntry = entry as SessionInfoEntry;
if (infoEntry.name) {
name = infoEntry.name.trim();
}
name = infoEntry.name?.trim() || undefined;
}
if (entry.type !== "message") continue;
@@ -913,12 +911,13 @@ export class SessionManager {
/** Get the current session name from the latest session_info entry, if any. */
getSessionName(): string | undefined {
// Walk entries in reverse to find the latest session_info with a name
// Walk entries in reverse to find the latest session_info entry.
// Empty names explicitly clear the session title.
const entries = this.getEntries();
for (let i = entries.length - 1; i >= 0; i--) {
const entry = entries[i];
if (entry.type === "session_info" && entry.name) {
return entry.name;
if (entry.type === "session_info") {
return entry.name?.trim() || undefined;
}
}
return undefined;

View File

@@ -302,7 +302,8 @@ class TreeList implements Component {
entry.type === "label" ||
entry.type === "custom" ||
entry.type === "model_change" ||
entry.type === "thinking_level_change";
entry.type === "thinking_level_change" ||
entry.type === "session_info";
switch (this.filterMode) {
case "user-only":
@@ -535,6 +536,10 @@ class TreeList implements Component {
case "branch_summary":
parts.push("branch summary", entry.summary);
break;
case "session_info":
parts.push("title");
if (entry.name) parts.push(entry.name);
break;
case "model_change":
parts.push("model", entry.modelId);
break;
@@ -755,6 +760,11 @@ class TreeList implements Component {
case "label":
result = theme.fg("dim", `[label: ${entry.label ?? "(cleared)"}]`);
break;
case "session_info":
result = entry.name
? [theme.fg("dim", "[title: "), theme.fg("dim", entry.name), theme.fg("dim", "]")].join("")
: [theme.fg("dim", "[title: "), theme.italic(theme.fg("dim", "empty")), theme.fg("dim", "]")].join("");
break;
default:
result = "";
}