fix: tool view fixes

This commit is contained in:
Vukasin 2025-06-04 16:23:22 +02:00
parent 0023ea9a0a
commit b82a0459f8
5 changed files with 31 additions and 71 deletions

View File

@ -543,13 +543,16 @@ For casual conversation and social interactions:
## 7.3 ATTACHMENT PROTOCOL ## 7.3 ATTACHMENT PROTOCOL
- **CRITICAL: ALL VISUALIZATIONS MUST BE ATTACHED:** - **CRITICAL: ALL VISUALIZATIONS MUST BE ATTACHED:**
* When using the 'ask' tool <ask attachments="file1, file2, file3"></ask>, ALWAYS attach ALL visualizations, markdown files, charts, graphs, reports, and any viewable content created * When using the 'ask' tool <ask attachments="file1, file2, file3"></ask>, ALWAYS attach ALL visualizations, markdown files, charts, graphs, reports, and any viewable content created
* **MANDATORY RULE: If you have created ANY files during this conversation, you MUST include them as attachments when using the ask tool**
* This includes but is not limited to: HTML files, PDF documents, markdown files, images, data visualizations, presentations, reports, dashboards, and UI mockups * This includes but is not limited to: HTML files, PDF documents, markdown files, images, data visualizations, presentations, reports, dashboards, and UI mockups
* **NEVER use the ask tool without attachments if you have created files** - this is a critical error
* NEVER mention a visualization or viewable content without attaching it * NEVER mention a visualization or viewable content without attaching it
* If you've created multiple visualizations, attach ALL of them * If you've created multiple visualizations, attach ALL of them
* Always make visualizations available to the user BEFORE marking tasks as complete * Always make visualizations available to the user BEFORE marking tasks as complete
* For web applications or interactive content, always attach the main HTML file * For web applications or interactive content, always attach the main HTML file
* When creating data analysis results, charts must be attached, not just described * When creating data analysis results, charts must be attached, not just described
* Remember: If the user should SEE it, you must ATTACH it with the 'ask' tool * Remember: If the user should SEE it, you must ATTACH it with the 'ask' tool
* **EXAMPLE: If you create files like main.py, README.md, config.json, notes.txt, you MUST use: <ask attachments="main.py,README.md,config.json,notes.txt">**
* Verify that ALL visual outputs have been attached before proceeding * Verify that ALL visual outputs have been attached before proceeding
- **Attachment Checklist:** - **Attachment Checklist:**
@ -562,7 +565,7 @@ For casual conversation and social interactions:
* Analysis results with visual components * Analysis results with visual components
* UI designs and mockups * UI designs and mockups
* Any file intended for user viewing or interaction * Any file intended for user viewing or interaction
* **ANY FILES CREATED DURING THE CONVERSATION - ALWAYS ATTACH THEM**
# 8. COMPLETION PROTOCOLS # 8. COMPLETION PROTOCOLS

View File

@ -1,5 +1,6 @@
from typing import List, Optional, Union from typing import List, Optional, Union
from agentpress.tool import Tool, ToolResult, openapi_schema, xml_schema from agentpress.tool import Tool, ToolResult, openapi_schema, xml_schema
from utils.logger import logger
class MessageTool(Tool): class MessageTool(Tool):
"""Tool for user communication and interaction. """Tool for user communication and interaction.
@ -68,11 +69,11 @@ This information will help me make sure the cake meets your expectations for the
Returns: Returns:
ToolResult indicating the question was successfully sent ToolResult indicating the question was successfully sent
""" """
try: try:
# Convert single attachment to list for consistent handling # Convert single attachment to list for consistent handling
if attachments and isinstance(attachments, str): if attachments and isinstance(attachments, str):
attachments = [attachments] attachments = [attachments]
return self.success_response({"status": "Awaiting user response..."}) return self.success_response({"status": "Awaiting user response..."})
except Exception as e: except Exception as e:
return self.fail_response(f"Error asking user: {str(e)}") return self.fail_response(f"Error asking user: {str(e)}")

View File

@ -107,7 +107,8 @@ class SandboxDeployTool(SandboxToolsBase):
npx wrangler pages deploy {full_path} --project-name {project_name}))''' npx wrangler pages deploy {full_path} --project-name {project_name}))'''
# Execute the command directly using the sandbox's process.exec method # Execute the command directly using the sandbox's process.exec method
response = self.sandbox.process.exec(deploy_cmd, timeout=300) response = self.sandbox.process.exec(f"/bin/sh -c \"{deploy_cmd}\"",
timeout=300)
print(f"Deployment command output: {response.result}") print(f"Deployment command output: {response.result}")

View File

