Skip to content

Commit f909967

Browse files
committed
replace static SCRIPTS_DIR with dynamic user_dir based on request
1 parent 12b8572 commit f909967

1 file changed

Lines changed: 28 additions & 51 deletions

File tree

llms/extensions/browser/__init__.py

Lines changed: 28 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
import asyncio
22
import json
33
import os
4+
from pathlib import Path
45
import subprocess
56
import shutil
67
import time
78
from collections import deque
89

910
from aiohttp import web
1011

11-
SCRIPTS_DIR = None
12-
PROFILE_DIR = None
13-
STATE_FILE = None
1412
AGENT_BROWSER_USER_AGENT = os.getenv(
1513
"AGENT_BROWSER_USER_AGENT",
1614
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.52 Safari/537.36",
@@ -20,23 +18,25 @@
2018

2119

2220
def install(ctx):
23-
global SCRIPTS_DIR, PROFILE_DIR, STATE_FILE
2421

2522
# Check for agent-browser binary
2623
if not shutil.which("agent-browser"):
2724
ctx.log("agent-browser not found. See https://agent-browser.dev/installation to use the browser extension.")
2825
ctx.disabled = True
2926
return
3027

31-
user_path = ctx.get_user_path()
32-
SCRIPTS_DIR = os.path.join(user_path, "browser", "scripts")
33-
PROFILE_DIR = os.path.join(user_path, "browser", "profile")
34-
STATE_FILE = os.path.join(user_path, "browser", "state.json")
28+
def ensure_dir(path):
29+
os.makedirs(path, exist_ok=True)
30+
return path
3531

36-
os.makedirs(SCRIPTS_DIR, exist_ok=True)
37-
os.makedirs(PROFILE_DIR, exist_ok=True)
32+
def get_script_dir(req):
33+
return ensure_dir(os.path.join(ctx.get_user_path(user=ctx.get_username(req)), "browser", "scripts"))
3834

39-
_browser_env = {"AGENT_BROWSER_PROFILE": PROFILE_DIR, "AGENT_BROWSER_USER_AGENT": AGENT_BROWSER_USER_AGENT}
35+
def get_profile_dir(req):
36+
return ensure_dir(os.path.join(ctx.get_user_path(user=ctx.get_username(req)), "browser", "profile"))
37+
38+
def get_state_file(req):
39+
return os.path.join(ctx.get_user_path(user=ctx.get_username(req)), "browser", "state.json")
4040

4141
def _add_debug_log(cmd_str, result, duration):
4242
global DEBUG_LOG_COUNTER
@@ -54,33 +54,6 @@ def _add_debug_log(cmd_str, result, duration):
5454
}
5555
)
5656

57-
def run_browser_cmd(*args, timeout=30, env=None):
58-
"""Run agent-browser command and return output."""
59-
cmd = ["agent-browser"] + list(args)
60-
cmd_str = " ".join(cmd)
61-
t0 = time.monotonic()
62-
try:
63-
ctx.dbg(f"Running: {cmd_str}")
64-
result = subprocess.run(
65-
cmd,
66-
capture_output=True,
67-
text=True,
68-
timeout=timeout,
69-
env={**os.environ, **env} if env else None,
70-
)
71-
ret = {
72-
"success": result.returncode == 0,
73-
"stdout": result.stdout,
74-
"stderr": result.stderr,
75-
"returncode": result.returncode,
76-
}
77-
except subprocess.TimeoutExpired:
78-
ret = {"success": False, "error": "Command timed out"}
79-
except Exception as e:
80-
ret = {"success": False, "error": str(e)}
81-
_add_debug_log(cmd_str, ret, time.monotonic() - t0)
82-
return ret
83-
8457
async def run_browser_cmd_async(*args, timeout=30, env=None):
8558
"""Run agent-browser command asynchronously."""
8659
cmd = ["agent-browser"] + list(args)
@@ -108,7 +81,7 @@ async def run_browser_cmd_async(*args, timeout=30, env=None):
10881
ret = {"success": False, "error": str(e)}
10982
_add_debug_log(cmd_str, ret, time.monotonic() - t0)
11083
return ret
111-
84+
11285
# =========================================================================
11386
# Status & Screenshot Endpoints
11487
# =========================================================================
@@ -206,6 +179,7 @@ async def browser_open(req):
206179
if not url:
207180
return web.json_response({"error": "URL required"}, status=400)
208181

