diff --git a/packages/tui/src/routes/session/index.tsx b/packages/tui/src/routes/session/index.tsx
index ed2fb307b2d..2b75cb11cbc 100644
--- a/packages/tui/src/routes/session/index.tsx
+++ b/packages/tui/src/routes/session/index.tsx
@@ -2595,58 +2595,61 @@ type ToolProps = {
}
function GenericTool(props: ToolProps) {
const theme = useTheme()
- const { currentSyntax: syntax } = useThemes()
const output = createMemo(() => props.output?.trim() ?? "")
- const args = createMemo(() => JSON.stringify(props.input, null, 2))
+ const input = createMemo(() => Object.entries(props.input))
const [expanded, setExpanded] = createSignal(false)
- const expandable = createMemo(() => Object.keys(props.input).length > 0 || output().length > 0)
+ const expandable = createMemo(() => input().length > 0 || output().length > 0)
+ const loading = createMemo(() => props.part.state.status === "streaming" || props.part.state.status === "running")
return (
- setExpanded((value) => !value) : undefined}
- >
+ <>
+ setExpanded((value) => !value) : undefined}
+ >
+ {genericToolSummary(props.tool, props.input)}
+
-
- 0}>
-
-
- Input
-
-
-
+
+
+ {([key, value]) => (
+
+
+ {key}:{" "}
+
+
+ {typeof value === "string" ? value : JSON.stringify(value, null, 2)}
+
-
-
+ )}
+
{(value) => (
-
-
- Output
+
+
+ output:{" "}
+
+
+ {value()}
-
-
- {value()}
-
-
)}
-
+ >
)
}
+export function genericToolSummary(tool: string, input: Record) {
+ const args = primitiveInputSummary(input).replace(/\s+/g, " ")
+ return `${tool}${args ? ` ${args}` : ""}`
+}
+
function useToolPermission(part: () => SessionMessageAssistantTool | undefined) {
const ctx = use()
const data = useData()
diff --git a/packages/tui/test/cli/tui/inline-tool-wrap-snapshot.test.tsx b/packages/tui/test/cli/tui/inline-tool-wrap-snapshot.test.tsx
index e6958334c92..997c627ac0e 100644
--- a/packages/tui/test/cli/tui/inline-tool-wrap-snapshot.test.tsx
+++ b/packages/tui/test/cli/tui/inline-tool-wrap-snapshot.test.tsx
@@ -4,6 +4,7 @@ import { testRender, type JSX } from "@opentui/solid"
import {
InlineToolRow,
executeCallSummary,
+ genericToolSummary,
isBackgroundSubagent,
parseApplyPatchFiles,
parseDiagnostics,
@@ -199,6 +200,21 @@ describe("TUI inline tool wrapping", () => {
).toBe("↳ session.prompt [text=first line second line]")
})
+ test("summarizes generic tool arguments on one line", () => {
+ expect(
+ genericToolSummary("demo_search_catalog", {
+ query: "wireless keyboard",
+ limit: 8,
+ includeArchived: false,
+ filters: { category: "accessories" },
+ }),
+ ).toBe("demo_search_catalog [query=wireless keyboard, limit=8, includeArchived=false]")
+ expect(genericToolSummary("demo_get_weather", { city: "Tokyo", units: "celsius" })).toBe(
+ "demo_get_weather [city=Tokyo, units=celsius]",
+ )
+ expect(genericToolSummary("demo_refresh", {})).toBe("demo_refresh")
+ })
+
test("ignores diagnostics with malformed nested ranges", () => {
expect(
parseDiagnostics(