// Per-agent display metadata (icons + role blurb). Built-ins + known custom agents.
const ROUTER_AGENT_META = {
opencode: { icon: '🔧', blurb: 'Code & DevOps' },
hermes: { icon: '⚡', blurb: 'Memory & Scheduling' },
gemini: { icon: '🧠', blurb: 'Research & Analysis' },
jarvis: { icon: '🤖', blurb: 'Local-first AI / Deep Research' },
kilocode: { icon: '💻', blurb: 'AI Coding Assistant' },
codex: { icon: '🧩', blurb: 'Code Generation' },
};
function routerAgentMeta(name) {
return ROUTER_AGENT_META[name] || { icon: '🤖', blurb: 'Custom agent' };
}
async function renderSmartRouter() {
const content = document.getElementById('pageContent');
content.innerHTML = `
Routing Rules
`;
await loadRouterAgents();
}
// Pull the live agent list from the server so the dropdown + rules table
// always reflect every registered agent (built-in AND custom).
async function loadRouterAgents() {
let agents = [];
try {
const data = await api.getAgents();
agents = (data.agents || []).map(a => a.name);
} catch (e) {
// Fallback to known built-ins if the API is unreachable.
agents = ['opencode', 'hermes', 'gemini'];
}
const select = document.getElementById('routerAgentSelect');
const table = document.getElementById('routerRulesTable');
if (!select || !table) return;
// Populate dropdown (preserve the Auto option already in the DOM).
agents.forEach(name => {
const meta = routerAgentMeta(name);
const opt = document.createElement('option');
opt.value = name;
opt.textContent = `${meta.icon} ${name} (${meta.blurb})`;
select.appendChild(opt);
});
// Populate routing-rules table.
const rows = agents.map(name => {
const meta = routerAgentMeta(name);
const kw = (window._routerKeywords && window._routerKeywords[name]) || [];
return `
| ${meta.icon} ${name} |
${meta.blurb} |
${kw.join(', ') || '—'} |
`;
}).join('');
table.innerHTML = `| Agent | Best For | Keywords |
${rows}`;
}
async function suggestRouter() {
const task = document.getElementById('routerTaskInput').value.trim();
if (!task) { showToast('Describe your task first', 'warning'); return; }
const btn = document.querySelector('button[onclick="suggestRouter()"]');
if (btn) { btn.disabled = true; btn.textContent = '⏳ Thinking...'; }
try {
const data = await api.suggestRouter(task);
// Cache keyword map from scores for the rules table refresh.
window._routerKeywords = data.scores ? Object.keys(data.scores).reduce((m, a) => m, {}) : {};
const result = document.getElementById('routerResult');
const agentIcons = {
opencode: '🔧', hermes: '⚡', gemini: '🧠',
jarvis: '🤖', kilocode: '💻', codex: '🧩'
};
const confidenceColors = { high: 'var(--green)', medium: 'var(--yellow)', low: 'var(--text-muted)' };
result.innerHTML = `
${agentIcons[data.suggested_agent] || '🤖'} ${data.suggested_agent}
Confidence: ${data.confidence}
${data.confidence === 'high' ? '✅' : data.confidence === 'medium' ? '⚠️' : '❓'}
Best Match
${Object.entries(data.scores || {}).map(([agent, score]) => `
${agentIcons[agent] || '🤖'} ${agent}: ${score}
`).join('')}
`;
document.getElementById('routerAgentSelect').value = data.suggested_agent || 'auto';
} catch (err) {
showToast('Suggestion failed: ' + err.message, 'error');
} finally {
if (btn) { btn.disabled = false; btn.textContent = '🤖 Suggest Agent'; }
}
}
async function routeTask() {
const task = document.getElementById('routerTaskInput').value.trim();
if (!task) { showToast('Describe your task first', 'warning'); return; }
let agent = document.getElementById('routerAgentSelect').value;
if (agent === 'auto') {
showToast('Click "Suggest Agent" first or pick an agent manually', 'warning');
return;
}
const btn = document.querySelector('button[onclick="routeTask()"]');
if (btn) { btn.disabled = true; btn.textContent = '⏳ Routing...'; }
try {
const data = await api.routeTask(task, agent);
showToast(`✅ Task routed to ${agent}`, 'success');
const result = document.getElementById('routerResult');
result.innerHTML += `
✅
Task Routed
${data.message}
`;
} catch (err) {
showToast('Routing failed: ' + err.message, 'error');
} finally {
if (btn) { btn.disabled = false; btn.textContent = '🚀 Route Task'; }
}
}