Merge pull request #1671 from KrishavRajSingh/feat/wait_tool

Feat/wait tool
This commit is contained in:
Krishav 2025-09-18 15:42:43 +05:30 committed by GitHub
commit a1582112ad
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 224 additions and 0 deletions

View File

@ -828,6 +828,22 @@ Your approach is adaptive and context-aware:
6. **Be Human:** Use natural, conversational language throughout all interactions
7. **Show Personality:** Be warm, helpful, and genuinely interested in helping the user succeed
**PACED EXECUTION & WAIT TOOL USAGE:**
8. **Deliberate Pacing:** Use the 'wait' tool frequently during long processes to maintain a steady, thoughtful pace rather than rushing through tasks
9. **Strategic Waiting:** Add brief pauses to:
- Allow file operations to complete properly
- Prevent overwhelming the system with rapid-fire operations
- Ensure quality execution over speed
- Add breathing room between complex operations
- Let long-running commands finish naturally instead of abandoning them
10. **Wait Tool Usage:**
- Use 1-3 seconds for brief pauses between operations
- Use 5-10 seconds for processing waits
- Use 10-30 seconds for long-running commands (npm install, build processes, etc.)
- Proactively use wait tool during long processes to prevent rushing
11. **Quality Over Speed:** Prioritize thorough, accurate execution over rapid completion
12. **Patience with Long Processes:** When a command is running (like create-react-app, npm install, etc.), wait for it to complete rather than switching to alternative approaches
**EXECUTION CYCLES:**
- **Conversational Cycle:** Question Response Follow-up User Input
- **Task Execution Cycle:** Analyze Plan Execute Update Complete

View File

@ -369,6 +369,67 @@ All deliverables are attached for your review.</parameter>
except Exception as e:
return self.fail_response(f"Error entering complete state: {str(e)}")
@openapi_schema({
"type": "function",
"function": {
"name": "wait",
"description": "Pause execution for a specified number of seconds. Use this tool to add deliberate pauses in long-running processes to prevent rushing and maintain a steady, thoughtful pace. This helps prevent errors and ensures quality execution.",
"parameters": {
"type": "object",
"properties": {
"seconds": {
"type": "integer",
"description": "Number of seconds to wait (1-300 seconds). Use 1-3 seconds for brief pauses, 5-10 seconds for processing waits, 60+ seconds for longer operations.",
"minimum": 1,
"maximum": 300
}
},
"required": ["seconds"]
}
}
})
@usage_example('''
<function_calls>
<invoke name="wait">
<parameter name="seconds">3</parameter>
</invoke>
</function_calls>
<function_calls>
<invoke name="wait">
<parameter name="seconds">5</parameter>
</invoke>
</function_calls>
''')
async def wait(self, seconds: int) -> ToolResult:
"""Pause execution for a specified number of seconds.
Args:
seconds: Number of seconds to wait (1-300)
Returns:
ToolResult indicating the wait was completed
"""
try:
# Validate duration
if seconds < 1 or seconds > 300:
return self.fail_response("Duration must be between 1 and 300 seconds")
# Import asyncio for the sleep
import asyncio
# Log the wait
logger.info(f"Agent waiting {seconds} seconds")
# Perform the wait
await asyncio.sleep(seconds)
# Return success
return self.success_response(f"Waited {seconds} seconds")
except Exception as e:
return self.fail_response(f"Error during wait: {str(e)}")
if __name__ == "__main__":
import asyncio

View File