@ -35,7 +35,7 @@ export function AskToolView({
onFileClick, onFileClick,
project, project,
}: AskToolViewProps) { }: AskToolViewProps) {
const { const {
text, text,
attachments, attachments,
@ -190,12 +190,7 @@ export function AskToolView({
})} })}
</div> </div>
{actualAssistantTimestamp && (
<div className="flex items-center gap-2 text-xs text-muted-foreground">
<Clock className="h-3 w-3" />
{formatTimestamp(actualAssistantTimestamp)}
</div>
)}
</div> </div>
) : ( ) : (
<div className="flex flex-col items-center justify-center py-8 text-center"> <div className="flex flex-col items-center justify-center py-8 text-center">

View File

@ -68,16 +68,16 @@ export function CommandToolView({
} }
} catch (e) { } catch (e) {
} }
processedOutput = String(processedOutput); processedOutput = String(processedOutput);
processedOutput = processedOutput.replace(/\\\\/g, '\\'); processedOutput = processedOutput.replace(/\\\\/g, '\\');
processedOutput = processedOutput processedOutput = processedOutput
.replace(/\\n/g, '\n') .replace(/\\n/g, '\n')
.replace(/\\t/g, '\t') .replace(/\\t/g, '\t')
.replace(/\\"/g, '"') .replace(/\\"/g, '"')
.replace(/\\'/g, "'"); .replace(/\\'/g, "'");
processedOutput = processedOutput.replace(/\\u([0-9a-fA-F]{4})/g, (match, group) => { processedOutput = processedOutput.replace(/\\u([0-9a-fA-F]{4})/g, (match, group) => {
return String.fromCharCode(parseInt(group, 16)); return String.fromCharCode(parseInt(group, 16));
}); });
@ -102,13 +102,13 @@ export function CommandToolView({
</CardTitle> </CardTitle>
</div> </div>
</div> </div>
{!isStreaming && ( {!isStreaming && (
<Badge <Badge
variant="secondary" variant="secondary"
className={ className={
actualIsSuccess actualIsSuccess
? "bg-gradient-to-b from-emerald-200 to-emerald-100 text-emerald-700 dark:from-emerald-800/50 dark:to-emerald-900/60 dark:text-emerald-300" ? "bg-gradient-to-b from-emerald-200 to-emerald-100 text-emerald-700 dark:from-emerald-800/50 dark:to-emerald-900/60 dark:text-emerald-300"
: "bg-gradient-to-b from-rose-200 to-rose-100 text-rose-700 dark:from-rose-800/50 dark:to-rose-900/60 dark:text-rose-300" : "bg-gradient-to-b from-rose-200 to-rose-100 text-rose-700 dark:from-rose-800/50 dark:to-rose-900/60 dark:text-rose-300"
} }
> >
@ -117,8 +117,8 @@ export function CommandToolView({
) : ( ) : (
<AlertTriangle className="h-3.5 w-3.5 mr-1" /> <AlertTriangle className="h-3.5 w-3.5 mr-1" />
)} )}
{actualIsSuccess ? {actualIsSuccess ?
(name === 'check-command-output' ? 'Output retrieved successfully' : 'Command executed successfully') : (name === 'check-command-output' ? 'Output retrieved successfully' : 'Command executed successfully') :
(name === 'check-command-output' ? 'Failed to retrieve output' : 'Command failed') (name === 'check-command-output' ? 'Failed to retrieve output' : 'Command failed')
} }
</Badge> </Badge>
@ -128,7 +128,7 @@ export function CommandToolView({
<CardContent className="p-0 h-full flex-1 overflow-hidden relative"> <CardContent className="p-0 h-full flex-1 overflow-hidden relative">
{isStreaming ? ( {isStreaming ? (
<LoadingState <LoadingState
icon={Terminal} icon={Terminal}
iconColor="text-purple-500 dark:text-purple-400" iconColor="text-purple-500 dark:text-purple-400"
bgColor="bg-gradient-to-b from-purple-100 to-purple-50 shadow-inner dark:from-purple-800/40 dark:to-purple-900/60 dark:shadow-purple-950/20" bgColor="bg-gradient-to-b from-purple-100 to-purple-50 shadow-inner dark:from-purple-800/40 dark:to-purple-900/60 dark:shadow-purple-950/20"
@ -139,52 +139,12 @@ export function CommandToolView({
) : displayText ? ( ) : displayText ? (
<ScrollArea className="h-full w-full"> <ScrollArea className="h-full w-full">
<div className="p-4"> <div className="p-4">
<div className="mb-4 bg-zinc-100 dark:bg-neutral-900 rounded-lg overflow-hidden border border-zinc-200 dark:border-zinc-800">
<div className="bg-zinc-200 dark:bg-zinc-800 px-4 py-2 flex items-center gap-2">
<Code 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">{displayLabel}</span>
{sessionName && cwd && (
<Badge variant="outline" className="text-xs ml-auto">
{cwd}
</Badge>
)}
</div>
<div className="p-4 font-mono text-sm text-zinc-700 dark:text-zinc-300 flex gap-2">
<span className="text-purple-500 dark:text-purple-400 select-none">{displayPrefix}</span>
<code className="flex-1 break-all">{displayText}</code>
</div>
</div>
{output && ( {output && (
<div className="mb-4"> <div className="mb-4">
<div className="flex items-center justify-between mb-2">
<h3 className="text-sm font-medium text-zinc-700 dark:text-zinc-300 flex items-center">
<ArrowRight className="h-4 w-4 mr-2 text-zinc-500 dark:text-zinc-400" />
Output
</h3>
<div className="flex items-center gap-2">
{completed !== null && (
<Badge
variant="outline"
className="text-xs"
>
{completed ? 'Completed' : 'Running'}
</Badge>
)}
{exitCode !== null && (
<Badge
className={cn(
exitCode === 0
? "bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400"
: "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400"
)}
>
{exitCode === 0 ? 'Success' : `Exit ${exitCode}`}
</Badge>
)}
</div>
</div>
<div className="bg-zinc-100 dark:bg-neutral-900 rounded-lg overflow-hidden border border-zinc-200/20"> <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-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"> <div className="bg-zinc-200 w-full dark:bg-zinc-800 px-4 py-2 flex items-center gap-2">
@ -201,8 +161,8 @@ export function CommandToolView({
<div className="p-4 max-h-96 overflow-auto scrollbar-hide"> <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"> <pre className="text-xs text-zinc-600 dark:text-zinc-300 font-mono whitespace-pre-wrap break-all overflow-visible">
{linesToShow.map((line, index) => ( {linesToShow.map((line, index) => (
<div <div
key={index} key={index}
className="py-0.5 bg-transparent" className="py-0.5 bg-transparent"
> >
{line || ' '} {line || ' '}
@ -218,7 +178,7 @@ export function CommandToolView({
</div> </div>
</div> </div>
)} )}
{!output && !isStreaming && ( {!output && !isStreaming && (
<div className="bg-black rounded-lg overflow-hidden border border-zinc-700/20 shadow-md p-6 flex items-center justify-center"> <div className="bg-black rounded-lg overflow-hidden border border-zinc-700/20 shadow-md p-6 flex items-center justify-center">
<div className="text-center"> <div className="text-center">
@ -238,7 +198,7 @@ export function CommandToolView({
{name === 'check-command-output' ? 'No Session Found' : 'No Command Found'} {name === 'check-command-output' ? 'No Session Found' : 'No Command Found'}
</h3> </h3>
<p className="text-sm text-zinc-500 dark:text-zinc-400 text-center max-w-md"> <p className="text-sm text-zinc-500 dark:text-zinc-400 text-center max-w-md">
{name === 'check-command-output' {name === 'check-command-output'
? 'No session name was detected. Please provide a valid session name to check.' ? 'No session name was detected. Please provide a valid session name to check.'
: 'No command was detected. Please provide a valid command to execute.' : 'No command was detected. Please provide a valid command to execute.'
} }
@ -246,7 +206,7 @@ export function CommandToolView({
</div> </div>
)} )}
</CardContent> </CardContent>
<div className="px-4 py-2 h-10 bg-gradient-to-r from-zinc-50/90 to-zinc-100/90 dark:from-zinc-900/90 dark:to-zinc-800/90 backdrop-blur-sm border-t border-zinc-200 dark:border-zinc-800 flex justify-between items-center gap-4"> <div className="px-4 py-2 h-10 bg-gradient-to-r from-zinc-50/90 to-zinc-100/90 dark:from-zinc-900/90 dark:to-zinc-800/90 backdrop-blur-sm border-t border-zinc-200 dark:border-zinc-800 flex justify-between items-center gap-4">
<div className="h-full flex items-center gap-2 text-sm text-zinc-500 dark:text-zinc-400"> <div className="h-full flex items-center gap-2 text-sm text-zinc-500 dark:text-zinc-400">
{!isStreaming && displayText && ( {!isStreaming && displayText && (
@ -256,7 +216,7 @@ export function CommandToolView({
</Badge> </Badge>
)} )}
</div> </div>
<div className="text-xs text-zinc-500 dark:text-zinc-400 flex items-center gap-2"> <div className="text-xs text-zinc-500 dark:text-zinc-400 flex items-center gap-2">
<Clock className="h-3.5 w-3.5" /> <Clock className="h-3.5 w-3.5" />
{actualToolTimestamp && !isStreaming {actualToolTimestamp && !isStreaming