vibesurf 0.1.11__tar.gz → 0.1.13__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 (112) hide show
  1. {vibesurf-0.1.11 → vibesurf-0.1.13}/.github/workflows/publish.yml +22 -93
  2. {vibesurf-0.1.11 → vibesurf-0.1.13}/PKG-INFO +1 -1
  3. {vibesurf-0.1.11 → vibesurf-0.1.13}/scripts/build-local.sh +32 -32
  4. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/_version.py +3 -3
  5. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/agents/vibe_surf_agent.py +1 -0
  6. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/backend/api/task.py +47 -14
  7. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/backend/shared_state.py +12 -5
  8. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/backend/utils/llm_factory.py +10 -8
  9. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/scripts/api-client.js +6 -0
  10. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/scripts/modal-manager.js +41 -32
  11. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/scripts/session-manager.js +10 -0
  12. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/scripts/settings-manager.js +32 -0
  13. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/scripts/ui-manager.js +67 -1
  14. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/styles/components.css +173 -20
  15. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/styles/input.css +1 -95
  16. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/cli.py +2 -1
  17. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/llm/openai_compatible.py +72 -9
  18. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/tools/file_system.py +25 -3
  19. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibesurf.egg-info/PKG-INFO +1 -1
  20. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibesurf.spec +31 -95
  21. {vibesurf-0.1.11 → vibesurf-0.1.13}/.env.example +0 -0
  22. {vibesurf-0.1.11 → vibesurf-0.1.13}/.gitignore +0 -0
  23. {vibesurf-0.1.11 → vibesurf-0.1.13}/.python-version +0 -0
  24. {vibesurf-0.1.11 → vibesurf-0.1.13}/LICENSE +0 -0
  25. {vibesurf-0.1.11 → vibesurf-0.1.13}/MANIFEST.in +0 -0
  26. {vibesurf-0.1.11 → vibesurf-0.1.13}/README.md +0 -0
  27. {vibesurf-0.1.11 → vibesurf-0.1.13}/docs/EXECUTABLE_BUILD.md +0 -0
  28. {vibesurf-0.1.11 → vibesurf-0.1.13}/docs/PYPI_SETUP.md +0 -0
  29. {vibesurf-0.1.11 → vibesurf-0.1.13}/pyproject.toml +0 -0
  30. {vibesurf-0.1.11 → vibesurf-0.1.13}/scripts/build-local.bat +0 -0
  31. {vibesurf-0.1.11 → vibesurf-0.1.13}/setup.cfg +0 -0
  32. {vibesurf-0.1.11 → vibesurf-0.1.13}/tests/test_agents.py +0 -0
  33. {vibesurf-0.1.11 → vibesurf-0.1.13}/tests/test_backend_api.py +0 -0
  34. {vibesurf-0.1.11 → vibesurf-0.1.13}/tests/test_browser.py +0 -0
  35. {vibesurf-0.1.11 → vibesurf-0.1.13}/tests/test_tools.py +0 -0
  36. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/__init__.py +0 -0
  37. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/agents/__init__.py +0 -0
  38. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/agents/browser_use_agent.py +0 -0
  39. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/agents/prompts/__init__.py +0 -0
  40. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/agents/prompts/report_writer_prompt.py +0 -0
  41. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/agents/prompts/vibe_surf_prompt.py +0 -0
  42. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/agents/report_writer_agent.py +0 -0
  43. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/agents/views.py +0 -0
  44. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/backend/__init__.py +0 -0
  45. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/backend/api/__init__.py +0 -0
  46. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/backend/api/activity.py +0 -0
  47. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/backend/api/browser.py +0 -0
  48. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/backend/api/config.py +0 -0
  49. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/backend/api/files.py +0 -0
  50. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/backend/api/models.py +0 -0
  51. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/backend/database/__init__.py +0 -0
  52. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/backend/database/manager.py +0 -0
  53. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/backend/database/models.py +0 -0
  54. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/backend/database/queries.py +0 -0
  55. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/backend/database/schemas.py +0 -0
  56. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/backend/llm_config.py +0 -0
  57. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/backend/main.py +0 -0
  58. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/backend/migrations/__init__.py +0 -0
  59. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/backend/migrations/init_db.py +0 -0
  60. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/backend/migrations/seed_data.py +0 -0
  61. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/backend/utils/__init__.py +0 -0
  62. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/backend/utils/encryption.py +0 -0
  63. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/browser/__init__.py +0 -0
  64. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/browser/agen_browser_profile.py +0 -0
  65. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/browser/agent_browser_session.py +0 -0
  66. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/browser/browser_manager.py +0 -0
  67. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/browser/utils.py +0 -0
  68. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/browser/watchdogs/__init__.py +0 -0
  69. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/browser/watchdogs/action_watchdog.py +0 -0
  70. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/browser/watchdogs/dom_watchdog.py +0 -0
  71. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/background.js +0 -0
  72. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/config.js +0 -0
  73. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/content.js +0 -0
  74. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/dev-reload.js +0 -0
  75. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/icons/convert-svg.js +0 -0
  76. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/icons/logo-preview.html +0 -0
  77. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/icons/logo.icns +0 -0
  78. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/icons/logo.png +0 -0
  79. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/manifest.json +0 -0
  80. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/popup.html +0 -0
  81. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/scripts/file-manager.js +0 -0
  82. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/scripts/history-manager.js +0 -0
  83. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/scripts/main.js +0 -0
  84. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/scripts/markdown-it.min.js +0 -0
  85. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/sidepanel.html +0 -0
  86. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/styles/activity.css +0 -0
  87. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/styles/animations.css +0 -0
  88. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/styles/base.css +0 -0
  89. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/styles/history-modal.css +0 -0
  90. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/styles/layout.css +0 -0
  91. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/styles/responsive.css +0 -0
  92. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/styles/settings-environment.css +0 -0
  93. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/styles/settings-forms.css +0 -0
  94. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/styles/settings-modal.css +0 -0
  95. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/styles/settings-profiles.css +0 -0
  96. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/styles/settings-responsive.css +0 -0
  97. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/styles/settings-utilities.css +0 -0
  98. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/chrome_extension/styles/variables.css +0 -0
  99. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/common.py +0 -0
  100. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/llm/__init__.py +0 -0
  101. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/logger.py +0 -0
  102. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/tools/__init__.py +0 -0
  103. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/tools/browser_use_tools.py +0 -0
  104. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/tools/mcp_client.py +0 -0
  105. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/tools/report_writer_tools.py +0 -0
  106. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/tools/vibesurf_tools.py +0 -0
  107. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibe_surf/tools/views.py +0 -0
  108. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibesurf.egg-info/SOURCES.txt +0 -0
  109. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibesurf.egg-info/dependency_links.txt +0 -0
  110. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibesurf.egg-info/entry_points.txt +0 -0
  111. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibesurf.egg-info/requires.txt +0 -0
  112. {vibesurf-0.1.11 → vibesurf-0.1.13}/vibesurf.egg-info/top_level.txt +0 -0
