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:
1 parent
2759480331
commit
034cce47e0
17 files changed
+613
-30
No files matched your search
@@ -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
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in new issue
Block a user