Skip to content

Commit a4172d3

Browse files
yanmxaclaude
andcommitted
feat: improve AskUserQuestion tool result display
Show meaningful answer summaries instead of generic line counts. Tool call line: AskUserQuestion(2 questions) instead of AskUserQuestion() Result lines: each answer on its own line (e.g. ⎿ Language: Go) instead of generic ⎿ AskUserQuestion → 5 lines Co-Authored-By: Claude Opus 4 <noreply@anthropic.com> Signed-off-by: Meng Yan <myan@redhat.com>
1 parent 955fd38 commit a4172d3

3 files changed

Lines changed: 41 additions & 3 deletions

File tree

internal/app/render/message_tool_inline.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ func RenderToolResultInline(data ToolResultData, mdRenderer *MDRenderer) string
2121
return RenderTaskResultInline(data, mdRenderer)
2222
case tool.ToolTaskOutput:
2323
return RenderTaskOutputResultInline(data)
24+
case tool.ToolAskUserQuestion:
25+
return renderAskUserResultInline(data)
2426
}
2527

2628
sizeInfo := FormatToolResultSize(toolName, data.Content)
@@ -39,6 +41,34 @@ func RenderToolResultInline(data ToolResultData, mdRenderer *MDRenderer) string
3941
return sb.String()
4042
}
4143

44+
// renderAskUserResultInline renders AskUserQuestion result with answer summary.
45+
func renderAskUserResultInline(data ToolResultData) string {
46+
icon := toolResultIcon(data.IsError)
47+
48+
if data.IsError {
49+
return ToolResultStyle.Render(fmt.Sprintf(" %s %s", icon, data.Content)) + "\n"
50+
}
51+
52+
if strings.Contains(data.Content, "User cancelled") {
53+
return ToolResultStyle.Render(fmt.Sprintf(" %s Cancelled", icon)) + "\n"
54+
}
55+
56+
var answers []string
57+
for line := range strings.SplitSeq(data.Content, "\n") {
58+
line = strings.TrimSpace(line)
59+
if line == "" || line == "User responses:" {
60+
continue
61+
}
62+
answers = append(answers, line)
63+
}
64+
65+
var sb strings.Builder
66+
for _, a := range answers {
67+
sb.WriteString(ToolResultStyle.Render(fmt.Sprintf(" %s %s", icon, a)) + "\n")
68+
}
69+
return sb.String()
70+
}
71+
4272
// RenderSkillResultInline renders a skill result with clean formatting.
4373
func RenderSkillResultInline(data ToolResultData) string {
4474
icon := toolResultIcon(data.IsError)

internal/app/render/message_tool_parse.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,13 @@ func ExtractToolArgs(input string) string {
152152
if s, ok := params["skill"].(string); ok {
153153
return s
154154
}
155+
if qs, ok := params["questions"].([]any); ok {
156+
count := len(qs)
157+
if count == 1 {
158+
return "1 question"
159+
}
160+
return fmt.Sprintf("%d questions", count)
161+
}
155162

156163
keys := make([]string, 0, len(params))
157164
for k := range params {

internal/tool/schema.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@ const (
2323
ToolCronCreate = "CronCreate"
2424
ToolCronDelete = "CronDelete"
2525
ToolCronList = "CronList"
26-
ToolEnterWorktree = "EnterWorktree"
27-
ToolExitWorktree = "ExitWorktree"
28-
ToolToolSearch = "ToolSearch"
26+
ToolEnterWorktree = "EnterWorktree"
27+
ToolExitWorktree = "ExitWorktree"
28+
ToolToolSearch = "ToolSearch"
29+
ToolAskUserQuestion = "AskUserQuestion"
2930
)
3031

3132
// IsAgentToolName reports whether the tool name represents an agent-like worker tool.

0 commit comments

Comments
 (0)