Refine tool call summaries and scrolling (#2069)

* feat(app): refine tool call summaries and scrolling

Keep summary groups stable from the first tool call, preserve live activity feedback, and scroll expanded groups to the latest entry. Consolidate web scrollbar styling around the native browser mechanism.

* refactor(app): reuse tool call height constant

* fix(app): preserve tool call summary state

* fix(app): refresh web tool groups on expand

* fix(app): preserve grouped tool errors
This commit is contained in:
Mohamed Boudra
2026-07-14 21:16:29 +02:00
committed by GitHub
parent d781b68711
commit 1b8af2e58e
55 changed files with 1484 additions and 2488 deletions
@@ -341,14 +341,14 @@ describe("appearance settings", () => {
expect((await loadAppSettingsFromStorage(deps)).toolCallDetailLevel).toBe("overview");
});
it("loads an explicit tool call detail level", async () => {
it("maps an unrecognized tool call detail level to overview", async () => {
const deps = makeDeps({
storage: createInMemoryKeyValueStorage({
[APP_SETTINGS_KEY]: JSON.stringify({ toolCallDetailLevel: "concise" }),
[APP_SETTINGS_KEY]: JSON.stringify({ toolCallDetailLevel: "unknown" }),
}),
});
expect((await loadAppSettingsFromStorage(deps)).toolCallDetailLevel).toBe("concise");
expect((await loadAppSettingsFromStorage(deps)).toolCallDetailLevel).toBe("overview");
});
it("clamps the UI font size into range and rejects non-numeric values", async () => {
+12 -11
View File
@@ -12,16 +12,12 @@ export type SendBehavior = "interrupt" | "queue";
export type ReleaseChannel = "stable" | "beta";
export type ServiceUrlBehavior = "ask" | "in-app" | "external";
export type WorkspaceTitleSource = "title" | "branch";
export type ToolCallDetailLevel = "overview" | "concise" | "detailed";
export type ToolCallDetailLevel = "overview" | "detailed";
const VALID_THEMES = new Set<string>([...Object.keys(THEME_TO_UNISTYLES), "auto"]);
const VALID_SERVICE_URL_BEHAVIORS = new Set<ServiceUrlBehavior>(["ask", "in-app", "external"]);
const VALID_WORKSPACE_TITLE_SOURCES = new Set<WorkspaceTitleSource>(["title", "branch"]);
const VALID_TOOL_CALL_DETAIL_LEVELS = new Set<ToolCallDetailLevel>([
"overview",
"concise",
"detailed",
]);
const VALID_TOOL_CALL_DETAIL_LEVELS = new Set<ToolCallDetailLevel>(["overview", "detailed"]);
export const DEFAULT_TERMINAL_SCROLLBACK_LINES = 10_000;
export const MIN_TERMINAL_SCROLLBACK_LINES = 0;
export const MAX_TERMINAL_SCROLLBACK_LINES = 1_000_000;
@@ -172,11 +168,16 @@ export function normalizeAppSettings(value: unknown): AppSettings {
}
function parseToolCallDetailLevel(stored: StoredAppSettings): ToolCallDetailLevel | null {
if (
typeof stored.toolCallDetailLevel === "string" &&
VALID_TOOL_CALL_DETAIL_LEVELS.has(stored.toolCallDetailLevel)
) {
return stored.toolCallDetailLevel;
if (stored.toolCallDetailLevel !== undefined) {
if (
typeof stored.toolCallDetailLevel === "string" &&
VALID_TOOL_CALL_DETAIL_LEVELS.has(stored.toolCallDetailLevel)
) {
return stored.toolCallDetailLevel;
}
// COMPAT(toolCallDetailLevelConcise): removed in v0.1.107; legacy "concise" values
// deliberately follow the unknown-value fallback. Remove after 2027-01-14.
return "overview";
}
if (typeof stored.compactToolCalls === "boolean") {
// COMPAT(compactToolCalls): migrated in v0.1.105, remove after 2027-01-12.
-1
View File
@@ -1 +0,0 @@
export * from "./use-web-scrollbar-style.web";
@@ -1,5 +0,0 @@
import type { ViewStyle } from "react-native";
export function useWebScrollbarStyle(): ViewStyle | undefined {
return undefined;
}
@@ -1,21 +0,0 @@
import { useMemo } from "react";
import type { ViewStyle } from "react-native";
import { useUnistyles } from "react-native-unistyles";
// CSS scrollbar properties are supported by React Native Web at runtime
// but are not included in React Native's ViewStyle type definition.
interface WebScrollbarStyle extends ViewStyle {
scrollbarColor: string;
scrollbarWidth: string;
}
export function useWebScrollbarStyle(): WebScrollbarStyle {
const { theme } = useUnistyles();
return useMemo(
(): WebScrollbarStyle => ({
scrollbarColor: `${theme.colors.scrollbarHandle} transparent`,
scrollbarWidth: "thin",
}),
[theme.colors.scrollbarHandle],
);
}