vibesurf 0.1.22__tar.gz → 0.1.24__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 (125) hide show
  1. {vibesurf-0.1.22 → vibesurf-0.1.24}/PKG-INFO +2 -1
  2. {vibesurf-0.1.22 → vibesurf-0.1.24}/pyproject.toml +1 -0
  3. {vibesurf-0.1.22 → vibesurf-0.1.24}/tests/test_agents.py +51 -44
  4. {vibesurf-0.1.22 → vibesurf-0.1.24}/tests/test_browser.py +25 -2
  5. {vibesurf-0.1.22 → vibesurf-0.1.24}/tests/test_tools.py +12 -1
  6. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/_version.py +3 -3
  7. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/agents/prompts/vibe_surf_prompt.py +10 -0
  8. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/agents/vibe_surf_agent.py +13 -2
  9. vibesurf-0.1.24/vibe_surf/backend/api/agent.py +38 -0
  10. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/backend/api/config.py +3 -1
  11. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/backend/api/task.py +1 -1
  12. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/backend/main.py +2 -0
  13. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/backend/utils/llm_factory.py +2 -1
  14. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/browser/agent_browser_session.py +5 -5
  15. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/scripts/api-client.js +5 -0
  16. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/scripts/main.js +1 -1
  17. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/scripts/ui-manager.js +397 -20
  18. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/sidepanel.html +13 -1
  19. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/styles/input.css +115 -0
  20. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/llm/openai_compatible.py +35 -10
  21. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/tools/browser_use_tools.py +0 -90
  22. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/tools/file_system.py +2 -2
  23. vibesurf-0.1.24/vibe_surf/tools/finance_tools.py +586 -0
  24. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/tools/report_writer_tools.py +2 -1
  25. vibesurf-0.1.24/vibe_surf/tools/vibesurf_registry.py +52 -0
  26. vibesurf-0.1.24/vibe_surf/tools/vibesurf_tools.py +1697 -0
  27. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/tools/views.py +93 -0
  28. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibesurf.egg-info/PKG-INFO +2 -1
  29. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibesurf.egg-info/SOURCES.txt +6 -0
  30. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibesurf.egg-info/requires.txt +1 -0
  31. vibesurf-0.1.22/vibe_surf/tools/vibesurf_tools.py +0 -659
  32. {vibesurf-0.1.22 → vibesurf-0.1.24}/.env.example +0 -0
  33. {vibesurf-0.1.22 → vibesurf-0.1.24}/.github/workflows/publish.yml +0 -0
  34. {vibesurf-0.1.22 → vibesurf-0.1.24}/.gitignore +0 -0
  35. {vibesurf-0.1.22 → vibesurf-0.1.24}/.python-version +0 -0
  36. {vibesurf-0.1.22 → vibesurf-0.1.24}/LICENSE +0 -0
  37. {vibesurf-0.1.22 → vibesurf-0.1.24}/MANIFEST.in +0 -0
  38. {vibesurf-0.1.22 → vibesurf-0.1.24}/README.md +0 -0
  39. {vibesurf-0.1.22 → vibesurf-0.1.24}/docs/EXECUTABLE_BUILD.md +0 -0
  40. {vibesurf-0.1.22 → vibesurf-0.1.24}/docs/PYPI_SETUP.md +0 -0
  41. {vibesurf-0.1.22 → vibesurf-0.1.24}/scripts/build-local.bat +0 -0
  42. {vibesurf-0.1.22 → vibesurf-0.1.24}/scripts/build-local.sh +0 -0
  43. {vibesurf-0.1.22 → vibesurf-0.1.24}/setup.cfg +0 -0
  44. {vibesurf-0.1.22 → vibesurf-0.1.24}/tests/test_backend_api.py +0 -0
  45. {vibesurf-0.1.22 → vibesurf-0.1.24}/tests/test_voice_api.py +0 -0
  46. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/__init__.py +0 -0
  47. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/agents/__init__.py +0 -0
  48. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/agents/browser_use_agent.py +0 -0
  49. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/agents/prompts/__init__.py +0 -0
  50. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/agents/prompts/report_writer_prompt.py +0 -0
  51. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/agents/report_writer_agent.py +0 -0
  52. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/agents/views.py +0 -0
  53. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/backend/__init__.py +0 -0
  54. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/backend/api/__init__.py +0 -0
  55. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/backend/api/activity.py +0 -0
  56. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/backend/api/browser.py +0 -0
  57. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/backend/api/files.py +0 -0
  58. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/backend/api/models.py +0 -0
  59. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/backend/api/voices.py +0 -0
  60. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/backend/database/__init__.py +0 -0
  61. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/backend/database/manager.py +0 -0
  62. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/backend/database/migrations/v001_initial_schema.sql +0 -0
  63. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/backend/database/migrations/v002_add_agent_mode.sql +0 -0
  64. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/backend/database/migrations/v003_fix_task_status_case.sql +0 -0
  65. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/backend/database/migrations/v004_add_voice_profiles.sql +0 -0
  66. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/backend/database/models.py +0 -0
  67. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/backend/database/queries.py +0 -0
  68. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/backend/database/schemas.py +0 -0
  69. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/backend/llm_config.py +0 -0
  70. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/backend/shared_state.py +0 -0
  71. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/backend/utils/__init__.py +0 -0
  72. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/backend/utils/encryption.py +0 -0
  73. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/backend/voice_model_config.py +0 -0
  74. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/browser/__init__.py +0 -0
  75. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/browser/agen_browser_profile.py +0 -0
  76. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/browser/browser_manager.py +0 -0
  77. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/browser/utils.py +0 -0
  78. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/browser/watchdogs/__init__.py +0 -0
  79. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/browser/watchdogs/action_watchdog.py +0 -0
  80. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/browser/watchdogs/dom_watchdog.py +0 -0
  81. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/background.js +0 -0
  82. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/config.js +0 -0
  83. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/content.js +0 -0
  84. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/dev-reload.js +0 -0
  85. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/icons/logo.icns +0 -0
  86. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/icons/logo.png +0 -0
  87. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/manifest.json +0 -0
  88. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/permission-iframe.html +0 -0
  89. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/permission-request.html +0 -0
  90. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/popup.html +0 -0
  91. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/scripts/file-manager.js +0 -0
  92. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/scripts/history-manager.js +0 -0
  93. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/scripts/markdown-it.min.js +0 -0
  94. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/scripts/modal-manager.js +0 -0
  95. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/scripts/permission-iframe-request.js +0 -0
  96. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/scripts/permission-request.js +0 -0
  97. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/scripts/session-manager.js +0 -0
  98. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/scripts/settings-manager.js +0 -0
  99. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/scripts/user-settings-storage.js +0 -0
  100. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/scripts/voice-recorder.js +0 -0
  101. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/styles/activity.css +0 -0
  102. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/styles/animations.css +0 -0
  103. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/styles/base.css +0 -0
  104. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/styles/components.css +0 -0
  105. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/styles/history-modal.css +0 -0
  106. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/styles/layout.css +0 -0
  107. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/styles/responsive.css +0 -0
  108. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/styles/settings-environment.css +0 -0
  109. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/styles/settings-forms.css +0 -0
  110. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/styles/settings-modal.css +0 -0
  111. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/styles/settings-profiles.css +0 -0
  112. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/styles/settings-responsive.css +0 -0
  113. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/styles/settings-utilities.css +0 -0
  114. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/chrome_extension/styles/variables.css +0 -0
  115. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/cli.py +0 -0
  116. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/common.py +0 -0
  117. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/llm/__init__.py +0 -0
  118. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/logger.py +0 -0
  119. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/tools/__init__.py +0 -0
  120. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/tools/mcp_client.py +0 -0
  121. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibe_surf/tools/voice_asr.py +0 -0
  122. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibesurf.egg-info/dependency_links.txt +0 -0
  123. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibesurf.egg-info/entry_points.txt +0 -0
  124. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibesurf.egg-info/top_level.txt +0 -0
  125. {vibesurf-0.1.22 → vibesurf-0.1.24}/vibesurf.spec +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vibesurf
