Add global backend defaults with runtime fallback
New fields: GlobalAwsSettings.default_model_id, plus GlobalOllamaSettings and GlobalOpenAiCompatibleSettings (base_url + default_model_id each). When a per-project base_url or model_id is blank, the container env vars and config fingerprints fall back to the global value. Container recreation is triggered whenever the resolved value changes, so editing a global default updates existing projects on next start. UI: added the new fields to AwsSettings and two new global settings components, slotted into the Backends accordion. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,7 @@ export default function AwsSettings() {
|
||||
aws_config_path: null,
|
||||
aws_profile: null,
|
||||
aws_region: null,
|
||||
default_model_id: null,
|
||||
};
|
||||
|
||||
// Load profiles when component mounts or aws_config_path changes
|
||||
@@ -105,6 +106,18 @@ export default function AwsSettings() {
|
||||
className="w-full px-2 py-1.5 text-xs bg-[var(--bg-primary)] border border-[var(--border-color)] rounded focus:outline-none focus:border-[var(--accent)]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Default Model ID */}
|
||||
<div>
|
||||
<span className="text-[var(--text-secondary)] text-xs block mb-1">Default Model ID<Tooltip text="Default Bedrock model ID. Used when a Bedrock project doesn't set its own Model ID." /></span>
|
||||
<input
|
||||
type="text"
|
||||
value={globalAws.default_model_id ?? ""}
|
||||
onChange={(e) => handleChange("default_model_id", e.target.value)}
|
||||
placeholder="anthropic.claude-sonnet-4-20250514-v1:0"
|
||||
className="w-full px-2 py-1.5 text-xs bg-[var(--bg-primary)] border border-[var(--border-color)] rounded focus:outline-none focus:border-[var(--accent)]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import { useSettings } from "../../hooks/useSettings";
|
||||
import Tooltip from "../ui/Tooltip";
|
||||
|
||||
export default function OllamaSettings() {
|
||||
const { appSettings, saveSettings } = useSettings();
|
||||
|
||||
const globalOllama = appSettings?.global_ollama ?? {
|
||||
base_url: null,
|
||||
default_model_id: null,
|
||||
};
|
||||
|
||||
const handleChange = async (field: "base_url" | "default_model_id", value: string) => {
|
||||
if (!appSettings) return;
|
||||
await saveSettings({
|
||||
...appSettings,
|
||||
global_ollama: { ...globalOllama, [field]: value || null },
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-2">Ollama Configuration</label>
|
||||
<div className="space-y-3 text-sm">
|
||||
<p className="text-xs text-[var(--text-secondary)]">
|
||||
Global Ollama defaults. Used when a per-project field is blank.
|
||||
Changes here require a container rebuild to take effect.
|
||||
</p>
|
||||
|
||||
<div>
|
||||
<span className="text-[var(--text-secondary)] text-xs block mb-1">Default Base URL<Tooltip text="URL of your Ollama server. Used when a per-project Ollama base URL is blank." /></span>
|
||||
<input
|
||||
type="text"
|
||||
value={globalOllama.base_url ?? ""}
|
||||
onChange={(e) => handleChange("base_url", e.target.value)}
|
||||
placeholder="http://host.docker.internal:11434"
|
||||
className="w-full px-2 py-1.5 text-xs bg-[var(--bg-primary)] border border-[var(--border-color)] rounded focus:outline-none focus:border-[var(--accent)]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span className="text-[var(--text-secondary)] text-xs block mb-1">Default Model<Tooltip text="Default Ollama model name. Used when a per-project Ollama model is blank." /></span>
|
||||
<input
|
||||
type="text"
|
||||
value={globalOllama.default_model_id ?? ""}
|
||||
onChange={(e) => handleChange("default_model_id", e.target.value)}
|
||||
placeholder="qwen3.5:27b"
|
||||
className="w-full px-2 py-1.5 text-xs bg-[var(--bg-primary)] border border-[var(--border-color)] rounded focus:outline-none focus:border-[var(--accent)]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import { useSettings } from "../../hooks/useSettings";
|
||||
import Tooltip from "../ui/Tooltip";
|
||||
|
||||
export default function OpenAiCompatibleSettings() {
|
||||
const { appSettings, saveSettings } = useSettings();
|
||||
|
||||
const globalOai = appSettings?.global_openai_compatible ?? {
|
||||
base_url: null,
|
||||
default_model_id: null,
|
||||
};
|
||||
|
||||
const handleChange = async (field: "base_url" | "default_model_id", value: string) => {
|
||||
if (!appSettings) return;
|
||||
await saveSettings({
|
||||
...appSettings,
|
||||
global_openai_compatible: { ...globalOai, [field]: value || null },
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<label className="block text-sm font-medium mb-2">OpenAI Compatible Configuration</label>
|
||||
<div className="space-y-3 text-sm">
|
||||
<p className="text-xs text-[var(--text-secondary)]">
|
||||
Global defaults for any OpenAI-compatible endpoint (LiteLLM, OpenRouter, vLLM, etc.).
|
||||
Used when a per-project field is blank. Changes require a container rebuild.
|
||||
</p>
|
||||
|
||||
<div>
|
||||
<span className="text-[var(--text-secondary)] text-xs block mb-1">Default Base URL<Tooltip text="Default OpenAI-compatible endpoint URL. Used when a per-project base URL is blank." /></span>
|
||||
<input
|
||||
type="text"
|
||||
value={globalOai.base_url ?? ""}
|
||||
onChange={(e) => handleChange("base_url", e.target.value)}
|
||||
placeholder="http://host.docker.internal:4000"
|
||||
className="w-full px-2 py-1.5 text-xs bg-[var(--bg-primary)] border border-[var(--border-color)] rounded focus:outline-none focus:border-[var(--accent)]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span className="text-[var(--text-secondary)] text-xs block mb-1">Default Model<Tooltip text="Default model identifier. Used when a per-project model is blank." /></span>
|
||||
<input
|
||||
type="text"
|
||||
value={globalOai.default_model_id ?? ""}
|
||||
onChange={(e) => handleChange("default_model_id", e.target.value)}
|
||||
placeholder="gpt-4o / gemini-pro / etc."
|
||||
className="w-full px-2 py-1.5 text-xs bg-[var(--bg-primary)] border border-[var(--border-color)] rounded focus:outline-none focus:border-[var(--accent)]"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import DockerSettings from "./DockerSettings";
|
||||
import AwsSettings from "./AwsSettings";
|
||||
import OllamaSettings from "./OllamaSettings";
|
||||
import OpenAiCompatibleSettings from "./OpenAiCompatibleSettings";
|
||||
import { useSettings } from "../../hooks/useSettings";
|
||||
import { useUpdates } from "../../hooks/useUpdates";
|
||||
import ClaudeInstructionsModal from "../projects/ClaudeInstructionsModal";
|
||||
@@ -148,6 +150,10 @@ export default function SettingsPanel() {
|
||||
|
||||
<AccordionSection id="backends" title="Backends" defaultOpen={false}>
|
||||
<AwsSettings />
|
||||
<div className="pt-3 border-t border-[var(--border-color)]" />
|
||||
<OllamaSettings />
|
||||
<div className="pt-3 border-t border-[var(--border-color)]" />
|
||||
<OpenAiCompatibleSettings />
|
||||
</AccordionSection>
|
||||
|
||||
<AccordionSection id="container" title="Container" defaultOpen={false}>
|
||||
|
||||
@@ -116,6 +116,17 @@ export interface GlobalAwsSettings {
|
||||
aws_config_path: string | null;
|
||||
aws_profile: string | null;
|
||||
aws_region: string | null;
|
||||
default_model_id: string | null;
|
||||
}
|
||||
|
||||
export interface GlobalOllamaSettings {
|
||||
base_url: string | null;
|
||||
default_model_id: string | null;
|
||||
}
|
||||
|
||||
export interface GlobalOpenAiCompatibleSettings {
|
||||
base_url: string | null;
|
||||
default_model_id: string | null;
|
||||
}
|
||||
|
||||
export interface AppSettings {
|
||||
@@ -126,6 +137,8 @@ export interface AppSettings {
|
||||
image_source: ImageSource;
|
||||
custom_image_name: string | null;
|
||||
global_aws: GlobalAwsSettings;
|
||||
global_ollama: GlobalOllamaSettings;
|
||||
global_openai_compatible: GlobalOpenAiCompatibleSettings;
|
||||
global_claude_instructions: string | null;
|
||||
global_custom_env_vars: EnvVar[];
|
||||
auto_check_updates: boolean;
|
||||
|
||||
Reference in New Issue
Block a user