vibesurf 0.1.9a5__tar.gz → 0.1.10__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.

Potentially problematic release.


This version of vibesurf might be problematic. Click here for more details.

Files changed (109) hide show
  1. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/.github/workflows/publish.yml +9 -4
  2. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/PKG-INFO +18 -2
  3. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/README.md +17 -1
  4. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/_version.py +3 -3
  5. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/agents/vibe_surf_agent.py +25 -15
  6. vibesurf-0.1.10/vibe_surf/backend/api/browser.py +66 -0
  7. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/backend/api/task.py +2 -1
  8. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/backend/main.py +76 -1
  9. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/backend/shared_state.py +2 -0
  10. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/browser/agent_browser_session.py +312 -62
  11. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/browser/browser_manager.py +57 -92
  12. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/browser/watchdogs/dom_watchdog.py +43 -43
  13. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/chrome_extension/background.js +84 -0
  14. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/chrome_extension/manifest.json +3 -1
  15. vibesurf-0.1.10/vibe_surf/chrome_extension/scripts/file-manager.js +526 -0
  16. vibesurf-0.1.10/vibe_surf/chrome_extension/scripts/history-manager.js +658 -0
  17. vibesurf-0.1.10/vibe_surf/chrome_extension/scripts/modal-manager.js +487 -0
  18. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/chrome_extension/scripts/session-manager.js +31 -8
  19. vibesurf-0.1.10/vibe_surf/chrome_extension/scripts/settings-manager.js +1214 -0
  20. vibesurf-0.1.10/vibe_surf/chrome_extension/scripts/ui-manager.js +1414 -0
  21. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/chrome_extension/sidepanel.html +27 -4
  22. vibesurf-0.1.10/vibe_surf/chrome_extension/styles/activity.css +574 -0
  23. vibesurf-0.1.10/vibe_surf/chrome_extension/styles/base.css +76 -0
  24. vibesurf-0.1.10/vibe_surf/chrome_extension/styles/history-modal.css +791 -0
  25. vibesurf-0.1.10/vibe_surf/chrome_extension/styles/input.css +429 -0
  26. vibesurf-0.1.10/vibe_surf/chrome_extension/styles/layout.css +186 -0
  27. vibesurf-0.1.10/vibe_surf/chrome_extension/styles/responsive.css +454 -0
  28. vibesurf-0.1.10/vibe_surf/chrome_extension/styles/settings-environment.css +165 -0
  29. vibesurf-0.1.10/vibe_surf/chrome_extension/styles/settings-forms.css +389 -0
  30. vibesurf-0.1.10/vibe_surf/chrome_extension/styles/settings-modal.css +141 -0
  31. vibesurf-0.1.10/vibe_surf/chrome_extension/styles/settings-profiles.css +244 -0
  32. vibesurf-0.1.10/vibe_surf/chrome_extension/styles/settings-responsive.css +144 -0
  33. vibesurf-0.1.10/vibe_surf/chrome_extension/styles/settings-utilities.css +25 -0
  34. vibesurf-0.1.10/vibe_surf/chrome_extension/styles/variables.css +54 -0
  35. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/cli.py +1 -0
  36. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/controller/vibesurf_tools.py +0 -2
  37. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibesurf.egg-info/PKG-INFO +18 -2
  38. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibesurf.egg-info/SOURCES.txt +38 -6
  39. vibesurf-0.1.9a5/vibe_surf/chrome_extension/scripts/ui-manager.js +0 -3830
  40. vibesurf-0.1.9a5/vibe_surf/chrome_extension/styles/main.css +0 -2338
  41. vibesurf-0.1.9a5/vibe_surf/chrome_extension/styles/settings.css +0 -1100
  42. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/.env.example +0 -0
  43. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/.gitignore +0 -0
  44. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/.python-version +0 -0
  45. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/LICENSE +0 -0
  46. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/MANIFEST.in +0 -0
  47. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/docs/EXECUTABLE_BUILD.md +0 -0
  48. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/docs/PYPI_SETUP.md +0 -0
  49. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/pyproject.toml +0 -0
  50. {vibesurf-0.1.9a5 → vibesurf-0.1.10/scripts}/build-local.bat +0 -0
  51. {vibesurf-0.1.9a5 → vibesurf-0.1.10/scripts}/build-local.sh +0 -0
  52. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/setup.cfg +0 -0
  53. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/tests/test_agents.py +0 -0
  54. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/tests/test_backend_api.py +0 -0
  55. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/tests/test_browser.py +0 -0
  56. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/tests/test_controller.py +0 -0
  57. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/__init__.py +0 -0
  58. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/agents/__init__.py +0 -0
  59. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/agents/browser_use_agent.py +0 -0
  60. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/agents/prompts/__init__.py +0 -0
  61. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/agents/prompts/vibe_surf_prompt.py +0 -0
  62. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/agents/report_writer_agent.py +0 -0
  63. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/backend/__init__.py +0 -0
  64. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/backend/api/__init__.py +0 -0
  65. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/backend/api/activity.py +0 -0
  66. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/backend/api/config.py +0 -0
  67. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/backend/api/files.py +0 -0
  68. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/backend/api/models.py +0 -0
  69. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/backend/database/__init__.py +0 -0
  70. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/backend/database/manager.py +0 -0
  71. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/backend/database/models.py +0 -0
  72. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/backend/database/queries.py +0 -0
  73. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/backend/database/schemas.py +0 -0
  74. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/backend/llm_config.py +0 -0
  75. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/backend/migrations/__init__.py +0 -0
  76. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/backend/migrations/init_db.py +0 -0
  77. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/backend/migrations/seed_data.py +0 -0
  78. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/backend/utils/__init__.py +0 -0
  79. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/backend/utils/encryption.py +0 -0
  80. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/backend/utils/llm_factory.py +0 -0
  81. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/browser/__init__.py +0 -0
  82. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/browser/agen_browser_profile.py +0 -0
  83. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/browser/utils.py +0 -0
  84. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/browser/watchdogs/__init__.py +0 -0
  85. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/browser/watchdogs/action_watchdog.py +0 -0
  86. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/chrome_extension/config.js +0 -0
  87. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/chrome_extension/content.js +0 -0
  88. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/chrome_extension/dev-reload.js +0 -0
  89. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/chrome_extension/icons/convert-svg.js +0 -0
  90. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/chrome_extension/icons/logo-preview.html +0 -0
  91. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/chrome_extension/icons/logo.icns +0 -0
  92. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/chrome_extension/icons/logo.png +0 -0
  93. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/chrome_extension/popup.html +0 -0
  94. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/chrome_extension/scripts/api-client.js +0 -0
  95. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/chrome_extension/scripts/main.js +0 -0
  96. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/chrome_extension/scripts/markdown-it.min.js +0 -0
  97. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/chrome_extension/styles/animations.css +0 -0
  98. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/chrome_extension/styles/components.css +0 -0
  99. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/controller/__init__.py +0 -0
  100. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/controller/file_system.py +0 -0
  101. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/controller/mcp_client.py +0 -0
  102. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/controller/views.py +0 -0
  103. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/llm/__init__.py +0 -0
  104. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibe_surf/llm/openai_compatible.py +0 -0
  105. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibesurf.egg-info/dependency_links.txt +0 -0
  106. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibesurf.egg-info/entry_points.txt +0 -0
  107. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibesurf.egg-info/requires.txt +0 -0
  108. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibesurf.egg-info/top_level.txt +0 -0
  109. {vibesurf-0.1.9a5 → vibesurf-0.1.10}/vibesurf.spec +0 -0