3
- Version: 0.1.22
3
+ Version: 0.1.24
4
4
  Summary: VibeSurf: A powerful browser assistant for vibe surfing
5
5
  Author: Shao Warm
6
6
  License: Apache-2.0
@@ -43,6 +43,7 @@ Requires-Dist: nanoid>=2.0.0
43
43
  Requires-Dist: markdownify>=1.2.0
44
44
  Requires-Dist: pathvalidate>=3.3.1
45
45
  Requires-Dist: dashscope>=1.24.5
46
+ Requires-Dist: yfinance>=0.2.66
46
47
  Dynamic: license-file
47
48
 
48
49
  # VibeSurf: A powerful browser assistant for vibe surfing
@@ -44,6 +44,7 @@ dependencies = [
44
44
  "markdownify>=1.2.0",
45
45
  "pathvalidate>=3.3.1",
46
46
  "dashscope>=1.24.5",
47
+ "yfinance>=0.2.66",
47
48
  ]
48
49
 
49
50
  [project.urls]
@@ -18,9 +18,11 @@ from vibe_surf.browser.agen_browser_profile import AgentBrowserProfile
18
18
  from vibe_surf.tools.browser_use_tools import BrowserUseTools
19
19
  from vibe_surf.tools.vibesurf_tools import VibeSurfTools