@@ -93,10 +93,6 @@ jobs:
93
93
  - os: macos-14
94
94
  asset_name: vibesurf-macos-apple-silicon
95
95
  activate_cmd: source .venv/bin/activate
96
- # Linux x64
97
- - os: ubuntu-latest
98
- asset_name: vibesurf-linux-x64
99
- activate_cmd: source .venv/bin/activate
100
96
 
101
97
  runs-on: ${{ matrix.os }}
102
98
 
@@ -168,83 +164,28 @@ jobs:
168
164
  # Windows: rename .exe file
169
165
  mv dist/vibesurf.exe dist/${{ matrix.asset_name }}
170
166
  elif [[ "$RUNNER_OS" == "macOS" ]]; then
171
- # macOS: handle .app bundle
172
- if [ -d "dist/VibeSurf.app" ]; then
173
- echo "Found macOS .app bundle"
174
-
175
- # Apply ad-hoc code signing FIRST, before creating archive
176
- echo "Adding ad-hoc code signature to .app bundle..."
177
- codesign --force --deep --sign - dist/VibeSurf.app || echo "Code signing failed, continuing..."
178
-
179
- # Remove quarantine attribute to help with Gatekeeper
180
- xattr -cr dist/VibeSurf.app 2>/dev/null || echo "No quarantine attributes to remove"
181
-
182
- # Verify signing
183
- echo "Verifying code signature..."
184
- codesign --verify --deep dist/VibeSurf.app && echo "✅ Signature verified" || echo "⚠️ Signature verification failed"
185
-
186
- # Create professional DMG disk image (macOS standard)
187
- echo "Creating DMG disk image with signed .app bundle..."
188
- cd dist
189
-
190
- # Create a temporary directory for DMG contents
191
- mkdir -p dmg_temp
192
- cp -R VibeSurf.app dmg_temp/
193
-
194
- # Create a symbolic link to Applications folder for easy installation
195
- ln -s /Applications dmg_temp/Applications
196
-
197
- # Create the DMG with proper settings
198
- hdiutil create -volname "VibeSurf" \
199
- -srcfolder dmg_temp \
200
- -ov -format UDZO \
201
- -imagekey zlib-level=9 \
202
- ${{ matrix.asset_name }}.dmg
203
-
204
- # Clean up temporary directory
205
- rm -rf dmg_temp
206
-
207
- # Verify DMG was created
208
- if [ -f "${{ matrix.asset_name }}.dmg" ]; then
209
- echo "✅ DMG created successfully: ${{ matrix.asset_name }}.dmg"
210
- ls -lh ${{ matrix.asset_name }}.dmg
211
- echo "Professional macOS disk image created"
212
- else
213
- echo "❌ Failed to create DMG"
214
- exit 1
215
- fi
216
- cd ..
217
-
218
- # Clean up: remove the .app bundle to avoid duplicate uploads
219
- echo "Cleaning up .app bundle after DMG creation..."
220
- rm -rf dist/VibeSurf.app
221
- else
222
- # Fallback: single executable
223
- echo "No .app bundle found, using single executable"
224
- mv dist/vibesurf dist/${{ matrix.asset_name }}
225
- chmod +x dist/${{ matrix.asset_name }}
226
- codesign --force --deep --sign - dist/${{ matrix.asset_name }} || echo "Code signing failed, continuing..."
227
- fi
228
- else
229
- # Linux: single executable
167
+ # macOS: handle single executable (CLI application with console support)
168
+ echo "Processing macOS CLI executable with icon..."
230
169
  mv dist/vibesurf dist/${{ matrix.asset_name }}