@@ -233,11 +233,16 @@ jobs:
233
233
 
234
234
  # Show final result
235
235
  echo "=== Final executable/archive ==="
236
- if [[ "$RUNNER_OS" == "macOS" ]] && [ -d "dist/VibeSurf.app" ]; then
237
- # For macOS with .app bundle, check the DMG file
238
- ls -lh dist/${{ matrix.asset_name }}.dmg
236
+ if [[ "$RUNNER_OS" == "macOS" ]]; then
237
+ # For macOS, check the DMG file (after .app bundle cleanup)
238
+ if [ -f "dist/${{ matrix.asset_name }}.dmg" ]; then
239
+ ls -lh dist/${{ matrix.asset_name }}.dmg
240
+ else
241
+ # Fallback: check for executable if DMG creation failed
242
+ ls -lh dist/${{ matrix.asset_name }}
243
+ fi
239
244
  else
240
- # For other platforms or fallback macOS executable
245
+ # For other platforms, check the executable
241
246
  ls -lh dist/${{ matrix.asset_name }}
242
247
  fi
243
248
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vibesurf
3
- Version: 0.1.9a5
3
+ Version: 0.1.10
4
4
  Summary: VibeSurf: A powerful browser assistant for vibe surfing
5
5
  Author: Shao Warm