20
20
  from vibe_surf.llm.openai_compatible import ChatOpenAICompatible
21
+ from browser_use.llm.deepseek.chat import ChatDeepSeek
21
22
  from vibe_surf.agents.browser_use_agent import BrowserUseAgent
22
23
  from vibe_surf.agents.vibe_surf_agent import VibeSurfAgent
23
24
 
25
+
24
26
  async def run_single_bu_agent():
25
27
  import platform
26
28
  if platform.system() != "Darwin":
@@ -46,9 +48,13 @@ async def run_single_bu_agent():
46
48
  # base_url=os.getenv("ALIBABA_ENDPOINT"),
47
49
  # api_key=os.getenv("ALIBABA_API_KEY"))
48
50
 
49
- llm = ChatOpenAICompatible(model='kimi-k2-turbo-preview',
50
- base_url=os.getenv("MOONSHOT_ENDPOINT"),
51
- api_key=os.getenv("MOONSHOT_API_KEY"))
51
+ # llm = ChatOpenAICompatible(model='kimi-k2-turbo-preview',
52
+ # base_url=os.getenv("MOONSHOT_ENDPOINT"),
53
+ # api_key=os.getenv("MOONSHOT_API_KEY"))
54
+
55
+ llm = ChatOpenAICompatible(model='deepseek-reasoner',
56
+ base_url=os.getenv("DEEPSEEK_ENDPOINT"),
57
+ api_key=os.getenv("DEEPSEEK_API_KEY"))
52
58
 
53
59
  task = "Search Google for 'Elon Mask' and tell me the top 3 results"
54
60
 
@@ -159,20 +165,22 @@ async def test_vibe_surf_agent():
159
165
  await main_browser_session.start()
160
166
  vs_tools = VibeSurfTools()
161
167
  browser_manager = BrowserManager(main_browser_session=main_browser_session)
162
- llm = ChatOpenAICompatible(model='gemini-2.5-flash',
163
- base_url=os.getenv("OPENAI_ENDPOINT"),
164
- api_key=os.getenv("OPENAI_API_KEY"))
168
+ # llm = ChatOpenAICompatible(model='gemini-2.5-flash',
169
+ # base_url=os.getenv("OPENAI_ENDPOINT"),
170
+ # api_key=os.getenv("OPENAI_API_KEY"))
171
+
172
+ llm = ChatOpenAICompatible(model='deepseek-chat',
173
+ base_url=os.getenv("DEEPSEEK_ENDPOINT"),
174
+ api_key=os.getenv("DEEPSEEK_API_KEY"))
165
175
 
166
-
167
176
  # Create VibeSurfAgent
168
177
  agent = VibeSurfAgent(
169
178
  llm=llm,
170
179
  browser_manager=browser_manager,
171
180
  tools=vs_tools,
172
- workspace_dir=os.path.abspath("./tmp/vibesurf_tests"),
173
- calculate_token_cost=True
181
+ workspace_dir=os.path.abspath("./tmp/vibesurf_tests")
174
182
  )