231
170
  chmod +x dist/${{ matrix.asset_name }}
171
+
172
+ # Apply ad-hoc code signing for macOS security
173
+ echo "Adding ad-hoc code signature to executable..."
174
+ codesign --force --sign - dist/${{ matrix.asset_name }} || echo "Code signing failed, continuing..."
175
+
176
+ # Remove quarantine attribute to help with Gatekeeper
177
+ xattr -c dist/${{ matrix.asset_name }} 2>/dev/null || echo "No quarantine attributes to remove"
178
+
179
+ # Verify signing
180
+ echo "Verifying code signature..."
181
+ codesign --verify dist/${{ matrix.asset_name }} && echo "✅ Signature verified" || echo "⚠️ Signature verification failed"
182
+
183
+ echo "✅ macOS executable ready - double-click will open in Terminal with console interface"
232
184
  fi
233
185
 
234
186
  # Show final result
235
- echo "=== Final executable/archive ==="
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
244
- else
245
- # For other platforms, check the executable
246
- ls -lh dist/${{ matrix.asset_name }}
247
- fi
187
+ echo "=== Final executable ==="
188
+ ls -lh dist/${{ matrix.asset_name }}
248
189
 
249
190
  - name: Test executable
250
191
  shell: bash
@@ -254,18 +195,7 @@ jobs:
254
195
  echo "Testing Windows executable..."
255
196
  ls -la dist/${{ matrix.asset_name }}
256
197
  elif [[ "$RUNNER_OS" == "macOS" ]]; then
257
- echo "Testing macOS .app bundle..."
258
- if [ -d "dist/VibeSurf.app" ]; then
259
- echo "✅ VibeSurf.app bundle exists"
260
- ls -la dist/VibeSurf.app/Contents/MacOS/
261
- # Test the executable inside the bundle
262
- ./dist/VibeSurf.app/Contents/MacOS/vibesurf --help || echo "Basic app test completed"
263
- else
264
- echo "Testing macOS executable..."
265
- ./dist/${{ matrix.asset_name }} --help || echo "Basic test completed"
266
- fi
267
- else
268
- echo "Testing Linux executable..."
198
+ echo "Testing macOS executable..."
269
199
  ./dist/${{ matrix.asset_name }} --help || echo "Basic test completed"
270
200
  fi
271
201
 
@@ -273,8 +203,8 @@ jobs:
273
203
  uses: actions/upload-artifact@v4
274
204
  with:
275
205
  name: ${{ matrix.asset_name }}
276
- # For macOS, upload the .dmg file; for others, upload the executable
277
- path: ${{ runner.os == 'macOS' && format('dist/{0}.dmg', matrix.asset_name) || format('dist/{0}', matrix.asset_name) }}
206
+ # Upload the executable file
207
+ path: dist/${{ matrix.asset_name }}
278
208
  retention-days: 90
279
209
 
280
210
  publish-pypi:
@@ -316,6 +246,5 @@ jobs:
316
246
  with:
317
247
  files: |
318
248
  vibesurf-windows-x64.exe/vibesurf-windows-x64.exe
319
- vibesurf-macos-intel-x64/vibesurf-macos-intel-x64.dmg
320
- vibesurf-macos-apple-silicon/vibesurf-macos-apple-silicon.dmg
321
- vibesurf-linux-x64/vibesurf-linux-x64
249
+ vibesurf-macos-intel-x64/vibesurf-macos-intel-x64
250
+ vibesurf-macos-apple-silicon/vibesurf-macos-apple-silicon
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vibesurf
3
- Version: 0.1.11
3
+ Version: 0.1.13
4
4
  Summary: VibeSurf: A powerful browser assistant for vibe surfing
