refactor: remove reasoning title extraction from chat pipeline (#22926)

Removes the backend and frontend logic that extracted compact titles
from reasoning/thinking blocks. The `Title` field on `ChatMessagePart`
remains for other part types (e.g. source), but reasoning blocks no
longer have titles derived from first-line markdown bold text or
provider metadata summaries.

**Backend:**
- Remove `ReasoningTitleFromFirstLine`, `reasoningTitleFromContent`,
`reasoningSummaryTitle`, `compactReasoningSummaryTitle`, and
`reasoningSummaryHeadline` from chatprompt
- Simplify `marshalContentBlock` to plain `json.Marshal` (no title
injection)
- Remove title tracking maps and `setReasoningTitleFromText` from
chatloop stream processing
- Remove `reasoningStoredTitle` from db2sdk
- Remove related tests from db2sdk_test

**Frontend:**
- Remove `mergeThinkingTitles` from blockUtils
- Simplify `appendTextBlock` to always merge consecutive thinking blocks
- Remove `applyStreamThinkingTitle` from streamState
- Simplify reasoning/thinking stream handler to ignore title-only parts
- Update tests accordingly

Net: **-487 lines / +42 lines**
This commit is contained in:
Kyle Carberry
2026-03-11 11:01:26 +00:00
committed by GitHub
parent 2d7dd73106
commit 0a026fde39
11 changed files with 47 additions and 512 deletions
+2 -41
View File
@@ -428,27 +428,6 @@ func processStepStream(
activeReasoningContent := make(map[string]reasoningState)
// Track tool names by ID for input delta publishing.
toolNames := make(map[string]string)
// Track reasoning text/titles for title extraction.
reasoningTitles := make(map[string]string)
reasoningText := make(map[string]string)
setReasoningTitleFromText := func(id string, text string) {
if id == "" || strings.TrimSpace(text) == "" {
return
}
if reasoningTitles[id] != "" {
return
}
reasoningText[id] += text
if !strings.ContainsAny(reasoningText[id], "\r\n") {
return
}
title := chatprompt.ReasoningTitleFromFirstLine(reasoningText[id])
if title == "" {
return
}
reasoningTitles[id] = title
}
for part := range stream {
switch part.Type {
@@ -485,12 +464,9 @@ func processStepStream(
active.options = part.ProviderMetadata
activeReasoningContent[part.ID] = active
}
setReasoningTitleFromText(part.ID, part.Delta)
title := reasoningTitles[part.ID]
publishMessagePart(fantasy.MessageRoleAssistant, codersdk.ChatMessagePart{
Type: codersdk.ChatMessagePartTypeReasoning,
Text: part.Delta,
Title: title,
Type: codersdk.ChatMessagePartTypeReasoning,
Text: part.Delta,
})
case fantasy.StreamPartTypeReasoningEnd:
@@ -504,21 +480,6 @@ func processStepStream(
}
result.content = append(result.content, content)
delete(activeReasoningContent, part.ID)
// Derive reasoning title at end of reasoning
// block if we haven't yet.
if reasoningTitles[part.ID] == "" {
reasoningTitles[part.ID] = chatprompt.ReasoningTitleFromFirstLine(
reasoningText[part.ID],
)
}
title := reasoningTitles[part.ID]
if title != "" {
publishMessagePart(fantasy.MessageRoleAssistant, codersdk.ChatMessagePart{
Type: codersdk.ChatMessagePartTypeReasoning,
Title: title,
})
}
}
case fantasy.StreamPartTypeToolInputStart:
activeToolCalls[part.ID] = &fantasy.ToolCallContent{