6
6
  License: Apache-2.0
@@ -81,9 +81,25 @@ uv pip install vibesurf -U
81
81
 
82
82
  ### Step 3: Launch
83
83
  ```bash
84
- vibesurf
84
+ uv run vibesurf
85
85
  ```
86
86
 
87
+ ## 🗺️ Roadmap
88
+
89
+ ### 🤖 Agent Enhancements
90
+
91
+ - **VibeSurf Agent Refactoring**: Remove LangGraph framework dependency to make the agent more flexible and powerful
92
+ - **Advanced Coding Agent**: Design a powerful coding agent capable of handling and analyzing complex data, generating charts and visualizations. Combined with VibeSurf agent, this will create a "local Manus" experience
93
+ - **Enhanced Report Writer Agent**: Optimize the report writer to generate more visually appealing reports with rich graphics and illustrations
94
+ - **Global Memory System**: Implement global memory capabilities to make VibeSurf understand and adapt to user preferences better
95
+
96
+ ### 🧩 Extension Features
97
+
98
+ - **Enhanced Tab Management**: Add @specific tab handling with `/research` and `/deep_research` specialized task commands
99
+ - **Smart Text Processing**: Implement word/paragraph translation, summarization, and explanation features for selected content
100
+ - **Local Credential Management**: Add secure credential configuration system to keep your privacy data stored locally
101
+
102
+
87
103
  ## 🎬 Demo
88
104
 
89
105
  ### How to use?
@@ -39,9 +39,25 @@ uv pip install vibesurf -U
39
39
 
40
40
  ### Step 3: Launch
41
41
  ```bash
42
- vibesurf
42
+ uv run vibesurf
43
43
  ```
44
44
 
45
+ ## 🗺️ Roadmap
46
+
47
+ ### 🤖 Agent Enhancements
48
+
49
+ - **VibeSurf Agent Refactoring**: Remove LangGraph framework dependency to make the agent more flexible and powerful
50
+ - **Advanced Coding Agent**: Design a powerful coding agent capable of handling and analyzing complex data, generating charts and visualizations. Combined with VibeSurf agent, this will create a "local Manus" experience
51
+ - **Enhanced Report Writer Agent**: Optimize the report writer to generate more visually appealing reports with rich graphics and illustrations
52
+ - **Global Memory System**: Implement global memory capabilities to make VibeSurf understand and adapt to user preferences better
53
+
54
+ ### 🧩 Extension Features
55
+
56
+ - **Enhanced Tab Management**: Add @specific tab handling with `/research` and `/deep_research` specialized task commands
57
+ - **Smart Text Processing**: Implement word/paragraph translation, summarization, and explanation features for selected content
58
+ - **Local Credential Management**: Add secure credential configuration system to keep your privacy data stored locally
59
+
60
+
45
61
  ## 🎬 Demo
46
62
 
47
63
  ### How to use?
@@ -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.9a5'
32
- __version_tuple__ = version_tuple = (0, 1, 9, 'a5')
31
+ __version__ = version = '0.1.10'
32
+ __version_tuple__ = version_tuple = (0, 1, 10)
33
33
 
34
- __commit_id__ = commit_id = 'gecc8ca6f3'
34
+ __commit_id__ = commit_id = 'g3e1f64f34'
@@ -473,7 +473,12 @@ async def _supervisor_agent_node_impl(state: VibeSurfState) -> VibeSurfState:
473
473
  browser_tabs_md = format_browser_tabs(browser_tabs)
474
474
  if browser_tabs_md:
475
475
  supervisor_message_history.append(UserMessage(
476
- content=f"Available Browser Tabs:\n{browser_tabs_md}"))
476
+ content=f"Available Browser Tabs:\n{browser_tabs_md}\n"))
477
+ active_browser_tab = await state.browser_manager.get_activate_tab()
478
+ if active_browser_tab:
479
+ active_tab_md = f"Page Title: {active_browser_tab.title}, Page Url: {active_browser_tab.url}, Page ID: {active_browser_tab.target_id}"
480
+ supervisor_message_history.append(UserMessage(
481
+ content=f"Current Active Browser Tab:\n{active_tab_md}\n"))
477
482
 
478
483
  # Reset prev_browser_results
479
484
  state.prev_browser_results = []
@@ -536,23 +541,28 @@ async def _supervisor_agent_node_impl(state: VibeSurfState) -> VibeSurfState:
536
541
  if tasks_to_execute:
537
542
  tasks_to_execute_new = []
538
543
  todo_indices = [] # Track which todo items are being executed
539
-
540
544
  for task_item in tasks_to_execute:
541
545
  if isinstance(task_item, list):
542
546
  # Format: [page_index, todo_index]
543
547
  page_index, todo_index = task_item
544
- if todo_index < len(state.todo_list):
545
- task_description = state.todo_list[todo_index].task
546
- tasks_to_execute_new.append([browser_tabs[page_index].target_id, task_description])
547
- todo_indices.append(todo_index)
548
+ if isinstance(todo_index, int):
549
+ if todo_index < len(state.todo_list):
550
+ task_description = state.todo_list[todo_index].task
551
+ tasks_to_execute_new.append([browser_tabs[page_index].target_id, task_description])
552
+ todo_indices.append(todo_index)
553
+ elif isinstance(todo_index, str):
554
+ tasks_to_execute_new.append([browser_tabs[page_index].target_id, todo_index])
548
555
  else:
549
556
  # Format: todo_index
550
557
  todo_index = task_item
