feat: add support for API chats

This commit is contained in:
2026-02-04 13:44:44 -08:00
parent a0804ed32a
commit ae06cc301d
6 changed files with 1108 additions and 2 deletions
+190
View File
@@ -23,6 +23,14 @@
auto_granted_tools: [],
ollama_base_url: "http://localhost:11434",
ollama_model: null,
openai_api_key: null,
openai_base_url: "https://api.openai.com/v1",
openai_model: null,
anthropic_api_key: null,
anthropic_base_url: "https://api.anthropic.com",
anthropic_model: null,
gemini_api_key: null,
gemini_model: null,
theme: "dark",
greeting_enabled: true,
greeting_custom_prompt: null,
@@ -79,6 +87,9 @@
const availableProviders: { value: ProviderType; label: string; description: string }[] = [
{ value: "claude_cli", label: "Claude CLI", description: "Use Claude Code CLI for AI assistance" },
{ value: "ollama", label: "Ollama (Local)", description: "Use locally running Ollama models" },
{ value: "open_ai", label: "OpenAI API", description: "Direct OpenAI API access (GPT-4o, etc.)" },
{ value: "anthropic", label: "Anthropic API", description: "Direct Anthropic API access (Claude models)" },
{ value: "gemini", label: "Google Gemini", description: "Direct Google Gemini API access" },
];
const availableModels = [
@@ -97,6 +108,29 @@
{ value: "gemma2", label: "Gemma 2" },
];
const openaiModels = [
{ value: "", label: "Default (gpt-4o)" },
{ value: "gpt-4o", label: "GPT-4o" },
{ value: "gpt-4o-mini", label: "GPT-4o Mini" },
{ value: "gpt-4-turbo", label: "GPT-4 Turbo" },
{ value: "gpt-3.5-turbo", label: "GPT-3.5 Turbo" },
];
const anthropicModels = [
{ value: "", label: "Default (Claude Sonnet 4.5)" },
{ value: "claude-sonnet-4-5-20250514", label: "Claude Sonnet 4.5" },
{ value: "claude-opus-4-20250514", label: "Claude Opus 4" },
{ value: "claude-3-5-sonnet-20241022", label: "Claude 3.5 Sonnet" },
{ value: "claude-3-5-haiku-20241022", label: "Claude 3.5 Haiku" },
];
const geminiModels = [
{ value: "", label: "Default (gemini-2.0-flash)" },
{ value: "gemini-2.0-flash", label: "Gemini 2.0 Flash" },
{ value: "gemini-1.5-pro", label: "Gemini 1.5 Pro" },
{ value: "gemini-1.5-flash", label: "Gemini 1.5 Flash" },
];
const commonTools = [
"Read",
"Write",
@@ -297,6 +331,162 @@
</div>
</div>
{/if}
<!-- OpenAI-specific settings -->
{#if config.provider_type === "open_ai"}
<div class="mt-4 p-3 bg-[var(--bg-primary)] rounded-lg border border-[var(--border-color)]">
<h4 class="text-sm font-medium text-[var(--text-primary)] mb-3">OpenAI Settings</h4>
<!-- OpenAI API Key -->
<div class="mb-3">
<label for="openai-api-key" class="block text-xs text-[var(--text-secondary)] mb-1">
API Key
</label>
<input
id="openai-api-key"
type="password"
bind:value={config.openai_api_key}
placeholder="sk-..."
class="w-full px-3 py-2 text-sm bg-[var(--bg-secondary)] border border-[var(--border-color)] rounded-lg text-[var(--text-primary)] focus:outline-none focus:border-[var(--accent-primary)]"
/>
</div>
<!-- OpenAI Base URL -->
<div class="mb-3">
<label for="openai-url" class="block text-xs text-[var(--text-secondary)] mb-1">
Base URL <span class="text-[var(--text-tertiary)]">(for OpenAI-compatible APIs)</span>
</label>
<input
id="openai-url"
type="text"
bind:value={config.openai_base_url}
placeholder="https://api.openai.com/v1"
class="w-full px-3 py-2 text-sm bg-[var(--bg-secondary)] border border-[var(--border-color)] rounded-lg text-[var(--text-primary)] focus:outline-none focus:border-[var(--accent-primary)]"
/>
</div>
<!-- OpenAI Model Selection -->
<div class="mb-3">
<label for="openai-model" class="block text-xs text-[var(--text-secondary)] mb-1">
Model
</label>
<select
id="openai-model"
bind:value={config.openai_model}
class="w-full px-3 py-2 text-sm bg-[var(--bg-secondary)] border border-[var(--border-color)] rounded-lg text-[var(--text-primary)] focus:outline-none focus:border-[var(--accent-primary)]"
>
{#each openaiModels as model (model.value)}
<option value={model.value}>{model.label}</option>
{/each}
</select>
</div>
<div class="p-2 bg-blue-500/10 border border-blue-500/30 rounded text-xs text-blue-400">
<strong>Tip:</strong> You can use this with any OpenAI-compatible API (Groq, Together AI, etc.)
by changing the Base URL.
</div>
</div>
{/if}
<!-- Anthropic-specific settings -->
{#if config.provider_type === "anthropic"}
<div class="mt-4 p-3 bg-[var(--bg-primary)] rounded-lg border border-[var(--border-color)]">
<h4 class="text-sm font-medium text-[var(--text-primary)] mb-3">Anthropic Settings</h4>
<!-- Anthropic API Key -->
<div class="mb-3">
<label for="anthropic-api-key" class="block text-xs text-[var(--text-secondary)] mb-1">
API Key
</label>
<input
id="anthropic-api-key"
type="password"
bind:value={config.anthropic_api_key}
placeholder="sk-ant-..."
class="w-full px-3 py-2 text-sm bg-[var(--bg-secondary)] border border-[var(--border-color)] rounded-lg text-[var(--text-primary)] focus:outline-none focus:border-[var(--accent-primary)]"
/>
</div>
<!-- Anthropic Base URL -->
<div class="mb-3">
<label for="anthropic-url" class="block text-xs text-[var(--text-secondary)] mb-1">
Base URL <span class="text-[var(--text-tertiary)]">(optional)</span>
</label>
<input
id="anthropic-url"
type="text"
bind:value={config.anthropic_base_url}
placeholder="https://api.anthropic.com"
class="w-full px-3 py-2 text-sm bg-[var(--bg-secondary)] border border-[var(--border-color)] rounded-lg text-[var(--text-primary)] focus:outline-none focus:border-[var(--accent-primary)]"
/>
</div>
<!-- Anthropic Model Selection -->
<div class="mb-3">
<label for="anthropic-model" class="block text-xs text-[var(--text-secondary)] mb-1">
Model
</label>
<select
id="anthropic-model"
bind:value={config.anthropic_model}
class="w-full px-3 py-2 text-sm bg-[var(--bg-secondary)] border border-[var(--border-color)] rounded-lg text-[var(--text-primary)] focus:outline-none focus:border-[var(--accent-primary)]"
>
{#each anthropicModels as model (model.value)}
<option value={model.value}>{model.label}</option>
{/each}
</select>
</div>
<div class="p-2 bg-purple-500/10 border border-purple-500/30 rounded text-xs text-purple-400">
<strong>Note:</strong> This uses the Anthropic API directly without Claude Code CLI features
like tools, MCP, or thinking blocks.
</div>
</div>
{/if}
<!-- Gemini-specific settings -->
{#if config.provider_type === "gemini"}
<div class="mt-4 p-3 bg-[var(--bg-primary)] rounded-lg border border-[var(--border-color)]">
<h4 class="text-sm font-medium text-[var(--text-primary)] mb-3">Gemini Settings</h4>
<!-- Gemini API Key -->
<div class="mb-3">
<label for="gemini-api-key" class="block text-xs text-[var(--text-secondary)] mb-1">
API Key
</label>
<input
id="gemini-api-key"
type="password"
bind:value={config.gemini_api_key}
placeholder="AIza..."
class="w-full px-3 py-2 text-sm bg-[var(--bg-secondary)] border border-[var(--border-color)] rounded-lg text-[var(--text-primary)] focus:outline-none focus:border-[var(--accent-primary)]"
/>
<p class="text-xs text-[var(--text-tertiary)] mt-1">
Get your API key from <a href="https://aistudio.google.com/apikey" target="_blank" class="text-[var(--accent-secondary)] hover:underline">Google AI Studio</a>
</p>
</div>
<!-- Gemini Model Selection -->
<div class="mb-3">
<label for="gemini-model" class="block text-xs text-[var(--text-secondary)] mb-1">
Model
</label>
<select
id="gemini-model"
bind:value={config.gemini_model}
class="w-full px-3 py-2 text-sm bg-[var(--bg-secondary)] border border-[var(--border-color)] rounded-lg text-[var(--text-primary)] focus:outline-none focus:border-[var(--accent-primary)]"
>
{#each geminiModels as model (model.value)}
<option value={model.value}>{model.label}</option>
{/each}
</select>
</div>
<div class="p-2 bg-green-500/10 border border-green-500/30 rounded text-xs text-green-400">
<strong>Note:</strong> Gemini has a generous free tier! Great for experimenting.
</div>
</div>
{/if}
</section>
<!-- Agent Settings Section -->
+16
View File
@@ -51,6 +51,14 @@
auto_granted_tools: [],
ollama_base_url: "http://localhost:11434",
ollama_model: null,
openai_api_key: null,
openai_base_url: "https://api.openai.com/v1",
openai_model: null,
anthropic_api_key: null,
anthropic_base_url: "https://api.anthropic.com",
anthropic_model: null,
gemini_api_key: null,
gemini_model: null,
theme: "dark",
greeting_enabled: true,
greeting_custom_prompt: null,
@@ -157,6 +165,14 @@
allowed_tools: allAllowedTools,
ollama_base_url: currentConfig.ollama_base_url || "http://localhost:11434",
ollama_model: currentConfig.ollama_model || null,
openai_api_key: currentConfig.openai_api_key || null,
openai_base_url: currentConfig.openai_base_url || "https://api.openai.com/v1",
openai_model: currentConfig.openai_model || null,
anthropic_api_key: currentConfig.anthropic_api_key || null,
anthropic_base_url: currentConfig.anthropic_base_url || "https://api.anthropic.com",
anthropic_model: currentConfig.anthropic_model || null,
gemini_api_key: currentConfig.gemini_api_key || null,
gemini_model: currentConfig.gemini_model || null,
},
});
} catch (error) {
+21 -1
View File
@@ -2,7 +2,7 @@ import { writable, derived } from "svelte/store";
import { invoke } from "@tauri-apps/api/core";
export type Theme = "dark" | "light" | "high-contrast" | "custom";
export type ProviderType = "claude_cli" | "ollama";
export type ProviderType = "claude_cli" | "ollama" | "open_ai" | "anthropic" | "gemini";
export interface CustomThemeColors {
bg_primary: string | null;
@@ -22,8 +22,20 @@ export interface HikariConfig {
custom_instructions: string | null;
mcp_servers_json: string | null;
auto_granted_tools: string[];
// Ollama settings
ollama_base_url: string;
ollama_model: string | null;
// OpenAI settings
openai_api_key: string | null;
openai_base_url: string;
openai_model: string | null;
// Anthropic settings
anthropic_api_key: string | null;
anthropic_base_url: string;
anthropic_model: string | null;
// Gemini settings
gemini_api_key: string | null;
gemini_model: string | null;
theme: Theme;
greeting_enabled: boolean;
greeting_custom_prompt: string | null;
@@ -52,6 +64,14 @@ const defaultConfig: HikariConfig = {
auto_granted_tools: [],
ollama_base_url: "http://localhost:11434",
ollama_model: null,
openai_api_key: null,
openai_base_url: "https://api.openai.com/v1",
openai_model: null,
anthropic_api_key: null,
anthropic_base_url: "https://api.anthropic.com",
anthropic_model: null,
gemini_api_key: null,
gemini_model: null,
theme: "dark",
greeting_enabled: true,
greeting_custom_prompt: null,