fix(ai): Codex CLI provider reliability fixes for DBX Desktop

* fix(ai): resolve Codex CLI from shell PATH on macOS

* fix(ai): hide Codex CLI subprocess windows on Windows

* feat(ai): allow to set environment variable for Codex CLI

* fix(ai): parse Codex MCP tool events

* fix(mcp): honor Postgres TLS settings in direct queries
This commit is contained in:
Oleksandr Liakhevych authored and GitHub committed 2026-06-25 22:31:14 +08:00
1 parent 2759480331
commit 034cce47e0
17 files changed
+613 -30

No files matched your search

+30
View File
@@ -1,3 +1,4 @@
use std::path::Path;
use std::sync::Arc;
use tauri::{AppHandle, Emitter, State};
@@ -6,11 +7,13 @@ pub use dbx_core::ai::*;
#[tauri::command]
pub async fn ai_test_connection(config: AiConfig) -> Result<AiTestConnectionResult, String> {
let config = resolve_codex_cli_config(config);
dbx_core::ai::test_connection_core(&config).await
}
#[tauri::command]
pub async fn ai_list_models(config: AiConfig) -> Result<Vec<AiModelInfo>, String> {
let config = resolve_codex_cli_config(config);
dbx_core::ai::list_models_core(&config).await
}
@@ -64,6 +67,7 @@ pub async fn ai_agent_stream(
db_type: String,
mode: Option<String>,
) -> Result<String, String> {
let request = resolve_codex_cli_request(request);
let cancelled = dbx_core::ai::register_stream(&session_id).await;
let parsed_db_type: DatabaseType =
@@ -105,6 +109,32 @@ pub async fn ai_agent_stream(
result
}
fn resolve_codex_cli_request(mut request: AiCompletionRequest) -> AiCompletionRequest {
request.config = resolve_codex_cli_config(request.config);
request
}
fn resolve_codex_cli_config(mut config: AiConfig) -> AiConfig {
if !matches!(config.provider, AiProvider::CodexCli) {
return config;
}
let command = config.codex_cli_path.as_deref().map(str::trim).filter(|path| !path.is_empty()).unwrap_or("codex");
if is_explicit_cli_path(command) {
return config;
}
if let Some(path) = super::mcp::locate_command(command) {
config.codex_cli_path = Some(path);
}
config
}
fn is_explicit_cli_path(command: &str) -> bool {
let path = Path::new(command);
path.is_absolute() || command.contains('/') || command.contains('\\')
}
#[tauri::command]
pub async fn save_ai_conversation(state: State<'_, Arc<AppState>>, conversation: AiConversation) -> Result<(), String> {
state.storage.save_ai_conversation(&conversation).await
+7 -3
View File
@@ -120,17 +120,21 @@ pub(crate) fn resolve_mcp_server_command() -> Option<(String, Vec<String>)> {
.or_else(|| installed_mcp_bin_script().map(|script| ("node".to_string(), vec![script])))
}
fn locate_mcp_bin() -> Option<String> {
pub(crate) fn locate_command(command: &str) -> Option<String> {
#[cfg(windows)]
{
return locate_windows_command("dbx-mcp-server");
return locate_windows_command(command);
}
#[cfg(not(windows))]
{
command_stdout("which", &["dbx-mcp-server"]).ok().and_then(first_non_empty_line)
command_stdout("which", &[command]).ok().and_then(first_non_empty_line)
}
}
fn locate_mcp_bin() -> Option<String> {
locate_command("dbx-mcp-server")
}
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");