mirror of
https://github.com/coder/coder.git
synced 2026-09-22 05:05:20 +08:00
fix(site): enable streaming-mode Streamdown for live chat output (#23676)
This commit is contained in:
@@ -103,3 +103,39 @@ export const JsxInProse: Story = {
|
||||
expect(marker2).toBeInTheDocument();
|
||||
},
|
||||
};
|
||||
|
||||
// Verifies that streaming mode closes incomplete inline markdown via
|
||||
// remend so the user never sees raw syntax during the reveal animation.
|
||||
export const StreamingInlineMarkdown: Story = {
|
||||
args: {
|
||||
children: "This is **bold text that has not been close",
|
||||
streaming: true,
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
// remend should close the unclosed ** so the text renders
|
||||
// as <strong>, not as a raw "**" literal.
|
||||
const el = await canvas.findByText(/bold text/);
|
||||
expect(el).toBeInTheDocument();
|
||||
// The raw double-asterisk should not appear as visible text.
|
||||
const bodyText = canvasElement.textContent ?? "";
|
||||
expect(bodyText).not.toContain("**");
|
||||
},
|
||||
};
|
||||
|
||||
// Verifies that an incomplete fenced code block in streaming mode
|
||||
// renders inside a code element rather than showing raw backticks.
|
||||
export const StreamingCodeFence: Story = {
|
||||
args: {
|
||||
children: "```ts\nconst x = 1",
|
||||
streaming: true,
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
const codeContent = await canvas.findByText(/const x = 1/);
|
||||
expect(codeContent).toBeInTheDocument();
|
||||
// The raw triple-backtick should not appear as visible text.
|
||||
const bodyText = canvasElement.textContent ?? "";
|
||||
expect(bodyText).not.toContain("```");
|
||||
},
|
||||
};
|
||||
|
||||
@@ -15,6 +15,10 @@ import { cn } from "utils/cn";
|
||||
interface ResponseProps extends Omit<ComponentPropsWithRef<"div">, "children"> {
|
||||
children: string;
|
||||
urlTransform?: UrlTransform;
|
||||
/** Enable streaming-mode Streamdown with incomplete-markdown
|
||||
* preprocessing (remend) and useTransition-based render
|
||||
* scheduling. Pass true only for live-streaming output. */
|
||||
streaming?: boolean;
|
||||
}
|
||||
|
||||
// Omit rehype-raw so HTML-like syntax in LLM output is rendered as
|
||||
@@ -231,6 +235,7 @@ export const Response = ({
|
||||
children,
|
||||
ref,
|
||||
urlTransform,
|
||||
streaming,
|
||||
...props
|
||||
}: ResponseProps) => {
|
||||
const theme = useTheme();
|
||||
@@ -253,6 +258,8 @@ export const Response = ({
|
||||
components={components}
|
||||
urlTransform={urlTransform}
|
||||
rehypePlugins={chatRehypePlugins}
|
||||
mode={streaming ? "streaming" : "static"}
|
||||
parseIncompleteMarkdown={streaming}
|
||||
>
|
||||
{children}
|
||||
</Streamdown>
|
||||
|
||||
@@ -69,6 +69,7 @@ const ReasoningDisclosure: FC<{
|
||||
<Response
|
||||
className="text-[11px] text-content-secondary"
|
||||
urlTransform={urlTransform}
|
||||
streaming={isStreaming}
|
||||
>
|
||||
{displayText}
|
||||
</Response>
|
||||
@@ -117,7 +118,11 @@ const SmoothedResponse: FC<{
|
||||
bypassSmoothing: false,
|
||||
streamKey,
|
||||
});
|
||||
return <Response urlTransform={urlTransform}>{visibleText}</Response>;
|
||||
return (
|
||||
<Response streaming urlTransform={urlTransform}>
|
||||
{visibleText}
|
||||
</Response>
|
||||
);
|
||||
};
|
||||
|
||||
const InlineTextAttachmentButton: FC<{
|
||||
|
||||
Reference in New Issue
Block a user