tiny-army / web /codingModelBar.js
polats's picture
Add Coding Model setting + Skill Forge sandbox
1f1908e
// Coding-model picker for the Settings page. A trimmed modelBar: no engine selector and
// no cache/delete controls (these are ZeroGPU sidecars with no browser download). Drives
// the shared codingModel.js store, so the Skill Forge uses whatever is chosen here.
import {
listCodingModels, getCodingModelId, setCodingModel, currentCodingModel, onCodingModelChange,
} from '/web/codingModel.js'
function el(tag, props = {}, kids = []) {
const n = document.createElement(tag)
for (const [k, v] of Object.entries(props)) {
if (k === 'class') n.className = v
else if (k.startsWith('on') && typeof v === 'function') n.addEventListener(k.slice(2), v)
else if (v != null) n.setAttribute(k, v)
}
for (const kid of [].concat(kids)) if (kid != null) n.append(kid)
return n
}
export function mountCodingModelBar(host, { onChange } = {}) {
const sel = el('select', { class: 'model-select' })
const info = el('div', { class: 'model-info' })
host.append(el('div', { class: 'model-bar' }, [
el('label', { class: 'persona-label' }, 'Model'),
sel,
el('div', { class: 'model-row' }, [info]),
]))
function render() {
sel.replaceChildren(...listCodingModels().map((m) =>
el('option', { value: m.id }, `${m.label}${m.params ? ` · ${m.params}` : ''}`)))
sel.value = getCodingModelId()
const m = currentCodingModel()
info.textContent = [m.params, m.backend, m.note].filter(Boolean).join(' · ')
}
sel.addEventListener('change', () => { setCodingModel(sel.value); render(); onChange && onChange(sel.value) })
onCodingModelChange(render)
render()
return { refresh: render }
}