@ -0,0 +1,144 @@
'use client';
import React from 'react';
import { Clock, CheckCircle, AlertTriangle, Loader2, Timer } from 'lucide-react';
import { ToolViewProps } from '../types';
import { formatTimestamp, extractToolData, getToolTitle } from '../utils';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { ScrollArea } from "@/components/ui/scroll-area";
import { cn } from '@/lib/utils';
interface WaitToolViewProps extends ToolViewProps {
// No additional props needed
}
const extractWaitData = (toolContent?: any, isSuccess: boolean = true) => {
let seconds = 0;
let actualIsSuccess = isSuccess;
if (toolContent) {
try {
const toolData = extractToolData(toolContent);
const toolResult = toolData.toolResult;
const arguments_ = toolResult?.arguments || {};
seconds = arguments_.seconds || 0;
actualIsSuccess = toolResult ? toolResult.isSuccess : isSuccess;
} catch (error) {
console.error('Error parsing wait tool content:', error);
}
}
return {
seconds,
isSuccess: actualIsSuccess
};
};
export function WaitToolView({
name = 'wait',
assistantContent,
toolContent,
assistantTimestamp,
toolTimestamp,
isSuccess = true,
isStreaming = false,
}: WaitToolViewProps) {
const { seconds, isSuccess: actualIsSuccess } = extractWaitData(toolContent, isSuccess);
const formatDuration = (seconds: number) => {
if (seconds < 60) {
return `${seconds}s`;
} else {
const minutes = Math.floor(seconds / 60);
const remainingSeconds = seconds % 60;
return remainingSeconds > 0 ? `${minutes}m ${remainingSeconds}s` : `${minutes}m`;
}
};
const toolTitle = getToolTitle(name) || 'Wait';
return (
<Card className="gap-0 flex border shadow-none border-t border-b-0 border-x-0 p-0 rounded-none flex-col h-full overflow-hidden bg-card">
<CardHeader className="h-14 bg-zinc-50/80 dark:bg-zinc-900/80 backdrop-blur-sm border-b p-2 px-4 space-y-2">
<div className="flex flex-row items-center justify-between">
<div className="flex items-center gap-2">
<div className="relative p-2 rounded-xl bg-gradient-to-br from-orange-500/20 to-orange-600/10 border border-orange-500/20">
<Clock className="w-5 h-5 text-orange-500 dark:text-orange-400" />
</div>
<div>
<CardTitle className="text-base font-medium text-zinc-900 dark:text-zinc-100">
{toolTitle}
</CardTitle>
</div>
</div>
{!isStreaming && (
<Badge
variant="secondary"
className={
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-rose-200 to-rose-100 text-rose-700 dark:from-rose-800/50 dark:to-rose-900/60 dark:text-rose-300"
}
>
{actualIsSuccess ? (
<CheckCircle className="h-3.5 w-3.5 mr-1" />
) : (
<AlertTriangle className="h-3.5 w-3.5 mr-1" />
)}
{actualIsSuccess ? 'Completed' : 'Failed'}
</Badge>
)}
{isStreaming && (
<Badge className="bg-gradient-to-b from-orange-200 to-orange-100 text-orange-700 dark:from-orange-800/50 dark:to-orange-900/60 dark:text-orange-300">
<Loader2 className="h-3.5 w-3.5 animate-spin mr-1" />
Waiting
</Badge>
)}
</div>
</CardHeader>
<CardContent className="p-0 flex-1 overflow-hidden relative">
<div className="h-full flex items-center justify-center p-8">
<div className="flex flex-col items-center text-center max-w-md">
<Timer className="h-24 w-24 text-muted-foreground mb-6" />
<div className="text-5xl font-medium text-foreground mb-3">
{formatDuration(seconds)}
</div>
<div className="text-sm text-muted-foreground mb-4">
{isStreaming
? 'The system is currently pausing execution for the specified duration.'
: `The system paused execution for ${formatDuration(seconds)} as requested.`
}
</div>
{seconds > 0 && (
<div className="text-xs text-muted-foreground bg-muted/50 px-3 py-2 rounded-full">
{isStreaming ? 'Please wait...' : 'Wait completed successfully'}
</div>
)}
</div>
</div>
</CardContent>
{/* Footer */}
<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">
<Badge className="h-6 py-0.5" variant="outline">
<Clock className="h-3 w-3 mr-1" />
Timing Control
</Badge>
</div>
<div className="text-xs text-zinc-500 dark:text-zinc-400">
{toolTimestamp ? formatTimestamp(toolTimestamp) : assistantTimestamp ? formatTimestamp(assistantTimestamp) : ''}
</div>
</div>
</Card>
);
}

View File

@ -15,6 +15,7 @@ import { SeeImageToolView } from '../see-image-tool/SeeImageToolView';
import { TerminateCommandToolView } from '../command-tool/TerminateCommandToolView';
import { AskToolView } from '../ask-tool/AskToolView';
import { CompleteToolView } from '../CompleteToolView';
import { WaitToolView } from '../wait-tool/WaitToolView';
import { ExecuteDataProviderCallToolView } from '../data-provider-tool/ExecuteDataProviderCallToolView';
import { DataProviderEndpointsToolView } from '../data-provider-tool/DataProviderEndpointsToolView';
import { DeployToolView } from '../DeployToolView';
@ -107,6 +108,7 @@ const defaultRegistry: ToolViewRegistryType = {
'ask': AskToolView,
'complete': CompleteToolView,
'wait': WaitToolView,
'deploy': DeployToolView,

View File

@ -331,6 +331,7 @@ const TOOL_DISPLAY_NAMES = new Map([
['deploy', 'Deploying'],
['ask', 'Ask'],
['wait', 'Wait'],
['create-tasks', 'Creating Tasks'],
['update-tasks', 'Updating Tasks'],
['complete', 'Completing Task'],