summaryrefslogtreecommitdiffhomepage
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/ui/src/components/message-part.tsx60
1 files changed, 55 insertions, 5 deletions
diff --git a/packages/ui/src/components/message-part.tsx b/packages/ui/src/components/message-part.tsx
index 6fee7cd26..31103b35c 100644
--- a/packages/ui/src/components/message-part.tsx
+++ b/packages/ui/src/components/message-part.tsx
@@ -1,4 +1,15 @@
-import { Component, createEffect, createMemo, createSignal, For, Match, Show, Switch, type JSX } from "solid-js"
+import {
+ Component,
+ createEffect,
+ createMemo,
+ createSignal,
+ For,
+ Match,
+ Show,
+ Switch,
+ onCleanup,
+ type JSX,
+} from "solid-js"
import { Dynamic } from "solid-js/web"
import {
AssistantMessage,
@@ -80,6 +91,41 @@ export type PartComponent = Component<MessagePartProps>
export const PART_MAPPING: Record<string, PartComponent | undefined> = {}
+const TEXT_RENDER_THROTTLE_MS = 250
+
+function createThrottledValue(getValue: () => string) {
+ const [value, setValue] = createSignal(getValue())
+ let timeout: ReturnType<typeof setTimeout> | undefined
+ let last = 0
+
+ createEffect(() => {
+ const next = getValue()
+ const now = Date.now()
+ const remaining = TEXT_RENDER_THROTTLE_MS - (now - last)
+ if (remaining <= 0) {
+ if (timeout) {
+ clearTimeout(timeout)
+ timeout = undefined
+ }
+ last = now
+ setValue(next)
+ return
+ }
+ if (timeout) clearTimeout(timeout)
+ timeout = setTimeout(() => {
+ last = Date.now()
+ setValue(next)
+ timeout = undefined
+ }, remaining)
+ })
+
+ onCleanup(() => {
+ if (timeout) clearTimeout(timeout)
+ })
+
+ return value
+}
+
function relativizeProjectPaths(text: string, directory?: string) {
if (!text) return ""
if (!directory) return text
@@ -464,11 +510,12 @@ PART_MAPPING["text"] = function TextPartDisplay(props) {
const data = useData()
const part = props.part as TextPart
const displayText = () => relativizeProjectPaths((part.text ?? "").trim(), data.directory)
+ const throttledText = createThrottledValue(displayText)
return (
- <Show when={displayText()}>
+ <Show when={throttledText()}>
<div data-component="text-part">
- <Markdown text={displayText()} />
+ <Markdown text={throttledText()} />
</div>
</Show>
)
@@ -476,10 +523,13 @@ PART_MAPPING["text"] = function TextPartDisplay(props) {
PART_MAPPING["reasoning"] = function ReasoningPartDisplay(props) {
const part = props.part as ReasoningPart
+ const text = () => part.text.trim()
+ const throttledText = createThrottledValue(text)
+
return (
- <Show when={part.text.trim()}>
+ <Show when={throttledText()}>
<div data-component="reasoning-part">
- <Markdown text={part.text.trim()} />
+ <Markdown text={throttledText()} />
</div>
</Show>
)