'use strict'; const state = { models: [], selected: null, registrationEnabled: false }; const $ = selector => document.querySelector(selector); const esc = value => String(value ?? '').replace(/[&<>'"]/g, char => ({'&':'&','<':'<','>':'>',"'":''','"':'"'}[char])); const integer = value => new Intl.NumberFormat().format(Number(value || 0)); const protocolName = value => ({chat_completions:'Chat Completions',responses:'Responses',embeddings:'Embeddings',messages:'Anthropic Messages'}[value] || value); const price = (micros, currency='usd') => new Intl.NumberFormat(undefined, {style:'currency', currency:String(currency).toUpperCase(), minimumFractionDigits:2, maximumFractionDigits:6}).format(Number(micros || 0) / 1_000_000); const date = value => value ? new Intl.DateTimeFormat(undefined, {year:'numeric',month:'short',day:'numeric'}).format(new Date(value)) : 'Not published'; function healthLabel(model) { if (model.health_status === 'unavailable') return ['Unavailable', 'unavailable']; if (model.health_status === 'degraded') return [`${model.available_provider_count}/${model.provider_count} routes`, 'degraded']; return ['Available', 'available']; } function renderStats(models) { const protocols = new Set(models.flatMap(model => model.supported_wire_apis || [])); $('#model-count').textContent = integer(models.length); $('#provider-count').textContent = integer(models.reduce((sum, model) => sum + Number(model.provider_count || 0), 0)); $('#protocol-count').textContent = integer(protocols.size); } function renderFilters() { const owners = [...new Set(state.models.map(model => model.owned_by).filter(Boolean))].sort(); const protocols = [...new Set(state.models.flatMap(model => model.supported_wire_apis || []))].sort(); $('#owner').innerHTML = '' + owners.map(owner => ``).join(''); $('#protocol').innerHTML = '' + protocols.map(item => ``).join(''); } function filteredModels() { const query = $('#search').value.trim().toLowerCase(); const protocol = $('#protocol').value; const input = $('#input').value; const owner = $('#owner').value; const result = state.models.filter(model => { const haystack = [model.public_id, model.display_name, model.description, model.owned_by, ...(model.capabilities || []), ...(model.aliases || [])].join(' ').toLowerCase(); return (!query || haystack.includes(query)) && (!protocol || (model.supported_wire_apis || []).includes(protocol)) && (!input || (model.input_modalities || []).includes(input)) && (!owner || model.owned_by === owner); }); const sort = $('#sort').value; result.sort((a,b) => { if (sort === 'name') return String(a.display_name || a.public_id).localeCompare(String(b.display_name || b.public_id)); if (sort === 'input_price') return Number(a.input_price_micros_per_million) - Number(b.input_price_micros_per_million); if (sort === 'output_price') return Number(a.output_price_micros_per_million) - Number(b.output_price_micros_per_million); if (sort === 'context') return Number(b.context_window) - Number(a.context_window); return new Date(b.released_at || 0) - new Date(a.released_at || 0) || String(a.public_id).localeCompare(String(b.public_id)); }); return result; } function renderCatalog() { const models = filteredModels(); $('#catalog-empty').classList.toggle('hidden', models.length !== 0); $('#catalog-grid').innerHTML = models.map(model => { const [health, healthClass] = healthLabel(model); return `
${esc(model.owned_by || 'Independent')}

${esc(model.display_name || model.public_id)}

${esc(health)}
${esc(model.public_id)}

${esc(model.description || 'No description published.')}

${(model.supported_wire_apis || []).map(item => `${esc(protocolName(item))}`).join('')}${(model.input_modalities || []).map(item => `${esc(item)}`).join('')}
Input
${price(model.input_price_micros_per_million, model.price_currency)} / 1M
Output
${price(model.output_price_micros_per_million, model.price_currency)} / 1M
Context
${integer(model.context_window)}
View model
`; }).join(''); } function renderEstimate() { if (!state.selected) return; const input = Math.max(0, Number($('#estimate-input').value || 0)); const output = Math.max(0, Number($('#estimate-output').value || 0)); const totalMicros = (Number(state.selected.input_price_micros_per_million || 0) * input + Number(state.selected.output_price_micros_per_million || 0) * output) / 1_000_000; $('#estimate-total').textContent = `${price(totalMicros, state.selected.price_currency)} estimated`; } function openModel(publicID) { const model = state.models.find(item => item.public_id === publicID); if (!model) return; state.selected = model; const [health, healthClass] = healthLabel(model); $('#detail-owner').textContent = model.owned_by || 'Independent'; $('#detail-name').textContent = model.display_name || model.public_id; $('#detail-id').textContent = model.public_id; $('#detail-description').textContent = model.description || 'No description published.'; $('#detail-tags').innerHTML = [...(model.supported_wire_apis || []).map(protocolName), ...(model.capabilities || []), ...(model.input_modalities || []).map(item => `${item} input`), ...(model.output_modalities || []).map(item => `${item} output`)].map(item => `${esc(item)}`).join(''); const rows = [ ['Status', `${esc(health)}`], ['Input price', `${price(model.input_price_micros_per_million, model.price_currency)} / 1M tokens`], ['Output price', `${price(model.output_price_micros_per_million, model.price_currency)} / 1M tokens`], ['Cached input', `${price(model.cache_read_price_micros_per_million, model.price_currency)} / 1M tokens`], ['Context window', `${integer(model.context_window)} tokens`], ['Max output', `${integer(model.max_output_tokens)} tokens`], ['Regions', esc((model.regions || []).join(', ') || 'Global')], ['Released', esc(date(model.released_at))] ]; $('#detail-grid').innerHTML = rows.map(([label,value]) => `
${esc(label)}
${value}
`).join(''); const register = $('#detail-register'); register.classList.toggle('hidden', !state.registrationEnabled); register.href = `./?auth=register&model=${encodeURIComponent(model.public_id)}`; renderEstimate(); $('#model-dialog').showModal(); } async function start() { try { const response = await fetch('./api/public/models', {headers:{Accept:'application/json'}}); if (!response.ok) throw new Error(`Catalog request failed (${response.status})`); const payload = await response.json(); state.models = Array.isArray(payload.data) ? payload.data : []; state.registrationEnabled = Boolean(payload.registration_enabled); $('#create-account').classList.toggle('hidden', !state.registrationEnabled); renderStats(state.models); renderFilters(); renderCatalog(); } catch (error) { $('#catalog-error').textContent = error.message || 'The model catalog is temporarily unavailable.'; $('#catalog-error').classList.remove('hidden'); } } $('#catalog-filters').addEventListener('input', renderCatalog); $('#catalog-grid').addEventListener('click', event => { const button = event.target.closest('[data-model]'); if (button) openModel(button.dataset.model); }); $('#close-dialog').addEventListener('click', () => $('#model-dialog').close()); $('#model-dialog').addEventListener('click', event => { if (event.target === $('#model-dialog')) $('#model-dialog').close(); }); $('#estimate-input').addEventListener('input', renderEstimate); $('#estimate-output').addEventListener('input', renderEstimate); start();