Compare commits

...

1 Commits

Author SHA1 Message Date
openhands
49ec11ac10 Fix color output in message window
- Add ansi-to-html utility to convert ANSI color codes to HTML
- Add TerminalOutput component to handle terminal output in chat messages
- Update ChatMessage to detect and handle terminal output with color codes

Fixes #5485
2024-12-09 20:55:39 +00:00
5 changed files with 66 additions and 11 deletions

View File

@@ -18,6 +18,7 @@
"@vitejs/plugin-react": "^4.3.2",
"@xterm/addon-fit": "^0.10.0",
"@xterm/xterm": "^5.4.0",
"ansi-html-community": "^0.0.8",
"axios": "^1.7.7",
"clsx": "^2.1.1",
"eslint-config-airbnb-typescript": "^18.0.0",
@@ -6481,6 +6482,18 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/ansi-html-community": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz",
"integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==",
"engines": [
"node >= 0.8.0"
],
"license": "Apache-2.0",
"bin": {
"ansi-html": "bin/ansi-html"
}
},
"node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",

View File

@@ -17,6 +17,7 @@
"@vitejs/plugin-react": "^4.3.2",
"@xterm/addon-fit": "^0.10.0",
"@xterm/xterm": "^5.4.0",
"ansi-html-community": "^0.0.8",
"axios": "^1.7.7",
"clsx": "^2.1.1",
"eslint-config-airbnb-typescript": "^18.0.0",

View File

@@ -5,6 +5,7 @@ import { code } from "../markdown/code";
import { cn } from "#/utils/utils";
import { ul, ol } from "../markdown/list";
import { CopyToClipboardButton } from "#/components/shared/buttons/copy-to-clipboard-button";
import { TerminalOutput } from "./terminal-output";
interface ChatMessageProps {
type: "user" | "assistant";
@@ -56,17 +57,21 @@ export function ChatMessage({
onClick={handleCopyToClipboard}
mode={isCopy ? "copied" : "copy"}
/>
<Markdown
className="text-sm overflow-auto"
components={{
code,
ul,
ol,
}}
remarkPlugins={[remarkGfm]}
>
{message}
</Markdown>
{message.includes('\u001b[') ? (
<TerminalOutput content={message} />
) : (
<Markdown
className="text-sm overflow-auto"
components={{
code,
ul,
ol,
}}
remarkPlugins={[remarkGfm]}
>
{message}
</Markdown>
)}
{children}
</article>
);

View File

@@ -0,0 +1,17 @@
import React from 'react';
import { convertAnsiToHtml } from '#/utils/ansi-to-html';
interface TerminalOutputProps {
content: string;
}
export function TerminalOutput({ content }: TerminalOutputProps) {
const htmlContent = convertAnsiToHtml(content);
return (
<pre
className="bg-black rounded-lg p-4 overflow-x-auto"
dangerouslySetInnerHTML={{ __html: htmlContent }}
/>
);
}

View File

@@ -0,0 +1,19 @@
import ansiHTML from 'ansi-html-community';
// Initialize ansi-html
ansiHTML.setColors({
reset: ['fff', '000'],
black: '000',
red: 'f00',
green: '0f0',
yellow: 'ff0',
blue: '00f',
magenta: 'f0f',
cyan: '0ff',
lightgrey: 'eee',
darkgrey: '666'
});
export function convertAnsiToHtml(text: string): string {
return ansiHTML(text);
}