vibesurf 0.1.6__tar.gz → 0.1.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. {vibesurf-0.1.6 → vibesurf-0.1.8}/PKG-INFO +8 -3
  2. {vibesurf-0.1.6 → vibesurf-0.1.8}/README.md +5 -1
  3. {vibesurf-0.1.6 → vibesurf-0.1.8}/pyproject.toml +2 -1
  4. {vibesurf-0.1.6 → vibesurf-0.1.8}/tests/test_agents.py +10 -12
  5. {vibesurf-0.1.6 → vibesurf-0.1.8}/tests/test_browser.py +5 -4
  6. {vibesurf-0.1.6 → vibesurf-0.1.8}/tests/test_controller.py +1 -2
  7. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/_version.py +3 -3
  8. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/agents/browser_use_agent.py +48 -154
  9. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/agents/vibe_surf_agent.py +13 -12
  10. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/backend/shared_state.py +1 -1
  11. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/backend/utils/encryption.py +5 -35
  12. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/browser/agen_browser_profile.py +3 -4
  13. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/browser/agent_browser_session.py +115 -52
  14. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/browser/browser_manager.py +2 -2
  15. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/browser/utils.py +8 -15
  16. vibesurf-0.1.8/vibe_surf/browser/watchdogs/action_watchdog.py +105 -0
  17. vibesurf-0.1.8/vibe_surf/browser/watchdogs/dom_watchdog.py +282 -0
  18. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/chrome_extension/scripts/session-manager.js +0 -2
  19. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/chrome_extension/scripts/ui-manager.js +3 -3
  20. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/cli.py +7 -1
  21. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/controller/mcp_client.py +0 -4
  22. vibesurf-0.1.6/vibe_surf/controller/vibesurf_controller.py → vibesurf-0.1.8/vibe_surf/controller/vibesurf_tools.py +13 -48
  23. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibesurf.egg-info/PKG-INFO +8 -3
  24. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibesurf.egg-info/SOURCES.txt +2 -2
  25. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibesurf.egg-info/requires.txt +2 -1
  26. vibesurf-0.1.6/vibe_surf/browser/watchdogs/action_watchdog.py +0 -291
  27. vibesurf-0.1.6/vibe_surf/browser/watchdogs/dom_watchdog.py +0 -954
  28. {vibesurf-0.1.6 → vibesurf-0.1.8}/.env.example +0 -0
  29. {vibesurf-0.1.6 → vibesurf-0.1.8}/.github/workflows/publish.yml +0 -0
  30. {vibesurf-0.1.6 → vibesurf-0.1.8}/.gitignore +0 -0
  31. {vibesurf-0.1.6 → vibesurf-0.1.8}/.python-version +0 -0
  32. {vibesurf-0.1.6 → vibesurf-0.1.8}/LICENSE +0 -0
  33. {vibesurf-0.1.6 → vibesurf-0.1.8}/MANIFEST.in +0 -0
  34. {vibesurf-0.1.6 → vibesurf-0.1.8}/docs/PYPI_SETUP.md +0 -0
  35. {vibesurf-0.1.6 → vibesurf-0.1.8}/setup.cfg +0 -0
  36. {vibesurf-0.1.6 → vibesurf-0.1.8}/tests/test_backend_api.py +0 -0
  37. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/__init__.py +0 -0
  38. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/agents/__init__.py +0 -0
  39. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/agents/prompts/__init__.py +0 -0
  40. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/agents/prompts/vibe_surf_prompt.py +0 -0
  41. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/agents/report_writer_agent.py +0 -0
  42. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/backend/__init__.py +0 -0
  43. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/backend/api/__init__.py +0 -0
  44. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/backend/api/activity.py +0 -0
  45. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/backend/api/config.py +0 -0
  46. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/backend/api/files.py +0 -0
  47. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/backend/api/models.py +0 -0
  48. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/backend/api/task.py +0 -0
  49. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/backend/database/__init__.py +0 -0
  50. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/backend/database/manager.py +0 -0
  51. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/backend/database/models.py +0 -0
  52. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/backend/database/queries.py +0 -0
  53. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/backend/database/schemas.py +0 -0
  54. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/backend/llm_config.py +0 -0
  55. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/backend/main.py +0 -0
  56. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/backend/migrations/__init__.py +0 -0
  57. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/backend/migrations/init_db.py +0 -0
  58. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/backend/migrations/seed_data.py +0 -0
  59. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/backend/utils/__init__.py +0 -0
  60. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/backend/utils/llm_factory.py +0 -0
  61. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/browser/__init__.py +0 -0
  62. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/browser/watchdogs/__init__.py +0 -0
  63. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/chrome_extension/background.js +0 -0
  64. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/chrome_extension/config.js +0 -0
  65. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/chrome_extension/content.js +0 -0
  66. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/chrome_extension/dev-reload.js +0 -0
  67. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/chrome_extension/icons/convert-svg.js +0 -0
  68. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/chrome_extension/icons/logo-preview.html +0 -0
  69. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/chrome_extension/icons/logo.png +0 -0
  70. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/chrome_extension/manifest.json +0 -0
  71. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/chrome_extension/popup.html +0 -0
  72. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/chrome_extension/scripts/api-client.js +0 -0
  73. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/chrome_extension/scripts/main.js +0 -0
  74. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/chrome_extension/scripts/markdown-it.min.js +0 -0
  75. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/chrome_extension/sidepanel.html +0 -0
  76. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/chrome_extension/styles/animations.css +0 -0
  77. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/chrome_extension/styles/components.css +0 -0
  78. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/chrome_extension/styles/main.css +0 -0
  79. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/chrome_extension/styles/settings.css +0 -0
  80. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/controller/__init__.py +0 -0
  81. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/controller/file_system.py +0 -0
  82. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/controller/views.py +0 -0
  83. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/llm/__init__.py +0 -0
  84. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibe_surf/llm/openai_compatible.py +0 -0
  85. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibesurf.egg-info/dependency_links.txt +0 -0
  86. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibesurf.egg-info/entry_points.txt +0 -0
  87. {vibesurf-0.1.6 → vibesurf-0.1.8}/vibesurf.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vibesurf