5
5
  Author: Shao Warm
6
6
  License: Apache-2.0
@@ -92,40 +92,31 @@ PLATFORM=$(uname -s)
92
92
  print_status "Detected platform: $PLATFORM"
93
93
 
94
94
  if [ "$PLATFORM" = "Darwin" ]; then
95
- # macOS - check for .app bundle
96
- if [ -d "dist/VibeSurf.app" ]; then
97
- print_success "macOS .app bundle built successfully!"
98
-
99
- # Run macOS post-build script if it exists
100
- if [ -f "macos-post-build.sh" ]; then
101
- print_status "Running macOS post-build processing..."
102
- chmod +x macos-post-build.sh
103
- ./macos-post-build.sh
104
- else
105
- print_warning "macos-post-build.sh not found - skipping post-processing"
106
- echo ""
107
- echo "📊 App Bundle Information:"
108
- echo "========================="
109
- ls -lah dist/VibeSurf.app
110
- echo ""
111
- print_success "🎉 Build completed successfully!"
112
- echo "📁 Your app is located at: ./dist/VibeSurf.app"
113
- echo "🚀 To run: open ./dist/VibeSurf.app"
114
- fi
115
-
116
- else
117
- print_error "Build failed - VibeSurf.app bundle not found"
118
- exit 1
119
- fi
120
-
121
- else
122
- # Linux/Unix - check for regular executable
95
+ # macOS - check for single executable (CLI application with icon)
123
96
  if [ -f "dist/vibesurf" ]; then
124
- print_success "Executable built successfully!"
97
+ print_success "macOS CLI executable with icon built successfully!"
125
98
 
126
- # Make executable and test
99
+ # Make executable and apply code signing
127
100
  chmod +x dist/vibesurf
128
101
 
102
+ print_status "Applying ad-hoc code signature..."
103
+ codesign --force --sign - dist/vibesurf || {
104
+ print_warning "Code signing failed, but executable should still work"
105
+ }
106
+
107
+ # Remove quarantine attribute
108
+ xattr -c dist/vibesurf 2>/dev/null || {
109
+ print_warning "No quarantine attributes to remove"
110
+ }
111
+
112
+ # Verify signing
113
+ print_status "Verifying code signature..."
114
+ codesign --verify dist/vibesurf && {
115
+ print_success "✅ Signature verified"
116
+ } || {
117
+ print_warning "⚠️ Signature verification failed"
118
+ }
119
+
129
120
  print_status "Testing executable..."
