hide attachments, non-blocking shell exec

This commit is contained in:
marko-kraemer 2025-04-21 13:41:01 +01:00
parent b71762bafd
commit b7105e71d3
5 changed files with 77 additions and 37 deletions

View File

@ -108,6 +108,14 @@ You have the ability to execute operations using both Python and CLI tools:
- Always clean up sessions after use
- Avoid commands requiring confirmation; actively use -y or -f flags for automatic confirmation
- Avoid commands with excessive output; save to files when necessary
- **IMPORTANT**: Shell commands are blocking by default - they will not return control until the command completes, which can cause timeouts with long-running operations
- For non-blocking, long-running commands, use these simple approaches:
1. Run a command in the background using `&`: `command &`
2. Make a process immune to hangups: `nohup command > output.log 2>&1 &`
3. Start a background process and get its PID: `command & echo $!`
4. Check if a process is still running: `ps -p PID_NUMBER`
5. View output of a background process: `tail -f output.log`
6. Kill a background process: `kill PID_NUMBER` or `pkill PROCESS_NAME`
- Chain multiple commands with operators to minimize interruptions and improve efficiency:
1. Use && for sequential execution: `command1 && command2 && command3`
2. Use || for fallback execution: `command1 || command2`

View File

@ -36,7 +36,7 @@ class SandboxShellTool(SandboxToolsBase):
"type": "function",
"function": {
"name": "execute_command",
"description": "Execute a shell command in the workspace directory. Uses sessions to maintain state between commands. This tool is essential for running CLI tools, installing packages, and managing system operations. Always verify command outputs before using the data. Commands can be chained using && for sequential execution, || for fallback execution, and | for piping output.",
"description": "Execute a shell command in the workspace directory. IMPORTANT: By default, commands are blocking and will wait for completion before returning. For long-running operations, use background execution techniques (& operator, nohup) to prevent timeouts. Uses sessions to maintain state between commands. This tool is essential for running CLI tools, installing packages, and managing system operations. Always verify command outputs before using the data. Commands can be chained using && for sequential execution, || for fallback execution, and | for piping output.",
"parameters": {
"type": "object",
"properties": {
@ -55,7 +55,7 @@ class SandboxShellTool(SandboxToolsBase):
},
"timeout": {
"type": "integer",
"description": "Optional timeout in seconds. Increase for long-running commands. Defaults to 60.",
"description": "Optional timeout in seconds. Increase for long-running commands. Defaults to 60. For commands that might exceed this timeout, use background execution with & operator instead.",
"default": 60
}
},
@ -72,30 +72,59 @@ class SandboxShellTool(SandboxToolsBase):
{"param_name": "timeout", "node_type": "attribute", "path": ".", "required": False}
],
example='''
<!-- Example 1: Basic command execution -->
<!-- IMPORTANT: By default, all commands are blocking and will wait for completion -->
<!-- Example 1: Basic command execution (blocking) -->
<execute-command>
ls -l
</execute-command>
<!-- Example 2: Command in specific directory -->
<!-- Example 2: Command in specific directory (blocking) -->
<execute-command folder="data/pdfs">
pdftotext document.pdf -layout
</execute-command>
<!-- Example 3: Using named session for related commands -->
<!-- Example 3: Using named session for related commands (blocking) -->
<execute-command session_name="pdf_processing">
pdftotext input.pdf -layout > output.txt
</execute-command>
<!-- Example 4: Complex command with pipes and chaining -->
<!-- Example 4: Complex command with pipes and chaining (blocking) -->
<execute-command>
find . -type f -name "*.txt" | sort && grep -r "pattern" . | awk '{print $1}' | sort | uniq -c
</execute-command>
<!-- Example 5: Command with error handling and chaining -->
<!-- Example 5: Command with error handling and chaining (blocking) -->
<execute-command>
pdftotext input.pdf -layout 2>&1 || echo "Error processing PDF" && ls -la output.txt
</execute-command>
<!-- NON-BLOCKING COMMANDS: Use these for long-running operations to prevent timeouts -->
<!-- Example 6: Basic non-blocking command with & operator -->
<execute-command>
python scraper.py --large-dataset > scraper_output.log 2>&1 &
</execute-command>
<!-- Example 7: Run a process with nohup for immunity to hangups -->
<execute-command>
nohup python processor.py --heavy-computation > processor.log 2>&1 &
</execute-command>
<!-- Example 8: Starting a background process and storing its PID -->
<execute-command>
python long_task.py & echo $! > task.pid
</execute-command>
<!-- Example 9: Checking if a process is still running -->
<execute-command>
ps -p $(cat task.pid)
</execute-command>
<!-- Example 10: Killing a background process -->
<execute-command>
kill $(cat task.pid)
</execute-command>
'''
)
async def execute_command(
@ -122,7 +151,7 @@ class SandboxShellTool(SandboxToolsBase):
from sandbox.sandbox import SessionExecuteRequest
req = SessionExecuteRequest(
command=command,
var_async=False,
var_async=False, # This makes the command blocking by default
cwd=cwd # Still set the working directory for reference
)

View File

@ -96,6 +96,7 @@ function DashboardContent() {
placeholder="Describe what you need help with..."
value={inputValue}
onChange={setInputValue}
hideAttachments={true}
/>
</div>
</div>

View File

@ -42,6 +42,7 @@ interface ChatInputProps {
onChange?: (value: string) => void;
onFileBrowse?: () => void;
sandboxId?: string;
hideAttachments?: boolean;
}
interface UploadedFile {
@ -61,7 +62,8 @@ export function ChatInput({
value: controlledValue,
onChange: controlledOnChange,
onFileBrowse,
sandboxId
sandboxId,
hideAttachments = false
}: ChatInputProps) {
const isControlled = controlledValue !== undefined && controlledOnChange !== undefined;
@ -398,29 +400,31 @@ export function ChatInput({
</TooltipProvider>
)} */}
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button
type="button"
onClick={handleFileUpload}
variant="ghost"
size="icon"
className="h-8 w-8 rounded-md text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800"
disabled={loading || (disabled && !isAgentRunning) || isUploading}
>
{isUploading ? (
<Loader2 className="h-4 w-4 animate-spin" />
) : (
<Paperclip className="h-4 w-4" />
)}
</Button>
</TooltipTrigger>
<TooltipContent side="top">
<p>Attach files</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
{!hideAttachments && (
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button
type="button"
onClick={handleFileUpload}
variant="ghost"
size="icon"
className="h-8 w-8 rounded-md text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800"
disabled={loading || (disabled && !isAgentRunning) || isUploading}
>
{isUploading ? (
<Loader2 className="h-4 w-4 animate-spin" />
) : (
<Paperclip className="h-4 w-4" />
)}
</Button>
</TooltipTrigger>
<TooltipContent side="top">
<p>Attach files</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
)}
<input
type="file"

View File

@ -5,7 +5,7 @@ import { oneDark, oneLight } from 'react-syntax-highlighter/dist/esm/styles/pris
import { ToolViewProps } from "./types";
import { extractFilePath, extractFileContent, getFileType, formatTimestamp, getToolTitle } from "./utils";
import { GenericToolView } from "./GenericToolView";
import { Markdown } from "@/components/ui/markdown";
import { MarkdownRenderer } from "@/components/file-renderers/markdown-renderer";
import { CsvRenderer } from "@/components/file-renderers/csv-renderer";
import { cn } from "@/lib/utils";
import { useTheme } from "next-themes";
@ -380,10 +380,8 @@ export function FileOperationToolView({
{/* Markdown Preview */}
{isMarkdown && viewMode === 'preview' && isSuccess && (
<div className="flex-1 overflow-auto bg-white dark:bg-zinc-950 text-zinc-900 dark:text-zinc-100 p-4">
<Markdown className="text-sm prose prose-sm dark:prose-invert max-w-none">
{fileContent}
</Markdown>
<div className="flex-1 overflow-auto bg-white dark:bg-zinc-950 text-zinc-900 dark:text-zinc-100">
<MarkdownRenderer content={fileContent} />
</div>
)}