feat: add LLM provider settings to web UI with encrypted API key storage
Add full LLM configuration section to the setup page with provider dropdown, model/API key fields for cloud providers (Anthropic, OpenAI, Gemini), and endpoint/model fields for Ollama. API keys are encrypted with AES-256-GCM and stored in the database.
This commit is contained in:
@@ -37,6 +37,7 @@
|
||||
<a href="#ac" class="px-3 py-1 bg-gray-200 dark:bg-gray-700 rounded hover:bg-gray-300 dark:hover:bg-gray-600">AC Units</a>
|
||||
<a href="#toggles" class="px-3 py-1 bg-gray-200 dark:bg-gray-700 rounded hover:bg-gray-300 dark:hover:bg-gray-600">Toggles</a>
|
||||
<a href="#forecast" class="px-3 py-1 bg-gray-200 dark:bg-gray-700 rounded hover:bg-gray-300 dark:hover:bg-gray-600">Forecast</a>
|
||||
<a href="#llm" class="px-3 py-1 bg-gray-200 dark:bg-gray-700 rounded hover:bg-gray-300 dark:hover:bg-gray-600">LLM</a>
|
||||
</div>
|
||||
|
||||
{{template "profiles" .}}
|
||||
@@ -46,6 +47,7 @@
|
||||
{{template "ac_units" .}}
|
||||
{{template "toggles" .}}
|
||||
{{template "forecast" .}}
|
||||
{{template "llm" .}}
|
||||
|
||||
<footer class="mt-8 text-center text-xs text-gray-500 dark:text-gray-500 py-4">
|
||||
<p>Heatwave Autopilot</p>
|
||||
@@ -540,3 +542,47 @@
|
||||
{{end}}
|
||||
</section>
|
||||
{{end}}
|
||||
|
||||
{{define "llm"}}
|
||||
<section id="llm" class="mb-8">
|
||||
<h2 class="text-xl font-semibold mb-3">LLM Provider</h2>
|
||||
<form method="POST" action="/setup/llm/save" class="p-4 bg-white dark:bg-gray-800 rounded-lg shadow dark:shadow-gray-700">
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
<div class="sm:col-span-2">
|
||||
<label class="block text-sm text-gray-600 dark:text-gray-400 mb-1">Provider</label>
|
||||
<select name="provider" id="llm-provider" class="w-full px-3 py-2 border dark:border-gray-600 rounded bg-white dark:bg-gray-700"
|
||||
onchange="document.getElementById('llm-cloud').style.display=(this.value==='anthropic'||this.value==='openai'||this.value==='gemini')?'':'none';document.getElementById('llm-local').style.display=(this.value==='ollama')?'':'none';">
|
||||
<option value="none" {{if eq .LLMProvider "none"}}selected{{end}}>None</option>
|
||||
<option value="anthropic" {{if eq .LLMProvider "anthropic"}}selected{{end}}>Anthropic</option>
|
||||
<option value="openai" {{if eq .LLMProvider "openai"}}selected{{end}}>OpenAI</option>
|
||||
<option value="gemini" {{if eq .LLMProvider "gemini"}}selected{{end}}>Gemini</option>
|
||||
<option value="ollama" {{if eq .LLMProvider "ollama"}}selected{{end}}>Ollama (local)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div id="llm-cloud" style="{{if or (eq .LLMProvider "anthropic") (eq .LLMProvider "openai") (eq .LLMProvider "gemini")}}{{else}}display:none{{end}}" class="sm:col-span-2 grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label class="block text-sm text-gray-600 dark:text-gray-400 mb-1">Model</label>
|
||||
<input type="text" name="cloud_model" value="{{.LLMModel}}" placeholder="e.g. claude-sonnet-4-5-20250929" class="w-full px-3 py-2 border dark:border-gray-600 rounded bg-white dark:bg-gray-700">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm text-gray-600 dark:text-gray-400 mb-1">API Key</label>
|
||||
<input type="password" name="api_key" placeholder="Leave blank to keep current key" class="w-full px-3 py-2 border dark:border-gray-600 rounded bg-white dark:bg-gray-700">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="llm-local" style="{{if eq .LLMProvider "ollama"}}{{else}}display:none{{end}}" class="sm:col-span-2 grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label class="block text-sm text-gray-600 dark:text-gray-400 mb-1">Endpoint URL</label>
|
||||
<input type="text" name="endpoint" value="{{.LLMEndpoint}}" placeholder="http://localhost:11434" class="w-full px-3 py-2 border dark:border-gray-600 rounded bg-white dark:bg-gray-700">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm text-gray-600 dark:text-gray-400 mb-1">Model</label>
|
||||
<input type="text" name="local_model" value="{{.LLMModel}}" placeholder="e.g. llama3" class="w-full px-3 py-2 border dark:border-gray-600 rounded bg-white dark:bg-gray-700">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="mt-4 px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700">Save LLM Settings</button>
|
||||
</form>
|
||||
</section>
|
||||
{{end}}
|
||||
|
||||
Reference in New Issue
Block a user