Skip to content

Commit 31a891b

Browse files
committed
feat: add interactive wait tool for human-in-the-loop tasks
1 parent d6b242a commit 31a891b

1 file changed

Lines changed: 27 additions & 2 deletions

File tree

agent.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,23 @@
5858
def multiply_numbers(x: float, y: float) -> dict:
5959
"""Multiplies two numbers."""
6060
return {"result": x * y}
61-
61+
def wait_for_user_input(prompt_text: str) -> dict:
62+
"""Pauses the agent and waits for the user to press Enter in the terminal.
63+
64+
Useful when the agent needs the user to perform an action outside the browser
65+
(like scanning a QR code, entering a 2FA code) before continuing.
66+
67+
Args:
68+
prompt_text: The message to display to the user explaining what they need to do.
69+
"""
70+
print(f"\n" + "="*40)
71+
print(f"🛑 AGENT REQUEST: {prompt_text}")
72+
print(f"="*40 + "\n")
73+
74+
# 这行代码会让程序“卡住”,直到你按回车
75+
input("Press Enter to continue execution...")
76+
77+
return {"status": "success", "message": "User confirmed action complete."}
6278

6379
class BrowserAgent:
6480
def __init__(
@@ -96,7 +112,10 @@ def __init__(
96112
# For example:
97113
types.FunctionDeclaration.from_callable(
98114
client=self._client, callable=multiply_numbers
99-
)
115+
),
116+
types.FunctionDeclaration.from_callable(
117+
client=self._client, callable=wait_for_user_input
118+
),
100119
]
101120

102121
self._generate_content_config = GenerateContentConfig(
@@ -122,6 +141,7 @@ def handle_action(self, action: types.FunctionCall) -> FunctionResponseT:
122141
"""Handles the action and returns the environment state."""
123142
if action.name == "open_web_browser":
124143
return self._browser_computer.open_web_browser()
144+
125145
elif action.name == "click_at":
126146
x = self.denormalize_x(action.args["x"])
127147
y = self.denormalize_y(action.args["y"])
@@ -193,6 +213,9 @@ def handle_action(self, action: types.FunctionCall) -> FunctionResponseT:
193213
# Handle the custom function declarations here.
194214
elif action.name == multiply_numbers.__name__:
195215
return multiply_numbers(x=action.args["x"], y=action.args["y"])
216+
elif action.name == wait_for_user_input.__name__:
217+
return wait_for_user_input(prompt_text=action.args["prompt_text"])
218+
# --------------------
196219
else:
197220
raise ValueError(f"Unsupported function: {action}")
198221

@@ -347,6 +370,8 @@ def run_one_iteration(self) -> Literal["COMPLETE", "CONTINUE"]:
347370
)
348371
)
349372
elif isinstance(fc_result, dict):
373+
response_data = fc_result.copy()
374+
response_data.update(extra_fr_fields)
350375
function_responses.append(
351376
FunctionResponse(name=function_call.name, response=fc_result)
352377
)

0 commit comments

Comments
 (0)