130
121
  ./dist/vibesurf --help > /dev/null 2>&1 && {
131
122
  print_success "Executable test passed!"
@@ -147,11 +138,20 @@ else
147
138
  print_success "🎉 Build completed successfully!"
148
139
  echo ""
149
140
  echo "📁 Your executable is located at: ./dist/vibesurf"
150
- echo "🚀 To run: ./dist/vibesurf"
141
+ echo "🚀 To run:"
142
+ echo " • Double-click vibesurf (opens in Terminal with console interface)"
143
+ echo " • Or run: ./dist/vibesurf"
144
+ echo "💡 This executable has an icon and will open console interface when double-clicked"
151
145
  echo ""
152
146
 
153
147
  else
154
- print_error "Build failed - executable not found"
148
+ print_error "Build failed - vibesurf executable not found"
155
149
  exit 1
156
150
  fi
151
+
152
+ else
153
+ # Other Unix-like systems are not supported
154
+ print_error "This build script currently only supports macOS."
155
+ print_error "For other platforms, please use the GitHub Actions workflow."
156
+ exit 1
157
157
  fi
@@ -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.11'
32
- __version_tuple__ = version_tuple = (0, 1, 11)
31
+ __version__ = version = '0.1.13'
32
+ __version_tuple__ = version_tuple = (0, 1, 13)
33
33
 
34
- __commit_id__ = commit_id = 'g542374226'
34
+ __commit_id__ = commit_id = 'g21ffa8cf4'
@@ -363,6 +363,7 @@ async def _vibesurf_agent_node_impl(state: VibeSurfState) -> VibeSurfState:
363
363
 
364
364
  # Format context information
365
365
  context_info = []
366
+ context_info.append(f"Current Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
366
367
  if browser_tabs:
367
368
  browser_tabs_info = {}
368
369
  for tab in browser_tabs:
@@ -22,7 +22,6 @@ from ..shared_state import (
22
22
  is_task_running,
23
23
  get_active_task_info,
24
24
  clear_active_task,
25
- browser_manager
26
25
  )
27
26
 
28
27
  from vibe_surf.logger import get_logger
@@ -49,7 +48,7 @@ async def submit_task(
49
48
  ):
50
49
  """Submit new task for execution (single task mode)"""
51
50
  from ..database.queries import LLMProfileQueries
52
- from ..shared_state import workspace_dir, active_task
51
+ from ..shared_state import workspace_dir, active_task, llm, current_llm_profile_name
53
52
 
54
53
  # Check if task is already running
55
54
  if is_task_running():
@@ -74,6 +73,18 @@ async def submit_task(
74
73
  detail=f"LLM profile '{task_request.llm_profile_name}' not found"
75
74
  )
76
75
 
76
+ # Initialize LLM for this task if needed
77
+ if not current_llm_profile_name or current_llm_profile_name != task_request.llm_profile_name:
78
+ current_llm_profile_name = task_request.llm_profile_name
79
+ success, message = await _ensure_llm_initialized(llm_profile)
80
+ if not success:
81
+ active_task = None
82
+ return {
83
+ "success": False,
84
+ "error": "llm_connection_failed",
85
+ "message": f"Cannot connect to LLM API: {message}",
86
+ "llm_profile": task_request.llm_profile_name
87
+ }
77
88
  # Generate task ID
78
89
  task_id = uuid7str()
79
90
 
@@ -106,10 +117,6 @@ async def submit_task(
106
117
  )
107
118
  await db.commit()
108
119
 
109
- # Initialize LLM for this task if needed
110
- if not active_task or active_task["llm_profile_name"] != task_request.llm_profile_name:
111
- await _ensure_llm_initialized(llm_profile)
112
-
113
120
  # Add background task
114
121
  background_tasks.add_task(
115
122
  execute_task_background,
@@ -139,20 +146,46 @@ async def submit_task(
139
146
 
140
147
 
141
148
  async def _ensure_llm_initialized(llm_profile):
142
- """Ensure LLM is initialized with the specified profile"""
149
+ """Ensure LLM is initialized with the specified profile and test connectivity"""
143
150
  from ..utils.llm_factory import create_llm_from_profile
144
151
  from ..shared_state import vibesurf_agent
152
+ from browser_use.llm import UserMessage
145
153
 
146
154
  if not vibesurf_agent:
147
155
  raise HTTPException(status_code=503, detail="VibeSurf agent not initialized")
148
156
 
149
- # Always create new LLM instance to ensure we're using the right profile
150
- new_llm = create_llm_from_profile(llm_profile)
157
+ try:
158
+ # Always create new LLM instance to ensure we're using the right profile
159
+ new_llm = create_llm_from_profile(llm_profile)
151
160
 
152
- # Update vibesurf agent's LLM and register with token cost service
153
- if vibesurf_agent and vibesurf_agent.token_cost_service:
154
- vibesurf_agent.llm = vibesurf_agent.token_cost_service.register_llm(new_llm)
155
- logger.info(f"LLM updated and registered for token tracking for profile: {llm_profile['profile_name']}")
161
+ # Test LLM connectivity with a simple question
162
+ test_message = UserMessage(content='What is the capital of France? Answer in one word.')
163
+
164
+ logger.info(f"Testing LLM connectivity for profile: {llm_profile['profile_name']}")
165
+ response = await new_llm.ainvoke([test_message])
166
+
167
+ # Check if response contains expected answer
168
+ if not response or not hasattr(response, 'completion'):
169
+ return False, f"LLM response validation failed: No completion content received"
170
+
171
+ completion = response.completion.lower() if response.completion else ""
172
+ if 'paris' not in completion:
173
+ logger.warning(f"LLM connectivity test returned unexpected answer: {response.completion}")
174
+ # Still continue if we got some response, just log the warning
175
+
176
+ logger.info(f"LLM connectivity test successful for profile: {llm_profile['profile_name']}")
177
+
178
+ # Update vibesurf agent's LLM and register with token cost service
179
+ if vibesurf_agent and vibesurf_agent.token_cost_service:
180
+ vibesurf_agent.llm = vibesurf_agent.token_cost_service.register_llm(new_llm)
181
+ logger.info(f"LLM updated and registered for token tracking for profile: {llm_profile['profile_name']}")
182
+
183
+ return True, "LLM initialized and tested successfully"
184
+
185
+ except Exception as e:
186
+ error_msg = f"LLM connectivity test failed: {str(e)}"
187
+ logger.error(error_msg)
188
+ return False, error_msg
156
189
 
157
190
 
158
191
  @router.post("/pause")
@@ -248,7 +281,7 @@ async def stop_task(control_request: TaskControlRequest):
248
281
  active_task["end_time"] = datetime.now()
249
282
 
250
283
  # Clear active task
251
- # clear_active_task()
284
+ clear_active_task()
252
285
 
253
286
  return {
254
287
  "success": True,
@@ -33,6 +33,7 @@ browser_manager: Optional[BrowserManager] = None
33
33
  vibesurf_tools: Optional[VibeSurfTools] = None
34
34
  llm: Optional[BaseChatModel] = None
35
35
  db_manager: Optional['DatabaseManager'] = None
36
+ current_llm_profile_name: Optional[str] = None
36
37
 
37
38
  # Environment variables
38
39
  workspace_dir: str = ""
@@ -51,7 +52,7 @@ active_task: Optional[Dict[str, Any]] = None
51
52
 
52
53
  def get_all_components():
53
54
  """Get all components as a dictionary"""
54
- global vibesurf_agent, browser_manager, vibesurf_tools, llm, db_manager
55
+ global vibesurf_agent, browser_manager, vibesurf_tools, llm, db_manager, current_llm_profile_name
55
56
  global workspace_dir, browser_execution_path, browser_user_data, active_mcp_server, envs
56
57
 
57
58
  return {
@@ -65,13 +66,14 @@ def get_all_components():
65
66
  "browser_user_data": browser_user_data,
66
67
  "active_mcp_server": active_mcp_server,
67
68
  "active_task": active_task,
69
+ "current_llm_profile_name": current_llm_profile_name,
68
70
  "envs": envs
69
71
  }
70
72
 
71
73
 
72
74
  def set_components(**kwargs):
73
75
  """Update global components"""
74
- global vibesurf_agent, browser_manager, vibesurf_tools, llm, db_manager
76
+ global vibesurf_agent, browser_manager, vibesurf_tools, llm, db_manager, current_llm_profile_name
75
77
  global workspace_dir, browser_execution_path, browser_user_data, active_mcp_server, envs
76
78
 
77
79
  if "vibesurf_agent" in kwargs:
@@ -94,6 +96,8 @@ def set_components(**kwargs):
94
96
  active_mcp_server = kwargs["active_mcp_server"]
95
97
  if "envs" in kwargs:
96
98
  envs = kwargs["envs"]
99
+ if "current_llm_profile_name" in kwargs:
100
+ envs = kwargs["current_llm_profile_name"]
97
101
 
98
102
 
99
103
  async def execute_task_background(
@@ -105,9 +109,11 @@ async def execute_task_background(
105
109
  db_session=None
106
110
  ):
107
111
  """Background task execution function for single task with LLM profile support"""
108
- global vibesurf_agent, active_task
112
+ global vibesurf_agent, active_task, current_llm_profile_name
109
113
 
110
114
  try:
115
+ current_llm_profile_name = llm_profile_name
116
+
111
117
  # Check if MCP server configuration needs update
112
118
  await _check_and_update_mcp_servers(db_session)
113
119
 
@@ -314,7 +320,7 @@ async def _load_active_mcp_servers():
314
320
 
315
321
  async def initialize_vibesurf_components():
316
322
  """Initialize VibeSurf components from environment variables and default LLM profile"""
317
- global vibesurf_agent, browser_manager, vibesurf_tools, llm, db_manager
323
+ global vibesurf_agent, browser_manager, vibesurf_tools, llm, db_manager, current_llm_profile_name
318
324
  global workspace_dir, browser_execution_path, browser_user_data, envs
319
325
  from vibe_surf import common
320
326
 
@@ -463,7 +469,7 @@ async def initialize_vibesurf_components():
463
469
 
464
470
  async def _initialize_default_llm():
465
471
  """Initialize LLM from default profile or fallback to environment variables"""
466
- global db_manager
472
+ global db_manager, current_llm_profile_name
467
473
 
468
474
  try:
469
475
  # Try to get default LLM profile from database
@@ -482,6 +488,7 @@ async def _initialize_default_llm():
482
488
  )
483
489
  if profile_with_key:
484
490
  llm_instance = create_llm_from_profile(profile_with_key)
491
+ current_llm_profile_name = default_profile.profile_name
485
492
  logger.info(f"✅ LLM initialized from default profile: {default_profile.profile_name}")
486
493
  return llm_instance
487
494
  break
@@ -4,6 +4,15 @@ LLM Factory utilities for creating LLM instances from profiles
4
4
 
5
5
  from typing import Optional
6
6
  import logging
7
+ # Import LLM classes from browser_use and vibe_surf
8
+ from browser_use.llm import (
9
+ BaseChatModel,
10
+ ChatOpenAI, ChatAnthropic, ChatGoogle, ChatAzureOpenAI,
11
+ ChatGroq, ChatOllama, ChatOpenRouter, ChatDeepSeek,
12
+ ChatAWSBedrock, ChatAnthropicBedrock
13
+ )
14
+ from vibe_surf.llm import ChatOpenAICompatible
15
+
7
16
  from ..llm_config import get_supported_providers, is_provider_supported
8
17
 
9
18
  from vibe_surf.logger import get_logger
@@ -11,16 +20,9 @@ from vibe_surf.logger import get_logger
11
20
  logger = get_logger(__name__)
12
21
 
13
22
 
14
- def create_llm_from_profile(llm_profile):
23
+ def create_llm_from_profile(llm_profile) -> BaseChatModel:
15
24
  """Create LLM instance from LLMProfile database record (dict or object)"""
16
25
  try:
17
- # Import LLM classes from browser_use and vibe_surf
18
- from browser_use.llm import (
19
- ChatOpenAI, ChatAnthropic, ChatGoogle, ChatAzureOpenAI,
20
- ChatGroq, ChatOllama, ChatOpenRouter, ChatDeepSeek,
21
- ChatAWSBedrock, ChatAnthropicBedrock
22
- )
23
- from vibe_surf.llm import ChatOpenAICompatible
24
26
 
25
27
  # Handle both dict and object access patterns
26
28
  def get_attr(obj, key, default=None):
@@ -99,6 +99,12 @@ class VibeSurfAPIClient {
99
99
  if (error.status >= 400 && error.status < 500) {
100
100
  throw error; // Client errors shouldn't be retried
101
101
  }
102
+
103
+ // Don't retry on LLM connection failures
104
+ if (error.data && error.data.error === 'llm_connection_failed') {
105
+ console.log('[API] LLM connection failed - skipping retry');
106
+ throw error;
107
+ }
102
108
  }
103
109
 
104
110
  // Don't retry on timeout for the last attempt
@@ -61,20 +61,24 @@ class VibeSurfModalManager {
61
61
 
62
62
  const modalId = this.generateModalId();
63
63
 
64
+ // Add warning icon to title and always show cancel for warning modals
65
+ const warningTitle = `⚠️ ${title}`;
66
+ const shouldShowCancel = showCancel || true; // Always show cancel for warning modals
67
+
64
68
  const modalHTML = `
65
- <div class="modal-overlay" id="${modalId}-overlay">
69
+ <div class="modal-overlay dynamic-modal warning-modal" id="${modalId}-overlay">
66
70
  <div class="modal warning-modal ${className}" id="${modalId}">
67
- <div class="modal-header">
68
- <h3>${this.escapeHtml(title)}</h3>
69
- <button class="modal-close-btn" data-modal-id="${modalId}">×</button>
70
- </div>
71
- <div class="modal-body">
72
- <div class="warning-icon">⚠️</div>
73
- <p>${this.escapeHtml(message)}</p>
74
- </div>
75
- <div class="modal-footer">
76
- ${showCancel ? `<button class="btn-secondary modal-cancel-btn" data-modal-id="${modalId}">${this.escapeHtml(cancelText)}</button>` : ''}
77
- <button class="btn-primary modal-confirm-btn" data-modal-id="${modalId}">${this.escapeHtml(confirmText)}</button>
71
+ <div class="modal-content">
72
+ <div class="modal-header">
73
+ <h3>${this.escapeHtml(warningTitle)}</h3>
74
+ </div>
75
+ <div class="modal-body">
76
+ <p>${this.escapeHtml(message)}</p>
77
+ </div>
78
+ <div class="modal-footer">
79
+ ${shouldShowCancel ? `<button class="btn-secondary modal-cancel-btn" data-modal-id="${modalId}">${this.escapeHtml(cancelText)}</button>` : ''}
80
+ <button class="btn-primary modal-confirm-btn" data-modal-id="${modalId}">${this.escapeHtml(confirmText)}</button>
81
+ </div>
78
82
  </div>
79
83
  </div>
80
84
  </div>
@@ -121,20 +125,23 @@ class VibeSurfModalManager {
121
125
 
122
126
  const icon = iconMap[type] || iconMap.question;
123
127
 
128
+ // Add icon to title and remove close button
129
+ const iconTitle = `${icon} ${title}`;
130
+
124
131
  const modalHTML = `
125
- <div class="modal-overlay" id="${modalId}-overlay">
132
+ <div class="modal-overlay dynamic-modal" id="${modalId}-overlay">
126
133
  <div class="modal confirm-modal ${className}" id="${modalId}">
127
- <div class="modal-header">
128
- <h3>${this.escapeHtml(title)}</h3>
129
- <button class="modal-close-btn" data-modal-id="${modalId}">×</button>
130
- </div>
131
- <div class="modal-body">
132
- <div class="confirm-icon">${icon}</div>
133
- <p>${this.escapeHtml(message)}</p>
134
- </div>
135
- <div class="modal-footer">
136
- <button class="btn-secondary modal-cancel-btn" data-modal-id="${modalId}">${this.escapeHtml(cancelText)}</button>
137
- <button class="btn-primary modal-confirm-btn" data-modal-id="${modalId}" ${type === 'danger' ? 'data-danger="true"' : ''}>${this.escapeHtml(confirmText)}</button>
134
+ <div class="modal-content">
135
+ <div class="modal-header">
136
+ <h3>${this.escapeHtml(iconTitle)}</h3>
137
+ </div>
138
+ <div class="modal-body">
139
+ <p>${this.escapeHtml(message)}</p>
140
+ </div>
141
+ <div class="modal-footer">
142
+ <button class="btn-secondary modal-cancel-btn" data-modal-id="${modalId}">${this.escapeHtml(cancelText)}</button>
143
+ <button class="btn-primary modal-confirm-btn" data-modal-id="${modalId}" ${type === 'danger' ? 'data-danger="true"' : ''}>${this.escapeHtml(confirmText)}</button>
144
+ </div>
138
145
  </div>
139
146
  </div>
140
147
  </div>
@@ -174,16 +181,18 @@ class VibeSurfModalManager {
174
181
  const modalId = this.generateModalId();
175
182
 
176
183
  const modalHTML = `
177
- <div class="modal-overlay ${backdrop ? 'backdrop' : ''}" id="${modalId}-overlay">
184
+ <div class="modal-overlay dynamic-modal ${backdrop ? 'backdrop' : ''}" id="${modalId}-overlay">
178
185
  <div class="modal ${className}" id="${modalId}">
179
- ${title || showCloseButton ? `
180
- <div class="modal-header">
181
- ${title ? `<h3>${this.escapeHtml(title)}</h3>` : ''}
182
- ${showCloseButton ? `<button class="modal-close-btn" data-modal-id="${modalId}">×</button>` : ''}
186
+ <div class="modal-content">
187
+ ${title || showCloseButton ? `
188
+ <div class="modal-header">
189
+ ${title ? `<h3>${this.escapeHtml(title)}</h3>` : ''}
190
+ ${showCloseButton ? `<button class="modal-close-btn" data-modal-id="${modalId}">×</button>` : ''}
191
+ </div>
192
+ ` : ''}
193
+ <div class="modal-body">
194
+ ${content}
183
195
  </div>
184
- ` : ''}
185
- <div class="modal-body">
186
- ${content}
187
196
  </div>
188
197
  </div>
189
198
  </div>
@@ -221,6 +221,16 @@ class VibeSurfSessionManager {
221
221
 
222
222
  const response = await this.apiClient.submitTask(taskPayload);
223
223
 
224
+ // Check if the response indicates LLM connection failure
225
+ if (response && response.success === false && response.error === 'llm_connection_failed') {
226
+ console.log('[SessionManager] LLM connection failed, emitting taskError');
227
+ this.emit('taskError', {
228
+ error: response,
229
+ sessionId: this.currentSession.id
230
+ });
231
+ throw new Error(response.message || 'LLM connection failed');
232
+ }
233
+
224
234
  // Update current session with task info
225
235
  this.currentSession.currentTask = {
226
236
  taskId: response.task_id,
@@ -1206,6 +1206,38 @@ class VibeSurfSettingsManager {
1206
1206
  this.elements.backendUrl.value = url;
1207
1207
  }
1208
1208
  }
1209
+
1210
+ // Navigate to specific LLM profile for editing
1211
+ async navigateToLLMProfile(profileName) {
1212
+ console.log('[SettingsManager] Navigating to LLM profile:', profileName);
1213
+
1214
+ // First show the settings modal
1215
+ this.showSettings();
1216
+
1217
+ // Switch to LLM profiles tab
1218
+ const llmTab = document.querySelector('.settings-tab[data-tab="llm-profiles"]');
1219
+ if (llmTab) {
1220
+ llmTab.click(); // This will trigger handleTabSwitch
1221
+ }
1222
+
1223
+ // Wait a moment for tab switching to complete
1224
+ setTimeout(async () => {
1225
+ // Find the profile in the current state
1226
+ const profile = this.state.llmProfiles.find(p => p.profile_name === profileName);
1227
+
1228
+ if (profile) {
1229
+ // Show the edit form for this profile
1230
+ await this.showProfileForm('llm', profile);
1231
+ console.log('[SettingsManager] LLM profile edit form shown for:', profileName);
1232
+ } else {
1233
+ console.warn('[SettingsManager] Profile not found:', profileName);
1234
+ this.emit('notification', {
1235
+ message: `LLM profile "${profileName}" not found. Please check if it still exists.`,
1236
+ type: 'warning'
1237
+ });
1238
+ }
1239
+ }, 100);
1240
+ }
1209
1241
  }
1210
1242
 
1211
1243
  // Export for use in other modules