vibesurf 0.1.31__tar.gz → 0.1.32__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 (140) hide show
  1. {vibesurf-0.1.31 → vibesurf-0.1.32}/PKG-INFO +1 -1
  2. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/_version.py +3 -3
  3. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/agents/vibe_surf_agent.py +1 -1
  4. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/tools/browser_use_tools.py +90 -90
  5. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibesurf.egg-info/PKG-INFO +1 -1
  6. {vibesurf-0.1.31 → vibesurf-0.1.32}/.env.example +0 -0
  7. {vibesurf-0.1.31 → vibesurf-0.1.32}/.github/workflows/publish.yml +0 -0
  8. {vibesurf-0.1.31 → vibesurf-0.1.32}/.gitignore +0 -0
  9. {vibesurf-0.1.31 → vibesurf-0.1.32}/.python-version +0 -0
  10. {vibesurf-0.1.31 → vibesurf-0.1.32}/LICENSE +0 -0
  11. {vibesurf-0.1.31 → vibesurf-0.1.32}/MANIFEST.in +0 -0
  12. {vibesurf-0.1.31 → vibesurf-0.1.32}/README.md +0 -0
  13. {vibesurf-0.1.31 → vibesurf-0.1.32}/README_zh.md +0 -0
  14. {vibesurf-0.1.31 → vibesurf-0.1.32}/docs/EXECUTABLE_BUILD.md +0 -0
  15. {vibesurf-0.1.31 → vibesurf-0.1.32}/docs/PYPI_SETUP.md +0 -0
  16. {vibesurf-0.1.31 → vibesurf-0.1.32}/pyproject.toml +0 -0
  17. {vibesurf-0.1.31 → vibesurf-0.1.32}/scripts/build-local.bat +0 -0
  18. {vibesurf-0.1.31 → vibesurf-0.1.32}/scripts/build-local.sh +0 -0
  19. {vibesurf-0.1.31 → vibesurf-0.1.32}/setup.cfg +0 -0
  20. {vibesurf-0.1.31 → vibesurf-0.1.32}/tests/test_agents.py +0 -0
  21. {vibesurf-0.1.31 → vibesurf-0.1.32}/tests/test_backend_api.py +0 -0
  22. {vibesurf-0.1.31 → vibesurf-0.1.32}/tests/test_browser.py +0 -0
  23. {vibesurf-0.1.31 → vibesurf-0.1.32}/tests/test_tools.py +0 -0
  24. {vibesurf-0.1.31 → vibesurf-0.1.32}/tests/test_voice_api.py +0 -0
  25. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/__init__.py +0 -0
  26. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/agents/__init__.py +0 -0
  27. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/agents/browser_use_agent.py +0 -0
  28. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/agents/prompts/__init__.py +0 -0
  29. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/agents/prompts/report_writer_prompt.py +0 -0
  30. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/agents/prompts/vibe_surf_prompt.py +0 -0
  31. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/agents/report_writer_agent.py +0 -0
  32. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/agents/views.py +0 -0
  33. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/backend/__init__.py +0 -0
  34. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/backend/api/__init__.py +0 -0
  35. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/backend/api/activity.py +0 -0
  36. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/backend/api/agent.py +0 -0
  37. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/backend/api/browser.py +0 -0
  38. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/backend/api/config.py +0 -0
  39. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/backend/api/files.py +0 -0
  40. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/backend/api/models.py +0 -0
  41. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/backend/api/task.py +0 -0
  42. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/backend/api/voices.py +0 -0
  43. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/backend/database/__init__.py +0 -0
  44. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/backend/database/manager.py +0 -0
  45. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/backend/database/migrations/v001_initial_schema.sql +0 -0
  46. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/backend/database/migrations/v002_add_agent_mode.sql +0 -0
  47. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/backend/database/migrations/v003_fix_task_status_case.sql +0 -0
  48. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/backend/database/migrations/v004_add_voice_profiles.sql +0 -0
  49. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/backend/database/models.py +0 -0
  50. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/backend/database/queries.py +0 -0
  51. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/backend/database/schemas.py +0 -0
  52. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/backend/llm_config.py +0 -0
  53. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/backend/main.py +0 -0
  54. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/backend/shared_state.py +0 -0
  55. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/backend/utils/__init__.py +0 -0
  56. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/backend/utils/encryption.py +0 -0
  57. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/backend/utils/llm_factory.py +0 -0
  58. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/backend/utils/utils.py +0 -0
  59. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/backend/voice_model_config.py +0 -0
  60. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/browser/__init__.py +0 -0
  61. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/browser/agen_browser_profile.py +0 -0
  62. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/browser/agent_browser_session.py +0 -0
  63. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/browser/browser_manager.py +0 -0
  64. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/browser/utils.py +0 -0
  65. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/browser/watchdogs/__init__.py +0 -0
  66. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/browser/watchdogs/action_watchdog.py +0 -0
  67. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/browser/watchdogs/dom_watchdog.py +0 -0
  68. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/background.js +0 -0
  69. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/config.js +0 -0
  70. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/content.js +0 -0
  71. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/dev-reload.js +0 -0
  72. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/icons/logo.icns +0 -0
  73. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/icons/logo.png +0 -0
  74. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/manifest.json +0 -0
  75. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/permission-iframe.html +0 -0
  76. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/permission-request.html +0 -0
  77. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/popup.html +0 -0
  78. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/scripts/api-client.js +0 -0
  79. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/scripts/file-manager.js +0 -0
  80. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/scripts/history-manager.js +0 -0
  81. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/scripts/main.js +0 -0
  82. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/scripts/markdown-it.min.js +0 -0
  83. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/scripts/modal-manager.js +0 -0
  84. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/scripts/permission-iframe-request.js +0 -0
  85. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/scripts/permission-request.js +0 -0
  86. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/scripts/session-manager.js +0 -0
  87. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/scripts/settings-manager.js +0 -0
  88. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/scripts/ui-manager.js +0 -0
  89. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/scripts/user-settings-storage.js +0 -0
  90. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/scripts/voice-recorder.js +0 -0
  91. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/sidepanel.html +0 -0
  92. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/styles/activity.css +0 -0
  93. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/styles/animations.css +0 -0
  94. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/styles/base.css +0 -0
  95. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/styles/components.css +0 -0
  96. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/styles/history-modal.css +0 -0
  97. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/styles/input.css +0 -0
  98. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/styles/layout.css +0 -0
  99. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/styles/responsive.css +0 -0
  100. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/styles/settings-environment.css +0 -0
  101. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/styles/settings-forms.css +0 -0
  102. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/styles/settings-modal.css +0 -0
  103. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/styles/settings-profiles.css +0 -0
  104. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/styles/settings-responsive.css +0 -0
  105. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/styles/settings-utilities.css +0 -0
  106. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/chrome_extension/styles/variables.css +0 -0
  107. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/cli.py +0 -0
  108. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/common.py +0 -0
  109. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/llm/__init__.py +0 -0
  110. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/llm/openai_compatible.py +0 -0
  111. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/logger.py +0 -0
  112. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/tools/__init__.py +0 -0
  113. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/tools/file_system.py +0 -0
  114. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/tools/finance_tools.py +0 -0
  115. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/tools/mcp_client.py +0 -0
  116. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/tools/report_writer_tools.py +0 -0
  117. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/tools/vibesurf_registry.py +0 -0
  118. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/tools/vibesurf_tools.py +0 -0
  119. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/tools/views.py +0 -0
  120. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/tools/voice_asr.py +0 -0
  121. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/tools/website_api/__init__.py +0 -0
  122. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/tools/website_api/douyin/__init__.py +0 -0
  123. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/tools/website_api/douyin/client.py +0 -0
  124. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/tools/website_api/douyin/douyin.js +0 -0
  125. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/tools/website_api/douyin/helpers.py +0 -0
  126. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/tools/website_api/weibo/__init__.py +0 -0
  127. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/tools/website_api/weibo/client.py +0 -0
  128. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/tools/website_api/weibo/helpers.py +0 -0
  129. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/tools/website_api/xhs/__init__.py +0 -0
  130. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/tools/website_api/xhs/client.py +0 -0
  131. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/tools/website_api/xhs/helpers.py +0 -0
  132. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/tools/website_api/youtube/__init__.py +0 -0
  133. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/tools/website_api/youtube/client.py +0 -0
  134. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibe_surf/tools/website_api/youtube/helpers.py +0 -0
  135. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibesurf.egg-info/SOURCES.txt +0 -0
  136. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibesurf.egg-info/dependency_links.txt +0 -0
  137. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibesurf.egg-info/entry_points.txt +0 -0
  138. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibesurf.egg-info/requires.txt +0 -0
  139. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibesurf.egg-info/top_level.txt +0 -0
  140. {vibesurf-0.1.31 → vibesurf-0.1.32}/vibesurf.spec +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vibesurf