182+
_browser_env = {"AGENT_BROWSER_PROFILE": get_profile_dir(req), "AGENT_BROWSER_USER_AGENT": AGENT_BROWSER_USER_AGENT}
209183
result = await run_browser_cmd_async("open", url, timeout=60, env=_browser_env)
210184
ctx.log(
211185
f"browser_open: Open result: success={result['success']}, stdout={result.get('stdout', '')[:100]}, stderr={result.get('stderr', '')[:100]}"
@@ -229,7 +203,7 @@ async def browser_open(req):
229203
async def browser_close(req):
230204
"""Close browser session and save state."""
231205
# Save state before closing
232-
await run_browser_cmd_async("state", "save", STATE_FILE)
206+
await run_browser_cmd_async("state", "save", get_state_file(req))
233207
result = await run_browser_cmd_async("close")
234208
return web.json_response({"success": result["success"]})
235209

@@ -326,17 +300,19 @@ async def browser_scroll(req):
326300

327301
async def save_state(req):
328302
"""Save browser session state."""
329-
result = await run_browser_cmd_async("state", "save", STATE_FILE)
330-
return web.json_response({"success": result["success"], "path": STATE_FILE if result["success"] else None})
303+
state_file = get_state_file(req)
304+
result = await run_browser_cmd_async("state", "save", state_file)
305+
return web.json_response({"success": result["success"], "path": state_file if result["success"] else None})
331306

332307
ctx.add_post("/browser/state/save", save_state)
333308

334309
async def load_state(req):
335310
"""Load browser session state."""
336-
if not os.path.exists(STATE_FILE):
311+
state_file = get_state_file(req)
312+
if not os.path.exists(state_file):
337313
return web.json_response({"error": "No saved state found"}, status=404)
338314

339-
result = await run_browser_cmd_async("state", "load", STATE_FILE)
315+
result = await run_browser_cmd_async("state", "load", state_file)
340316
return web.json_response({"success": result["success"]})
341317

342318
ctx.add_post("/browser/state/load", load_state)
@@ -356,10 +332,11 @@ async def list_sessions(req):
356332
async def list_scripts(req):
357333
"""List automation scripts."""
358334
scripts = []
359-
if os.path.exists(SCRIPTS_DIR):
360-
for name in os.listdir(SCRIPTS_DIR):
335+
scripts_dir = get_script_dir(req)
336+
if os.path.exists(scripts_dir):
337+
for name in os.listdir(scripts_dir):
361338
if name.endswith(".sh"):
362-
path = os.path.join(SCRIPTS_DIR, name)
339+
path = os.path.join(scripts_dir, name)
363340
scripts.append(
364341
{"name": name, "path": path, "size": os.path.getsize(path), "modified": os.path.getmtime(path)}
365342
)
@@ -372,7 +349,7 @@ async def get_script(req):
372349
name = req.match_info["name"]
373350
if not name.endswith(".sh"):
374351
name += ".sh"
375-
path = os.path.join(SCRIPTS_DIR, name)
352+
path = os.path.join(get_script_dir(req), name)
376353

377354
if not os.path.exists(path):
378355
return web.json_response({"error": "Script not found"}, status=404)
@@ -398,7 +375,7 @@ async def save_script(req):
398375

399376
# Sanitize name
400377
name = os.path.basename(name)
401-
path = os.path.join(SCRIPTS_DIR, name)
378+
path = os.path.join(get_script_dir(req), name)
402379

403380
with open(path, "w") as f:
404381
f.write(content)
@@ -414,7 +391,7 @@ async def delete_script(req):
414391
name = req.match_info["name"]
415392
if not name.endswith(".sh"):
416393
name += ".sh"
417-
path = os.path.join(SCRIPTS_DIR, os.path.basename(name))
394+
path = os.path.join(get_script_dir(req), os.path.basename(name))
418395

419396
if not os.path.exists(path):
420397
return web.json_response({"error": "Script not found"}, status=404)
@@ -429,7 +406,7 @@ async def run_script(req):
429406
name = req.match_info["name"]
430407
if not name.endswith(".sh"):
431408
name += ".sh"
432-
path = os.path.join(SCRIPTS_DIR, os.path.basename(name))
409+
path = os.path.join(get_script_dir(req), os.path.basename(name))
433410

434411
if not os.path.exists(path):
435412
return web.json_response({"error": "Script not found"}, status=404)

0 commit comments

Comments
 (0)