Skip to content

Commit e24de2d

Browse files
feat: adds initial implementation of waiting and waitingFor tool
1 parent 04e961b commit e24de2d

File tree

2 files changed

+189
-0
lines changed

2 files changed

+189
-0
lines changed

simple_waiting.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from askui.tools.store.universal import WaitingTool, WaitingForTool
2+
3+
# Test WaitingTool - waits for a fixed time (1 minute)
4+
waiting_tool = WaitingTool()
5+
print(waiting_tool(wait_time=1))
6+
7+
# Test WaitingForTool - waits until condition is met
8+
counter = {"value": 0}
9+
10+
def condition():
11+
counter["value"] += 1
12+
print(f"Check #{counter['value']}")
13+
return counter["value"] >= 3
14+
15+
waiting_for_tool = WaitingForTool(
16+
exit_criterion=condition,
17+
condition_description="the counter reaches 3"
18+
)
19+
print(f"Tool description: {waiting_for_tool.description}")
20+
print(waiting_for_tool(max_wait_time=1, check_interval=1))
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
import time
2+
import logging
3+
from typing import Callable
4+
5+
from askui.models.shared.tools import Tool
6+
7+
8+
logger = logging.getLogger(__name__)
9+
10+
11+
class WaitingForTool(Tool):
12+
"""
13+
Tool for waiting until a specific condition is met.
14+
15+
This tool periodically checks a user-provided exit criterion and waits until
16+
the condition returns True or the maximum wait time is reached. It is useful
17+
for scenarios where the agent needs to wait for an external event or state
18+
change, such as waiting for a process to complete, a file to appear, or a
19+
system to become available.
20+
21+
Args:
22+
exit_criterion (Callable[[], bool]): A callable that takes no arguments
23+
and returns a boolean. The tool will keep waiting until this callable
24+
returns True.
25+
condition_description (str): A human-readable description of what condition
26+
is being checked. This is shown to the agent so it understands what
27+
it is waiting for.
28+
29+
Example:
30+
```python
31+
from askui import VisionAgent
32+
from askui.tools.store.universal import WaitingForTool
33+
34+
def check_file_exists():
35+
return os.path.exists("/path/to/expected/file.txt")
36+
37+
with VisionAgent() as agent:
38+
agent.act(
39+
"Wait for the download to complete",
40+
tools=[WaitingForTool(
41+
exit_criterion=check_file_exists,
42+
condition_description="the file /path/to/expected/file.txt exists"
43+
)]
44+
)
45+
```
46+
"""
47+
48+
def __init__(
49+
self, exit_criterion: Callable[[], bool], condition_description: str
50+
) -> None:
51+
super().__init__(
52+
name="wait_for_tool",
53+
description=(
54+
f"Waits until {condition_description}. This tool periodically checks "
55+
"the condition and returns when it is met or the timeout is reached."
56+
),
57+
input_schema={
58+
"type": "object",
59+
"properties": {
60+
"max_wait_time": {
61+
"type": "integer",
62+
"description": (
63+
"The maximum wait time in minutes before timing out. "
64+
"Defaults to 10 minutes if not specified."
65+
),
66+
},
67+
"check_interval": {
68+
"type": "integer",
69+
"description": (
70+
"The interval time in seconds between two checks. "
71+
"Defaults to 10 seconds if not specified."
72+
),
73+
},
74+
},
75+
"required": [],
76+
},
77+
)
78+
self._exit_criterion = exit_criterion
79+
80+
def __call__(self, max_wait_time: int = 10, check_interval: int = 10) -> str:
81+
"""
82+
Wait for the exit criterion to be met.
83+
84+
Args:
85+
max_wait_time (int): The maximum wait time in minutes before timing out.
86+
Defaults to 10 minutes.
87+
check_interval (int): The interval time in seconds between two checks.
88+
Defaults to 10 seconds.
89+
90+
Returns:
91+
str: A message indicating whether the condition was met or the timeout
92+
was reached.
93+
"""
94+
latest_end_time = time.time() + max_wait_time * 60
95+
logger.info(f"Waiting for condition to be met (max {max_wait_time} minutes)...")
96+
while True:
97+
# Check wait exit criterion
98+
finished_waiting = self._exit_criterion()
99+
# Evaluate exit criteria
100+
if finished_waiting:
101+
logger.info("Finished Waiting")
102+
return "Finished Waiting"
103+
elif time.time() > latest_end_time:
104+
logger.warning("Maximum Waiting time reached")
105+
return (
106+
f"The maximum waiting time of {max_wait_time} minutes was reached "
107+
"without the exit criterion being met."
108+
)
109+
else:
110+
logger.info(f"Checking again in {check_interval} seconds...")
111+
time.sleep(check_interval)
112+
113+
114+
class WaitingTool(Tool):
115+
"""
116+
Tool for waiting (sleeping) for a specified amount of time.
117+
118+
This tool pauses execution for a given duration. It is useful when the agent
119+
needs to wait for a fixed amount of time, such as waiting for a slow operation
120+
to complete, giving the system time to process, or implementing a delay between
121+
actions.
122+
123+
Example:
124+
```python
125+
from askui import VisionAgent
126+
from askui.tools.store.universal import WaitingTool
127+
128+
with VisionAgent() as agent:
129+
agent.act(
130+
"Submit the form and wait 2 minutes for processing",
131+
tools=[WaitingTool()]
132+
)
133+
```
134+
"""
135+
136+
def __init__(self) -> None:
137+
super().__init__(
138+
name="waiting_tool",
139+
description=(
140+
"Waits (i.e. sleeps) for a specified time."
141+
),
142+
input_schema={
143+
"type": "object",
144+
"properties": {
145+
"wait_time": {
146+
"type": "integer",
147+
"description": (
148+
"The wait time in minutes before timing out. "
149+
),
150+
},
151+
},
152+
"required": ["wait_time"],
153+
},
154+
)
155+
156+
def __call__(self, wait_time: int = 10) -> str:
157+
"""
158+
Wait for the specified amount of time.
159+
160+
Args:
161+
wait_time (int): The wait time in minutes. Defaults to 10 minutes.
162+
163+
Returns:
164+
str: A confirmation message indicating that the wait has completed.
165+
"""
166+
logger.info(f"Waiting for {wait_time} minutes...")
167+
time.sleep(wait_time * 60)
168+
logger.info("Finished waiting")
169+
return "Finished waiting"

0 commit comments

Comments
 (0)