diff --git a/app/src/lib/ai/service.ts b/app/src/lib/ai/service.ts index 30554ba0b..6c3d1b2a1 100644 --- a/app/src/lib/ai/service.ts +++ b/app/src/lib/ai/service.ts @@ -14,6 +14,7 @@ import { MessageRole, type Prompt } from '$lib/ai/types'; +import { invoke } from '$lib/backend/ipc'; import { buildFailureFromAny, isFailure, ok, type Result } from '$lib/result'; import { splitMessage } from '$lib/utils/commitMessage'; import OpenAI from 'openai'; @@ -90,7 +91,17 @@ export class AIService { } async getOpenAIKey() { - return await this.gitConfig.get(GitAIConfigKey.OpenAIKey); + const secretInConfig = await this.gitConfig.get(GitAIConfigKey.OpenAIKey); + if (secretInConfig !== undefined) { + await invoke('secret_set_global', { + handle: 'aiOpenAIKey', + secret: secretInConfig + }); + await this.gitConfig.remove(GitAIConfigKey.OpenAIKey); + return secretInConfig; + } else { + return await invoke('secret_get_global', { handle: 'aiOpenAIKey' }); + } } async getOpenAIModleName() { @@ -108,7 +119,17 @@ export class AIService { } async getAnthropicKey() { - return await this.gitConfig.get(GitAIConfigKey.AnthropicKey); + const secretInConfig = await this.gitConfig.get(GitAIConfigKey.AnthropicKey); + if (secretInConfig !== undefined) { + await invoke('secret_set_global', { + handle: 'aiAnthropicKey', + secret: secretInConfig + }); + await this.gitConfig.remove(GitAIConfigKey.AnthropicKey); + return secretInConfig; + } else { + return await invoke('secret_get_global', { handle: 'aiAnthropicKey' }); + } } async getAnthropicModelName() { diff --git a/app/src/lib/backend/gitConfigService.ts b/app/src/lib/backend/gitConfigService.ts index 9e1843a1e..2197d132a 100644 --- a/app/src/lib/backend/gitConfigService.ts +++ b/app/src/lib/backend/gitConfigService.ts @@ -5,6 +5,10 @@ export class GitConfigService { return (await invoke('git_get_global_config', { key })) || undefined; } + async remove(key: string): Promise { + return await invoke('git_remove_global_config', { key }); + } + async getWithDefault(key: string, defaultValue: T): Promise { const value = await invoke('git_get_global_config', { key }); return value || defaultValue; diff --git a/app/src/routes/settings/ai/+page.svelte b/app/src/routes/settings/ai/+page.svelte index ebe028904..ed8cf3428 100644 --- a/app/src/routes/settings/ai/+page.svelte +++ b/app/src/routes/settings/ai/+page.svelte @@ -15,6 +15,7 @@ import TextBox from '$lib/shared/TextBox.svelte'; import { UserService } from '$lib/stores/user'; import { getContext } from '$lib/utils/context'; + import { invoke } from '@tauri-apps/api/tauri'; import { onMount, tick } from 'svelte'; const gitConfigService = getContext(GitConfigService); @@ -34,10 +35,17 @@ let ollamaEndpoint: string | undefined; let ollamaModel: string | undefined; - function setConfiguration(key: GitAIConfigKey, value: string | undefined) { + async function setConfiguration(key: GitAIConfigKey, value: string | undefined) { if (!initialized) return; - gitConfigService.set(key, value || ''); + if (key === GitAIConfigKey.OpenAIKey || key === GitAIConfigKey.AnthropicKey) { + await invoke('secret_set_global', { + handle: key.split('.')[1], + secret: value + }); + } else { + gitConfigService.set(key, value || ''); + } } $: setConfiguration(GitAIConfigKey.ModelProvider, modelKind); diff --git a/crates/gitbutler-tauri/src/app.rs b/crates/gitbutler-tauri/src/app.rs index 09121a091..a5390b6f9 100644 --- a/crates/gitbutler-tauri/src/app.rs +++ b/crates/gitbutler-tauri/src/app.rs @@ -79,6 +79,11 @@ impl App { Ok(value.to_string()) } + pub fn git_remove_global_config(key: &str) -> Result<()> { + let mut config = git2::Config::open_default()?; + Ok(config.remove(key)?) + } + pub fn git_get_global_config(key: &str) -> Result> { let config = git2::Config::open_default()?; let value = config.get_string(key); diff --git a/crates/gitbutler-tauri/src/commands.rs b/crates/gitbutler-tauri/src/commands.rs index 85157fc2b..4036c2dce 100644 --- a/crates/gitbutler-tauri/src/commands.rs +++ b/crates/gitbutler-tauri/src/commands.rs @@ -103,6 +103,12 @@ pub async fn git_set_global_config( Ok(result) } +#[tauri::command(async)] +#[instrument(err(Debug))] +pub async fn git_remove_global_config(key: &str) -> Result<(), Error> { + Ok(app::App::git_remove_global_config(key)?) +} + #[tauri::command(async)] #[instrument(skip(_handle), err(Debug))] pub async fn git_get_global_config( diff --git a/crates/gitbutler-tauri/src/lib.rs b/crates/gitbutler-tauri/src/lib.rs index 551357bea..9f92d795d 100644 --- a/crates/gitbutler-tauri/src/lib.rs +++ b/crates/gitbutler-tauri/src/lib.rs @@ -27,9 +27,9 @@ pub mod github; pub mod keys; pub mod projects; pub mod remotes; +pub mod secret; pub mod undo; pub mod users; pub mod virtual_branches; -pub mod secret; pub mod zip; diff --git a/crates/gitbutler-tauri/src/main.rs b/crates/gitbutler-tauri/src/main.rs index 10793d0dc..b5866dae6 100644 --- a/crates/gitbutler-tauri/src/main.rs +++ b/crates/gitbutler-tauri/src/main.rs @@ -168,6 +168,7 @@ fn main() { commands::delete_all_data, commands::mark_resolved, commands::git_set_global_config, + commands::git_remove_global_config, commands::git_get_global_config, commands::git_test_push, commands::git_test_fetch,