diff --git a/packages/ui/src/components/tool-call.tsx b/packages/ui/src/components/tool-call.tsx
index e3d4eba6..35bc02db 100644
--- a/packages/ui/src/components/tool-call.tsx
+++ b/packages/ui/src/components/tool-call.tsx
@@ -9,7 +9,14 @@ import type { DiffViewMode } from "../stores/preferences"
import { sendPermissionResponse } from "../stores/instances"
import type { TextPart, RenderCache } from "../types/message"
import { resolveToolRenderer } from "./tool-call/renderers"
-import type { DiffPayload, DiffRenderOptions, MarkdownRenderOptions, ToolCallPart, ToolRendererContext } from "./tool-call/types"
+import type {
+ DiffPayload,
+ DiffRenderOptions,
+ MarkdownRenderOptions,
+ ToolCallPart,
+ ToolRendererContext,
+ ToolScrollHelpers,
+} from "./tool-call/types"
import { getRelativePath, getToolIcon, getToolName, isToolStateCompleted, isToolStateError, isToolStateRunning } from "./tool-call/utils"
import { getLogger } from "../lib/logger"
@@ -419,7 +426,20 @@ export default function ToolCall(props: ToolCallProps) {
persistScrollSnapshot(event.currentTarget)
}
+ const scrollHelpers: ToolScrollHelpers = {
+ registerContainer: (element, options) => {
+ if (options?.disableTracking) return
+ initializeScrollContainer(element)
+ },
+ handleScroll: handleScrollEvent,
+ renderSentinel: (options) => {
+ if (options?.disableTracking) return null
+ return
+ },
+ }
+
createEffect(() => {
+
const container = scrollContainer()
if (!container) return
@@ -565,11 +585,8 @@ export default function ToolCall(props: ToolCallProps) {
return (
{
- if (options?.disableScrollTracking) return
- initializeScrollContainer(element)
- }}
- onScroll={options?.disableScrollTracking ? undefined : handleScrollEvent}
+ ref={(element) => scrollHelpers.registerContainer(element, { disableTracking: options?.disableScrollTracking })}
+ onScroll={options?.disableScrollTracking ? undefined : scrollHelpers.handleScroll}
>
)
}
@@ -630,14 +645,14 @@ export default function ToolCall(props: ToolCallProps) {
}
return (
-
initializeScrollContainer(element)} onScroll={handleScrollEvent}>
+
scrollHelpers.registerContainer(element)} onScroll={scrollHelpers.handleScroll}>
-
+ {scrollHelpers.renderSentinel()}
)
}
@@ -654,6 +669,7 @@ export default function ToolCall(props: ToolCallProps) {
partVersion: partVersionAccessor,
renderMarkdown: renderMarkdownContent,
renderDiff: renderDiffContent,
+ scrollHelpers,
}
let previousPartVersion: number | undefined
diff --git a/packages/ui/src/components/tool-call/renderers/task.tsx b/packages/ui/src/components/tool-call/renderers/task.tsx
index 76df18f5..5c146196 100644
--- a/packages/ui/src/components/tool-call/renderers/task.tsx
+++ b/packages/ui/src/components/tool-call/renderers/task.tsx
@@ -40,7 +40,7 @@ export const taskRenderer: ToolRenderer = {
}
return base
},
- renderBody({ toolState, toolCall, messageVersion, partVersion }) {
+ renderBody({ toolState, toolCall, messageVersion, partVersion, scrollHelpers }) {
const items = createMemo(() => {
// Track the reactive change points so we only recompute when the part/message changes
messageVersion?.()
@@ -63,7 +63,11 @@ export const taskRenderer: ToolRenderer = {
if (items().length === 0) return null
return (
-
+
scrollHelpers?.registerContainer(element)}
+ onScroll={scrollHelpers ? (event) => scrollHelpers.handleScroll(event as Event & { currentTarget: HTMLDivElement }) : undefined}
+ >
{(item) => {
@@ -78,7 +82,9 @@ export const taskRenderer: ToolRenderer = {
}}
+ {scrollHelpers?.renderSentinel?.()}
)
},
}
+
diff --git a/packages/ui/src/components/tool-call/types.ts b/packages/ui/src/components/tool-call/types.ts
index f0858628..d0cb8e00 100644
--- a/packages/ui/src/components/tool-call/types.ts
+++ b/packages/ui/src/components/tool-call/types.ts
@@ -21,6 +21,12 @@ export interface DiffRenderOptions {
label?: string
}
+export interface ToolScrollHelpers {
+ registerContainer(element: HTMLDivElement | null, options?: { disableTracking?: boolean }): void
+ handleScroll(event: Event & { currentTarget: HTMLDivElement }): void
+ renderSentinel(options?: { disableTracking?: boolean }): JSXElement | null
+}
+
export interface ToolRendererContext {
toolCall: Accessor
toolState: Accessor
@@ -29,6 +35,7 @@ export interface ToolRendererContext {
partVersion?: Accessor
renderMarkdown(options: MarkdownRenderOptions): JSXElement | null
renderDiff(payload: DiffPayload, options?: DiffRenderOptions): JSXElement | null
+ scrollHelpers?: ToolScrollHelpers
}
export interface ToolRenderer {