vibesurf 0.1.31__py3-none-any.whl → 0.1.33__py3-none-any.whl

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 (35) hide show
  1. vibe_surf/_version.py +2 -2
  2. vibe_surf/agents/browser_use_agent.py +1 -1
  3. vibe_surf/agents/prompts/vibe_surf_prompt.py +6 -0
  4. vibe_surf/agents/report_writer_agent.py +50 -0
  5. vibe_surf/agents/vibe_surf_agent.py +56 -1
  6. vibe_surf/backend/api/composio.py +952 -0
  7. vibe_surf/backend/database/migrations/v005_add_composio_integration.sql +33 -0
  8. vibe_surf/backend/database/migrations/v006_add_credentials_table.sql +26 -0
  9. vibe_surf/backend/database/models.py +53 -1
  10. vibe_surf/backend/database/queries.py +312 -2
  11. vibe_surf/backend/main.py +28 -0
  12. vibe_surf/backend/shared_state.py +123 -9
  13. vibe_surf/chrome_extension/scripts/api-client.js +32 -0
  14. vibe_surf/chrome_extension/scripts/settings-manager.js +954 -1
  15. vibe_surf/chrome_extension/sidepanel.html +190 -0
  16. vibe_surf/chrome_extension/styles/settings-integrations.css +927 -0
  17. vibe_surf/chrome_extension/styles/settings-modal.css +7 -3
  18. vibe_surf/chrome_extension/styles/settings-responsive.css +37 -5
  19. vibe_surf/cli.py +98 -3
  20. vibe_surf/telemetry/__init__.py +60 -0
  21. vibe_surf/telemetry/service.py +112 -0
  22. vibe_surf/telemetry/views.py +156 -0
  23. vibe_surf/tools/browser_use_tools.py +90 -90
  24. vibe_surf/tools/composio_client.py +456 -0
  25. vibe_surf/tools/mcp_client.py +21 -2
  26. vibe_surf/tools/vibesurf_tools.py +290 -87
  27. vibe_surf/tools/views.py +16 -0
  28. vibe_surf/tools/website_api/youtube/client.py +35 -13
  29. vibe_surf/utils.py +13 -0
  30. {vibesurf-0.1.31.dist-info → vibesurf-0.1.33.dist-info}/METADATA +11 -9
  31. {vibesurf-0.1.31.dist-info → vibesurf-0.1.33.dist-info}/RECORD +35 -26
  32. {vibesurf-0.1.31.dist-info → vibesurf-0.1.33.dist-info}/WHEEL +0 -0
  33. {vibesurf-0.1.31.dist-info → vibesurf-0.1.33.dist-info}/entry_points.txt +0 -0
  34. {vibesurf-0.1.31.dist-info → vibesurf-0.1.33.dist-info}/licenses/LICENSE +0 -0
  35. {vibesurf-0.1.31.dist-info → vibesurf-0.1.33.dist-info}/top_level.txt +0 -0
@@ -12,6 +12,8 @@ import os
12
12
  import json
13
13
  import platform
14
14
  from pathlib import Path
15
+ from composio import Composio
16
+ from composio_langchain import LangchainProvider
15
17
 
16
18
  # VibeSurf components
17
19
  from vibe_surf.agents.vibe_surf_agent import VibeSurfAgent
@@ -35,6 +37,7 @@ vibesurf_tools: Optional[VibeSurfTools] = None
35
37
  llm: Optional[BaseChatModel] = None
36
38
  db_manager: Optional['DatabaseManager'] = None
37
39
  current_llm_profile_name: Optional[str] = None
40
+ composio_instance: Optional[Any] = None # Global Composio instance
38
41
 
39
42
  # Environment variables
40
43
  workspace_dir: str = ""
@@ -54,7 +57,7 @@ active_task: Optional[Dict[str, Any]] = None
54
57
  def get_all_components():
55
58
  """Get all components as a dictionary"""
56
59
  global vibesurf_agent, browser_manager, vibesurf_tools, llm, db_manager, current_llm_profile_name
57
- global workspace_dir, browser_execution_path, browser_user_data, active_mcp_server, envs
60
+ global workspace_dir, browser_execution_path, browser_user_data, active_mcp_server, envs, composio_instance
58
61
 
59
62
  return {
60
63
  "vibesurf_agent": vibesurf_agent,
@@ -68,6 +71,7 @@ def get_all_components():
68
71
  "active_mcp_server": active_mcp_server,
69
72
  "active_task": active_task,
70
73
  "current_llm_profile_name": current_llm_profile_name,
74
+ "composio_instance": composio_instance,
71
75
  "envs": envs
72
76
  }
73
77
 
@@ -75,7 +79,7 @@ def get_all_components():
75
79
  def set_components(**kwargs):
76
80
  """Update global components"""
77
81
  global vibesurf_agent, browser_manager, vibesurf_tools, llm, db_manager, current_llm_profile_name
78
- global workspace_dir, browser_execution_path, browser_user_data, active_mcp_server, envs
82
+ global workspace_dir, browser_execution_path, browser_user_data, active_mcp_server, envs, composio_instance
79
83
 
