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

vibe_surf/_version.py CHANGED
@@ -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.5'
32
- __version_tuple__ = version_tuple = (0, 1, 5)
31
+ __version__ = version = '0.1.6'
32
+ __version_tuple__ = version_tuple = (0, 1, 6)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -47,7 +47,6 @@ class TodoItem(BaseModel):
47
47
  class ExecutionMode(BaseModel):
48
48
  """Execution mode configuration"""
49
49
  mode: Literal["single", "parallel"] = "single"
50
- max_parallel_agents: int = 5
51
50
  reason: str = Field(description="LLM reasoning for mode selection")
52
51
 
53
52
 
@@ -229,14 +228,12 @@ def parse_execution_planning_response(response_text: str) -> ExecutionMode:
229
228
  """Parse execution planning JSON response"""
230
229
  fallback = {
231
230
  "execution_mode": "single",
232
- "max_parallel_agents": 3,
233
231
  "reasoning": "Default single mode"
234
232
  }
235
233
  result = parse_json_response(response_text, fallback)
236
234
 
237
235
  return ExecutionMode(
238
236
  mode=result.get("execution_mode", "single"),
239
- max_parallel_agents=result.get("max_parallel_agents", 3),
240
237
  reason=result.get("reasoning", "Default execution mode")
241
238
  )
242
239
 
@@ -558,7 +555,6 @@ async def _supervisor_agent_node_impl(state: VibeSurfState) -> VibeSurfState:
558
555
 
559
556
  state.execution_mode = ExecutionMode(
560
557
  mode=task_type,
561
- max_parallel_agents=5 if task_type == "parallel" else 1,
562
558
  reason=reasoning
563
559
  )
564
560
  state.pending_tasks = tasks_to_execute_new
@@ -755,7 +751,7 @@ async def execute_parallel_browser_tasks(state: VibeSurfState) -> List[BrowserTa
755
751
 
756
752
  # Register agents with browser manager
757
753
  agents = []
758
- pending_tasks = state.pending_tasks[:state.execution_mode.max_parallel_agents]
754
+ pending_tasks = state.pending_tasks
759
755
  bu_agent_ids = []
760
756
  register_sessions = []
761
757
  for i, task in enumerate(pending_tasks):
@@ -801,7 +797,8 @@ async def execute_parallel_browser_tasks(state: VibeSurfState) -> List[BrowserTa
801
797
  task_id=f"{state.task_id}-{i + 1}",
802
798
  file_system_path=state.task_dir,
803
799
  register_new_step_callback=step_callback,
804
- extend_system_message="Please make sure the language of your output in JSON value should remain the same as the user's request or task."
800
+ extend_system_message="Please make sure the language of your output in JSON value should remain the same as the user's request or task.",
801
+ preload=False
805
802
  )
806
803
  agents.append(agent)
807
804
 
@@ -899,6 +896,7 @@ async def execute_single_browser_tasks(state: VibeSurfState) -> List[BrowserTask
899
896
  task_id=f"{state.task_id}-{i}",
900
897
  file_system_path=state.task_dir,
901
898
  register_new_step_callback=step_callback,
899
+ preload=False,
902
900
  extend_system_message="Please make sure the language of your output in JSON values should remain the same as the user's request or task."
903
901
  )
904
902
 
@@ -1586,9 +1584,6 @@ class VibeSurfAgent:
1586
1584
  agent_activity_logs.append(activity_entry)
1587
1585
  return f"# Task Execution Failed\n\n**Task:** {task}\n\n**Error:** {str(e)}\n\nPlease try again or contact support."
1588
1586
  finally:
1589
- # Reset state
1590
- self.save_message_history()
1591
- self.save_activity_logs()
1592
1587
  if agent_activity_logs:
1593
1588
  activity_entry = {
1594
1589
  "agent_name": "VibeSurfAgent",
@@ -1596,6 +1591,9 @@ class VibeSurfAgent:
1596
1591
  "agent_msg": "Finish Task."
1597
1592
  }
1598
1593
  agent_activity_logs.append(activity_entry)
1594
+ # Reset state
1595
+ self.save_message_history()
1596
+ self.save_activity_logs()
1599
1597
  async with self._control_lock:
1600
1598
  self._current_state = None
1601
1599
  self._execution_task = None
@@ -43,21 +43,21 @@ def create_llm_from_profile(llm_profile):
43
43
 
44
44
  # Define provider-specific parameter support
45
45
  provider_param_support = {
46
- "openai": ["temperature", "top_p", "frequency_penalty", "seed"],
47
- "anthropic": ["temperature", "top_p"],
48
- "google": ["temperature", "top_p"],
49
- "azure_openai": ["temperature", "top_p", "frequency_penalty", "seed"],
50
- "groq": ["temperature", "top_p"],
51
- "ollama": ["temperature"],
52
- "openrouter": ["temperature", "top_p"], # OpenRouter doesn't support max_tokens
53
- "deepseek": ["temperature", "top_p"],
46
+ "openai": ["temperature"],
47
+ "anthropic": ["temperature"],
48
+ "google": ["temperature"],
49
+ "azure_openai": ["temperature"],
50
+ "groq": ["temperature"],
51
+ "ollama": [],
52
+ "openrouter": ["temperature"], # OpenRouter doesn't support max_tokens
53
+ "deepseek": ["temperature"],
54
54
  "aws_bedrock": ["temperature"],
55
55
  "anthropic_bedrock": ["temperature"],
56
- "openai_compatible": ["temperature", "top_p", "frequency_penalty", "seed"]
56
+ "openai_compatible": ["temperature"]
57
57
  }
58
58
 
59
59
  # Build common parameters based on provider support
60
- supported_params = provider_param_support.get(provider, ["temperature", "top_p", "frequency_penalty", "seed"])
60
+ supported_params = provider_param_support.get(provider, [])
61
61
  common_params = {}
62
62
 
63
63
  if temperature is not None and "temperature" in supported_params:
@@ -200,12 +200,16 @@ class VibeSurfSessionManager {
200
200
  throw new Error('No active session. Please create a session first.');
201
201
  }
202
202
 
203
- const taskPayload = {
204
- session_id: this.currentSession.id,
205
- ...taskData
206
- };
207
-
208
203
  try {
204
+ // ✅ 改进:提交新任务前先同步session的所有activity logs
205
+ console.log('[SessionManager] 🔄 Syncing activity logs before task submission...');
206
+ await this.syncActivityLogsFromServer();
207
+
208
+ const taskPayload = {
209
+ session_id: this.currentSession.id,
210
+ ...taskData
211
+ };
212
+
209
213
  const response = await this.apiClient.submitTask(taskPayload);
210
214
 
211
215
  // Update current session with task info
@@ -353,8 +357,7 @@ class VibeSurfSessionManager {
353
357
  // Check both possible response formats
354
358
  const activityLog = response?.activity_log || response?.data?.activity_log;
355
359
  const totalAvailable = response?.total_available || response?.data?.total_available;
356
-
357
- // ✅ 关键逻辑:只有当获取到新log且与上一个不同时才处理
360
+
358
361
  if (response && activityLog) {
359
362
  const prevActivityLog = this.activityLogs.length > 0 ? this.activityLogs[this.activityLogs.length - 1] : null;
360
363
 
@@ -371,8 +374,8 @@ class VibeSurfSessionManager {
371
374
  }
372
375
 
373
376
  this.activityLogs.push(newLog);
374
-
375
- console.log(`[SessionManager] ✅ New unique activity received: ${newLog.agent_name} - ${newLog.agent_status}`);
377
+
378
+ console.log(`[SessionManager] ✅ New activity received: ${newLog.agent_name} - ${newLog.agent_status}`);
376
379
 
377
380
  await this.handleActivityUpdate(newLog);
378
381
 
@@ -383,8 +386,7 @@ class VibeSurfSessionManager {
383
386
  });
384
387
 
385
388
  // Check if task is completed or terminated
386
- const terminalStatuses = ['done', 'completed', 'finished', 'error', 'failed',
387
- 'terminated', 'stopped', 'cancelled', 'aborted'];
389
+ const terminalStatuses = ['done'];
388
390
 
389
391
  if (terminalStatuses.includes(newLog.agent_status?.toLowerCase())) {
390
392
  this.stopActivityPolling();
@@ -430,7 +432,6 @@ class VibeSurfSessionManager {
430
432
  }
431
433
  }
432
434
 
433
- // ✅ 新增:比较两个activity log是否相等的辅助方法
434
435
  areLogsEqual(log1, log2) {
435
436
  if (!log1 || !log2) return false;
436
437
 
@@ -477,6 +478,47 @@ class VibeSurfSessionManager {
477
478
  }
478
479
  }
479
480
 
481
+ async syncActivityLogsFromServer() {
482
+ if (!this.currentSession) return;
483
+
484
+ try {
485
+ console.log(`[SessionManager] 🔄 Syncing all activity logs from server for session: ${this.currentSession.id}`);
486
+
487
+ // Get all activity logs from server
488
+ const response = await this.apiClient.getSessionActivity(this.currentSession.id);
489
+
490
+ // Check both possible response formats
491
+ const serverLogs = response?.activity_logs || response?.data?.activity_logs || [];
492
+
493
+ if (Array.isArray(serverLogs)) {
494
+ // 完全同步:用服务器端的logs替换本地logs
495
+ const previousCount = this.activityLogs.length;
496
+
497
+ // 添加timestamp给没有的logs
498
+ const processedLogs = serverLogs.map(log => ({
499
+ ...log,
500
+ timestamp: log.timestamp || new Date().toISOString()
501
+ }));
502
+
503
+ this.activityLogs = processedLogs;
504
+
505
+ console.log(`[SessionManager] ✅ Activity logs synced: ${previousCount} -> ${this.activityLogs.length} logs`);
506
+
507
+ // 触发日志加载事件,让UI更新
508
+ this.emit('activityLogsLoaded', {
509
+ sessionId: this.currentSession.id,
510
+ logs: this.activityLogs
511
+ });
512
+ } else {
513
+ console.log(`[SessionManager] 📝 No activity logs found on server for session: ${this.currentSession.id}`);
514
+ this.activityLogs = [];
515
+ }
516
+ } catch (error) {
517
+ console.error(`[SessionManager] ❌ Failed to sync activity logs from server:`, error);
518
+ // 不抛出错误,允许任务提交继续进行
519
+ }
520
+ }
521
+
480
522
  async handleActivityUpdate(activityLog) {
481
523
  // Update current task status based on activity
482
524
  if (this.currentSession?.currentTask && activityLog.agent_status) {
@@ -543,7 +543,25 @@ class VibeSurfUIManager {
543
543
  handleTaskError(data) {
544
544
  console.error('[UIManager] Task error:', data.error);
545
545
  this.showNotification(`Task error: ${data.error}`, 'error');
546
- this.updateControlPanel('ready');
546
+
547
+ // ✅ FIXED: Keep control panel visible during errors
548
+ // Don't assume task stopped - it might still be running server-side
549
+ this.updateControlPanel('error');
550
+
551
+ // Optional: Verify task status after a delay
552
+ setTimeout(() => {
553
+ this.checkTaskStatus().then(status => {
554
+ if (!status.isRunning) {
555
+ console.log('[UIManager] Task confirmed stopped after error, hiding controls');
556
+ this.updateControlPanel('ready');
557
+ } else {
558
+ console.log('[UIManager] Task still running after error, keeping controls visible');
559
+ }
560
+ }).catch(err => {
561
+ console.warn('[UIManager] Could not verify task status after error:', err);
562
+ // If we can't verify, keep controls visible for safety
563
+ });
564
+ }, 2000);
547
565
  }
548
566
 
549
567
  // Task Status Monitoring
@@ -2413,11 +2431,13 @@ class VibeSurfUIManager {
2413
2431
  case 'ready':
2414
2432
  console.log('[UIManager] Setting control panel to ready (hidden)');
2415
2433
  panel.classList.add('hidden');
2434
+ panel.classList.remove('error-state');
2416
2435
  break;
2417
2436
 
2418
2437
  case 'running':
2419
2438
  console.log('[UIManager] Setting control panel to running (showing cancel button)');
2420
2439
  panel.classList.remove('hidden');
2440
+ panel.classList.remove('error-state');
2421
2441
  cancelBtn?.classList.remove('hidden');
2422
2442
  resumeBtn?.classList.add('hidden');
2423
2443
  terminateBtn?.classList.add('hidden');
@@ -2429,14 +2449,25 @@ class VibeSurfUIManager {
2429
2449
  case 'paused':
2430
2450
  console.log('[UIManager] Setting control panel to paused (showing resume/terminate buttons)');
2431
2451
  panel.classList.remove('hidden');
2452
+ panel.classList.remove('error-state');
2432
2453
  cancelBtn?.classList.add('hidden');
2433
2454
  resumeBtn?.classList.remove('hidden');
2434
2455
  terminateBtn?.classList.remove('hidden');
2435
2456
  break;
2436
2457
 
2458
+ case 'error':
2459
+ console.log('[UIManager] Setting control panel to error (keeping cancel/terminate buttons visible)');
2460
+ panel.classList.remove('hidden');
2461
+ panel.classList.add('error-state');
2462
+ cancelBtn?.classList.remove('hidden');
2463
+ resumeBtn?.classList.add('hidden');
2464
+ terminateBtn?.classList.remove('hidden');
2465
+ break;
2466
+
2437
2467
  default:
2438
2468
  console.log(`[UIManager] Unknown control panel status: ${status}, hiding panel`);
2439
2469
  panel.classList.add('hidden');
2470
+ panel.classList.remove('error-state');
2440
2471
  }
2441
2472
  }
2442
2473
 
@@ -417,6 +417,37 @@ body {
417
417
  background-color: rgba(220, 53, 69, 0.1);
418
418
  }
419
419
 
420
+ /* Control Panel Error State */
421
+ .control-panel.error-state {
422
+ background-color: rgba(220, 53, 69, 0.05);
423
+ border-left: 4px solid var(--danger-color);
424
+ border-color: rgba(220, 53, 69, 0.2);
425
+ box-shadow: 0 2px 8px rgba(220, 53, 69, 0.1);
426
+ }
427
+
428
+ .control-panel.error-state::before {
429
+ content: '⚠️ Error occurred - task controls remain available';
430
+ display: block;
431
+ font-size: var(--font-size-xs);
432
+ color: var(--danger-color);
433
+ margin-bottom: var(--spacing-sm);
434
+ padding: var(--spacing-xs) var(--spacing-sm);
435
+ background-color: rgba(220, 53, 69, 0.1);
436
+ border-radius: var(--radius-sm);
437
+ border: 1px solid rgba(220, 53, 69, 0.2);
438
+ font-weight: var(--font-weight-medium);
439
+ }
440
+
441
+ .control-panel.error-state .control-btn {
442
+ border-color: rgba(220, 53, 69, 0.3);
443
+ background-color: rgba(255, 255, 255, 0.9);
444
+ }
445
+
446
+ .control-panel.error-state .control-btn:hover {
447
+ background-color: var(--bg-primary);
448
+ box-shadow: 0 2px 4px rgba(220, 53, 69, 0.2);
449
+ }
450
+
420
451
  /* Input Section */
421
452
  .input-section {
422
453
  background-color: var(--bg-primary);
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vibesurf
3
- Version: 0.1.5
3
+ Version: 0.1.6
4
4
  Summary: VibeSurf: A powerful browser assistant for vibe surfing
5
5
  Author: Shao Warm
6
6
  License: Apache-2.0
@@ -1,10 +1,10 @@
1
1
  vibe_surf/__init__.py,sha256=WtduuMFGauMD_9dpk4fnRnLTAP6ka9Lfu0feAFNzLfo,339
2
- vibe_surf/_version.py,sha256=rdxBMYpwzYxiWk08QbPLHSAxHoDfeKWwyaJIAM0lSic,704
2
+ vibe_surf/_version.py,sha256=riGXiVTWXmtdoju9hVCWvTxpszEMAAIK0sZZWoLKlnU,704
3
3
  vibe_surf/cli.py,sha256=2VqPZMqgFMsB9siE-16adeeCaO6RUSc2KzoIH3ZiAjQ,16912
4
4
  vibe_surf/agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  vibe_surf/agents/browser_use_agent.py,sha256=NSSdZ9lnjtv_RyfR5Ay2rMnzJRJ-67S8Q3ytGAguiB0,50266
6
6
  vibe_surf/agents/report_writer_agent.py,sha256=E5mSirewzH4Oyv385-Nn2Mf1Ug3OCVBz99PoTbvKRfQ,13860
7
- vibe_surf/agents/vibe_surf_agent.py,sha256=EiWa58QPfE8w9RnoT8ibYKQAecl9RbEbiaARFyPPBoo,70616
7
+ vibe_surf/agents/vibe_surf_agent.py,sha256=Gryoob2or2E0jhkUqutiIKw-RDJBKu5Fc5KXKtB9NiQ,70425
8
8
  vibe_surf/agents/prompts/__init__.py,sha256=l4ieA0D8kLJthyNN85FKLNe4ExBa3stY3l-aImLDRD0,36
9
9
  vibe_surf/agents/prompts/vibe_surf_prompt.py,sha256=u-6KgLSnBbQohS5kiLZDcZ3aoT90ScVONXi9gNvdMoo,11006
10
10
  vibe_surf/backend/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -27,7 +27,7 @@ vibe_surf/backend/migrations/init_db.py,sha256=pY2Yq7K1vPxqT8r3jlAQcYEQWK-GGbb0F
27
27
  vibe_surf/backend/migrations/seed_data.py,sha256=L6Ll-u8P4cICAUlD5y9urQPSUld6M67erSBCEIdw8Uc,8239
28
28
  vibe_surf/backend/utils/__init__.py,sha256=V8leMFp7apAglUAoCHPZrNNcRHthSLYIudIJE5qwjb0,184
29
29
  vibe_surf/backend/utils/encryption.py,sha256=ppDRRsNX8pu9Or9yADcLS8KJUTm-edrSb-nZqVThNI0,4802
30
- vibe_surf/backend/utils/llm_factory.py,sha256=qxEQWSvio17d3mMWlrIB1x-RjWv7gLE08N5cSLjA-PY,9395
30
+ vibe_surf/backend/utils/llm_factory.py,sha256=4oHaKpizqA069dcXm0iK5G1SS-fhhOY5l6cM3SCFmwE,9172
31
31
  vibe_surf/browser/__init__.py,sha256=_UToO2fZfSCrfjOcxhn4Qq7ZLbYeyPuUUEmqIva-Yv8,325
32
32
  vibe_surf/browser/agen_browser_profile.py,sha256=TPH2H7Og4OxDUnjNn1nNeIJ621H4Gws5c8jkFbvZoz0,5644
33
33
  vibe_surf/browser/agent_browser_session.py,sha256=-o24Y0BfjPBURuQDfKlCTpOHntjx8QxqxeKxgBxs0WY,19551
@@ -49,11 +49,11 @@ vibe_surf/chrome_extension/icons/logo.png,sha256=wN3iMMGtLsURA70HABtj_3jiTk9aENA
49
49
  vibe_surf/chrome_extension/scripts/api-client.js,sha256=XwKmH4lP5eAkBqAM8EcQezI0gcMZK8l0RQ3ESEamcn8,13318
50
50
  vibe_surf/chrome_extension/scripts/main.js,sha256=WhmCGktQoSl7aaMl8a9ysJJiysAjf12bWGypMucCSVg,16913
51
51
  vibe_surf/chrome_extension/scripts/markdown-it.min.js,sha256=gZ3xe0BdCJplNiHWTKrm6AGZydPy34jJKZqFIf-7hIw,102948
52
- vibe_surf/chrome_extension/scripts/session-manager.js,sha256=MZHOgj4aucNP8c51xXKjXATxlyh1ODEky9BXIYuphvA,18070
53
- vibe_surf/chrome_extension/scripts/ui-manager.js,sha256=kq9PpyZWhDSdnzlhUryNrW4QTHoNYgm39KExTdGhU5k,141125
52
+ vibe_surf/chrome_extension/scripts/session-manager.js,sha256=VZNz887QHcfXaCD1EhCaK_YxaVRDXk8cMyQzAUsoYBw,19583
53
+ vibe_surf/chrome_extension/scripts/ui-manager.js,sha256=OB3whsiysgVbB_jMDc_xdLHRqm87dfO_KZYHY04hxK0,142440
54
54
  vibe_surf/chrome_extension/styles/animations.css,sha256=TLAet_xXBxCA-H36BWP4xBGBIVjbDdAj7Q6OPxPsbE8,7891
55
55
  vibe_surf/chrome_extension/styles/components.css,sha256=7K6khbJcONVAArfeS4qmPBUJxvGGs20-eEw62bD_7VI,14741
56
- vibe_surf/chrome_extension/styles/main.css,sha256=4KLqHoX8CV3sUuK_GGouiB8CN3p07iukcSbZkCMFKR8,47267
56
+ vibe_surf/chrome_extension/styles/main.css,sha256=Z5cIBkE6zJTQ2wvyhWXEqIubsMiwvnZib1p1-GARdeI,48219
57
57
  vibe_surf/chrome_extension/styles/settings.css,sha256=oKyLUiRsxW92f9VNkYwGkn7TNaXvjG0NPY2sxtYz5vo,20464
58
58
  vibe_surf/controller/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
59
  vibe_surf/controller/file_system.py,sha256=a2fXCzAhaC41qvV_bMLi9c50FmcFYjQ0nszSdKOdDrI,2637
@@ -62,9 +62,9 @@ vibe_surf/controller/vibesurf_controller.py,sha256=UWz8SvOAHr9KG8tn4nTciZvt3JkxY
62
62
  vibe_surf/controller/views.py,sha256=BaPlvcHTy5h-Lfr0OSgR_t6ynitgzNQF4-VUJJt8Hi0,1072
63
63
  vibe_surf/llm/__init__.py,sha256=_vDVPo6STf343p1SgMQrF5023hicAx0g83pK2Gbk4Ek,601
64
64
  vibe_surf/llm/openai_compatible.py,sha256=oY32VZF4oDS6ZG0h1WGtqAlWzdlximlJVTw8e8p5Zrg,10175
65
- vibesurf-0.1.5.dist-info/licenses/LICENSE,sha256=czn6QYya0-jhLnStD9JqnMS-hwP5wRByipkrGTvoXLI,11355
66
- vibesurf-0.1.5.dist-info/METADATA,sha256=II0EPpYw63rX35ubQwFdn5yz9CfTqoXxr3KsoCC6K70,3851
67
- vibesurf-0.1.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
68
- vibesurf-0.1.5.dist-info/entry_points.txt,sha256=UxqpvMocL-PR33S6vLF2OmXn-kVzM-DneMeZeHcPMM8,48
69
- vibesurf-0.1.5.dist-info/top_level.txt,sha256=VPZGHqSb6EEqcJ4ZX6bHIuWfon5f6HXl3c7BYpbRqnY,10
70
- vibesurf-0.1.5.dist-info/RECORD,,
65
+ vibesurf-0.1.6.dist-info/licenses/LICENSE,sha256=czn6QYya0-jhLnStD9JqnMS-hwP5wRByipkrGTvoXLI,11355
66
+ vibesurf-0.1.6.dist-info/METADATA,sha256=DOmjF0Grk_xlnXuHAqWq25D4EcTSQ_XMOclXsMDTdtc,3851
67
+ vibesurf-0.1.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
68
+ vibesurf-0.1.6.dist-info/entry_points.txt,sha256=UxqpvMocL-PR33S6vLF2OmXn-kVzM-DneMeZeHcPMM8,48
69
+ vibesurf-0.1.6.dist-info/top_level.txt,sha256=VPZGHqSb6EEqcJ4ZX6bHIuWfon5f6HXl3c7BYpbRqnY,10
70
+ vibesurf-0.1.6.dist-info/RECORD,,