mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-11 12:17:45 +02:00
[Haik]: ckpt, removed legacy deps from run_browser_loop. Now gonna refactor the new schemas.py to behave more like every other toolkit
This commit is contained in:
+11
-12
@@ -1,20 +1,18 @@
|
||||
import time
|
||||
from typing import Dict, List, Any
|
||||
from backend.apps.agents.browser.schemas import (
|
||||
BROWSER_TOOLS_SCHEMA, SYSTEM_PROMPT, MAX_TURNS,
|
||||
)
|
||||
|
||||
# NOTE: Hella dependancies, this baddddddd
|
||||
# TODO: fix this shit cuh
|
||||
from backend.apps.agents.browser.executor import execute_browser_tool, _format_tool_result
|
||||
from backend.apps.settings.settings import load_settings
|
||||
from backend.apps.settings.credentials import get_anthropic_client
|
||||
from backend.apps.common.model_registry import resolve_model_id
|
||||
from backend.apps.common.llm_helpers import _resolve_model as _resolve_9r
|
||||
|
||||
from backend.apps.agents.HaikFix.tools.make_builtin_toolkit.open_swarm_toolkits.browser_toolkit.handlers.utils.temp_sub_utils.model_ids import is_valid_model_id
|
||||
from backend.apps.agents.HaikFix.tools.make_builtin_toolkit.open_swarm_toolkits.browser_toolkit.handlers.utils.temp_sub_utils.model_ids import get_anthropic_client
|
||||
from backend.apps.agents.HaikFix.tools.make_builtin_toolkit.open_swarm_toolkits.browser_toolkit.handlers.utils.temp_sub_utils.schemas import BROWSER_TOOLS_SCHEMA, SYSTEM_PROMPT, MAX_TURNS
|
||||
|
||||
async def run_browser_loop(
|
||||
task: str,
|
||||
browser_id: str,
|
||||
model: str,
|
||||
model_id: str,
|
||||
initial_url: str | None = None,
|
||||
tab_id: str = "",
|
||||
) -> Dict[str, Any]:
|
||||
@@ -23,9 +21,10 @@ async def run_browser_loop(
|
||||
if initial_url:
|
||||
await execute_browser_tool("BrowserNavigate", {"url": initial_url}, browser_id, tab_id)
|
||||
|
||||
settings = load_settings()
|
||||
api_model = _resolve_9r(resolve_model_id(model), settings)
|
||||
client = get_anthropic_client(settings)
|
||||
if not is_valid_model_id(model_id):
|
||||
raise ValueError(f"Invalid model ID: {model_id}")
|
||||
|
||||
client = get_anthropic_client()
|
||||
|
||||
messages: List[Dict] = [{"role": "user", "content": task}]
|
||||
action_log: List[Dict] = []
|
||||
@@ -34,7 +33,7 @@ async def run_browser_loop(
|
||||
|
||||
for _ in range(MAX_TURNS):
|
||||
response = await client.messages.create(
|
||||
model=api_model,
|
||||
model=f"cc/{model_id}",
|
||||
max_tokens=4096,
|
||||
system=SYSTEM_PROMPT,
|
||||
tools=BROWSER_TOOLS_SCHEMA,
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
from typeguard import typechecked
|
||||
from backend.ports import NINE_ROUTER_PORT
|
||||
import anthropic
|
||||
import httpx
|
||||
|
||||
SONNET: str = "claude-sonnet-4-6"
|
||||
OPUS: str = "claude-opus-4-6"
|
||||
HAIKU: str = "claude-haiku-4-5"
|
||||
|
||||
@typechecked
|
||||
def is_valid_model_id(model_id: str) -> bool:
|
||||
return model_id in [SONNET, OPUS, HAIKU]
|
||||
|
||||
@typechecked
|
||||
def check_9router() -> bool:
|
||||
"""Check if 9Router is running locally."""
|
||||
try:
|
||||
response: httpx.Response = httpx.get(f"http://localhost:{NINE_ROUTER_PORT}/v1/models", timeout=2.0)
|
||||
return response.status_code == 200
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
@typechecked
|
||||
def get_anthropic_client() -> anthropic.AsyncAnthropic:
|
||||
if not check_9router():
|
||||
raise ValueError("9Router is not running")
|
||||
return anthropic.AsyncAnthropic(
|
||||
api_key="9router",
|
||||
base_url=f"http://localhost:{NINE_ROUTER_PORT}",
|
||||
)
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
"""Browser tool schemas, constants, and system prompt."""
|
||||
|
||||
BROWSER_TOOLS_SCHEMA = [
|
||||
{
|
||||
"name": "BrowserScreenshot",
|
||||
"description": (
|
||||
"Capture a screenshot of the browser page. Returns the screenshot as a "
|
||||
"base64-encoded PNG image. Use this to see what is currently displayed."
|
||||
),
|
||||
"input_schema": {"type": "object", "properties": {}, "required": []},
|
||||
},
|
||||
{
|
||||
"name": "BrowserGetText",
|
||||
"description": "Get the visible text content of the browser page. Returns up to 15000 characters.",
|
||||
"input_schema": {"type": "object", "properties": {}, "required": []},
|
||||
},
|
||||
{
|
||||
"name": "BrowserNavigate",
|
||||
"description": "Navigate the browser to a URL.",
|
||||
"input_schema": {
|
||||
"type": "object",
|
||||
"properties": {"url": {"type": "string", "description": "The URL to navigate to."}},
|
||||
"required": ["url"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "BrowserClick",
|
||||
"description": "Click an element identified by a CSS selector. Use BrowserGetElements first to discover valid selectors.",
|
||||
"input_schema": {
|
||||
"type": "object",
|
||||
"properties": {"selector": {"type": "string", "description": "CSS selector of the element to click."}},
|
||||
"required": ["selector"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "BrowserType",
|
||||
"description": "Type text into an input element. Clears existing value first.",
|
||||
"input_schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"selector": {"type": "string", "description": "CSS selector of the input element."},
|
||||
"text": {"type": "string", "description": "The text to type."},
|
||||
},
|
||||
"required": ["selector", "text"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "BrowserEvaluate",
|
||||
"description": "Evaluate a JavaScript expression in the browser page and return the result.",
|
||||
"input_schema": {
|
||||
"type": "object",
|
||||
"properties": {"expression": {"type": "string", "description": "JavaScript expression to evaluate."}},
|
||||
"required": ["expression"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "BrowserGetElements",
|
||||
"description": (
|
||||
"Get a list of interactive elements on the page with CSS selectors. "
|
||||
"Call this BEFORE clicking or typing so you know which selectors are valid."
|
||||
),
|
||||
"input_schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"selector": {
|
||||
"type": "string",
|
||||
"description": "Optional CSS selector to scope the search (e.g. 'form', '#main'). Defaults to 'body'.",
|
||||
},
|
||||
},
|
||||
"required": [],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "BrowserScroll",
|
||||
"description": (
|
||||
"Scroll the page up or down. Automatically finds the correct scrollable "
|
||||
"container. Returns scroll position info including whether top/bottom has been reached."
|
||||
),
|
||||
"input_schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"direction": {"type": "string", "enum": ["up", "down"], "description": "Scroll direction. Defaults to 'down'."},
|
||||
"amount": {"type": "number", "description": "Pixels to scroll. Defaults to 500."},
|
||||
},
|
||||
"required": [],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "BrowserWait",
|
||||
"description": (
|
||||
"Wait for a specified duration. Useful after navigation or actions that "
|
||||
"trigger page loads. Min 100ms, max 10000ms."
|
||||
),
|
||||
"input_schema": {
|
||||
"type": "object",
|
||||
"properties": {"milliseconds": {"type": "number", "description": "Duration to wait in milliseconds. Defaults to 1000."}},
|
||||
"required": [],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
ACTION_MAP = {
|
||||
"BrowserScreenshot": "screenshot",
|
||||
"BrowserGetText": "get_text",
|
||||
"BrowserNavigate": "navigate",
|
||||
"BrowserClick": "click",
|
||||
"BrowserType": "type",
|
||||
"BrowserEvaluate": "evaluate",
|
||||
"BrowserGetElements": "get_elements",
|
||||
"BrowserScroll": "scroll",
|
||||
"BrowserWait": "wait",
|
||||
}
|
||||
|
||||
SYSTEM_PROMPT = (
|
||||
"You are a browser automation agent. You control a single browser tab and "
|
||||
"execute the task you are given.\n\n"
|
||||
"Strategy:\n"
|
||||
"1. Start by taking a screenshot to understand the page.\n"
|
||||
"2. After navigation, use BrowserWait (1-3 seconds) to let the page finish loading.\n"
|
||||
"3. Use BrowserScroll to scroll through pages — do NOT use BrowserEvaluate with "
|
||||
"window.scrollBy() as many sites use nested scroll containers that BrowserScroll "
|
||||
"handles automatically.\n"
|
||||
"4. Use BrowserGetElements BEFORE clicking or typing to discover valid CSS selectors.\n"
|
||||
"5. After performing actions, take a screenshot to verify the result.\n"
|
||||
"6. If an action fails, try alternative selectors or approaches.\n"
|
||||
"7. When the task is complete, provide a clear summary of what you accomplished.\n\n"
|
||||
"Important notes:\n"
|
||||
"- BrowserGetText returns up to 15000 chars of visible text — use it to read page content.\n"
|
||||
"- BrowserScroll returns position info including atTop/atBottom — use this to know when "
|
||||
"you've reached the end of the page.\n"
|
||||
"- For complex SPAs (Notion, Gmail, etc.), prefer BrowserScroll over BrowserEvaluate for scrolling.\n"
|
||||
"- Avoid looping: if scrolling shows no new content (scrolled 0px), you're at the boundary.\n\n"
|
||||
"You have access ONLY to browser tools. Do not ask the user questions — "
|
||||
"complete the task autonomously to the best of your ability."
|
||||
)
|
||||
|
||||
MAX_TURNS = 25
|
||||
Reference in New Issue
Block a user