fix(sessions): skip local command output when titling Claude sessions (#8799)

This commit is contained in:
Lukas authored and GitHub committed 2026-10-24 20:54:29 +08:00
1 parent cae7c37540
commit 1a3057dc1f
1 file changed
+33 -2
@@ -176,8 +176,8 @@ fn parse_session_lines(
let text = message.get("content").map(extract_text).unwrap_or_default();
let trimmed = text.trim();
if !trimmed.is_empty()
&& !trimmed.contains("<local-command-caveat>")
&& !trimmed.starts_with("<command-name>")
&& !is_injected_text(trimmed)
{
first_user_message = Some(trimmed.to_string());
}
@@ -222,7 +222,12 @@ fn parse_session_lines(
}
if let Some(message) = value.get("message") {
let text = message.get("content").map(extract_text).unwrap_or_default();
if !text.trim().is_empty() {
let trimmed = text.trim();
// A local command run last, such as `/model`, ends the file with its command and output.
if !trimmed.is_empty()
&& !trimmed.starts_with("<command-name>")
&& !is_injected_text(trimmed)
{
summary = Some(text);
}
}
@@ -2072,6 +2077,32 @@ mod tests {
assert_eq!(meta.title.as_deref(), Some("帮我看看工作区的改动"));
}
#[test]
fn parse_session_skips_local_command_output_in_title_and_summary() {
let temp = tempdir().expect("tempdir");
let path = temp.path().join("session-model.jsonl");
std::fs::write(
&path,
concat!(
"{\"type\":\"user\",\"isMeta\":true,\"message\":{\"role\":\"user\",\"content\":\"<local-command-caveat>Caveat: The messages below were generated by the user while running local commands.</local-command-caveat>\"},\"sessionId\":\"session-model\",\"timestamp\":\"2026-03-06T10:00:00Z\",\"cwd\":\"/tmp/project\"}\n",
"{\"type\":\"user\",\"message\":{\"role\":\"user\",\"content\":\"<command-name>/model</command-name>\\n<command-message>model</command-message>\\n<command-args>opus</command-args>\"},\"sessionId\":\"session-model\",\"timestamp\":\"2026-03-06T10:00:01Z\",\"cwd\":\"/tmp/project\"}\n",
"{\"type\":\"user\",\"message\":{\"role\":\"user\",\"content\":\"<local-command-stdout>Set model to opus</local-command-stdout>\"},\"sessionId\":\"session-model\",\"timestamp\":\"2026-03-06T10:00:02Z\",\"cwd\":\"/tmp/project\"}\n",
"{\"type\":\"user\",\"message\":{\"role\":\"user\",\"content\":\"Fix the login redirect\"},\"sessionId\":\"session-model\",\"timestamp\":\"2026-03-06T10:01:00Z\",\"cwd\":\"/tmp/project\"}\n",
"{\"type\":\"assistant\",\"message\":{\"role\":\"assistant\",\"content\":\"The redirect now keeps the return URL.\"},\"timestamp\":\"2026-03-06T10:02:00Z\",\"cwd\":\"/tmp/project\"}\n",
"{\"type\":\"user\",\"message\":{\"role\":\"user\",\"content\":\"<command-name>/model</command-name>\\n<command-message>model</command-message>\\n<command-args>sonnet</command-args>\"},\"sessionId\":\"session-model\",\"timestamp\":\"2026-03-06T10:03:00Z\",\"cwd\":\"/tmp/project\"}\n",
"{\"type\":\"user\",\"message\":{\"role\":\"user\",\"content\":\"<local-command-stdout>Set model to sonnet</local-command-stdout>\"},\"sessionId\":\"session-model\",\"timestamp\":\"2026-03-06T10:03:01Z\",\"cwd\":\"/tmp/project\"}\n",
),
)
.expect("write");
let meta = parse_session(&path).unwrap();
assert_eq!(meta.title.as_deref(), Some("Fix the login redirect"));
assert_eq!(
meta.summary.as_deref(),
Some("The redirect now keeps the return URL.")
);
}
#[test]
fn workflow_journal_log_is_excluded_from_sessions() {
let temp = tempdir().expect("tempdir");