mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-15 12:03:35 +03:00
migrate AI tokens from the git-configuration to the keystore.
All AI related options are stored in the user-level git configuration file. Upon first access, they will be removed from there and placed into the keystore as part of the migration. The UI is provided with functions to store and save secrets which it will use specifically to interact with these keys. It's explicitly out of scope to *not* show the keys in plain-text anymore after entering them.
This commit is contained in:
parent
de00e4f049
commit
05506f49fa
@ -14,6 +14,7 @@ import {
|
|||||||
MessageRole,
|
MessageRole,
|
||||||
type Prompt
|
type Prompt
|
||||||
} from '$lib/ai/types';
|
} from '$lib/ai/types';
|
||||||
|
import { invoke } from '$lib/backend/ipc';
|
||||||
import { buildFailureFromAny, isFailure, ok, type Result } from '$lib/result';
|
import { buildFailureFromAny, isFailure, ok, type Result } from '$lib/result';
|
||||||
import { splitMessage } from '$lib/utils/commitMessage';
|
import { splitMessage } from '$lib/utils/commitMessage';
|
||||||
import OpenAI from 'openai';
|
import OpenAI from 'openai';
|
||||||
@ -90,7 +91,17 @@ export class AIService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getOpenAIKey() {
|
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() {
|
async getOpenAIModleName() {
|
||||||
@ -108,7 +119,17 @@ export class AIService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getAnthropicKey() {
|
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() {
|
async getAnthropicModelName() {
|
||||||
|
@ -5,6 +5,10 @@ export class GitConfigService {
|
|||||||
return (await invoke<T | undefined>('git_get_global_config', { key })) || undefined;
|
return (await invoke<T | undefined>('git_get_global_config', { key })) || undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async remove(key: string): Promise<undefined> {
|
||||||
|
return await invoke('git_remove_global_config', { key });
|
||||||
|
}
|
||||||
|
|
||||||
async getWithDefault<T extends string>(key: string, defaultValue: T): Promise<T> {
|
async getWithDefault<T extends string>(key: string, defaultValue: T): Promise<T> {
|
||||||
const value = await invoke<T | undefined>('git_get_global_config', { key });
|
const value = await invoke<T | undefined>('git_get_global_config', { key });
|
||||||
return value || defaultValue;
|
return value || defaultValue;
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
import TextBox from '$lib/shared/TextBox.svelte';
|
import TextBox from '$lib/shared/TextBox.svelte';
|
||||||
import { UserService } from '$lib/stores/user';
|
import { UserService } from '$lib/stores/user';
|
||||||
import { getContext } from '$lib/utils/context';
|
import { getContext } from '$lib/utils/context';
|
||||||
|
import { invoke } from '@tauri-apps/api/tauri';
|
||||||
import { onMount, tick } from 'svelte';
|
import { onMount, tick } from 'svelte';
|
||||||
|
|
||||||
const gitConfigService = getContext(GitConfigService);
|
const gitConfigService = getContext(GitConfigService);
|
||||||
@ -34,10 +35,17 @@
|
|||||||
let ollamaEndpoint: string | undefined;
|
let ollamaEndpoint: string | undefined;
|
||||||
let ollamaModel: string | undefined;
|
let ollamaModel: string | undefined;
|
||||||
|
|
||||||
function setConfiguration(key: GitAIConfigKey, value: string | undefined) {
|
async function setConfiguration(key: GitAIConfigKey, value: string | undefined) {
|
||||||
if (!initialized) return;
|
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);
|
$: setConfiguration(GitAIConfigKey.ModelProvider, modelKind);
|
||||||
|
@ -79,6 +79,11 @@ impl App {
|
|||||||
Ok(value.to_string())
|
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<Option<String>> {
|
pub fn git_get_global_config(key: &str) -> Result<Option<String>> {
|
||||||
let config = git2::Config::open_default()?;
|
let config = git2::Config::open_default()?;
|
||||||
let value = config.get_string(key);
|
let value = config.get_string(key);
|
||||||
|
@ -103,6 +103,12 @@ pub async fn git_set_global_config(
|
|||||||
Ok(result)
|
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)]
|
#[tauri::command(async)]
|
||||||
#[instrument(skip(_handle), err(Debug))]
|
#[instrument(skip(_handle), err(Debug))]
|
||||||
pub async fn git_get_global_config(
|
pub async fn git_get_global_config(
|
||||||
|
@ -27,9 +27,9 @@ pub mod github;
|
|||||||
pub mod keys;
|
pub mod keys;
|
||||||
pub mod projects;
|
pub mod projects;
|
||||||
pub mod remotes;
|
pub mod remotes;
|
||||||
|
pub mod secret;
|
||||||
pub mod undo;
|
pub mod undo;
|
||||||
pub mod users;
|
pub mod users;
|
||||||
pub mod virtual_branches;
|
pub mod virtual_branches;
|
||||||
pub mod secret;
|
|
||||||
|
|
||||||
pub mod zip;
|
pub mod zip;
|
||||||
|
@ -168,6 +168,7 @@ fn main() {
|
|||||||
commands::delete_all_data,
|
commands::delete_all_data,
|
||||||
commands::mark_resolved,
|
commands::mark_resolved,
|
||||||
commands::git_set_global_config,
|
commands::git_set_global_config,
|
||||||
|
commands::git_remove_global_config,
|
||||||
commands::git_get_global_config,
|
commands::git_get_global_config,
|
||||||
commands::git_test_push,
|
commands::git_test_push,
|
||||||
commands::git_test_fetch,
|
commands::git_test_fetch,
|
||||||
|
Loading…
Reference in New Issue
Block a user