Stand-in import of elffuss/code
One parentless commit with only the files that the open seed tasks touch and the modules they import. The full squashed import (SPEC 8.6) is a later step: this tree is not the cutoff tree. T2T-StandIn-Source-Commit: 43f95b7333efe73aeaebf806023f17bffea27aba
This commit is contained in:
59
web/js/settings.js
Normal file
59
web/js/settings.js
Normal file
@@ -0,0 +1,59 @@
|
||||
// Configuración avanzada de proveedores externos (opt-in). Elffuss corre en
|
||||
// LOCAL por defecto; esto solo se usa si el usuario lo activa a mano.
|
||||
// Las claves viven en localStorage de SU navegador y nunca salen de aquí
|
||||
// (las llamadas van directas del navegador al proveedor).
|
||||
const KEY = 'elffusscode.providers';
|
||||
|
||||
// Plantillas de proveedores externos. `kind` decide el dialecto de API.
|
||||
const DEFAULTS = {
|
||||
openai: {
|
||||
kind: 'openai', label: 'OpenAI', enabled: false,
|
||||
baseURL: 'https://api.openai.com/v1', model: 'gpt-4o-mini', apiKey: '',
|
||||
help: 'Tu clave sk-… Se queda en tu navegador. OpenAI permite llamadas directas (CORS).',
|
||||
},
|
||||
anthropic: {
|
||||
kind: 'anthropic', label: 'Anthropic (Claude)', enabled: false,
|
||||
baseURL: 'https://api.anthropic.com', model: 'claude-sonnet-5', apiKey: '',
|
||||
help: 'Tu clave sk-ant-… Se envía la cabecera de acceso directo desde navegador.',
|
||||
},
|
||||
ollama: {
|
||||
kind: 'openai', label: 'Ollama (local)', enabled: false,
|
||||
baseURL: 'http://localhost:11434/v1', model: 'llama3.2', apiKey: 'ollama',
|
||||
help: 'Ollama en tu máquina. Arráncalo con OLLAMA_ORIGINS=* para permitir el navegador.',
|
||||
},
|
||||
server: {
|
||||
kind: 'openai', label: 'Servidor Elffuss (Ornith 9B)', enabled: false,
|
||||
baseURL: 'https://elffuss-claw.utopiaia.com/v1', model: 'ornith-9b', apiKey: '',
|
||||
temperature: 1.0, top_p: 0.95, thinking: false,
|
||||
help: 'El modelo grande en el servidor de UtopiaIA. No es local: los mensajes salen de tu máquina.',
|
||||
},
|
||||
};
|
||||
|
||||
function load() {
|
||||
let saved = {};
|
||||
try { saved = JSON.parse(localStorage.getItem(KEY) || '{}'); } catch { /* corrupto */ }
|
||||
const out = {};
|
||||
for (const [id, def] of Object.entries(DEFAULTS)) out[id] = { ...def, ...saved[id] };
|
||||
return out;
|
||||
}
|
||||
|
||||
export function configs() { return load(); }
|
||||
export function get(id) { return load()[id]; }
|
||||
|
||||
export function update(id, patch) {
|
||||
const all = load();
|
||||
all[id] = { ...all[id], ...patch };
|
||||
// no persistir los campos de ayuda estáticos
|
||||
const slim = {};
|
||||
for (const [k, v] of Object.entries(all))
|
||||
slim[k] = { enabled: v.enabled, baseURL: v.baseURL, model: v.model, apiKey: v.apiKey };
|
||||
localStorage.setItem(KEY, JSON.stringify(slim));
|
||||
return all[id];
|
||||
}
|
||||
|
||||
// Externos habilitados → opciones del selector, como ext:<id>.
|
||||
export function enabledExternals() {
|
||||
return Object.entries(load())
|
||||
.filter(([, c]) => c.enabled)
|
||||
.map(([id, c]) => ({ id: 'ext:' + id, label: c.label + (id === 'ollama' || c.baseURL.startsWith('http://localhost') ? ' · local' : ' · nube') }));
|
||||
}
|
||||
Reference in New Issue
Block a user