vibesurf 0.1.16__py3-none-any.whl → 0.1.17__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.

Potentially problematic release.


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

@@ -175,7 +175,8 @@ class VibeSurfAPIClient {
175
175
  task_description,
176
176
  llm_profile_name,
177
177
  upload_files_path,
178
- mcp_server_config
178
+ mcp_server_config,
179
+ agent_mode
179
180
  } = taskData;
180
181
 
181
182
  return this.post('/tasks/submit', {
@@ -183,7 +184,8 @@ class VibeSurfAPIClient {
183
184
  task_description,
184
185
  llm_profile_name,
185
186
  upload_files_path,
186
- mcp_server_config
187
+ mcp_server_config,
188
+ agent_mode
187
189
  });
188
190
  }
189
191
 
@@ -48,6 +48,7 @@ class VibeSurfUIManager {
48
48
 
49
49
  // Input area
50
50
  llmProfileSelect: document.getElementById('llm-profile-select'),
51
+ agentModeSelect: document.getElementById('agent-mode-select'),
51
52
  taskInput: document.getElementById('task-input'),
52
53
  sendBtn: document.getElementById('send-btn'),
53
54
 
@@ -236,6 +237,9 @@ class VibeSurfUIManager {
236
237
  // LLM profile selection handling
237
238
  this.elements.llmProfileSelect?.addEventListener('change', this.handleLlmProfileChange.bind(this));
238
239
 
240
+ // Agent mode selection handling
241
+ this.elements.agentModeSelect?.addEventListener('change', this.handleAgentModeChange.bind(this));
242
+
239
243
  // Initialize auto-resize for textarea
240
244
  if (this.elements.taskInput) {
241
245
  this.autoResizeTextarea(this.elements.taskInput);
@@ -461,6 +465,11 @@ class VibeSurfUIManager {
461
465
  this.elements.llmProfileSelect.disabled = isRunning && !isPaused;
462
466
  }
463
467
 
468
+ if (this.elements.agentModeSelect) {
469
+ // Allow agent mode change only when not running
470
+ this.elements.agentModeSelect.disabled = isRunning && !isPaused;
471
+ }
472
+
464
473
  // Update file manager state - keep disabled during pause (as per requirement)
465
474
  this.fileManager.setEnabled(!isRunning);
466
475
 
@@ -505,6 +514,11 @@ class VibeSurfUIManager {
505
514
  this.elements.llmProfileSelect.disabled = true;
506
515
  }
507
516
 
517
+ // Keep agent mode disabled during pause (user doesn't need to change it)
518
+ if (this.elements.agentModeSelect) {
519
+ this.elements.agentModeSelect.disabled = true;
520
+ }
521
+
508
522
  // Keep file manager disabled during pause
509
523
  this.fileManager.setEnabled(false);
510
524
 
@@ -541,6 +555,10 @@ class VibeSurfUIManager {
541
555
  this.elements.llmProfileSelect.disabled = true;
542
556
  }
543
557
 
558
+ if (this.elements.agentModeSelect) {
559
+ this.elements.agentModeSelect.disabled = true;
560
+ }
561
+
544
562
  // Update file manager state
545
563
  this.fileManager.setEnabled(false);
546
564
 
@@ -716,7 +734,8 @@ class VibeSurfUIManager {
716
734
 
717
735
  const taskData = {
718
736
  task_description: taskDescription,
719
- llm_profile_name: llmProfile
737
+ llm_profile_name: llmProfile,
738
+ agent_mode: this.elements.agentModeSelect?.value || 'thinking'
720
739
  };
721
740
 
722
741
  // Add uploaded files path if any
@@ -867,6 +886,13 @@ class VibeSurfUIManager {
867
886
  }
868
887
  }
869
888
 
889
+ handleAgentModeChange(event) {
890
+ // Re-validate send button state when agent mode changes
891
+ if (this.elements.taskInput) {
892
+ this.handleTaskInputChange({ target: this.elements.taskInput });
893
+ }
894
+ }
895
+
870
896
  handleTaskInputChange(event) {
871
897
  console.log('[UIManager] handleTaskInputChange called with value:', event.target.value);
872
898
 
@@ -173,6 +173,11 @@
173
173
  <div class="input-footer">
174
174
  <select id="llm-profile-select" class="llm-select compact">
175
175
  </select>
176
+ <select id="agent-mode-select" class="agent-mode-select compact">
177
+ <option value="thinking" selected>Thinking</option>
178
+ <option value="no-thinking">No-thinking</option>
179
+ <option value="flash">Flash</option>
180
+ </select>
176
181
  </div>
177
182
  </div>
178
183
  <input type="file" id="file-input" class="hidden" multiple accept="*/*">
@@ -123,7 +123,8 @@
123
123
  margin-top: calc(var(--spacing-xs) / 2);
124
124
  }
125
125
 
126
- .llm-select {
126
+ .llm-select,
127
+ .agent-mode-select {
127
128
  padding: var(--spacing-sm) var(--spacing-md);
128
129
  border: 1px solid var(--border-color);
129
130
  border-radius: var(--radius-md);
@@ -136,12 +137,19 @@
136
137
  }
137
138
 
138
139
  .llm-select.compact {
139
- max-width: 100px;
140
+ max-width: 140px;
140
141
  font-size: var(--font-size-xs);
141
142
  padding: var(--spacing-xs) var(--spacing-sm);
142
143
  }
143
144
 
144
- .llm-select:focus {
145
+ .agent-mode-select.compact {
146
+ max-width: 70px;
147
+ font-size: var(--font-size-xs);
148
+ padding: var(--spacing-xs) var(--spacing-sm);
149
+ }
150
+
151
+ .llm-select:focus,
152
+ .agent-mode-select:focus {
145
153
  outline: none;
146
154
  border-color: var(--primary-color);
147
155
  box-shadow: 0 0 0 3px rgba(0, 122, 204, 0.1);
@@ -226,7 +226,7 @@ class ChatOpenAICompatible(ChatOpenAI):
226
226
  if self._is_qwen_model() or self._is_kimi_model():
227
227
  self.add_schema_to_system_prompt = True
228
228
 
229
- if not (self._is_gemini_model() or self._is_kimi_model()) or output_format is None:
229
+ if not (self._is_gemini_model() or self._is_kimi_model() or self._is_qwen_model()) or output_format is None:
230
230
  return await super().ainvoke(messages, output_format)
231
231
  openai_messages = OpenAIMessageSerializer.serialize_messages(messages)
232
232
 
@@ -281,7 +281,6 @@ class ChatOpenAICompatible(ChatOpenAI):
281
281
  fixed_schema = self._fix_kimi_schema(original_schema)
282
282
  else:
283
283
  fixed_schema = original_schema
284
-
285
284
  response_format: JSONSchema = {
286
285
  'name': 'agent_output',
287
286
  'strict': True,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vibesurf
3
- Version: 0.1.16
3
+ Version: 0.1.17
4
4
  Summary: VibeSurf: A powerful browser assistant for vibe surfing
5
5
  Author: Shao Warm
6
6
  License: Apache-2.0
@@ -1,35 +1,34 @@
1
1
  vibe_surf/__init__.py,sha256=WtduuMFGauMD_9dpk4fnRnLTAP6ka9Lfu0feAFNzLfo,339
2
- vibe_surf/_version.py,sha256=Fs2Vm6Mr4ZbSKXw60jeeSx9iEU9elx4fQcMl_5xXMJI,706
2
+ vibe_surf/_version.py,sha256=TtVjjQ5FSnY_MX0ZAPLaNmAfTJWa0sEMBdMs65ngXMM,706
3
3
  vibe_surf/cli.py,sha256=pbep2dBeQqralZ8AggkH4h2nayBarbdN8lhZxo35gNU,16689
4
4
  vibe_surf/common.py,sha256=_WWMxen5wFwzUjEShn3yDVC1OBFUiJ6Vccadi6tuG6w,1215
5
5
  vibe_surf/logger.py,sha256=k53MFA96QX6t9OfcOf1Zws8PP0OOqjVJfhUD3Do9lKw,3043
6
6
  vibe_surf/agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- vibe_surf/agents/browser_use_agent.py,sha256=KR8pIsB7At-G89iifeA2TqFu9IeFCX_mstr5ZknwFE8,46257
8
- vibe_surf/agents/report_writer_agent.py,sha256=tKELps-FjZq06OKXpoyS-zJzvfdYXM6UnXDrR2oZk6M,20970
9
- vibe_surf/agents/vibe_surf_agent.py,sha256=-pC7MSOd7I21JbLN0yY69RNHRfTFt-STfA4j6jIyrS4,73191
10
- vibe_surf/agents/views.py,sha256=bcVOxd9On2lJ4NSar5RqP1V7Nw_RBtkHJPE-f2kVdRA,4750
7
+ vibe_surf/agents/browser_use_agent.py,sha256=qmm3TAVzEYjvOvSQEa5xUZOgpBOR_8qePME8BjLjOd0,45951
8
+ vibe_surf/agents/report_writer_agent.py,sha256=0RZHcrk6WoC7GE66QshrPLt6ka7GlRtnCsgjO7Dfxfw,20966
9
+ vibe_surf/agents/vibe_surf_agent.py,sha256=i7O4Djw3Pd1ijwbkGbXkQqO1y0RunlelCqajjfJFfaQ,73687
10
+ vibe_surf/agents/views.py,sha256=yHjNJloa-aofVTGyuRy08tBYP_Y3XLqt1DUWOUmHRng,4825
11
11
  vibe_surf/agents/prompts/__init__.py,sha256=l4ieA0D8kLJthyNN85FKLNe4ExBa3stY3l-aImLDRD0,36
12
12
  vibe_surf/agents/prompts/report_writer_prompt.py,sha256=sZE8MUT1CDLmRzbnbEQzAvTwJjpITgh2Q8g1_eXmkzE,4454
13
13
  vibe_surf/agents/prompts/vibe_surf_prompt.py,sha256=gn8Q234zwtUxVzduzmINmqV-iooE-aJ9u2-yXQ3Wo6M,5573
14
14
  vibe_surf/backend/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  vibe_surf/backend/llm_config.py,sha256=9V8Gg065TQALbOKQnOqFWd8RzOJjegOD8w6YOf90Q7Y,5036
16
16
  vibe_surf/backend/main.py,sha256=nZDs_FkYU7NdqSm1O4OwHJslYIJZL1Gr3CEKa8ByaEY,7178
17
- vibe_surf/backend/shared_state.py,sha256=yEBWj6YI6WjVF2nuJ_nujo8yqHw2j8xikmxr0G8fnbs,23331
17
+ vibe_surf/backend/shared_state.py,sha256=doZv5A6h2Qvq1hM5a3-vnU0Jc8AAlHwuM9WhVu5mFk4,23446
18
18
  vibe_surf/backend/api/__init__.py,sha256=XxF1jUOORpLYCfFuPrrnUGRnOrr6ClH0_MNPU-4RnSs,68
19
19
  vibe_surf/backend/api/activity.py,sha256=_cnHusqolt5Hf3KdAf6FK-3sBc-TSaadmb5dJxGI57A,9398
20
20
  vibe_surf/backend/api/browser.py,sha256=NXedyZG3NIVRIx5O7d9mHwVWX-Q4_KsX5mSgfKt8UEA,2122
21
21
  vibe_surf/backend/api/config.py,sha256=EwzxYvC6HlaVo2OFWjtBmBMjX4eW2q8hp7l2LO2GZV0,27124
22
22
  vibe_surf/backend/api/files.py,sha256=kJMG9MWECKXwGh64Q6xvAzNjeZGcLhIEnn65HiMZHKE,11762
23
- vibe_surf/backend/api/models.py,sha256=iyMBdpDkOfwx0h2yRkjmYjRdFyDErhO8XZcWTurdcmU,10347
24
- vibe_surf/backend/api/task.py,sha256=jf9y7T5SjgFdw1XxKrHvc7nMpM544-VmUTBBMF4Msgg,14263
23
+ vibe_surf/backend/api/models.py,sha256=n_bu8vavvO8bIKA1WUAbaGPFeZKeamMJelDWU3DlFJc,10533
24
+ vibe_surf/backend/api/task.py,sha256=vpQMOn6YBuD_16jzfUajUvBYaydC0jj8Ny3WOJDVuck,14359
25
25
  vibe_surf/backend/database/__init__.py,sha256=XhmcscnhgMhUyXML7m4SnuQIqkFpyY_zJ0D3yYa2RqQ,239
26
- vibe_surf/backend/database/manager.py,sha256=aC8XQc68qDsaryrux7VfCEl2hnEZL5kfnEkXWXPg2ig,4427
27
- vibe_surf/backend/database/models.py,sha256=mePuHsaSqJKA4TthvXbup_Ioann2_chxywiLKqAWyh4,7009
28
- vibe_surf/backend/database/queries.py,sha256=2ff9w7piY6ssIPgqnEM15qCX8gsZuUgmS00fwaZSEHQ,33638
26
+ vibe_surf/backend/database/manager.py,sha256=Okmr6yG2aycmatONRMyRbHe6l53RkFIPeMxxPSD3ycY,11884
27
+ vibe_surf/backend/database/models.py,sha256=AomcjHTcKfJUEI4m7wUobxnruGehwiz6CJJvvDJuQmU,7151
28
+ vibe_surf/backend/database/queries.py,sha256=WEXZBNHQ1LWWR4Bv-49LMs8mZOkapFBx2_vM1GGLoA8,33723
29
29
  vibe_surf/backend/database/schemas.py,sha256=OPnpRKwYG1Cu8geJ6pajiEDF8x8mRestXnAfI4Gy18w,3402
30
- vibe_surf/backend/migrations/__init__.py,sha256=dLhZwW6AGyfBSid-QJPCpIlS4DnYDvO8NyI4s8JAZB8,383
31
- vibe_surf/backend/migrations/init_db.py,sha256=pY2Yq7K1vPxqT8r3jlAQcYEQWK-GGbb0F7W5asGpuew,10399
32
- vibe_surf/backend/migrations/seed_data.py,sha256=L6Ll-u8P4cICAUlD5y9urQPSUld6M67erSBCEIdw8Uc,8239
30
+ vibe_surf/backend/database/migrations/v001_initial_schema.sql,sha256=MC2fa1WHUEhHhdOTxz0qB4RI7JdGRpiGXZ77ytl3LRQ,4345
31
+ vibe_surf/backend/database/migrations/v002_add_agent_mode.sql,sha256=jKnW28HsphUeU9kudEx9QaLnUh8swmmOt-hFsZJay24,251
33
32
  vibe_surf/backend/utils/__init__.py,sha256=V8leMFp7apAglUAoCHPZrNNcRHthSLYIudIJE5qwjb0,184
34
33
  vibe_surf/backend/utils/encryption.py,sha256=CjLNh_n0Luhfa-6BB-icfzkiiDqj5b4Gu6MADU3p2eM,3754
35
34
  vibe_surf/backend/utils/llm_factory.py,sha256=mNy8o3sw7vYJ8gwiTsrgXbG7Ri_B11ylE4KGcfHULp8,8972
@@ -47,12 +46,12 @@ vibe_surf/chrome_extension/content.js,sha256=q6JRpmHAEdPWNnFSIqoPv8eBm0T574c3H5h
47
46
  vibe_surf/chrome_extension/dev-reload.js,sha256=xQpi-1Ekb5P8Ogsm6rUK09QzxafwH0H409zBKmaUFNw,1790
48
47
  vibe_surf/chrome_extension/manifest.json,sha256=B08nHuU-bPc-pUr30Y-of39TjMlrE7D5gP2sZjZ8CrE,1142
49
48
  vibe_surf/chrome_extension/popup.html,sha256=n3dI_-WbILm0q8O_za6xX0WvOofz5lwT_7YXs0u9RAE,4248
50
- vibe_surf/chrome_extension/sidepanel.html,sha256=ams_TCA68787uVRnQ7J70b4rNzMEWzQsgVvSHoabouI,25942
49
+ vibe_surf/chrome_extension/sidepanel.html,sha256=v6FBuKsKIZ5Mvup44rzoJsKV9gBH1ypvr25nu3j2yBk,26268
51
50
  vibe_surf/chrome_extension/icons/convert-svg.js,sha256=j137nZA7MJK35NtrwWff8yb3UEKa5XTAvnV6EjY-CVI,953
52
51
  vibe_surf/chrome_extension/icons/logo-preview.html,sha256=hrgU45uziKHKIb8be9P4ZrZJyGggWnm2M5oEu89V5sM,6962
53
52
  vibe_surf/chrome_extension/icons/logo.icns,sha256=ZzY1eIKF4dNhNW4CeE1UBQloxNVC7bQx3qcClo3CnMQ,1569615
54
53
  vibe_surf/chrome_extension/icons/logo.png,sha256=PLmv1E6sCGXUE5ZDxr-pFPQd9Gvaw_f1TnYmF8VIssU,566385
55
- vibe_surf/chrome_extension/scripts/api-client.js,sha256=YUnMZOKUcJaGFl8wCpGxgCSvBKqbwCtYbQLbI32otrY,13844
54
+ vibe_surf/chrome_extension/scripts/api-client.js,sha256=5H5GU-NsO_V_sEP3JheKJ3ejjxiruKZlM5hoqAaRjFs,13880
56
55
  vibe_surf/chrome_extension/scripts/file-manager.js,sha256=WcEaeoECq84jXqEo3Q2ywmqppwSUVm-0dtrbTYXL07g,15809
57
56
  vibe_surf/chrome_extension/scripts/history-manager.js,sha256=J_EiBKrRp2cTxuy0Sq5oCju5YuX0_2pGG6NWrJSjC24,22218
58
57
  vibe_surf/chrome_extension/scripts/main.js,sha256=WhmCGktQoSl7aaMl8a9ysJJiysAjf12bWGypMucCSVg,16913
@@ -60,13 +59,13 @@ vibe_surf/chrome_extension/scripts/markdown-it.min.js,sha256=gZ3xe0BdCJplNiHWTKr
60
59
  vibe_surf/chrome_extension/scripts/modal-manager.js,sha256=9ekFaTmy8sk94KK9HZJ7739ObsZ6ssllmRLP9rQxUKU,14187
61
60
  vibe_surf/chrome_extension/scripts/session-manager.js,sha256=sXh4j4dv3eKOGYeov8iUPt-DX5jKQLhcASDXRX9qW5Y,21126
62
61
  vibe_surf/chrome_extension/scripts/settings-manager.js,sha256=rgstYooxZtV9QjqP8KRRQclHbeiZJozZZfv80A6M_P4,48601
63
- vibe_surf/chrome_extension/scripts/ui-manager.js,sha256=_qMrS_3_jZn7lDlXkTlF4CwOZxdg3B3Enww95PaGsHA,81526
62
+ vibe_surf/chrome_extension/scripts/ui-manager.js,sha256=nFwe1vb9S74wD4Z3QreyMn21DuKMBKOMH3BwpvP-jfY,82488
64
63
  vibe_surf/chrome_extension/styles/activity.css,sha256=aEFa_abskrDQvwsesPVOyJW3rUQUEBQpMKPHhY94CoA,19601
65
64
  vibe_surf/chrome_extension/styles/animations.css,sha256=TLAet_xXBxCA-H36BWP4xBGBIVjbDdAj7Q6OPxPsbE8,7891
66
65
  vibe_surf/chrome_extension/styles/base.css,sha256=d8nt7Wej1r57G6pnBIGKEVkepFxlq8Ets0isngCf5w8,1296
67
66
  vibe_surf/chrome_extension/styles/components.css,sha256=cbpYgT1ujG11axRa9xnHizgm4wfrpSzq_nkUOdfNZ0A,18495
68
67
  vibe_surf/chrome_extension/styles/history-modal.css,sha256=xCg0EPz1N4kg47jnz9q9E1M4zGag8lJMt_msAOkZi3M,16583
69
- vibe_surf/chrome_extension/styles/input.css,sha256=Sn2QulNV4jS2NJRByp7RVyZtCJbexw48AjLxgpB-XRw,10566
68
+ vibe_surf/chrome_extension/styles/input.css,sha256=7gmWfXbm3CHPEPHtzwSwAtGeNGJtzrect7yYy57rnEo,10745
70
69
  vibe_surf/chrome_extension/styles/layout.css,sha256=ggh-lWpP6sHubFkshf9dcmA52LiXw7VJmQXcM5_EGcY,3528
71
70
  vibe_surf/chrome_extension/styles/responsive.css,sha256=a_SFX-PeOcenG4xMeoru5XFnnXdf0YhEyRzvTVVZHdI,8529
72
71
  vibe_surf/chrome_extension/styles/settings-environment.css,sha256=OzgezmfZZ_yD60Jy9Uiq83mDmMCfk2dPPcZISb9Eqd4,3390
@@ -77,7 +76,7 @@ vibe_surf/chrome_extension/styles/settings-responsive.css,sha256=jLE0yG15n2aI6_6
77
76
  vibe_surf/chrome_extension/styles/settings-utilities.css,sha256=3PuQS2857kg83d5erLbLdo_7J95-qV-qyNWS5M-w1oQ,505
78
77
  vibe_surf/chrome_extension/styles/variables.css,sha256=VbFJ8L76AaJUqb6gCz9jEG_V6OX4YJa65I2iyeNJIw4,1411
79
78
  vibe_surf/llm/__init__.py,sha256=_vDVPo6STf343p1SgMQrF5023hicAx0g83pK2Gbk4Ek,601
80
- vibe_surf/llm/openai_compatible.py,sha256=rdJTGXW-68yTho1hgzhkjMAocQOK0p_GSl8PmAx_C8Y,14974
79
+ vibe_surf/llm/openai_compatible.py,sha256=8v0LW_-ZoKv4gcO--6_SmU_BLF8XCJaiPxZ6kXFgM4I,14998
81
80
  vibe_surf/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
82
81
  vibe_surf/tools/browser_use_tools.py,sha256=gWiBj-YPz7kQYi0yekuvpPQ2Z2-EBLuutF6rf71iOcM,28781
83
82
  vibe_surf/tools/file_system.py,sha256=gVdTd6qUfoyVfZMzmX9DXTyBbfXY56jVhUqtfm1qqps,18878
@@ -85,9 +84,9 @@ vibe_surf/tools/mcp_client.py,sha256=OeCoTgyx4MoY7JxXndK6pGHIoyFOhf5r7XCbx25y1Ec
85
84
  vibe_surf/tools/report_writer_tools.py,sha256=sUqUFr-_Rs8RJ0Bs77Hrp07kNwRIvHv7ErzSPYSlbTg,705
86
85
  vibe_surf/tools/vibesurf_tools.py,sha256=VVhM2IZOXwpGvJ3v9jTXFHmxTxF2jAzhrwqFqxFVuX4,29976
87
86
  vibe_surf/tools/views.py,sha256=aPoabrXOCrn5vPCAauMKYvpyP9n0qC2xKn1IbjAGXwE,4218
88
- vibesurf-0.1.16.dist-info/licenses/LICENSE,sha256=czn6QYya0-jhLnStD9JqnMS-hwP5wRByipkrGTvoXLI,11355
89
- vibesurf-0.1.16.dist-info/METADATA,sha256=lq6wvtdIl2SyYNtSM82YP71H_53NhRMBWBt5yqDN2PA,5313
90
- vibesurf-0.1.16.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
91
- vibesurf-0.1.16.dist-info/entry_points.txt,sha256=UxqpvMocL-PR33S6vLF2OmXn-kVzM-DneMeZeHcPMM8,48
92
- vibesurf-0.1.16.dist-info/top_level.txt,sha256=VPZGHqSb6EEqcJ4ZX6bHIuWfon5f6HXl3c7BYpbRqnY,10
93
- vibesurf-0.1.16.dist-info/RECORD,,
87
+ vibesurf-0.1.17.dist-info/licenses/LICENSE,sha256=czn6QYya0-jhLnStD9JqnMS-hwP5wRByipkrGTvoXLI,11355
88
+ vibesurf-0.1.17.dist-info/METADATA,sha256=G79taMncHYGcyU0aq8EM1UF3EbZy41Lwc9C4G_-0D-U,5313
89
+ vibesurf-0.1.17.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
90
+ vibesurf-0.1.17.dist-info/entry_points.txt,sha256=UxqpvMocL-PR33S6vLF2OmXn-kVzM-DneMeZeHcPMM8,48
91
+ vibesurf-0.1.17.dist-info/top_level.txt,sha256=VPZGHqSb6EEqcJ4ZX6bHIuWfon5f6HXl3c7BYpbRqnY,10
92
+ vibesurf-0.1.17.dist-info/RECORD,,
@@ -1,16 +0,0 @@
1
- """
2
- Database Migration Scripts for VibeSurf Backend
3
-
4
- Contains migration scripts for database schema initialization and updates.
5
- """
6
-
7
- from .init_db import init_database, create_tables, drop_tables
8
- from .seed_data import seed_initial_data, create_sample_data
9
-
10
- __all__ = [
11
- "init_database",
12
- "create_tables",
13
- "drop_tables",
14
- "seed_initial_data",
15
- "create_sample_data"
16
- ]
@@ -1,303 +0,0 @@
1
- """
2
- Database Initialization and Migration Scripts - Simplified
3
-
4
- Handles database schema creation for Task, LLMProfile, and UploadedFile tables.
5
- """
6
-
7
- import asyncio
8
- from typing import Optional
9
- from sqlalchemy.ext.asyncio import AsyncEngine, create_async_engine
10
- from sqlalchemy import text
11
- from sqlalchemy.exc import SQLAlchemyError
12
-
13
- from ..database.models import Base
14
-
15
- async def init_database(database_url: str = "sqlite+aiosqlite:///./vibe_surf.db") -> bool:
16
- """
17
- Initialize the database with Task, LLMProfile, and UploadedFile tables and indexes.
18
-
19
- Args:
20
- database_url: Database connection URL
21
-
22
- Returns:
23
- bool: True if initialization was successful
24
- """
25
- try:
26
- # Create async engine
27
- engine = create_async_engine(
28
- database_url,
29
- echo=False,
30
- future=True,
31
- pool_pre_ping=True
32
- )
33
-
34
- # Create all tables
35
- success = await create_tables(engine)
36
-
37
- if success:
38
- print("✅ Database initialized successfully")
39
- print(f"📍 Database URL: {database_url}")
40
-
41
- # Print table information
42
- await print_table_info(engine)
43
- else:
44
- print("❌ Database initialization failed")
45
-
46
- await engine.dispose()
47
- return success
48
-
49
- except Exception as e:
50
- print(f"❌ Database initialization error: {e}")
51
- return False
52
-
53
- async def create_tables(engine: AsyncEngine) -> bool:
54
- """
55
- Create all tables (Task, LLMProfile, UploadedFile) and indexes.
56
-
57
- Args:
58
- engine: SQLAlchemy async engine
59
-
60
- Returns:
61
- bool: True if creation was successful
62
- """
63
- try:
64
- async with engine.begin() as conn:
65
- # Create all tables (Task, LLMProfile, UploadedFile)
66
- await conn.run_sync(Base.metadata.create_all)
67
-
68
- # Create additional indexes for performance
69
- await create_performance_indexes(conn)
70
-
71
- print("✅ Database tables created successfully")
72
- return True
73
-
74
- except SQLAlchemyError as e:
75
- print(f"❌ Error creating tables: {e}")
76
- return False
77
-
78
- async def drop_tables(engine: AsyncEngine) -> bool:
79
- """
80
- Drop all database tables (use with caution).
81
-
82
- Args:
83
- engine: SQLAlchemy async engine
84
-
85
- Returns:
86
- bool: True if drop was successful
87
- """
88
- try:
89
- async with engine.begin() as conn:
90
- await conn.run_sync(Base.metadata.drop_all)
91
-
92
- print("✅ Database tables dropped successfully")
93
- return True
94
-
95
- except SQLAlchemyError as e:
96
- print(f"❌ Error dropping tables: {e}")
97
- return False
98
-
99
- async def create_performance_indexes(conn):
100
- """
101
- Create additional performance indexes for all tables.
102
-
103
- Args:
104
- conn: Database connection
105
- """
106
- # Performance indexes for all tables
107
- indexes = [
108
- # Tasks - for session task tracking
109
- "CREATE INDEX IF NOT EXISTS idx_tasks_session_status ON tasks(session_id, status)",
110
- "CREATE INDEX IF NOT EXISTS idx_tasks_session_created ON tasks(session_id, created_at DESC)",
111
- "CREATE INDEX IF NOT EXISTS idx_tasks_status_created ON tasks(status, created_at DESC)",
112
- "CREATE INDEX IF NOT EXISTS idx_tasks_completed ON tasks(completed_at DESC)",
113
-
114
- # LLMProfile - for profile lookups
115
- "CREATE INDEX IF NOT EXISTS idx_llm_profiles_name ON llm_profiles(profile_name)",
116
- "CREATE INDEX IF NOT EXISTS idx_llm_profiles_provider ON llm_profiles(provider)",
117
- "CREATE INDEX IF NOT EXISTS idx_llm_profiles_created ON llm_profiles(created_at DESC)",
118
-
119
- # UploadedFile - for file management
120
- "CREATE INDEX IF NOT EXISTS idx_uploaded_files_session ON uploaded_files(session_id)",
121
- "CREATE INDEX IF NOT EXISTS idx_uploaded_files_session_active ON uploaded_files(session_id, is_deleted)",
122
- "CREATE INDEX IF NOT EXISTS idx_uploaded_files_upload_time ON uploaded_files(upload_time DESC)",
123
- "CREATE INDEX IF NOT EXISTS idx_uploaded_files_deleted ON uploaded_files(is_deleted, deleted_at)",
124
- "CREATE INDEX IF NOT EXISTS idx_uploaded_files_filename ON uploaded_files(original_filename)",
125
- ]
126
-
127
- for index_sql in indexes:
128
- try:
129
- await conn.execute(text(index_sql))
130
- print(f"✅ Created index: {index_sql.split('idx_')[1].split(' ')[0]}")
131
- except Exception as e:
132
- print(f"⚠️ Index creation warning: {e}")
133
-
134
- async def print_table_info(engine: AsyncEngine):
135
- """
136
- Print information about created tables.
137
-
138
- Args:
139
- engine: SQLAlchemy async engine
140
- """
141
- try:
142
- async with engine.connect() as conn:
143
- # Get table list
144
- if "sqlite" in str(engine.url):
145
- result = await conn.execute(text("SELECT name FROM sqlite_master WHERE type='table'"))
146
- else:
147
- result = await conn.execute(text("SELECT tablename FROM pg_tables WHERE schemaname='public'"))
148
-
149
- tables = [row[0] for row in result]
150
-
151
- print(f"\n📊 Created {len(tables)} tables:")
152
- for table in sorted(tables):
153
- if not table.startswith('sqlite_'): # Skip SQLite system tables
154
- print(f" • {table}")
155
-
156
- # Get approximate row counts (for SQLite)
157
- if "sqlite" in str(engine.url):
158
- print(f"\n📈 Table sizes:")
159
- for table in sorted(tables):
160
- if not table.startswith('sqlite_'):
161
- try:
162
- count_result = await conn.execute(text(f"SELECT COUNT(*) FROM {table}"))
163
- count = count_result.scalar()
164
- print(f" • {table}: {count} rows")
165
- except Exception:
166
- print(f" • {table}: - rows")
167
-
168
- except Exception as e:
169
- print(f"⚠️ Could not retrieve table information: {e}")
170
-
171
- async def verify_database_schema(database_url: str = "sqlite+aiosqlite:///./vibe_surf.db") -> bool:
172
- """
173
- Verify that the database schema is correctly set up.
174
-
175
- Args:
176
- database_url: Database connection URL
177
-
178
- Returns:
179
- bool: True if schema is valid
180
- """
181
- try:
182
- engine = create_async_engine(database_url, echo=False)
183
-
184
- # Expected tables (Task, LLMProfile, UploadedFile)
185
- expected_tables = ['tasks', 'llm_profiles', 'uploaded_files']
186
-
187
- async with engine.connect() as conn:
188
- # Check if all expected tables exist
189
- if "sqlite" in str(engine.url):
190
- result = await conn.execute(text("SELECT name FROM sqlite_master WHERE type='table'"))
191
- else:
192
- result = await conn.execute(text("SELECT tablename FROM pg_tables WHERE schemaname='public'"))
193
-
194
- existing_tables = {row[0] for row in result}
195
- missing_tables = set(expected_tables) - existing_tables
196
-
197
- if missing_tables:
198
- print(f"❌ Missing tables: {missing_tables}")
199
- await engine.dispose()
200
- return False
201
-
202
- # Test basic operations
203
- await conn.execute(text("SELECT 1"))
204
-
205
- await engine.dispose()
206
- print("✅ Database schema verification passed")
207
- return True
208
-
209
- except Exception as e:
210
- print(f"❌ Database schema verification failed: {e}")
211
- return False
212
-
213
- async def reset_database(database_url: str = "sqlite+aiosqlite:///./vibe_surf.db") -> bool:
214
- """
215
- Reset the database by dropping and recreating all tables.
216
-
217
- Args:
218
- database_url: Database connection URL
219
-
220
- Returns:
221
- bool: True if reset was successful
222
- """
223
- try:
224
- engine = create_async_engine(database_url, echo=False)
225
-
226
- print("🔄 Resetting database...")
227
-
228
- # Drop all tables
229
- if not await drop_tables(engine):
230
- await engine.dispose()
231
- return False
232
-
233
- # Recreate all tables
234
- if not await create_tables(engine):
235
- await engine.dispose()
236
- return False
237
-
238
- await engine.dispose()
239
- print("✅ Database reset completed successfully")
240
- return True
241
-
242
- except Exception as e:
243
- print(f"❌ Database reset failed: {e}")
244
- return False
245
-
246
- async def migrate_database(database_url: str = "sqlite+aiosqlite:///./vibe_surf.db") -> bool:
247
- """
248
- Apply database migrations and updates.
249
-
250
- Args:
251
- database_url: Database connection URL
252
-
253
- Returns:
254
- bool: True if migration was successful
255
- """
256
- try:
257
- engine = create_async_engine(database_url, echo=False)
258
-
259
- print("🔄 Running database migrations...")
260
-
261
- # For now, this is equivalent to create_tables
262
- # In the future, this could handle schema updates
263
- success = await create_tables(engine)
264
-
265
- await engine.dispose()
266
-
267
- if success:
268
- print("✅ Database migrations completed successfully")
269
- else:
270
- print("❌ Database migrations failed")
271
-
272
- return success
273
-
274
- except Exception as e:
275
- print(f"❌ Database migration failed: {e}")
276
- return False
277
-
278
- # CLI functions for direct usage
279
- async def main():
280
- """Main function for running migrations from command line."""
281
- import sys
282
-
283
- if len(sys.argv) < 2:
284
- print("Usage: python -m backend.migrations.init_db [init|reset|verify|migrate]")
285
- return
286
-
287
- command = sys.argv[1]
288
- database_url = sys.argv[2] if len(sys.argv) > 2 else "sqlite+aiosqlite:///./vibe_surf.db"
289
-
290
- if command == "init":
291
- await init_database(database_url)
292
- elif command == "reset":
293
- await reset_database(database_url)
294
- elif command == "verify":
295
- await verify_database_schema(database_url)
296
- elif command == "migrate":
297
- await migrate_database(database_url)
298
- else:
299
- print(f"Unknown command: {command}")
300
- print("Available commands: init, reset, verify, migrate")
301
-
302
- if __name__ == "__main__":
303
- asyncio.run(main())