feat(ai): add Codex CLI as a no-API-key AI provider for Desktop

* codex cli provider

* fixes

* mcp check

* reasoning

* simplify

* minor fixes
This commit is contained in:
Oleksandr Liakhevych authored and GitHub committed 2026-06-19 08:51:10 +08:00
1 parent 93a6a65707
commit 4f5d09aaa8
22 files changed
+1401 -101

No files matched your search

+13 -1
View File
@@ -44,6 +44,7 @@ pub async fn ai_stream(app: AppHandle, session_id: String, request: AiCompletion
use dbx_core::agent_events::AgentEvent;
use dbx_core::agent_loop::{run_agent_loop, AgentLoopContext};
use dbx_core::ai_cli_agent::CliAgentCommandSpec;
use dbx_core::models::connection::DatabaseType;
#[tauri::command]
@@ -68,7 +69,18 @@ pub async fn ai_agent_stream(
let parsed_db_type: DatabaseType =
serde_json::from_str(&format!("\"{}\"", db_type)).map_err(|_| format!("Unknown database type: {db_type}"))?;
let agent_ctx = AgentLoopContext { state: state.inner().clone(), connection_id, database, db_type: parsed_db_type };
let cli_mcp_server_command = if matches!(request.config.provider, AiProvider::CodexCli) {
super::mcp::resolve_mcp_server_command().map(|(program, args)| CliAgentCommandSpec { program, args })
} else {
None
};
let agent_ctx = AgentLoopContext {
state: state.inner().clone(),
connection_id,
database,
db_type: parsed_db_type,
cli_mcp_server_command,
};
let is_agent_mode = mode.as_deref() == Some("agent");
let result = run_agent_loop(
+12
View File
@@ -114,6 +114,12 @@ fn installed_mcp_version() -> Option<String> {
value.get("version")?.as_str().map(ToOwned::to_owned)
}
pub(crate) fn resolve_mcp_server_command() -> Option<(String, Vec<String>)> {
locate_mcp_bin()
.map(|path| (path, Vec::new()))
.or_else(|| installed_mcp_bin_script().map(|script| ("node".to_string(), vec![script])))
}
fn locate_mcp_bin() -> Option<String> {
#[cfg(windows)]
{
@@ -125,6 +131,12 @@ fn locate_mcp_bin() -> Option<String> {
}
}
fn installed_mcp_bin_script() -> Option<String> {
let root = command_stdout("npm", &["root", "-g"]).ok()?;
let script = Path::new(root.trim()).join(MCP_PACKAGE_NAME).join("dist").join("index.js");
script.is_file().then(|| script.to_string_lossy().to_string())
}
#[cfg(windows)]
fn locate_windows_command(command: &str) -> Option<String> {
command_stdout("where", &[command]).ok().and_then(first_non_empty_line).or_else(|| {