175
-
183
+
176
184
  try:
177
185
  # Test 1: Simple task (should not require browser)
178
186
  print("🧪 Testing simple task...")
@@ -200,16 +208,16 @@ async def test_vibe_surf_agent():
200
208
  # print("🎉 All VibeSurfAgent tests passed!")
201
209
 
202
210
  # Test 4: Browser parallel task
203
- print("🧪 Testing browser parallel tasks...")
204
- browser_task = "Search for Dify, n8n, browser-use and click into their own homepage, take screenshot and save"
205
- result4 = await agent.run(browser_task)
206
- print(f"✅ Browser task result:")
207
- pprint.pprint(result4)
208
- with open("./tmp/vibesurf_tests/parallel_test.md", "w", encoding='utf-8') as fw:
209
- fw.write(result4)
210
- assert result4 is not None and len(result4) > 0
211
+ # print("🧪 Testing browser parallel tasks...")
212
+ # browser_task = "Search for Dify, n8n, browser-use and click into their own homepage, take screenshot and save"
213
+ # result4 = await agent.run(browser_task)
214
+ # print(f"✅ Browser task result:")
215
+ # pprint.pprint(result4)
216
+ # with open("./tmp/vibesurf_tests/parallel_test.md", "w", encoding='utf-8') as fw:
217
+ # fw.write(result4)
218
+ # assert result4 is not None and len(result4) > 0
211
219
  print("🎉 All VibeSurfAgent tests passed!")
212
-
220
+
213
221
  except Exception as e:
214
222
  print(f"❌ VibeSurfAgent test failed: {e}")
215
223
  raise e
@@ -240,7 +248,6 @@ async def test_vibe_surf_agent_control():
240
248
  llm = ChatOpenAICompatible(model='gemini-2.5-pro',
241
249
  base_url=os.getenv("OPENAI_ENDPOINT"),
242
250
  api_key=os.getenv("OPENAI_API_KEY"))
243
-
244
251
 
245
252
  # Create VibeSurfAgent