3
- Version: 0.1.6
3
+ Version: 0.1.8
4
4
  Summary: VibeSurf: A powerful browser assistant for vibe surfing
5
5
  Author: Shao Warm
6
6
  License: Apache-2.0
@@ -26,7 +26,7 @@ Requires-Dist: json-repair>=0.48.0
26
26
  Requires-Dist: aiohttp>=3.12.15
27
27
  Requires-Dist: scikit-image>=0.25.2
28
28
  Requires-Dist: python-socks>=2.7.2
29
- Requires-Dist: browser-use==0.6.1
29
+ Requires-Dist: browser-use==0.7.1
30
30
  Requires-Dist: langgraph>=0.6.4
31
31
  Requires-Dist: fastapi>=0.104.0
32
32
  Requires-Dist: uvicorn[standard]>=0.24.0
@@ -37,6 +37,7 @@ Requires-Dist: sqlalchemy>=2.0.43
37
37
  Requires-Dist: aiosqlite>=0.21.0
38
38
  Requires-Dist: rich>=13.0.0
39
39
  Requires-Dist: greenlet>=3.2.4
40
+ Requires-Dist: getmac>=0.9.5
40
41
  Dynamic: license-file
41
42
 
42
43
  # VibeSurf: A powerful browser assistant for vibe surfing
@@ -75,7 +76,7 @@ powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | ie
75
76
  ### Step 2: Setup and Install
76
77
  ```bash
77
78
  uv venv --python 3.12
78
- uv pip install vibesurf
79
+ uv pip install vibesurf -U
79
80
  ```
80
81
 
81
82
  ### Step 3: Launch
@@ -85,8 +86,12 @@ vibesurf
85
86
 
86
87
  ## 🎬 Demo
87
88
 
89
+ ### How to use?
88
90
  <video src="https://github.com/user-attachments/assets/0a4650c0-c4ed-423e-9e16-7889e9f9816d" controls="controls">Your browser does not support playing this video!</video>
89
91
 
92
+ ### Dozens of agent running in on browser
93
+ <video src="https://github.com/user-attachments/assets/9c461a6e-5d97-4335-ba09-59e8ec4ad47b" controls="controls">Your browser does not support playing this video!</video>
94
+
90
95
 
91
96
  ## 📝 License
92
97
 
@@ -34,7 +34,7 @@ powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | ie
34
34
  ### Step 2: Setup and Install
35
35
  ```bash
36
36
  uv venv --python 3.12
37
- uv pip install vibesurf
37
+ uv pip install vibesurf -U
38
38
  ```
39
39
 
40
40
  ### Step 3: Launch
@@ -44,8 +44,12 @@ vibesurf
44
44
 
45
45
  ## 🎬 Demo
46
46
 
