fix: visual improvements

This commit is contained in:
Vukasin 2025-07-27 22:11:40 +02:00
parent 7de81b4d2f
commit d777b5b735
3 changed files with 76 additions and 49 deletions

View File

@ -154,7 +154,6 @@ export function DashboardContent() {
console.log('Handling BillingError:', error.detail);
onOpen("paymentRequiredDialog");
}
} finally {
setIsSubmitting(false);
}
};

View File

@ -59,19 +59,37 @@ export function CommandToolView({
const formattedOutput = React.useMemo(() => {
if (!output) return [];
let processedOutput = output;
try {
if (typeof output === 'string' && (output.trim().startsWith('{') || output.trim().startsWith('{'))) {
const parsed = JSON.parse(output);
if (parsed && typeof parsed === 'object' && parsed.output) {
processedOutput = parsed.output;
}
// Handle case where output is already an object
if (typeof output === 'object' && output !== null) {
try {
processedOutput = JSON.stringify(output, null, 2);
} catch (e) {
processedOutput = String(output);
}
} catch (e) {
} else if (typeof output === 'string') {
// Try to parse as JSON first
try {
if (output.trim().startsWith('{') || output.trim().startsWith('[')) {
const parsed = JSON.parse(output);
if (parsed && typeof parsed === 'object') {
// If it's a complex object, stringify it nicely
processedOutput = JSON.stringify(parsed, null, 2);
} else {
processedOutput = String(parsed);
}
} else {
processedOutput = output;
}
} catch (e) {
// If parsing fails, use as plain text
processedOutput = output;
}
} else {
processedOutput = String(output);
}
processedOutput = String(processedOutput);
processedOutput = processedOutput.replace(/\\\\/g, '\\');
processedOutput = processedOutput
.replace(/\\n/g, '\n')
.replace(/\\t/g, '\t')
@ -141,43 +159,39 @@ export function CommandToolView({
<div className="p-4">
{output && (
<div className="mb-4">
<div className="bg-zinc-100 dark:bg-neutral-900 rounded-lg overflow-hidden border border-zinc-200/20">
<div className="bg-zinc-300 dark:bg-neutral-800 flex items-center justify-between dark:border-zinc-700/50">
<div className="bg-zinc-200 w-full dark:bg-zinc-800 px-4 py-2 flex items-center gap-2">
<TerminalIcon className="h-4 w-4 text-zinc-600 dark:text-zinc-400" />
<span className="text-sm font-medium text-zinc-700 dark:text-zinc-300">Terminal output</span>
</div>
{exitCode !== null && exitCode !== 0 && (
<Badge variant="outline" className="text-xs h-5 border-red-700/30 text-red-400">
<AlertTriangle className="h-3 w-3 mr-1" />
Error
</Badge>
<div className="mb-4">
<div className="bg-zinc-100 dark:bg-neutral-900 rounded-lg overflow-hidden border border-zinc-200/20">
<div className="bg-zinc-300 dark:bg-neutral-800 flex items-center justify-between dark:border-zinc-700/50">
<div className="bg-zinc-200 w-full dark:bg-zinc-800 px-4 py-2 flex items-center gap-2">
<TerminalIcon className="h-4 w-4 text-zinc-600 dark:text-zinc-400" />
<span className="text-sm font-medium text-zinc-700 dark:text-zinc-300">Terminal</span>
</div>
{exitCode !== null && exitCode !== 0 && (
<Badge variant="outline" className="text-xs h-5 border-red-700/30 text-red-400">
<AlertTriangle className="h-3 w-3 mr-1" />
Error
</Badge>
)}
</div>
<div className="p-4 max-h-96 overflow-auto scrollbar-hide">
<pre className="text-xs text-zinc-600 dark:text-zinc-300 font-mono whitespace-pre-wrap break-all overflow-visible">
{/* Show command only */}
{command && (
<div className="py-0.5 bg-transparent">
<span className="text-green-500 dark:text-green-400 font-semibold">{displayPrefix} </span>
<span className="text-zinc-700 dark:text-zinc-300">{command}</span>
</div>
)}
</div>
<div className="p-4 max-h-96 overflow-auto scrollbar-hide">
<pre className="text-xs text-zinc-600 dark:text-zinc-300 font-mono whitespace-pre-wrap break-all overflow-visible">
{linesToShow.map((line, index) => (
<div
key={index}
className="py-0.5 bg-transparent"
>
{line || ' '}
</div>
))}
{!showFullOutput && hasMoreLines && (
<div className="text-zinc-500 mt-2 border-t border-zinc-700/30 pt-2">
+ {formattedOutput.length - 10} more lines
</div>
)}
</pre>
</div>
{!showFullOutput && hasMoreLines && (
<div className="text-zinc-500 mt-2 border-t border-zinc-700/30 pt-2">
+ {formattedOutput.length - 10} more lines
</div>
)}
</pre>
</div>
</div>
)}
</div>
{!output && !isStreaming && (
<div className="bg-black rounded-lg overflow-hidden border border-zinc-700/20 shadow-md p-6 flex items-center justify-center">

View File

@ -34,18 +34,32 @@ const extractFromNewFormat = (content: any): CommandData => {
const toolExecution = parsedContent.tool_execution;
const args = toolExecution.arguments || {};
let parsedOutput = toolExecution.result?.output;
if (typeof parsedOutput === 'string') {
// Handle the case where result.output is a string (like in your example)
let output = toolExecution.result?.output;
let parsedOutput: any = {};
if (typeof output === 'string') {
// First try to parse it as JSON
try {
parsedOutput = JSON.parse(parsedOutput);
parsedOutput = JSON.parse(output);
// If parsing succeeds, extract the actual output from the nested structure
if (parsedOutput && typeof parsedOutput === 'object') {
// Look for output in common nested structures
output = parsedOutput.output || parsedOutput.message || parsedOutput.content || output;
}
} catch (e) {
// If it's not JSON, treat it as plain text output
output = output;
}
} else if (typeof output === 'object' && output !== null) {
parsedOutput = output;
// Extract output from object structure
output = (output as any).output || (output as any).message || (output as any).content || null;
}
parsedOutput = parsedOutput || {};
const extractedData = {
command: args.command || null,
output: parsedOutput?.output || null,
output: output || parsedOutput?.output || null,
exitCode: parsedOutput?.exit_code || null,
sessionName: args.session_name || parsedOutput?.session_name || null,
cwd: parsedOutput?.cwd || null,