551
- if todo_index < len(state.todo_list):
552
- task_description = state.todo_list[todo_index].task
553
- tasks_to_execute_new.append(task_description)
554
- todo_indices.append(todo_index)
555
-
558
+ if isinstance(todo_index, int):
559
+ if todo_index < len(state.todo_list):
560
+ task_description = state.todo_list[todo_index].task
561
+ tasks_to_execute_new.append(task_description)
562
+ todo_indices.append(todo_index)
563
+ elif isinstance(todo_index, str):
564
+ tasks_to_execute_new.append(todo_index)
565
+ logger.info(f"tasks_to_execute: {tasks_to_execute}")
556
566
  state.execution_mode = ExecutionMode(
557
567
  mode=task_type,
558
568
  reason=reasoning
@@ -795,7 +805,7 @@ async def execute_parallel_browser_tasks(state: VibeSurfState) -> List[BrowserTa
795
805
  browser_session=agent_browser_sessions[i],
796
806
  controller=state.vibesurf_controller,
797
807
  task_id=f"{state.task_id}-{i + 1}",
798
- file_system_path=state.task_dir,
808
+ file_system_path=os.path.join(state.task_dir, f"{state.task_id}-{i + 1}"),
799
809
  register_new_step_callback=step_callback,
800
810
  extend_system_message="Please make sure the language of your output in JSON value should remain the same as the user's request or task.",
801
811
  )
@@ -867,17 +877,17 @@ async def execute_single_browser_tasks(state: VibeSurfState) -> List[BrowserTask
867
877
  for i, task in enumerate(state.pending_tasks):
868
878
  if isinstance(task, list):
869
879
  target_id, task_description = task
880
+ await state.browser_manager.main_browser_session.get_or_create_cdp_session(target_id, focus=True)
870
881
  else:
871
882
  task_description = task
883
+ await state.browser_manager.get_activate_tab()
872
884
  logger.info(f"🔄 Executing task ({i + 1}/{len(state.pending_tasks)}): {task_description}")
873
885
 
874
886
  agent_id = f"agent-single-{state.task_id[-4:]}-{i}"
875
887
 
876
888
  # Log agent activity
877
889
  log_agent_activity(state, f"browser_use_agent-{state.task_id[-4:]}", "working", f"{task_description}")
878
-
879
890
  try:
880
- await state.browser_manager._get_active_target()
881
891
  if state.upload_files:
882
892
  upload_files_md = format_upload_files_list(state.upload_files)
883
893
  bu_task = task_description + f"\nAvailable user uploaded files:\n{upload_files_md}\n"
@@ -893,7 +903,7 @@ async def execute_single_browser_tasks(state: VibeSurfState) -> List[BrowserTask
893
903
  browser_session=state.browser_manager.main_browser_session,
894
904
  controller=state.vibesurf_controller,
895
905
  task_id=f"{state.task_id}-{i}",
896
- file_system_path=state.task_dir,
906
+ file_system_path=os.path.join(state.task_dir, f"{state.task_id}-{i}"),
897
907
  register_new_step_callback=step_callback,
898
908
  extend_system_message="Please make sure the language of your output in JSON values should remain the same as the user's request or task."
899
909
  )
@@ -0,0 +1,66 @@
1
+ """
2
+ Browser Tabs Router
3
+
4
+ Handles retrieval of browser tab information including active tab and all tabs.
5
+ """
6
+
7
+ from fastapi import APIRouter, HTTPException
8
+ from typing import Dict, Any, Optional
9
+ import logging
10
+
11
+ # Import global variables from shared_state
12
+ from ..shared_state import browser_manager
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+ router = APIRouter(prefix="/browser", tags=["browser"])
17
+
18
+
19
+ @router.get("/active-tab")
20
+ async def get_active_tab() -> Dict[str, Dict[str, str]]:
21
+ """Get the current active tab information"""
22
+ if not browser_manager:
23
+ raise HTTPException(status_code=503, detail="Browser manager not initialized")
24
+
25
+ try:
26
+ # Get active tab info using browser manager
27
+ active_tab_info = await browser_manager.get_activate_tab()
28
+
29
+ if not active_tab_info:
30
+ return {}
31
+
32
+ # Return dict format: {tab_id: {url: , title: }}
33
+ return {
34
+ active_tab_info.target_id: {
35
+ "url": active_tab_info.url,
36
+ "title": active_tab_info.title
37
+ }
38
+ }
39
+
40
+ except Exception as e:
41
+ logger.error(f"Failed to get active tab: {e}")
42
+ raise HTTPException(status_code=500, detail=f"Failed to get active tab: {str(e)}")
43
+
44
+
45
+ @router.get("/all-tabs")
46
+ async def get_all_tabs() -> Dict[str, Dict[str, str]]:
47
+ """Get all browser tabs information"""
48
+ if not browser_manager:
49
+ raise HTTPException(status_code=503, detail="Browser manager not initialized")
50
+
51
+ try:
52
+ all_tab_infos = await browser_manager.get_all_tabs()
53
+
54
+ # Filter only page targets and build result dict
55
+ result = {}
56
+ for tab_info in all_tab_infos:
57
+ result[tab_info.target_id] = {
58
+ "url": tab_info.url,
59
+ "title": tab_info.title
60
+ }
61
+
62
+ return result
63
+
64
+ except Exception as e:
65
+ logger.error(f"Failed to get all tabs: {e}")
66
+ raise HTTPException(status_code=500, detail=f"Failed to get all tabs: {str(e)}")
@@ -21,7 +21,8 @@ from ..shared_state import (
21
21
  execute_task_background,
22
22
  is_task_running,
23
23
  get_active_task_info,
24
- clear_active_task
24
+ clear_active_task,
25
+ browser_manager
25
26
  )
26
27
 
27
28
  logger = logging.getLogger(__name__)
@@ -11,6 +11,7 @@ from fastapi.middleware.cors import CORSMiddleware
11
11
  import logging
12
12
  import argparse
13
13
  import os
14
+ import asyncio
14
15
  from datetime import datetime
15
16
 
16
17
  # Import routers
@@ -18,6 +19,7 @@ from .api.task import router as agents_router
18
19
  from .api.files import router as files_router
19
20
  from .api.activity import router as activity_router
20
21
  from .api.config import router as config_router
22
+ from .api.browser import router as browser_router
21
23
 
22
24
  # Import shared state
23
25
  from . import shared_state
@@ -46,18 +48,86 @@ app.include_router(agents_router, prefix="/api", tags=["tasks"])
46
48
  app.include_router(files_router, prefix="/api", tags=["files"])
47
49
  app.include_router(activity_router, prefix="/api", tags=["activity"])
48
50
  app.include_router(config_router, prefix="/api", tags=["config"])
51
+ app.include_router(browser_router, prefix="/api", tags=["browser"])
52
+
53
+ # Global variable to control browser monitoring task
54
+ browser_monitor_task = None
55
+
56
+ async def monitor_browser_connection():
57
+ """Background task to monitor browser connection"""
58
+ while True:
59
+ try:
60
+ await asyncio.sleep(2) # Check every 1 second
61
+
62
+ if shared_state.browser_manager:
63
+ is_connected = await shared_state.browser_manager.check_browser_connected()
64
+ if not is_connected:
65
+ logger.error("No Available Browser, Exiting...")
66
+
67
+ # Schedule a graceful shutdown using os.kill in a separate thread
68
+ import threading
69
+ import signal
70
+ import os
71
+
72
+ def trigger_shutdown():
73
+ try:
74
+ # Give a brief moment for any cleanup
75
+ import time
76
+ time.sleep(0.5)
77
+ # Send SIGTERM to current process for graceful shutdown
78
+ os.kill(os.getpid(), signal.SIGTERM)
79
+ except Exception as e:
80
+ logger.error(f"Error during shutdown trigger: {e}")
81
+ # Fallback to SIGKILL if SIGTERM doesn't work
82
+ try:
83
+ os.kill(os.getpid(), signal.SIGKILL)
84
+ except:
85
+ pass
86
+
87
+ # Start shutdown in a separate thread to avoid blocking the async loop
88
+ shutdown_thread = threading.Thread(target=trigger_shutdown)
89
+ shutdown_thread.daemon = True
90
+ shutdown_thread.start()
91
+
92
+ # Exit the monitoring loop
93
+ break
94
+
95
+ except asyncio.CancelledError:
96
+ logger.info("Browser monitor task cancelled")
97
+ break
98
+ except Exception as e:
99
+ logger.warning(f"Browser monitor error: {e}")
100
+ # Continue monitoring even if there's an error
49
101
 
50
102
  @app.on_event("startup")
51
103
  async def startup_event():
52
104
  """Initialize database and VibeSurf components on startup"""
105
+ global browser_monitor_task
106
+
53
107
  # Initialize VibeSurf components and update shared state
54
108
  await shared_state.initialize_vibesurf_components()
55
109
 
110
+ # Start browser monitoring task
111
+ browser_monitor_task = asyncio.create_task(monitor_browser_connection())
112
+ logger.info("🔍 Started browser connection monitor")
113
+
56
114
  logger.info("🚀 VibeSurf Backend API started with single-task execution model")
57
115
 
58
116
  @app.on_event("shutdown")
59
117
  async def shutdown_event():
60
118
  """Cleanup on shutdown"""
119
+ global browser_monitor_task
120
+
121
+ logger.info("🛑 Starting graceful shutdown...")
122
+
123
+ # Cancel browser monitor task
124
+ if browser_monitor_task and not browser_monitor_task.done():
125
+ browser_monitor_task.cancel()
126
+ try:
127
+ await asyncio.wait_for(browser_monitor_task, timeout=2.0)
128
+ except (asyncio.CancelledError, asyncio.TimeoutError):
129
+ pass
130
+ logger.info("✅ Browser monitor task stopped")
61
131
 
62
132
  # Cleanup VibeSurf components
63
133
  if shared_state.browser_manager:
@@ -70,7 +140,12 @@ async def shutdown_event():
70
140
 
71
141
  # Close database
72
142
  if shared_state.db_manager:
73
- await shared_state.db_manager.close()
143
+ try:
144
+ await shared_state.db_manager.close()
145
+ logger.info("✅ Database manager closed")
146
+ except Exception as e:
147
+ logger.error(f"❌ Error closing database manager: {e}")
148
+
74
149
  logger.info("🛑 VibeSurf Backend API stopped")
75
150
 
76
151
  # Health check endpoint
@@ -422,6 +422,8 @@ async def initialize_vibesurf_components():
422
422
  user_data_dir=browser_user_data,
423
423
  headless=False,
424
424
  keep_alive=True,
425
+ auto_download_pdfs=False,
426
+ highlight_elements=True,
425
427
  custom_extensions=[envs["VIBESURF_EXTENSION"]],
426
428
  window_size={"width": primary_monitor.width, "height": primary_monitor.height}
427
429
  )