Agent UI
Release rolling / release (push) Canceled after 3m10s

This commit is contained in:
Raven Scott
2026-07-30 17:32:59 -04:00
parent 6abc5999f2
commit e3d0f70b29
4 changed files with 987 additions and 62 deletions
+26 -37
View File
@@ -12,6 +12,7 @@ import {
synthesizeFromAgents,
} from './agents.js'
import { chartIdsFromToolLog, mountChartEmbeds } from './chart-embed.js'
import { createSwarmPanel } from './swarm-ui.js'
/**
* @param {{
@@ -269,41 +270,12 @@ export function createQvacView(opts) {
})
}
/** @type {Map<string, HTMLElement>} */
const agentChipEls = new Map()
const swarm = createSwarmPanel(opts.els.agentBar, {
onStop: () => stopInference(),
})
function clearAgentBar() {
const bar = opts.els.agentBar
if (!bar) return
bar.innerHTML = ''
bar.classList.add('hidden')
agentChipEls.clear()
}
/**
* @param {{ id: string, label: string, status: string, summary?: string, error?: string }} ev
*/
function paintAgentEvent(ev) {
const bar = opts.els.agentBar
if (!bar) return
bar.classList.remove('hidden')
let chip = agentChipEls.get(ev.id)
if (!chip) {
chip = document.createElement('span')
chip.className = 'qvac-agent-chip'
chip.dataset.agent = ev.id
bar.appendChild(chip)
agentChipEls.set(ev.id, chip)
}
chip.dataset.status = ev.status
const tip = ev.summary || ev.error || ''
chip.title = tip
chip.textContent =
ev.status === 'start'
? `${ev.label}`
: ev.status === 'error'
? `${ev.label}`
: `${ev.label}`
swarm.hide()
}
/** Finish onboarding in tools-only mode (no model download). */
@@ -810,6 +782,7 @@ export function createQvacView(opts) {
async function stopInference() {
if (!busy) return
setStatus('Stopping…', 'busy')
if (swarm.isOpen?.()) swarm.fail('Stopped by user')
try {
await engine.stop?.()
} catch (err) {
@@ -855,27 +828,43 @@ export function createQvacView(opts) {
opts.isConnected?.() &&
!engine.isAborted?.()
) {
setStatus('Spinning up agents…', 'busy')
setStatus('Multi-agent swarm…', 'busy')
if (streamBody) {
streamBody.innerHTML = formatMdLite('_Dispatching multi-agent investigation…_')
streamBody.innerHTML = formatMdLite(
'_Swarm is running — watch specialists above while tools gather live data…_'
)
}
const pack = await runSubAgents({
tools,
query: text,
maxAgents: prefs.maxSubAgents,
isAborted: () => Boolean(engine.isAborted?.()),
onPlan: (specs) => {
swarm.begin(
specs.map((s) => ({
id: s.id,
label: s.label,
description: s.description,
})),
text
)
},
onAgent: (ev) => {
if (engine.isAborted?.()) return
paintAgentEvent(ev)
setStatus(`Agent: ${ev.label}`, 'busy')
swarm.update(ev)
if (ev.status === 'start' || ev.status === 'running') {
setStatus(`${ev.label}`, 'busy')
}
},
})
if (engine.isAborted?.()) {
swarm.fail('Stopped')
acc = '_(Stopped during multi-agent investigation.)_'
paintAssistant(streamBody, acc, false)
setStatus('Stopped', 'warn')
return
}
swarm.complete('All agents done — synthesizing answer…')
completeOpts.agentBriefing = pack.contextText
completeOpts.agentFallbackText = synthesizeFromAgents(text, pack)
completeOpts.agentToolCalls = pack.agents.map((a) => ({