47
+ ### How to use?
47
48
  <video src="https://github.com/user-attachments/assets/0a4650c0-c4ed-423e-9e16-7889e9f9816d" controls="controls">Your browser does not support playing this video!</video>
48
49
 
50
+ ### Dozens of agent running in on browser
51
+ <video src="https://github.com/user-attachments/assets/9c461a6e-5d97-4335-ba09-59e8ec4ad47b" controls="controls">Your browser does not support playing this video!</video>
52
+
49
53
 
50
54
  ## 📝 License
51
55
 
@@ -27,7 +27,7 @@ dependencies = [
27
27
  "aiohttp>=3.12.15",
28
28
  "scikit-image>=0.25.2",
29
29
  "python-socks>=2.7.2",
30
- "browser-use==0.6.1",
30
+ "browser-use==0.7.1",
31
31
  "langgraph>=0.6.4",
32
32
  "fastapi>=0.104.0",
33
33
  "uvicorn[standard]>=0.24.0",
@@ -38,6 +38,7 @@ dependencies = [
38
38
  "aiosqlite>=0.21.0",
39
39
  "rich>=13.0.0",
40
40
  "greenlet>=3.2.4",
41
+ "getmac>=0.9.5",
41
42
  ]
42
43
 
43
44
  [project.urls]
@@ -14,10 +14,7 @@ from vibe_surf.browser.browser_manager import BrowserManager
14
14
  from vibe_surf.browser.agent_browser_session import AgentBrowserSession
15
15
 
16
16
  from vibe_surf.browser.agent_browser_session import AgentBrowserSession
17
- from browser_use.llm import ChatOpenAI
18
- from browser_use.controller.service import Controller
19
- from browser_use.agent.service import Agent as OrgBrowserUseAgent
20
- from vibe_surf.controller.vibesurf_controller import VibeSurfController
17
+ from vibe_surf.controller.vibesurf_tools import VibeSurfController
21
18
  from vibe_surf.llm.openai_compatible import ChatOpenAICompatible
22
19
  from vibe_surf.agents.browser_use_agent import BrowserUseAgent
23
20
  from vibe_surf.agents.vibe_surf_agent import VibeSurfAgent
@@ -89,8 +86,8 @@ async def run_multi_bu_agents():
89
86
  await main_browser_session.start()
90
87
  browser_manager = BrowserManager(main_browser_session=main_browser_session)
91
88
  controller = VibeSurfController()
92
- await controller.register_mcp_clients(mcp_server_config)
93
- llm = ChatOpenAICompatible(model='gemini-2.5-pro', base_url=os.getenv("OPENAI_ENDPOINT"),
89
+ # await controller.register_mcp_clients(mcp_server_config)
90
+ llm = ChatOpenAICompatible(model='gemini-2.5-flash', base_url=os.getenv("OPENAI_ENDPOINT"),
94
91
  api_key=os.getenv("OPENAI_API_KEY"))
95
92
  agent_browser_sessions = await asyncio.gather(
96
93
  browser_manager.register_agent("agent-1"),
@@ -129,7 +126,7 @@ async def run_multi_bu_agents():
129
126
  await main_browser_session.kill()
130
127
 
131
128
 
132
- async def test_swarm_surf_agent():
129
+ async def test_vibe_surf_agent():
133
130
  """Test VibeSurfAgent with both simple and browser tasks"""
134
131
  import platform
135
132
  if platform.system() != "Darwin":
@@ -143,6 +140,7 @@ async def test_swarm_surf_agent():
143
140
  user_data_dir=os.path.abspath('./tmp/chrome/profiles/default'),
144
141
  headless=False,
145
142
  keep_alive=True,
143
+ highlight_elements=True,
146
144
  window_size={"width": 1100, "height": 1280}
147
145
  # window_size={"width": primary_monitor.width, "height": primary_monitor.height}
148
146
  )
@@ -196,7 +194,7 @@ async def test_swarm_surf_agent():
196
194
 
197
195
  # Test 4: Browser parallel task
198
196
  print("🧪 Testing browser parallel tasks...")
199
- browser_task = "Search for Dify, n8n, browser-use and gather relative information, and generate a report for comparison"
197
+ browser_task = "Search for Dify, n8n, browser-use and get latest news"
200
198
  result4 = await agent.run(browser_task)
201
199
  print(f"✅ Browser task result:")
202
200
  pprint.pprint(result4)
@@ -214,7 +212,7 @@ async def test_swarm_surf_agent():
214
212
  await main_browser_session.kill()
215
213
 
216
214
 
217
- async def test_swarm_surf_agent_control():
215
+ async def test_vibe_surf_agent_control():
218
216
  """Test VibeSurfAgent control functionality (pause/resume/stop)"""
219
217
  import platform
220
218
  if platform.system() != "Darwin":
@@ -377,6 +375,6 @@ async def test_swarm_surf_agent_control():
377
375
 
378
376
  if __name__ == "__main__":
379
377
  # asyncio.run(run_single_bu_agent())
380
- # asyncio.run(run_multi_bu_agents())
381
- asyncio.run(test_swarm_surf_agent())
382
- # asyncio.run(test_swarm_surf_agent_control())
378
+ asyncio.run(run_multi_bu_agents())
379
+ # asyncio.run(test_vibe_surf_agent())
380
+ # asyncio.run(test_vibe_surf_agent_control())
@@ -163,8 +163,8 @@ async def test_browser_state_capture(manager: BrowserManager):
163
163
  task_start = time.time()
164
164
  logging.info(f"🔍 DIAGNOSIS: {agent_name} get state started at {task_start - start_time:.3f}s")
165
165
  # 使用新的并发导航方法绕过串行瓶颈
166
- # state = await agent.get_browser_state_summary()
167
- state = await agent.get_browser_state()
166
+ state = await agent.get_browser_state_summary()
167
+ # state = await agent.get_browser_state()
168
168
  task_end = time.time()
169
169
  logging.info(
170
170
  f"🔍 DIAGNOSIS: {agent_name} get state completed at {task_end - start_time:.3f}s (duration: {task_end - task_start:.3f}s)")
@@ -215,7 +215,7 @@ async def test_browser_state_capture(manager: BrowserManager):
215
215
 
216
216
  # Get new state for agent 1
217
217
  logging.info("Capturing new state for agent 1...")
218
- state1_new = await agent1.get_browser_state()
218
+ state1_new = await agent1.get_browser_state_summary()
219
219
 
220
220
  # Print new tabs and save screenshot
221
221
  logging.info(f"Agent 1 new tabs: {state1_new.tabs}")
@@ -255,13 +255,14 @@ async def main():
255
255
  from pathlib import Path
256
256
  current_file = Path(__file__)
257
257
  project_root = current_file.parent.parent # vibe_surf/browser -> vibe_surf -> project_root
258
- chrome_extension_path = project_root / "chrome_extension"
258
+ chrome_extension_path = project_root / "vibe_surf" / "chrome_extension"
259
259
  assert os.path.exists(chrome_extension_path)
260
260
 
261
261
  browser_profile = AgentBrowserProfile(
262
262
  executable_path=browser_exec_path,
263
263
  user_data_dir=os.path.abspath('./tmp/chrome/profiles/default'),
264
264
  headless=False,
265
+ highlight_elements=True,
265
266
  custom_extensions=[str(chrome_extension_path.absolute())]
266
267
  )
267
268
  # Use SwarmBrowserSession instead of BrowserSession to disable DVD animation
@@ -12,8 +12,7 @@ load_dotenv()
12
12
 
13
13
  async def test_controller_with_mcp():
14
14
  import os
15
- from vibe_surf.controller.vibesurf_controller import VibeSurfController
16
- from browser_use.controller.registry.views import ActionModel
15
+ from vibe_surf.controller.vibesurf_tools import VibeSurfController
17
16
 
18
17
  mcp_server_config = {
19
18
  "mcpServers": {
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '0.1.6'
32
- __version_tuple__ = version_tuple = (0, 1, 6)
31
+ __version__ = version = '0.1.8'
32
+ __version_tuple__ = version_tuple = (0, 1, 8)
33
33
 
34
- __commit_id__ = commit_id = 'g098f3e416'
34
+ __commit_id__ = commit_id = 'gaa38d8984'
@@ -53,12 +53,12 @@ from browser_use.agent.views import (
53
53
  StepMetadata,
54
54
  )
55
55
  from pydantic import BaseModel, ConfigDict, Field, ValidationError, create_model, model_validator
56
- from browser_use.browser import BrowserProfile, BrowserSession
56
+ from browser_use import Browser, BrowserProfile, BrowserSession
57
57
  from browser_use.browser.session import DEFAULT_BROWSER_PROFILE
58
58
  from browser_use.browser.views import BrowserStateSummary
59
59
  from browser_use.config import CONFIG
60
- from browser_use.controller.registry.views import ActionModel
61
- from browser_use.controller.service import Controller
60
+ from browser_use.tools.registry.views import ActionModel
61
+ from browser_use.tools.service import Controller, Tools
62
62
  from browser_use.dom.views import DOMInteractedElement
63
63
  from browser_use.filesystem.file_system import FileSystem
64
64
  from browser_use.observability import observe, observe_debug
@@ -79,45 +79,6 @@ from vibe_surf.controller.file_system import CustomFileSystem
79
79
  Context = TypeVar('Context')
80
80
 
81
81
 
82
- def log_response(response: AgentOutput, registry=None, logger=None) -> None:
83
- """Utility function to log the model's response."""
84
-
85
- # Use module logger if no logger provided
86
- if logger is None:
87
- logger = logging.getLogger(__name__)
88
-
89
- # Only log thinking if it's present
90
- if response.current_state.thinking:
91
- logger.info(f'💡 Thinking:\n{response.current_state.thinking}')
92
-
93
- # Only log evaluation if it's not empty
94
- eval_goal = response.current_state.evaluation_previous_goal
95
- if eval_goal:
96
- if 'success' in eval_goal.lower():
97
- emoji = '👍'
98
- # Green color for success
99
- logger.info(f' \033[32m{emoji} Eval: {eval_goal}\033[0m')
100
- elif 'failure' in eval_goal.lower():
101
- emoji = '⚠️'
102
- # Red color for failure
103
- logger.info(f' \033[31m{emoji} Eval: {eval_goal}\033[0m')
104
- else:
105
- emoji = '❔'
106
- # No color for unknown/neutral
107
- logger.info(f' {emoji} Eval: {eval_goal}')
108
-
109
- # Always log memory if present
110
- if response.current_state.memory:
111
- logger.debug(f'🧠 Memory: {response.current_state.memory}')
112
-
113
- # Only log next goal if it's not empty
114
- next_goal = response.current_state.next_goal
115
- if next_goal:
116
- # Blue color for next goal
117
- logger.info(f' \033[34m🎯 Next goal: {next_goal}\033[0m')
118
- else:
119
- logger.info('') # Add empty line for spacing
120
-
121
82
 
122
83
  class BrowserUseAgent(Agent):
123
84
  @time_execution_sync('--init')
@@ -128,7 +89,9 @@ class BrowserUseAgent(Agent):
128
89
  # Optional parameters
129
90
  browser_profile: BrowserProfile | None = None,
130
91
  browser_session: BrowserSession | None = None,
131
- controller: Controller[Context] | None = None,
92
+ browser: Browser | None = None, # Alias for browser_session
93
+ tools: Tools[Context] | None = None,
94
+ controller: Tools[Context] | None = None, # Alias for tools
132
95
  # Initial agent run parameters
133
96
  sensitive_data: dict[str, str | dict[str, str]] | None = None,
134
97
  initial_actions: list[dict[str, dict[str, Any]]] | None = None,
@@ -147,14 +110,11 @@ class BrowserUseAgent(Agent):
147
110
  # Agent settings
148
111
  output_model_schema: type[AgentStructuredOutput] | None = None,
149
112
  use_vision: bool = True,
150
- use_vision_for_planner: bool = False, # Deprecated
151
113
  save_conversation_path: str | Path | None = None,
152
114
  save_conversation_path_encoding: str | None = 'utf-8',
153
115
  max_failures: int = 3,
154
- retry_delay: int = 10,
155
116
  override_system_message: str | None = None,
156
117
  extend_system_message: str | None = None,
157
- validate_output: bool = False,
158
118
  generate_gif: bool | str = False,
159
119
  available_file_paths: list[str] | None = None,
160
120
  include_attributes: list[str] | None = None,
@@ -163,12 +123,7 @@ class BrowserUseAgent(Agent):
163
123
  flash_mode: bool = False,
164
124
  max_history_items: int | None = None,
165
125
  page_extraction_llm: BaseChatModel | None = None,
166
- planner_llm: BaseChatModel | None = None, # Deprecated
167
- planner_interval: int = 1, # Deprecated
168
- is_planner_reasoning: bool = False, # Deprecated
169
- extend_planner_system_message: str | None = None, # Deprecated
170
126
  injected_agent_state: AgentState | None = None,
171
- context: Context | None = None,
172
127
  source: str | None = None,
173
128
  file_system_path: str | None = None,
174
129
  task_id: str | None = None,
@@ -179,38 +134,11 @@ class BrowserUseAgent(Agent):
179
134
  vision_detail_level: Literal['auto', 'low', 'high'] = 'auto',
180
135
  llm_timeout: int = 90,
181
136
  step_timeout: int = 120,
182
- preload: bool = True,
137
+ directly_open_url: bool = True,
183
138
  include_recent_events: bool = False,
184
139
  allow_parallel_action_types: list[str] = ["extract_structured_data", "extract_content_from_file"],
185
140
  **kwargs,
186
141
  ):
187
- if not isinstance(llm, BaseChatModel):
188
- raise ValueError('invalid llm, must be from browser_use.llm')
189
- # Check for deprecated planner parameters
190
- planner_params = [
191
- planner_llm,
192
- use_vision_for_planner,
193
- is_planner_reasoning,
194
- extend_planner_system_message,
195
- ]
196
- if any(param is not None and param is not False for param in planner_params) or planner_interval != 1:
197
- self.logger.warning(
198
- '⚠️ Planner functionality has been removed in browser-use v0.3.3+. '
199
- 'The planner_llm, use_vision_for_planner, planner_interval, is_planner_reasoning, '
200
- 'and extend_planner_system_message parameters are deprecated and will be ignored. '
201
- 'Please remove these parameters from your Agent() initialization.'
202
- )
203
-
204
- # Check for deprecated memory parameters
205
- if kwargs.get('enable_memory', False) or kwargs.get('memory_config') is not None:
206
- self.logger.warning(
207
- 'Memory support has been removed as of version 0.3.2. '
208
- 'The agent context for memory is significantly improved and no longer requires the old memory system. '
209
- "Please remove the 'enable_memory' and 'memory_config' parameters."
210
- )
211
- kwargs['enable_memory'] = False
212
- kwargs['memory_config'] = None
213
-
214
142
  if page_extraction_llm is None:
215
143
  page_extraction_llm = llm
216
144
  if available_file_paths is None:
@@ -221,39 +149,49 @@ class BrowserUseAgent(Agent):
221
149
  self.session_id: str = uuid7str()
222
150
  self.allow_parallel_action_types = allow_parallel_action_types
223
151
 
152
+ browser_profile = browser_profile or DEFAULT_BROWSER_PROFILE
153
+
154
+ # Handle browser vs browser_session parameter (browser takes precedence)
155
+ if browser and browser_session:
156
+ raise ValueError(
157
+ 'Cannot specify both "browser" and "browser_session" parameters. Use "browser" for the cleaner API.')
158
+ browser_session = browser or browser_session
159
+
160
+ self.browser_session = browser_session or BrowserSession(
161
+ browser_profile=browser_profile,
162
+ id=uuid7str()[:-4] + self.id[-4:], # re-use the same 4-char suffix so they show up together in logs
163
+ )
164
+
224
165
  # Initialize available file paths as direct attribute
225
166
  self.available_file_paths = available_file_paths
226
167
 
227
- # Temporary logger for initialization (will be replaced by property)
228
- self._logger = None
229
-
230
168
  # Core components
231
169
  self.task = task
232
170
  self.llm = llm
233
- self.preload = preload
171
+ self.directly_open_url = directly_open_url
234
172
  self.include_recent_events = include_recent_events
235
- self.controller = (
236
- controller if controller is not None else Controller(display_files_in_done_text=display_files_in_done_text)
237
- )
173
+ if tools is not None:
174
+ self.tools = tools
175
+ elif controller is not None:
176
+ self.tools = controller
177
+ else:
178
+ self.tools = Tools(display_files_in_done_text=display_files_in_done_text)
238
179
 
239
180
  # Structured output
240
181
  self.output_model_schema = output_model_schema
241
182
  if self.output_model_schema is not None:
242
- self.controller.use_structured_output_action(self.output_model_schema)
183
+ self.tools.use_structured_output_action(self.output_model_schema)
243
184
 
244
185
  self.sensitive_data = sensitive_data
245
186
 
246
187
  self.settings = AgentSettings(
247
188
  use_vision=use_vision,
248
189
  vision_detail_level=vision_detail_level,
249
- use_vision_for_planner=False, # Always False now (deprecated)
250
190
  save_conversation_path=save_conversation_path,
251
191
  save_conversation_path_encoding=save_conversation_path_encoding,
252
192
  max_failures=max_failures,
253
- retry_delay=retry_delay,
254
193
  override_system_message=override_system_message,
255
194
  extend_system_message=extend_system_message,
256
- validate_output=validate_output,
257
195
  generate_gif=generate_gif,
258
196
  include_attributes=include_attributes,
259
197
  max_actions_per_step=max_actions_per_step,
@@ -261,10 +199,6 @@ class BrowserUseAgent(Agent):
261
199
  flash_mode=flash_mode,
262
200
  max_history_items=max_history_items,
263
201
  page_extraction_llm=page_extraction_llm,
264
- planner_llm=None, # Always None now (deprecated)
265
- planner_interval=1, # Always 1 now (deprecated)
266
- is_planner_reasoning=False, # Always False now (deprecated)
267
- extend_planner_system_message=None, # Always None now (deprecated)
268
202
  calculate_cost=calculate_cost,
269
203
  include_tool_call_examples=include_tool_call_examples,
270
204
  llm_timeout=llm_timeout,
@@ -275,7 +209,6 @@ class BrowserUseAgent(Agent):
275
209
  self.token_cost_service = TokenCost(include_cost=calculate_cost)
276
210
  self.token_cost_service.register_llm(llm)
277
211
  self.token_cost_service.register_llm(page_extraction_llm)
278
- # Note: No longer registering planner_llm (deprecated)
279
212
 
280
213
  # Initialize state
281
214
  self.state = injected_agent_state or AgentState()
@@ -297,8 +230,19 @@ class BrowserUseAgent(Agent):
297
230
  # Action setup
298
231
  self._setup_action_models()
299
232
  self._set_browser_use_version_and_source(source)
300
- self.initial_actions = self._convert_initial_actions(initial_actions) if initial_actions else None
301
233
 
234
+ initial_url = None
235
+
236
+ # only load url if no initial actions are provided
237
+ if self.directly_open_url and not self.state.follow_up_task and not initial_actions:
238
+ initial_url = self._extract_url_from_task(self.task)
239
+ if initial_url:
240
+ self.logger.info(f'🔗 Found URL in task: {initial_url}, adding as initial action...')
241
+ initial_actions = [{'go_to_url': {'url': initial_url, 'new_tab': False}}]
242
+
243
+ self.initial_url = initial_url
244
+
245
+ self.initial_actions = self._convert_initial_actions(initial_actions) if initial_actions else None
302
246
  # Verify we can connect to the model
303
247
  self._verify_and_setup_llm()
304
248
 
@@ -308,40 +252,35 @@ class BrowserUseAgent(Agent):
308
252
  self.logger.warning(
309
253
  '⚠️ DeepSeek models do not support use_vision=True yet. Setting use_vision=False for now...')
310
254
  self.settings.use_vision = False
311
- # Note: No longer checking planner_llm for DeepSeek (deprecated)
312
255
 
313
256
  # Handle users trying to use use_vision=True with XAI models
314
257
  if 'grok' in self.llm.model.lower():
315
258
  self.logger.warning('⚠️ XAI models do not support use_vision=True yet. Setting use_vision=False for now...')
316
259
  self.settings.use_vision = False
317
- # Note: No longer checking planner_llm for XAI models (deprecated)
318
260
 
319
261
  self.logger.info(f'🧠 Starting a browser-use version {self.version} with model={self.llm.model}')
320
- self.logger.debug(
262
+ self.logger.info(
321
263
  f'{" +vision" if self.settings.use_vision else ""}'
322
264
  f' extraction_model={self.settings.page_extraction_llm.model if self.settings.page_extraction_llm else "Unknown"}'
323
- # Note: No longer logging planner_model (deprecated)
324
265
  f'{" +file_system" if self.file_system else ""}'
325
266
  )
326
267
 
327
268
  # Initialize available actions for system prompt (only non-filtered actions)
328
269
  # These will be used for the system prompt to maintain caching
329
- self.unfiltered_actions = self.controller.registry.get_prompt_description()
270
+ self.unfiltered_actions = self.tools.registry.get_prompt_description()
330
271
 
331
272
  # Initialize message manager with state
332
273
  # Initial system prompt with all actions - will be updated during each step
333
- system_message = SystemPrompt(
274
+ self._message_manager = MessageManager(
275
+ task=task,
276
+ system_message=SystemPrompt(
334
277
  action_description=self.unfiltered_actions,
335
278
  max_actions_per_step=self.settings.max_actions_per_step,
336
279
  override_system_message=override_system_message,
337
280
  extend_system_message=extend_system_message,
338
281
  use_thinking=self.settings.use_thinking,
339
282
  flash_mode=self.settings.flash_mode,
340
- ).get_system_message()
341
- self.logger.debug(system_message)
342
- self._message_manager = MessageManager(
343
- task=task,
344
- system_message=system_message,
283
+ ).get_system_message(),
345
284
  file_system=self.file_system,
346
285
  state=self.state.message_manager_state,
347
286
  use_thinking=self.settings.use_thinking,
@@ -354,13 +293,6 @@ class BrowserUseAgent(Agent):
354
293
  include_recent_events=self.include_recent_events,
355
294
  )
356
295
 
357
- browser_profile = browser_profile or DEFAULT_BROWSER_PROFILE
358
-
359
- self.browser_session = browser_session or BrowserSession(
360
- browser_profile=browser_profile,
361
- id=uuid7str()[:-4] + self.id[-4:], # re-use the same 4-char suffix so they show up together in logs
362
- )
363
-
364
296
  if self.sensitive_data:
365
297
  # Check if sensitive_data has domain-specific credentials
366
298
  has_domain_specific_credentials = any(isinstance(v, dict) for v in self.sensitive_data.values())
@@ -430,9 +362,6 @@ class BrowserUseAgent(Agent):
430
362
  self.register_done_callback = register_done_callback
431
363
  self.register_external_agent_status_raise_error_callback = register_external_agent_status_raise_error_callback
432
364
 
433
- # Context
434
- self.context: Context | None = context
435
-
436
365
  # Telemetry
437
366
  self.telemetry = ProductTelemetry()
438
367
 
@@ -586,39 +515,6 @@ class BrowserUseAgent(Agent):
586
515
 
587
516
  self.logger.debug('🔧 Browser session started with watchdogs attached')
588
517
 
589
- # Check if task contains a URL and add it as an initial action (only if preload is enabled)
590
- if self.preload:
591
- initial_url = self._extract_url_from_task(self.task)
592
- if initial_url:
593
- self.logger.info(f'🔗 Found URL in task: {initial_url}, adding as initial action...')
594
-
595
- # Create a go_to_url action for the initial URL
596
- go_to_url_action = {
597
- 'go_to_url': {
598
- 'url': initial_url,
599
- 'new_tab': False, # Navigate in current tab
600
- }
601
- }
602
-
603
- # Add to initial_actions or create new list if none exist
604
- if self.initial_actions:
605
- # Convert back to dict format, prepend URL navigation, then convert back
606
- initial_actions_dicts = []
607
- for action in self.initial_actions:
608
- action_data = action.model_dump(exclude_unset=True)
609
- initial_actions_dicts.append(action_data)
610
-
611
- # Prepend the go_to_url action
612
- initial_actions_dicts = [go_to_url_action] + initial_actions_dicts
613
-
614
- # Convert back to ActionModel instances
615
- self.initial_actions = self._convert_initial_actions(initial_actions_dicts)
616
- else:
617
- # Create new initial_actions with just the go_to_url
618
- self.initial_actions = self._convert_initial_actions([go_to_url_action])
619
-
620
- self.logger.debug(f'✅ Added navigation to {initial_url} as initial action')
621
-
622
518
  # Execute initial actions if provided
623
519
  if self.initial_actions:
624
520
  self.logger.debug(f'⚡ Executing {len(self.initial_actions)} initial actions...')
@@ -964,14 +860,13 @@ class BrowserUseAgent(Agent):
964
860
  self.logger.info(f' 🦾 {blue}[PARALLEL ACTION {action_index + 1}/{total_actions}]{reset} {action_params}')
965
861
 
966
862
  # Execute the action
967
- result = await self.controller.act(
863
+ result = await self.tools.act(
968
864
  action=action,
969
865
  browser_session=self.browser_session,
970
866
  file_system=self.file_system,
971
867
  page_extraction_llm=self.settings.page_extraction_llm,
972
868
  sensitive_data=self.sensitive_data,
973
869
  available_file_paths=self.available_file_paths,
974
- context=self.context,
975
870
  )
976
871
 
977
872
  time_end = time.time()
@@ -1086,14 +981,13 @@ class BrowserUseAgent(Agent):
1086
981
 
1087
982
  self.logger.info(f' 🦾 {blue}[ACTION {action_index + 1}/{total_actions}]{reset} {action_params}')
1088
983
 
1089
- result = await self.controller.act(
984
+ result = await self.tools.act(
1090
985
  action=action,
1091
986
  browser_session=self.browser_session,
1092
987
  file_system=self.file_system,
1093
988
  page_extraction_llm=self.settings.page_extraction_llm,
1094
989
  sensitive_data=self.sensitive_data,
1095
990
  available_file_paths=self.available_file_paths,
1096
- context=self.context,
1097
991
  )
1098
992
 
1099
993
  time_end = time.time()