3
- Version: 0.1.31
3
+ Version: 0.1.32
4
4
  Summary: VibeSurf: A powerful browser assistant for vibe surfing
5
5
  Author: WarmShao
6
6
  License: Apache-2.0
@@ -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.31'
32
- __version_tuple__ = version_tuple = (0, 1, 31)
31
+ __version__ = version = '0.1.32'
32
+ __version_tuple__ = version_tuple = (0, 1, 32)
33
33
 
34
- __commit_id__ = commit_id = 'gf2d6ab8af'
34
+ __commit_id__ = commit_id = 'g5ca20a39e'
@@ -479,7 +479,7 @@ 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.startswith("skill_"):
482
+ if action_name in ['skill_search', 'skill_crawl', 'skill_summary', 'skill_deep_research']:
483
483
  state.current_step = "END"
484
484
  # Format final response
485
485
  final_response = f"{result.extracted_content}" or f"{result.error}"
@@ -594,93 +594,93 @@ class BrowserUseTools(Tools, VibeSurfTools):
594
594
  logger.error(error_msg)
595
595
  return ActionResult(error=error_msg)
596
596
 
597
- async def _detect_file_format(self, url: str, headers: dict, content: bytes) -> str:
598
- """Detect file format from URL, headers, and content"""
599
-
600
- # Try Content-Type header first
601
- content_type = headers.get('content-type', '').lower()
602
- if content_type:
603
- # Common image formats
604
- if 'image/jpeg' in content_type or 'image/jpg' in content_type:
605
- return '.jpg'
606
- elif 'image/png' in content_type:
607
- return '.png'
608
- elif 'image/gif' in content_type:
609
- return '.gif'
610
- elif 'image/webp' in content_type:
611
- return '.webp'
612
- elif 'image/svg' in content_type:
613
- return '.svg'
614
- elif 'image/bmp' in content_type:
615
- return '.bmp'
616
- elif 'image/tiff' in content_type:
617
- return '.tiff'
618
- # Video formats
619
- elif 'video/mp4' in content_type:
620
- return '.mp4'
621
- elif 'video/webm' in content_type:
622
- return '.webm'
623
- elif 'video/avi' in content_type:
624
- return '.avi'
625
- elif 'video/mov' in content_type or 'video/quicktime' in content_type:
626
- return '.mov'
627
- # Audio formats
628
- elif 'audio/mpeg' in content_type or 'audio/mp3' in content_type:
629
- return '.mp3'
630
- elif 'audio/wav' in content_type:
631
- return '.wav'
632
- elif 'audio/ogg' in content_type:
633
- return '.ogg'
634
- elif 'audio/webm' in content_type:
635
- return '.webm'
636
-
637
- # Try magic number detection
638
- if len(content) >= 8:
639
- # JPEG
640
- if content.startswith(b'\xff\xd8\xff'):
641
- return '.jpg'
642
- # PNG
643
- elif content.startswith(b'\x89PNG\r\n\x1a\n'):
644
- return '.png'
645
- # GIF
646
- elif content.startswith(b'GIF87a') or content.startswith(b'GIF89a'):
647
- return '.gif'
648
- # WebP
649
- elif content[8:12] == b'WEBP':
650
- return '.webp'
651
- # BMP
652
- elif content.startswith(b'BM'):
653
- return '.bmp'
654
- # TIFF
655
- elif content.startswith(b'II*\x00') or content.startswith(b'MM\x00*'):
656
- return '.tiff'
657
- # MP4
658
- elif b'ftyp' in content[4:12]:
659
- return '.mp4'
660
- # PDF
661
- elif content.startswith(b'%PDF'):
662
- return '.pdf'
663
-
664
- # Try URL path extension
665
- url_path = urllib.parse.urlparse(url).path
666
- if url_path:
667
- ext = os.path.splitext(url_path)[1].lower()
668
- if ext in ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.svg', '.bmp', '.tiff',
669
- '.mp4', '.webm', '.avi', '.mov', '.wmv', '.flv',
670
- '.mp3', '.wav', '.ogg', '.aac', '.flac',
671
- '.pdf', '.doc', '.docx', '.txt']:
672
- return ext
673
-
674
- # Default fallback
675
- return '.bin'
676
-
677
- def _format_file_size(self, size_bytes: int) -> str:
678
- """Format file size in human readable format"""
679
- if size_bytes == 0:
680
- return "0 B"
681
- size_names = ["B", "KB", "MB", "GB", "TB"]
682
- i = 0
683
- while size_bytes >= 1024.0 and i < len(size_names) - 1:
684
- size_bytes /= 1024.0
685
- i += 1
686
- return f"{size_bytes:.1f} {size_names[i]}"
597
+ async def _detect_file_format(self, url: str, headers: dict, content: bytes) -> str:
598
+ """Detect file format from URL, headers, and content"""
599
+
600
+ # Try Content-Type header first
601
+ content_type = headers.get('content-type', '').lower()
602
+ if content_type:
603
+ # Common image formats
604
+ if 'image/jpeg' in content_type or 'image/jpg' in content_type:
605
+ return '.jpg'
606
+ elif 'image/png' in content_type:
607
+ return '.png'
608
+ elif 'image/gif' in content_type:
609
+ return '.gif'
610
+ elif 'image/webp' in content_type:
611
+ return '.webp'
612
+ elif 'image/svg' in content_type:
613
+ return '.svg'
614
+ elif 'image/bmp' in content_type:
615
+ return '.bmp'
616
+ elif 'image/tiff' in content_type:
617
+ return '.tiff'
618
+ # Video formats
619
+ elif 'video/mp4' in content_type:
620
+ return '.mp4'
621
+ elif 'video/webm' in content_type:
622
+ return '.webm'
623
+ elif 'video/avi' in content_type:
624
+ return '.avi'
625
+ elif 'video/mov' in content_type or 'video/quicktime' in content_type:
626
+ return '.mov'
627
+ # Audio formats
628
+ elif 'audio/mpeg' in content_type or 'audio/mp3' in content_type:
629
+ return '.mp3'
630
+ elif 'audio/wav' in content_type:
631
+ return '.wav'
632
+ elif 'audio/ogg' in content_type:
633
+ return '.ogg'
634
+ elif 'audio/webm' in content_type:
635
+ return '.webm'
636
+
637
+ # Try magic number detection
638
+ if len(content) >= 8:
639
+ # JPEG
640
+ if content.startswith(b'\xff\xd8\xff'):
641
+ return '.jpg'
642
+ # PNG
643
+ elif content.startswith(b'\x89PNG\r\n\x1a\n'):
644
+ return '.png'
645
+ # GIF
646
+ elif content.startswith(b'GIF87a') or content.startswith(b'GIF89a'):
647
+ return '.gif'
648
+ # WebP
649
+ elif content[8:12] == b'WEBP':
650
+ return '.webp'
651
+ # BMP
652
+ elif content.startswith(b'BM'):
653
+ return '.bmp'
654
+ # TIFF
655
+ elif content.startswith(b'II*\x00') or content.startswith(b'MM\x00*'):
656
+ return '.tiff'
657
+ # MP4
658
+ elif b'ftyp' in content[4:12]:
659
+ return '.mp4'
660
+ # PDF
661
+ elif content.startswith(b'%PDF'):
662
+ return '.pdf'
663
+
664
+ # Try URL path extension
665
+ url_path = urllib.parse.urlparse(url).path
666
+ if url_path:
667
+ ext = os.path.splitext(url_path)[1].lower()
668
+ if ext in ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.svg', '.bmp', '.tiff',
669
+ '.mp4', '.webm', '.avi', '.mov', '.wmv', '.flv',
670
+ '.mp3', '.wav', '.ogg', '.aac', '.flac',
671
+ '.pdf', '.doc', '.docx', '.txt']:
672
+ return ext
673
+
674
+ # Default fallback
675
+ return '.bin'
676
+
677
+ def _format_file_size(self, size_bytes: int) -> str:
678
+ """Format file size in human readable format"""
679
+ if size_bytes == 0:
680
+ return "0 B"
681
+ size_names = ["B", "KB", "MB", "GB", "TB"]
682
+ i = 0
683
+ while size_bytes >= 1024.0 and i < len(size_names) - 1:
684
+ size_bytes /= 1024.0
685
+ i += 1
686
+ return f"{size_bytes:.1f} {size_names[i]}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vibesurf
3
- Version: 0.1.31
3
+ Version: 0.1.32
4
4
  Summary: VibeSurf: A powerful browser assistant for vibe surfing
5
5
  Author: WarmShao
6
6
  License: Apache-2.0
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes