vibesurf 0.1.4__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 +2 -2
- vibe_surf/agents/report_writer_agent.py +16 -0
- vibe_surf/agents/vibe_surf_agent.py +23 -9
- vibe_surf/backend/utils/llm_factory.py +10 -10
- vibe_surf/chrome_extension/scripts/session-manager.js +54 -12
- vibe_surf/chrome_extension/scripts/ui-manager.js +32 -1
- vibe_surf/chrome_extension/styles/main.css +31 -0
- vibe_surf/cli.py +68 -3
- {vibesurf-0.1.4.dist-info → vibesurf-0.1.6.dist-info}/METADATA +1 -1
- {vibesurf-0.1.4.dist-info → vibesurf-0.1.6.dist-info}/RECORD +14 -14
- {vibesurf-0.1.4.dist-info → vibesurf-0.1.6.dist-info}/WHEEL +0 -0
- {vibesurf-0.1.4.dist-info → vibesurf-0.1.6.dist-info}/entry_points.txt +0 -0
- {vibesurf-0.1.4.dist-info → vibesurf-0.1.6.dist-info}/licenses/LICENSE +0 -0
- {vibesurf-0.1.4.dist-info → vibesurf-0.1.6.dist-info}/top_level.txt +0 -0
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.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 1,
|
|
31
|
+
__version__ = version = '0.1.6'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 1, 6)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -91,6 +91,14 @@ class ReportWriterAgent:
|
|
|
91
91
|
)
|
|
92
92
|
|
|
93
93
|
response = await self.llm.ainvoke([UserMessage(content=content_prompt)])
|
|
94
|
+
logger.debug(f"Content generation response type: {type(response)}")
|
|
95
|
+
logger.debug(f"Content generation completion: {response.completion}")
|
|
96
|
+
logger.debug(f"Content generation completion type: {type(response.completion)}")
|
|
97
|
+
|
|
98
|
+
if response.completion is None:
|
|
99
|
+
logger.error("❌ Content generation returned None completion")
|
|
100
|
+
raise ValueError("LLM response completion is None - unable to generate report content")
|
|
101
|
+
|
|
94
102
|
return response.completion
|
|
95
103
|
|
|
96
104
|
async def _format_as_html(self, content: str) -> str:
|
|
@@ -98,6 +106,14 @@ class ReportWriterAgent:
|
|
|
98
106
|
format_prompt = REPORT_FORMAT_PROMPT.format(report_content=content)
|
|
99
107
|
|
|
100
108
|
response = await self.llm.ainvoke([UserMessage(content=format_prompt)])
|
|
109
|
+
logger.debug(f"Format generation response type: {type(response)}")
|
|
110
|
+
logger.debug(f"Format generation completion: {response.completion}")
|
|
111
|
+
logger.debug(f"Format generation completion type: {type(response.completion)}")
|
|
112
|
+
|
|
113
|
+
if response.completion is None:
|
|
114
|
+
logger.error("❌ Format generation returned None completion")
|
|
115
|
+
raise ValueError("LLM response completion is None - unable to format report as HTML")
|
|
116
|
+
|
|
101
117
|
html_content = response.completion
|
|
102
118
|
|
|
103
119
|
# Clean up the HTML content if needed
|
|
@@ -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
|
|
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
|
|
|
@@ -1565,14 +1563,27 @@ class VibeSurfAgent:
|
|
|
1565
1563
|
|
|
1566
1564
|
except asyncio.CancelledError:
|
|
1567
1565
|
logger.info("🛑 VibeSurfAgent execution was cancelled")
|
|
1566
|
+
# Add cancellation activity log
|
|
1567
|
+
if agent_activity_logs:
|
|
1568
|
+
activity_entry = {
|
|
1569
|
+
"agent_name": "VibeSurfAgent",
|
|
1570
|
+
"agent_status": "cancelled",
|
|
1571
|
+
"agent_msg": "Task execution was cancelled by user request."
|
|
1572
|
+
}
|
|
1573
|
+
agent_activity_logs.append(activity_entry)
|
|
1568
1574
|
return f"# Task Execution Cancelled\n\n**Task:** {task}\n\nExecution was stopped by user request."
|
|
1569
1575
|
except Exception as e:
|
|
1570
1576
|
logger.error(f"❌ VibeSurfAgent execution failed: {e}")
|
|
1577
|
+
# Add error activity log
|
|
1578
|
+
if agent_activity_logs:
|
|
1579
|
+
activity_entry = {
|
|
1580
|
+
"agent_name": "VibeSurfAgent",
|
|
1581
|
+
"agent_status": "error",
|
|
1582
|
+
"agent_msg": f"Task execution failed: {str(e)}"
|
|
1583
|
+
}
|
|
1584
|
+
agent_activity_logs.append(activity_entry)
|
|
1571
1585
|
return f"# Task Execution Failed\n\n**Task:** {task}\n\n**Error:** {str(e)}\n\nPlease try again or contact support."
|
|
1572
1586
|
finally:
|
|
1573
|
-
# Reset state
|
|
1574
|
-
self.save_message_history()
|
|
1575
|
-
self.save_activity_logs()
|
|
1576
1587
|
if agent_activity_logs:
|
|
1577
1588
|
activity_entry = {
|
|
1578
1589
|
"agent_name": "VibeSurfAgent",
|
|
@@ -1580,6 +1591,9 @@ class VibeSurfAgent:
|
|
|
1580
1591
|
"agent_msg": "Finish Task."
|
|
1581
1592
|
}
|
|
1582
1593
|
agent_activity_logs.append(activity_entry)
|
|
1594
|
+
# Reset state
|
|
1595
|
+
self.save_message_history()
|
|
1596
|
+
self.save_activity_logs()
|
|
1583
1597
|
async with self._control_lock:
|
|
1584
1598
|
self._current_state = None
|
|
1585
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"
|
|
47
|
-
"anthropic": ["temperature"
|
|
48
|
-
"google": ["temperature"
|
|
49
|
-
"azure_openai": ["temperature"
|
|
50
|
-
"groq": ["temperature"
|
|
51
|
-
"ollama": [
|
|
52
|
-
"openrouter": ["temperature"
|
|
53
|
-
"deepseek": ["temperature"
|
|
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"
|
|
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, [
|
|
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
|
|
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'
|
|
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
|
-
|
|
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);
|
vibe_surf/cli.py
CHANGED
|
@@ -7,6 +7,7 @@ A command-line interface for VibeSurf browser automation tool.
|
|
|
7
7
|
import os
|
|
8
8
|
import sys
|
|
9
9
|
import glob
|
|
10
|
+
import json
|
|
10
11
|
import socket
|
|
11
12
|
import platform
|
|
12
13
|
import importlib.util
|
|
@@ -35,6 +36,17 @@ VIBESURF_LOGO = """
|
|
|
35
36
|
|
|
36
37
|
console = Console()
|
|
37
38
|
|
|
39
|
+
# Add logger import for the workspace directory logging
|
|
40
|
+
try:
|
|
41
|
+
import logging
|
|
42
|
+
logger = logging.getLogger(__name__)
|
|
43
|
+
logging.basicConfig(level=logging.INFO)
|
|
44
|
+
except ImportError:
|
|
45
|
+
class SimpleLogger:
|
|
46
|
+
def info(self, msg):
|
|
47
|
+
console.print(f"[dim]{msg}[/dim]")
|
|
48
|
+
logger = SimpleLogger()
|
|
49
|
+
|
|
38
50
|
|
|
39
51
|
def find_chrome_browser() -> Optional[str]:
|
|
40
52
|
"""Find Chrome browser executable."""
|
|
@@ -322,6 +334,55 @@ def start_backend(port: int) -> None:
|
|
|
322
334
|
sys.exit(1)
|
|
323
335
|
|
|
324
336
|
|
|
337
|
+
def get_browser_execution_path() -> Optional[str]:
|
|
338
|
+
"""Get browser execution path from envs.json or environment variables."""
|
|
339
|
+
# 1. Load environment variables
|
|
340
|
+
env_workspace_dir = os.getenv("VIBESURF_WORKSPACE", "")
|
|
341
|
+
if not env_workspace_dir or not env_workspace_dir.strip():
|
|
342
|
+
# Set default workspace directory based on OS
|
|
343
|
+
if platform.system() == "Windows":
|
|
344
|
+
default_workspace = os.path.join(os.environ.get("APPDATA", ""), "VibeSurf")
|
|
345
|
+
elif platform.system() == "Darwin": # macOS
|
|
346
|
+
default_workspace = os.path.join(os.path.expanduser("~"), "Library", "Application Support", "VibeSurf")
|
|
347
|
+
else: # Linux and others
|
|
348
|
+
default_workspace = os.path.join(os.path.expanduser("~"), ".vibesurf")
|
|
349
|
+
workspace_dir = default_workspace
|
|
350
|
+
else:
|
|
351
|
+
workspace_dir = env_workspace_dir
|
|
352
|
+
workspace_dir = os.path.abspath(workspace_dir)
|
|
353
|
+
os.makedirs(workspace_dir, exist_ok=True)
|
|
354
|
+
logger.info("WorkSpace directory: {}".format(workspace_dir))
|
|
355
|
+
|
|
356
|
+
# Load environment configuration from envs.json
|
|
357
|
+
envs_file_path = os.path.join(workspace_dir, "envs.json")
|
|
358
|
+
browser_path_from_envs = None
|
|
359
|
+
try:
|
|
360
|
+
if os.path.exists(envs_file_path):
|
|
361
|
+
with open(envs_file_path, 'r', encoding='utf-8') as f:
|
|
362
|
+
envs = json.load(f)
|
|
363
|
+
browser_path_from_envs = envs.get("BROWSER_EXECUTION_PATH", "")
|
|
364
|
+
if browser_path_from_envs:
|
|
365
|
+
browser_path_from_envs = browser_path_from_envs.strip()
|
|
366
|
+
except (json.JSONDecodeError, IOError) as e:
|
|
367
|
+
logger.info(f"Failed to load envs.json: {e}")
|
|
368
|
+
browser_path_from_envs = None
|
|
369
|
+
|
|
370
|
+
# 2. Get BROWSER_EXECUTION_PATH from environment variables
|
|
371
|
+
browser_path_from_env = os.getenv("BROWSER_EXECUTION_PATH", "")
|
|
372
|
+
if browser_path_from_env:
|
|
373
|
+
browser_path_from_env = browser_path_from_env.strip()
|
|
374
|
+
|
|
375
|
+
# Check paths in priority order: 1. envs.json -> 2. environment variables
|
|
376
|
+
for source, path in [("envs.json", browser_path_from_envs), ("environment variable", browser_path_from_env)]:
|
|
377
|
+
if path and os.path.exists(path) and os.path.isfile(path):
|
|
378
|
+
console.print(f"[green]✅ Using browser path from {source}: {path}[/green]")
|
|
379
|
+
return path
|
|
380
|
+
elif path:
|
|
381
|
+
console.print(f"[yellow]⚠️ Browser path from {source} exists but file not found: {path}[/yellow]")
|
|
382
|
+
|
|
383
|
+
return None
|
|
384
|
+
|
|
385
|
+
|
|
325
386
|
def main():
|
|
326
387
|
"""Main CLI entry point."""
|
|
327
388
|
try:
|
|
@@ -329,10 +390,14 @@ def main():
|
|
|
329
390
|
console.print(Panel(VIBESURF_LOGO, title="[bold cyan]VibeSurf CLI[/bold cyan]", border_style="cyan"))
|
|
330
391
|
console.print("[dim]A powerful browser automation tool for vibe surfing 🏄♂️[/dim]\n")
|
|
331
392
|
|
|
332
|
-
#
|
|
333
|
-
browser_path =
|
|
393
|
+
# Check for existing browser path from configuration
|
|
394
|
+
browser_path = get_browser_execution_path()
|
|
395
|
+
|
|
396
|
+
# If no valid browser path found, ask user to select
|
|
334
397
|
if not browser_path:
|
|
335
|
-
|
|
398
|
+
browser_path = select_browser()
|
|
399
|
+
if not browser_path:
|
|
400
|
+
return
|
|
336
401
|
|
|
337
402
|
# Port configuration
|
|
338
403
|
port = configure_port()
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
vibe_surf/__init__.py,sha256=WtduuMFGauMD_9dpk4fnRnLTAP6ka9Lfu0feAFNzLfo,339
|
|
2
|
-
vibe_surf/_version.py,sha256=
|
|
3
|
-
vibe_surf/cli.py,sha256=
|
|
2
|
+
vibe_surf/_version.py,sha256=riGXiVTWXmtdoju9hVCWvTxpszEMAAIK0sZZWoLKlnU,704
|
|
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
|
-
vibe_surf/agents/report_writer_agent.py,sha256=
|
|
7
|
-
vibe_surf/agents/vibe_surf_agent.py,sha256=
|
|
6
|
+
vibe_surf/agents/report_writer_agent.py,sha256=E5mSirewzH4Oyv385-Nn2Mf1Ug3OCVBz99PoTbvKRfQ,13860
|
|
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=
|
|
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=
|
|
53
|
-
vibe_surf/chrome_extension/scripts/ui-manager.js,sha256=
|
|
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=
|
|
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.
|
|
66
|
-
vibesurf-0.1.
|
|
67
|
-
vibesurf-0.1.
|
|
68
|
-
vibesurf-0.1.
|
|
69
|
-
vibesurf-0.1.
|
|
70
|
-
vibesurf-0.1.
|
|
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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|