246
253
  agent = VibeSurfAgent(
@@ -253,69 +260,69 @@ async def test_vibe_surf_agent_control():
253
260
 
254
261
  try:
255
262
  print("🧪 Testing VibeSurfAgent control functionality...")
256
-
263
+
257
264
  # Test 1: Status check when idle
258
265
  print("📊 Testing initial status...")
259
266
  status = agent.get_status()
260
267
  print(f"Initial status: {status.overall_status}")
261
268
  assert status.overall_status == "idle"
262
-
269
+
263
270
  # Test 2: Start a long-running browser task
264
271
  print("🚀 Starting long-running browser task...")
265
272
  browser_task = "Search for Dify, n8n, langflow and gather relative information, and generate a detailed report for comparison"
266
-
273
+
267
274
  # Start task in background
268
275
  async def run_task():
269
276
  return await agent.run(browser_task)
270
-
277
+
271
278
  task_coroutine = asyncio.create_task(run_task())
272
-
279
+
273
280
  # Wait a bit for task to start
274
281
  await asyncio.sleep(10)
275
-
282
+
276
283
  # Test 3: Check status during execution
277
284
  print("📊 Checking status during execution...")
278
285
  status = agent.get_status()
279
286
  print(f"Running status: {status.overall_status}")
280
287
  print(f"Progress: {status.progress}")
281
288
  print(f"Active agents: {len(status.agent_statuses)}")
282
-
289
+
283
290
  # Test 4: Pause execution
284
291
  print("⏸️ Testing pause functionality...")
285
292
  pause_result = await agent.pause("Testing pause functionality")
286
293
  print(f"Pause result: {pause_result.success} - {pause_result.message}")
287
294
  assert pause_result.success
288
-
295
+
289
296
  # Check status after pause
290
297
  await asyncio.sleep(1)
291
298
  status = agent.get_status()
292
299
  print(f"Paused status: {status.overall_status}")
293
300
  assert status.overall_status == "paused"
294
-
301
+
295
302
  # Test 5: Resume execution
296
303
  print("▶️ Testing resume functionality...")
297
304
  resume_result = await agent.resume("Testing resume functionality")
298
305
  print(f"Resume result: {resume_result.success} - {resume_result.message}")
299
306
  assert resume_result.success
300
-
307
+
301
308
  # Check status after resume
302
309
  await asyncio.sleep(1)
303
310
  status = agent.get_status()
304
311
  print(f"Resumed status: {status.overall_status}")
305
-
312
+
306
313
  # Let it run a bit more
307
314
  await asyncio.sleep(50)
308
-
315
+
309
316
  # Test 6: Stop execution
310
317
  print("🛑 Testing stop functionality...")
311
318
  stop_result = await agent.stop("Testing stop functionality")
312
319
  print(f"Stop result: {stop_result.success} - {stop_result.message}")
313
-
320
+
314
321
  # Check status after stop (should be stopped even if stop had issues)
315
322
  await asyncio.sleep(1)
316
323
  status = agent.get_status()
317
324
  print(f"Stopped status: {status.overall_status}")
318
-
325
+
319
326
  # Wait for task to complete (it should be cancelled)
320
327
  try:
321
328
  result = await asyncio.wait_for(task_coroutine, timeout=3)
@@ -329,38 +336,38 @@ async def test_vibe_surf_agent_control():
329
336
  pass
330
337
  except asyncio.CancelledError:
331
338
  print("✅ Task was cancelled as expected")
332
-
339
+
333
340
  # Verify stop worked (may have timed out but should still be effective)
334
341
  if stop_result.success:
335
342
  assert status.overall_status == "idle"
336
343
  else:
337
344
  print(f"⚠️ Stop operation had issues but continuing: {stop_result.message}")
338
-
345
+
339
346
  # Test 7: Test simple task control (should work quickly)
340
347
  print("🔄 Testing control on simple task...")
341
348
  simple_task = "Find out who is the founder of Browser-Use."
342
-
349
+
343
350
  async def run_simple_task():
344
351
  return await agent.run(simple_task)
345
-
352
+
346
353
  simple_task_coroutine = asyncio.create_task(run_simple_task())
347
-
354
+
348
355
  # Pause quickly
349
356
  await asyncio.sleep(0.5)
350
357
  pause_result = await agent.pause("Testing simple task pause")
351
358
  print(f"Simple task pause: {pause_result.success}")
352
-
359
+
353
360
  # Resume
354
361
  await asyncio.sleep(0.5)
355
362
  resume_result = await agent.resume("Testing simple task resume")
356
363
  print(f"Simple task resume: {resume_result.success}")
357
-
364
+
358
365
  # Let it complete
359
366
  simple_result = await simple_task_coroutine
360
367
  print(f"Simple task completed: {len(simple_result) > 0}")
361
368
  print(simple_result)
362
369
  print("🎉 All VibeSurfAgent control tests passed!")
363
-
370
+
364
371
  except Exception as e:
365
372
  print(f"❌ VibeSurfAgent control test failed: {e}")
366
373
  import traceback
@@ -377,7 +384,7 @@ async def test_vibe_surf_agent_control():
377
384
 
378
385
 
379
386
  if __name__ == "__main__":
380
- asyncio.run(run_single_bu_agent())
387
+ # asyncio.run(run_single_bu_agent())
381
388
  # asyncio.run(run_multi_bu_agents())
382
- # asyncio.run(test_vibe_surf_agent())
389
+ asyncio.run(test_vibe_surf_agent())
383
390
  # asyncio.run(test_vibe_surf_agent_control())
@@ -117,7 +117,6 @@ async def test_browser_state_capture(manager: BrowserManager):
117
117
  # f"🔍 DIAGNOSIS: {agent_name} navigation completed at {task_end - start_time:.3f}s (duration: {task_end - task_start:.3f}s)")
118
118
  # return None
119
119
 
120
-
121
120
  # Navigate to different pages
122
121
  await asyncio.gather(
123
122
  navigate_with_timing(agent1, "https://www.python.org", "agent1"),
@@ -240,6 +239,29 @@ async def test_browser_state_capture(manager: BrowserManager):
240
239
  print(main_tabs)
241
240
 
242
241
 
242
+ async def get_all_css_selector(browser_session: AgentBrowserSession):
243
+ target_id = await browser_session.navigate_to_url("https://github.com/", new_tab=True)
244
+ result = await browser_session.cdp_client.send.Target.attachToTarget({'targetId': target_id, 'flatten': True})
245
+ session_id = result['sessionId']
246
+ doc_result = await browser_session.cdp_client.send.DOM.getDocument(session_id=session_id)
247
+ document_node_id = doc_result['root']['nodeId']
248
+ from browser_use.dom.service import DomService
249
+ dom_service = DomService(browser_session)
250
+ pdb.set_trace()
251
+ # Query selector all
252
+ query_params = {'nodeId': document_node_id}
253
+ result = await browser_session.cdp_client.send.DOM.querySelectorAll(query_params, session_id=session_id)
254
+
255
+ elements = []
256
+
257
+ # Convert node IDs to backend node IDs
258
+ for node_id in result['nodeIds']:
259
+ # Get backend node ID
260
+ describe_params = {'nodeId': node_id}
261
+ node_result = await browser_session.cdp_client.send.DOM.describeNode(describe_params, session_id=session_id)
262
+ pdb.set_trace()
263
+
264
+
243
265
  async def main():
244
266
  """
245
267
  Main function to run all browser session tests.
@@ -273,7 +295,8 @@ async def main():
273
295
  # await test_manual_page_assignment(manager)
274
296
  # await test_agent_cleanup(manager)
275
297
  # await test_agent_tab_isolation(manager)
276
- await test_browser_state_capture(manager)
298
+ # await test_browser_state_capture(manager)
299
+ await get_all_css_selector(main_browser_session)
277
300
 
278
301
  except Exception as e:
279
302
  logging.error(f"An error occurred during tests: {e}", exc_info=True)
@@ -116,8 +116,19 @@ async def test_vibesurf_tools():
116
116
  print(tools.registry.registry.actions.keys())
117
117
 
118
118
 
119
+ async def test_finance_tools():
120
+ from vibe_surf.tools.finance_tools import FinanceDataRetriever
121
+
122
+ retriever = FinanceDataRetriever('TSLA')
123
+
124
+ result = retriever.get_finance_data(["get_news"])
125
+
126
+ pdb.set_trace()
127
+
128
+
119
129
  if __name__ == '__main__':
120
130
  # asyncio.run(test_tools_with_mcp())
121
131
  # asyncio.run(test_filesystem())
122
132
  # asyncio.run(test_bu_tools())
123
- asyncio.run(test_vibesurf_tools())
133
+ # asyncio.run(test_vibesurf_tools())
134
+ asyncio.run(test_finance_tools())
@@ -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.22'
32
- __version_tuple__ = version_tuple = (0, 1, 22)
31
+ __version__ = version = '0.1.24'
32
+ __version_tuple__ = version_tuple = (0, 1, 24)
33
33
 
34
- __commit_id__ = commit_id = 'g95ec3c7e7'
34
+ __commit_id__ = commit_id = 'gebf62a182'
@@ -65,6 +65,15 @@ You will receive contextual information including:
65
65
  - Include file references in task descriptions when relevant
66
66
  - All file operations automatically resolve relative to the workspace directory
67
67
 
68
+ ## Skills Command Processing
69
+ - When users input commands in `/skill_name` format, please use the corresponding skill action:
70
+ - **Tab Targeting[Optional]**: Such as `/crawl @1234` → Execute `skill_crawl` with tab_id "1234"
71
+ - **Parameter Processing**: Sometimes user provide uncompleted or simple prompt, please convert it to correct and optimized params. Such as convert natural language to valid JavaScript for code skill
72
+ - **Special Cases**: `skill_deep_research` only returns guidelines only, then follow guidelines to conduct actual research
73
+ - **Execution Policy**: Skill actions execute only once (no need to retry if errors occur), and all results - whether successful or failed - should be presented to users in structured markdown format.
74
+ - **Follow-up Operations**: When users input skill operations without specifying additional tasks, do not automatically perform subsequent operations. Only perform additional tool operations when users specifically request actions like saving results to files or writing reports.
75
+ - After `/search` completion, NEVER use browser agent to deeply investigate search result (unless explicitly emphasized by the user). The user usually only need the search results. Just return the search results.
76
+
68
77
  ## Language Adaptability
69
78
 
70
79
  **Critical**: Your output language must match the user's request language. If the user communicates in Chinese, respond in Chinese. If in English, respond in English. Maintain consistency throughout the interaction.
@@ -77,6 +86,7 @@ Before executing any action:
77
86
  3. **Plan Resource Usage**: Consider tab management and session optimization
78
87
  4. **Validate Completeness**: Ensure all user requirements are addressed
79
88
 
89
+
80
90
  Execute with precision, leverage concurrent capabilities for efficiency, and deliver professional results that exceed expectations.
81
91
  """
82
92
 
@@ -479,6 +479,16 @@ async def _vibesurf_agent_node_impl(state: VibeSurfState) -> VibeSurfState:
479
479
  llm=vibesurf_agent.llm,
480
480
  file_system=vibesurf_agent.file_system,
481
481
  )
482
+ if action_name in ["skill_search", "skill_crawl", "skill_summary", "skill_finance"]:
483
+ state.current_step = "END"
484
+ # Format final response
485
+ final_response = f"{result.extracted_content}"
486
+ await log_agent_activity(state, agent_name, "result", final_response)
487
+ state.final_response = final_response
488
+ logger.debug(final_response)
489
+ state.is_complete = True
490
+ return state
491
+
482
492
  state.current_step = "vibesurf_agent"
483
493
  if result.extracted_content:
484
494
  vibesurf_agent.message_history.append(
@@ -1479,8 +1489,9 @@ Please continue with your assigned work, incorporating this guidance only if it'
1479
1489
  """
1480
1490
  activity_entry = {
1481
1491
  "agent_name": 'user',
1482
- "agent_status": 'request', # working, result, error
1483
- "agent_msg": f"{new_task}"
1492
+ "agent_status": 'additional_request', # working, result, error
1493
+ "agent_msg": f"{new_task}",
1494
+ "timestamp": datetime.now().isoformat()
1484
1495
  }
1485
1496
  self.activity_logs.append(activity_entry)
1486
1497
 
@@ -0,0 +1,38 @@
1
+ """
2
+ Agent API endpoints
3
+ """
4
+ from typing import List
5
+ from fastapi import APIRouter, HTTPException
6
+
7
+ from vibe_surf.logger import get_logger
8
+
9
+ logger = get_logger(__name__)
10
+
11
+ router = APIRouter(prefix="/agent", tags=["agent"])
12
+
13
+
14
+ @router.get("/get_all_skills", response_model=List[str])
15
+ async def get_all_skills():
16
+ """
17
+ Get all available skill names from the VibeSurf tools registry.
18
+ Returns skill names with the 'skill_' prefix removed.
19
+ """
20
+ try:
21
+ from ..shared_state import vibesurf_tools
22
+ if not vibesurf_tools:
23
+ raise HTTPException(status_code=500, detail="VibeSurf tools not initialized")
24
+
25
+ # Get all action names from the registry
26
+ all_actions = vibesurf_tools.registry.registry.actions.keys()
27
+
28
+ # Filter for actions that start with 'skill_' and remove the prefix
29
+ skill_names = [
30
+ action_name.replace('skill_', '')
31
+ for action_name in all_actions
32
+ if action_name.startswith('skill_')
33
+ ]
34
+ logger.info(skill_names)
35
+ return skill_names
36
+
37
+ except Exception as e:
38
+ raise HTTPException(status_code=500, detail=f"Failed to get skills: {str(e)}")
@@ -234,7 +234,9 @@ async def update_llm_profile(
234
234
 
235
235
  # Return updated profile
236
236
  updated_profile = await LLMProfileQueries.get_profile(db, profile_name)
237
-
237
+ from ..shared_state import current_llm_profile_name
238
+ if current_llm_profile_name != profile_name:
239
+ current_llm_profile_name = None
238
240
  # Use safe extraction to avoid greenlet issues
239
241
  return LLMProfileResponse(**_profile_to_response_dict(updated_profile))
240
242
 
@@ -287,7 +287,7 @@ async def stop_task(control_request: TaskControlRequest):
287
287
  active_task["end_time"] = datetime.now()
288
288
 
289
289
  # Clear active task
290
- # clear_active_task()
290
+ clear_active_task()
291
291
 
292
292
  return {
293
293
  "success": True,
@@ -21,6 +21,7 @@ from .api.activity import router as activity_router
21
21
  from .api.config import router as config_router
22
22
  from .api.browser import router as browser_router
23
23
  from .api.voices import router as voices_router
24
+ from .api.agent import router as agent_router
24
25
 
25
26
  # Import shared state
26
27
  from . import shared_state
@@ -53,6 +54,7 @@ app.include_router(activity_router, prefix="/api", tags=["activity"])
53
54
  app.include_router(config_router, prefix="/api", tags=["config"])
54
55
  app.include_router(browser_router, prefix="/api", tags=["browser"])
55
56
  app.include_router(voices_router, prefix="/api", tags=["voices"])
57
+ app.include_router(agent_router, prefix="/api", tags=["agent"])
56
58
 
57
59
  # Global variable to control browser monitoring task
58
60
  browser_monitor_task = None
@@ -142,8 +142,9 @@ def create_llm_from_profile(llm_profile) -> BaseChatModel:
142
142
  )
143
143
 
144
144
  elif provider == "deepseek":
145
- return ChatDeepSeek(
145
+ return ChatOpenAICompatible(
146
146
  model=model,
147
+ base_url="https://api.deepseek.com",
147
148
  api_key=api_key,
148
149
  **common_params
149
150
  )
@@ -407,11 +407,11 @@ class AgentBrowserSession(BrowserSession):
407
407
  self.logger.info('🚫 VibeSurfBrowserSession: AboutBlankWatchdog disabled - no DVD animation will be shown')
408
408
 
409
409
  # Initialize DownloadsWatchdog
410
- DownloadsWatchdog.model_rebuild()
411
- self._downloads_watchdog = DownloadsWatchdog(event_bus=self.event_bus, browser_session=self)
412
- self._downloads_watchdog.attach_to_session()
413
- if self.browser_profile.auto_download_pdfs:
414
- self.logger.info('📄 PDF auto-download enabled for this session')
410
+ # DownloadsWatchdog.model_rebuild()
411
+ # self._downloads_watchdog = DownloadsWatchdog(event_bus=self.event_bus, browser_session=self)
412
+ # self._downloads_watchdog.attach_to_session()
413
+ # if self.browser_profile.auto_download_pdfs:
414
+ # self.logger.info('📄 PDF auto-download enabled for this session')
415
415
 
416
416
  # Initialize LocalBrowserWatchdog
417
417
  LocalBrowserWatchdog.model_rebuild()
@@ -498,6 +498,11 @@ class VibeSurfAPIClient {
498
498
  return this.get('/browser/all-tabs');
499
499
  }
500
500
 
501
+ // Agent APIs - Get available skills
502
+ async getAllSkills() {
503
+ return this.get('/agent/get_all_skills');
504
+ }
505
+
501
506
  // Utility methods
502
507
  delay(ms) {
503
508
  return new Promise(resolve => setTimeout(resolve, ms));
@@ -340,7 +340,7 @@ class VibeSurfApp {
340
340
  <div class="input-container">
341
341
  <div class="input-main">
342
342
  <div class="textarea-container">
343
- <textarea id="task-input" class="task-input" placeholder="Describe your browsing task..." rows="3"></textarea>
343
+ <textarea id="task-input" class="task-input" placeholder="Ask anything (/ for skills, @ to specify tab)" rows="3"></textarea>
344
344
  <div class="input-actions">
345
345
  <button id="attach-file-btn" class="action-btn attach-btn" title="Attach Files">
346
346
  <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">