80
84
  if "vibesurf_agent" in kwargs:
81
85
  vibesurf_agent = kwargs["vibesurf_agent"]
@@ -98,7 +102,9 @@ def set_components(**kwargs):
98
102
  if "envs" in kwargs:
99
103
  envs = kwargs["envs"]
100
104
  if "current_llm_profile_name" in kwargs:
101
- envs = kwargs["current_llm_profile_name"]
105
+ current_llm_profile_name = kwargs["current_llm_profile_name"]
106
+ if "composio_instance" in kwargs:
107
+ composio_instance = kwargs["composio_instance"]
102
108
 
103
109
 
104
110
  async def execute_task_background(
@@ -118,6 +124,9 @@ async def execute_task_background(
118
124
 
119
125
  # Check if MCP server configuration needs update
120
126
  await _check_and_update_mcp_servers(db_session)
127
+
128
+ # Check if Composio tools configuration needs update
129
+ await _check_and_update_composio_tools(db_session)
121
130
 
122
131
  # Update active task status to running
123
132
  active_task = {
@@ -272,6 +281,55 @@ async def _check_and_update_mcp_servers(db_session):
272
281
  logger.error(f"Failed to check and update MCP servers: {e}")
273
282
 
274
283
 
284
+ async def _check_and_update_composio_tools(db_session):
285
+ """Check if Composio tools configuration has changed and update tools if needed"""
286
+ global vibesurf_tools, composio_instance
287
+
288
+ try:
289
+ if not db_session:
290
+ return
291
+
292
+ from .database.queries import ComposioToolkitQueries
293
+
294
+ # Get current enabled Composio toolkits from database
295
+ enabled_toolkits = await ComposioToolkitQueries.get_enabled_toolkits(db_session)
296
+
297
+ # Build toolkit_tools_dict from enabled toolkits
298
+ current_toolkit_tools = {}
299
+ for toolkit in enabled_toolkits:
300
+ if toolkit.tools:
301
+ try:
302
+ tools_data = json.loads(toolkit.tools)
303
+ current_toolkit_tools[toolkit.slug] = tools_data
304
+ except (json.JSONDecodeError, TypeError) as e:
305
+ logger.warning(f"Failed to parse tools for toolkit {toolkit.slug}: {e}")
306
+
307
+ # Check if Composio tools need to be updated
308
+ tools_changed = False
309
+ if vibesurf_tools and vibesurf_tools.composio_client:
310
+ # Compare current tools with registered tools
311
+ if vibesurf_tools.composio_client._toolkit_tools != current_toolkit_tools:
312
+ tools_changed = True
313
+ elif current_toolkit_tools:
314
+ # No composio client but we have enabled tools - need to register
315
+ tools_changed = True
316
+
317
+ if tools_changed:
318
+ logger.info(f"Composio tools configuration changed. Updating tools...")
319
+ logger.info(f"New toolkit tools: {list(current_toolkit_tools.keys())}")
320
+
321
+ # Update Composio tools in vibesurf_tools
322
+ if vibesurf_tools:
323
+ await vibesurf_tools.update_composio_tools(
324
+ composio_instance=composio_instance,
325
+ toolkit_tools_dict=current_toolkit_tools
326
+ )
327
+ logger.info("✅ Composio tools configuration updated successfully")
328
+
329
+ except Exception as e:
330
+ logger.error(f"Failed to check and update Composio tools: {e}")
331
+
332
+
275
333
  async def _build_mcp_server_config(active_profiles) -> Dict[str, Any]:
276
334
  """Build MCP server configuration from active profiles"""
277
335
  mcp_server_config = {
@@ -313,17 +371,54 @@ async def _load_active_mcp_servers():
313
371
  except Exception as e:
314
372
  logger.warning(f"Failed to load MCP servers from database: {e}")
315
373
  return {"mcpServers": {}}
316
- finally:
317
- break
318
374
 
319
375
  except Exception as e:
320
376
  logger.warning(f"Database not available for MCP server loading: {e}")
321
377
  return {"mcpServers": {}}
322
378
 
323
379
 
380
+ async def _load_enabled_composio_toolkits():
381
+ """Load enabled Composio toolkits from database and return toolkit_tools_dict"""
382
+ global db_manager
383
+
384
+ try:
385
+ if not db_manager:
386
+ logger.info("Database manager not available, returning empty Composio config")
387
+ return {}
388
+
389
+ from .database.queries import ComposioToolkitQueries
390
+
391
+ async for db in db_manager.get_session():
392
+ try:
393
+ # Get all enabled Composio toolkits
394
+ enabled_toolkits = await ComposioToolkitQueries.get_enabled_toolkits(db)
395
+
396
+ # Build toolkit_tools_dict from enabled toolkits
397
+ toolkit_tools_dict = {}
398
+ for toolkit in enabled_toolkits:
399
+ if toolkit.tools:
400
+ try:
401
+ tools_data = json.loads(toolkit.tools)
402
+ toolkit_tools_dict[toolkit.slug] = tools_data
403
+ except (json.JSONDecodeError, TypeError) as e:
404
+ logger.warning(f"Failed to parse tools for toolkit {toolkit.slug}: {e}")
405
+
406
+ logger.info(f"✅ Loaded {len(toolkit_tools_dict)} enabled Composio toolkits: {list(toolkit_tools_dict.keys())}")
407
+
408
+ return toolkit_tools_dict
409
+
410
+ except Exception as e:
411
+ logger.warning(f"Failed to load Composio toolkits from database: {e}")
412
+ return {}
413
+
414
+ except Exception as e:
415
+ logger.warning(f"Database not available for Composio toolkit loading: {e}")
416
+ return {}
417
+
418
+
324
419
  async def initialize_vibesurf_components():
325
420
  """Initialize VibeSurf components from environment variables and default LLM profile"""
326
- global vibesurf_agent, browser_manager, vibesurf_tools, llm, db_manager, current_llm_profile_name
421
+ global vibesurf_agent, browser_manager, vibesurf_tools, llm, db_manager, current_llm_profile_name, composio_instance
327
422
  global workspace_dir, browser_execution_path, browser_user_data, envs
328
423
  from vibe_surf import common
329
424
 
@@ -447,6 +542,28 @@ async def initialize_vibesurf_components():
447
542
  await vibesurf_tools.register_mcp_clients()
448
543
  logger.info(f"✅ Registered {len(mcp_server_config['mcpServers'])} MCP servers")
449
544
 
545
+ # Load and register Composio tools from enabled toolkits
546
+ from .api.composio import _get_composio_api_key_from_db
547
+ api_key = await _get_composio_api_key_from_db()
548
+ if api_key:
549
+ try:
550
+ # Create Composio instance
551
+ composio_instance = Composio(
552
+ api_key=api_key,
553
+ provider=LangchainProvider()
554
+ )
555
+ logger.info("Successfully create Composio instance!")
556
+ except Exception as e:
557
+ logger.error(f"Failed to create Composio instance: {e}")
558
+ composio_instance = None
559
+ toolkit_tools_dict = await _load_enabled_composio_toolkits()
560
+ if toolkit_tools_dict:
561
+ await vibesurf_tools.register_composio_clients(
562
+ composio_instance=composio_instance,
563
+ toolkit_tools_dict=toolkit_tools_dict
564
+ )
565
+ logger.info(f"✅ Registered Composio tools from {len(toolkit_tools_dict)} enabled toolkits")
566
+
450
567
  # Initialize VibeSurfAgent
451
568
  vibesurf_agent = VibeSurfAgent(
452
569
  llm=llm,
@@ -544,8 +661,6 @@ async def update_llm_from_profile(profile_name: str):
544
661
  except Exception as e:
545
662
  logger.error(f"Failed to update LLM from profile {profile_name}: {e}")
546
663
  raise
547
- finally:
548
- break
549
664
 
550
665
  except Exception as e:
551
666
  logger.error(f"Database error while updating LLM profile: {e}")
@@ -591,7 +706,6 @@ def _update_extension_backend_url(extension_path: str, backend_url: str):
591
706
  with open(config_js_path, 'r', encoding='utf-8') as f:
592
707
  content = f.read()
593
708
 
594
- # 匹配 BACKEND_URL: 'xyz' 或 BACKEND_URL: "xyz",xyz是任意内容
595
709
  pattern = r"BACKEND_URL:\s*(['\"]).*?\1"
596
710
  replacement = f"BACKEND_URL: '{backend_url}'"
597
711
 
@@ -541,6 +541,38 @@ class VibeSurfAPIClient {
541
541
  return `${prefix}${timestamp}_${random}`;
542
542
  }
543
543
  }
544
+
545
+ // Composio APIs
546
+ async verifyComposioKey(apiKey) {
547
+ return this.post('/composio/verify-key', { api_key: apiKey });
548
+ }
549
+
550
+ async getComposioToolkits(params = {}) {
551
+ return this.get('/composio/toolkits', { params });
552
+ }
553
+
554
+ async toggleComposioToolkit(slug, enabled) {
555
+ return this.post(`/composio/toolkit/${encodeURIComponent(slug)}/toggle`, { enabled });
556
+ }
557
+
558
+ async getComposioToolkitTools(slug) {
559
+ return this.get(`/composio/toolkit/${encodeURIComponent(slug)}/tools`);
560
+ }
561
+
562
+ async updateComposioToolkitTools(slug, selectedTools) {
563
+ console.log(`[APIClient] Updating toolkit tools for ${slug}:`, selectedTools);
564
+ const response = await this.post(`/composio/toolkit/${encodeURIComponent(slug)}/tools`, { selected_tools: selectedTools });
565
+ console.log(`[APIClient] Update toolkit tools response:`, response);
566
+ return response;
567
+ }
568
+
569
+ async getComposioToolkitConnectionStatus(slug) {
570
+ return this.get(`/composio/toolkit/${encodeURIComponent(slug)}/connection-status`);
571
+ }
572
+
573
+ async getComposioStatus() {
574
+ return this.get('/composio/status');
575
+ }
544
576
  }
545
577
 
546
578
  // Custom error class for API errors