Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions apps/web/src/components/chat/CommandOutputPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { EnvironmentId, ThreadId, TurnItemId } from "@t3tools/contracts";
import { TERMINAL_PALETTES, terminalOutputSpans } from "@t3tools/shared/terminalOutput";
import { useLayoutEffect, useMemo, useRef } from "react";
import { useLayoutEffect, useRef } from "react";

import { useTheme } from "../../hooks/useTheme";
import { useServerConfigs } from "../../state/entities";
Expand All @@ -22,6 +22,13 @@ export function useCommandOutputStreaming(environmentId: EnvironmentId): boolean
* shows its final output. Mount it only when `useCommandOutputStreaming` holds.
* It subscribes only while mounted, so collapsed rows and other threads receive nothing.
*/
// Parsing ANSI output is linear in its length, and the compiler would redo it on
// every render because the layout effect runs after it.
function useTerminalOutputSpans(text: string, resolvedTheme: keyof typeof TERMINAL_PALETTES) {
"use memo";
return terminalOutputSpans(text, TERMINAL_PALETTES[resolvedTheme]);
}

export function CommandOutputPanel(props: {
readonly environmentId: EnvironmentId;
readonly threadId: ThreadId;
Expand All @@ -38,10 +45,7 @@ export function CommandOutputPanel(props: {
const followRef = useRef(true);
const text = data?.output.text ?? "";
const { resolvedTheme } = useTheme();
const spans = useMemo(
() => terminalOutputSpans(text, TERMINAL_PALETTES[resolvedTheme]),
[text, resolvedTheme],
);
const spans = useTerminalOutputSpans(text, resolvedTheme);

// This panel only re-renders when its output changes, so keep the end in view after each.
useLayoutEffect(() => {
Expand Down
Loading