mirror of
https://github.com/different-ai/openwork
synced 2026-04-25 17:15:34 +02:00
feat(desktop): default to control-chrome executable without npx (#534)
This commit is contained in:
@@ -24,7 +24,7 @@ description: Guide users through browser automation setup using Chrome DevTools
|
||||
4. If DevTools MCP calls fail:
|
||||
- Ask the user to open Chrome and keep it running.
|
||||
- Retry `chrome-devtools_list_pages`.
|
||||
- If it still fails, ensure `opencode.jsonc` includes `mcp.chrome-devtools` with command `['npx','-y','chrome-devtools-mcp@latest']` and ask the user to restart OpenWork/OpenCode.
|
||||
- If it still fails, ensure `opencode.jsonc` includes `mcp.control-chrome` with command `['chrome-devtools-mcp']` and ask the user to restart OpenWork/OpenCode.
|
||||
- Retry the DevTools MCP check.
|
||||
5. If DevTools MCP is ready:
|
||||
- Offer a first task ("Let's try opening a webpage").
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"mcp": {
|
||||
"chrome-devtools": {
|
||||
"control-chrome": {
|
||||
"type": "local",
|
||||
"command": [
|
||||
"npx",
|
||||
"-y",
|
||||
"chrome-devtools-mcp@latest"
|
||||
"chrome-devtools-mcp"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -75,10 +75,10 @@ export const MCP_QUICK_CONNECT: McpDirectoryInfo[] = [
|
||||
oauth: false,
|
||||
},
|
||||
{
|
||||
name: "Chrome DevTools",
|
||||
name: "Control Chrome",
|
||||
description: "Drive Chrome tabs with browser automation.",
|
||||
type: "local",
|
||||
command: ["npx", "-y", "chrome-devtools-mcp@latest"],
|
||||
command: ["chrome-devtools-mcp"],
|
||||
oauth: false,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
use std::path::Path;
|
||||
|
||||
use tauri::async_runtime::Receiver;
|
||||
use tauri::AppHandle;
|
||||
use tauri::{AppHandle, Manager};
|
||||
use tauri_plugin_shell::process::{CommandChild, CommandEvent};
|
||||
use tauri_plugin_shell::ShellExt;
|
||||
|
||||
use crate::paths::{candidate_xdg_config_dirs, candidate_xdg_data_dirs, maybe_infer_xdg_home};
|
||||
use crate::paths::{prepended_path_env, sidecar_path_candidates};
|
||||
|
||||
pub fn find_free_port() -> Result<u16, String> {
|
||||
let listener = std::net::TcpListener::bind(("127.0.0.1", 0)).map_err(|e| e.to_string())?;
|
||||
@@ -77,6 +78,16 @@ pub fn spawn_engine(
|
||||
command = command.env("OPENCODE_CLIENT", "openwork");
|
||||
command = command.env("OPENWORK", "1");
|
||||
|
||||
let resource_dir = app.path().resource_dir().ok();
|
||||
let current_bin_dir = tauri::process::current_binary(&app.env())
|
||||
.ok()
|
||||
.and_then(|path| path.parent().map(|parent| parent.to_path_buf()));
|
||||
let sidecar_paths =
|
||||
sidecar_path_candidates(resource_dir.as_deref(), current_bin_dir.as_deref());
|
||||
if let Some(path_env) = prepended_path_env(&sidecar_paths) {
|
||||
command = command.env("PATH", path_env);
|
||||
}
|
||||
|
||||
if let Some(username) = opencode_username {
|
||||
if !username.trim().is_empty() {
|
||||
command = command.env("OPENCODE_SERVER_USERNAME", username);
|
||||
|
||||
@@ -4,11 +4,12 @@ use std::path::{Path, PathBuf};
|
||||
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tauri::AppHandle;
|
||||
use tauri::{AppHandle, Manager};
|
||||
use tauri_plugin_shell::process::{CommandChild, CommandEvent};
|
||||
use tauri_plugin_shell::ShellExt;
|
||||
|
||||
use crate::paths::home_dir;
|
||||
use crate::paths::{prepended_path_env, sidecar_path_candidates};
|
||||
use crate::types::{
|
||||
OpenwrkBinaryState, OpenwrkDaemonState, OpenwrkOpencodeState, OpenwrkSidecarInfo,
|
||||
OpenwrkStatus, OpenwrkWorkspace,
|
||||
@@ -237,8 +238,19 @@ pub fn spawn_openwrk_daemon(
|
||||
}
|
||||
}
|
||||
|
||||
let mut command = command.args(args);
|
||||
|
||||
let resource_dir = app.path().resource_dir().ok();
|
||||
let current_bin_dir = tauri::process::current_binary(&app.env())
|
||||
.ok()
|
||||
.and_then(|path| path.parent().map(|parent| parent.to_path_buf()));
|
||||
let sidecar_paths =
|
||||
sidecar_path_candidates(resource_dir.as_deref(), current_bin_dir.as_deref());
|
||||
if let Some(path_env) = prepended_path_env(&sidecar_paths) {
|
||||
command = command.env("PATH", path_env);
|
||||
}
|
||||
|
||||
command
|
||||
.args(args)
|
||||
.spawn()
|
||||
.map_err(|e| format!("Failed to start openwrk: {e}"))
|
||||
}
|
||||
|
||||
@@ -90,3 +90,57 @@ pub fn resolve_in_path(name: &str) -> Option<PathBuf> {
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn sidecar_path_candidates(
|
||||
resource_dir: Option<&Path>,
|
||||
current_bin_dir: Option<&Path>,
|
||||
) -> Vec<PathBuf> {
|
||||
let mut candidates = Vec::new();
|
||||
|
||||
if let Some(current_bin_dir) = current_bin_dir {
|
||||
candidates.push(current_bin_dir.to_path_buf());
|
||||
}
|
||||
|
||||
if let Some(resource_dir) = resource_dir {
|
||||
candidates.push(resource_dir.join("sidecars"));
|
||||
candidates.push(resource_dir.to_path_buf());
|
||||
}
|
||||
|
||||
candidates.push(PathBuf::from("src-tauri/sidecars"));
|
||||
|
||||
let mut unique = Vec::new();
|
||||
for candidate in candidates {
|
||||
if !candidate.is_dir() {
|
||||
continue;
|
||||
}
|
||||
if unique
|
||||
.iter()
|
||||
.any(|existing: &PathBuf| existing == &candidate)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
unique.push(candidate);
|
||||
}
|
||||
|
||||
unique
|
||||
}
|
||||
|
||||
pub fn prepended_path_env(prefixes: &[PathBuf]) -> Option<std::ffi::OsString> {
|
||||
let mut entries = Vec::<PathBuf>::new();
|
||||
|
||||
for prefix in prefixes {
|
||||
if prefix.is_dir() {
|
||||
entries.push(prefix.clone());
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(existing) = env::var_os("PATH") {
|
||||
entries.extend(env::split_paths(&existing));
|
||||
}
|
||||
|
||||
if entries.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
env::join_paths(entries).ok()
|
||||
}
|
||||
|
||||
@@ -460,12 +460,12 @@ pub fn ensure_workspace_files(workspace_path: &str, preset: &str) -> Result<(),
|
||||
_ => serde_json::Map::new(),
|
||||
};
|
||||
|
||||
if !mcp_obj.contains_key("chrome-devtools") {
|
||||
if !mcp_obj.contains_key("control-chrome") {
|
||||
mcp_obj.insert(
|
||||
"chrome-devtools".to_string(),
|
||||
"control-chrome".to_string(),
|
||||
serde_json::json!({
|
||||
"type": "local",
|
||||
"command": ["npx", "-y", "chrome-devtools-mcp@latest"]
|
||||
"command": ["chrome-devtools-mcp"]
|
||||
}),
|
||||
);
|
||||
config_changed = true;
|
||||
|
||||
Reference in New Issue
Block a user