From d0978633ab8e20470a959f708defd9566fa8266b Mon Sep 17 00:00:00 2001 From: William Valentin Date: Thu, 19 Feb 2026 09:53:05 -0800 Subject: [PATCH] feat(dashboard): add model tier default controls and document cancel path --- docs/api/PROTOCOL.md | 3 ++ docs/plans/state.json | 24 +++++++++ src/gateway/ui/pages/dashboard.js | 89 +++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+) diff --git a/docs/api/PROTOCOL.md b/docs/api/PROTOCOL.md index 7f9efb6..ce6d0f7 100644 --- a/docs/api/PROTOCOL.md +++ b/docs/api/PROTOCOL.md @@ -698,6 +698,9 @@ When queue policy rejects/supersedes a request before execution, the server emit Cancel the current agent operation. +Used by the web dashboard/chat stop button and channel-level `/stop` / `/cancel` command fast-paths. +Cancellation is best-effort and stops at the next agent/tool-loop safe point. + ### Node Methods #### `node.register` diff --git a/docs/plans/state.json b/docs/plans/state.json index 1c72264..549c5cd 100644 --- a/docs/plans/state.json +++ b/docs/plans/state.json @@ -5807,5 +5807,29 @@ "src/backends/native/agent.ts" ], "test_status": "4/4 passing" + }, + "dashboard-model-defaults-and-stop-controls": { + "date": "2026-02-19", + "summary": "Added dashboard controls for persistent model tier defaults (`agents.primary_tier`, `agents.delegation.*`) and background provider/model overrides with fallback tier (`agents.background_models.*`). Added command-registry `/stop` (alias `/cancel`), wired channel/gateway cancellation services, implemented web chat send-button stop state + `agent.cancel` wiring, and added Telegram `/stop` + `/cancel` command forwarding.", + "files_modified": [ + "src/config/schema.ts", + "src/gateway/handlers/config.ts", + "src/backends/native/orchestrator.ts", + "src/context/compaction.ts", + "src/daemon/routing.ts", + "src/gateway/session-bridge.ts", + "src/commands/types.ts", + "src/commands/builtin/index.ts", + "src/commands/index.ts", + "src/gateway/handlers/agent.ts", + "src/gateway/ui/pages/chat.js", + "src/gateway/ui/pages/dashboard.js", + "src/channels/telegram/adapter.ts", + "src/channels/telegram/adapter.test.ts", + "src/commands/builtin/index.test.ts", + "src/gateway/handlers/agent.test.ts", + "docs/api/PROTOCOL.md" + ], + "test_status": "pnpm test:run src/commands/builtin/index.test.ts src/channels/telegram/adapter.test.ts src/gateway/handlers/agent.test.ts src/gateway/session-bridge.test.ts src/daemon/routing.test.ts src/config/schema.test.ts src/gateway/handlers/handlers.test.ts + pnpm typecheck passing" } } diff --git a/src/gateway/ui/pages/dashboard.js b/src/gateway/ui/pages/dashboard.js index d77997a..1b4a3f1 100644 --- a/src/gateway/ui/pages/dashboard.js +++ b/src/gateway/ui/pages/dashboard.js @@ -692,6 +692,9 @@ function updateAssistantHealth(configData) { : 'not configured'; const briefingReady = dailyBriefing && Boolean(briefingOutput?.channel && briefingOutput?.peer); const playbookLikeReady = announce || (memoryDaily && memoryProactive); + const modelTier = configData?.agents?.primary_tier ?? 'default'; + const delegation = configData?.agents?.delegation ?? {}; + const backgroundModels = configData?.agents?.background_models ?? {}; const checklistRows = [ { label: 'Set briefing output channel + peer', done: Boolean(briefingOutput?.channel && briefingOutput?.peer) }, { label: 'Enable assistant behavior profile', done: playbookLikeReady }, @@ -704,6 +707,16 @@ function updateAssistantHealth(configData) { ${value ? 'ON' : 'OFF'} `; + const tierOption = (selected) => ['fast', 'default', 'complex', 'local'] + .map((tier) => ``) + .join(''); + const taskRows = [ + { key: 'compaction', label: 'Compaction' }, + { key: 'memory_extraction', label: 'Memory extraction' }, + { key: 'classification', label: 'Classification' }, + { key: 'tool_summarisation', label: 'Tool summarisation' }, + { key: 'complex_reasoning', label: 'Complex reasoning' }, + ]; el.innerHTML = `
@@ -752,6 +765,60 @@ function updateAssistantHealth(configData) {
Executive: announce + voice + aggressive interrupt. Operator: announce + memory-first + steer backlog. Focus: reactive, quieter mode.
+
+
Model Tier Defaults
+
+ +
+
Delegation tiers + background model overrides
+
+ ${taskRows.map((task) => { + const background = backgroundModels?.[task.key] ?? {}; + const delegationTier = delegation?.[task.key] ?? 'fast'; + return ` +
+
${escapeHtml(task.label)}
+
+ + + + + +
+
+ `; + }).join('')} +
+
+ +
+
Assistant Activation Checklist
@@ -856,6 +923,28 @@ function updateAssistantHealth(configData) { 'automation.daily_briefing.enabled': true, }; _assistantManualOverrides.add('automation.daily_briefing.enabled'); + } else if (action === 'save-model-defaults') { + const tasks = ['compaction', 'memory_extraction', 'classification', 'tool_summarisation', 'complex_reasoning']; + patches = { + 'agents.primary_tier': (el.querySelector('#assist-primary-tier')?.value ?? 'default'), + }; + for (const task of tasks) { + const delegationTier = el.querySelector(`#assist-delegation-${task}`)?.value ?? 'fast'; + const enabled = Boolean(el.querySelector(`#assist-bg-${task}-enabled`)?.checked); + const provider = (el.querySelector(`#assist-bg-${task}-provider`)?.value ?? '').trim(); + const model = (el.querySelector(`#assist-bg-${task}-model`)?.value ?? '').trim(); + const fallbackTier = el.querySelector(`#assist-bg-${task}-fallback`)?.value ?? 'fast'; + + patches[`agents.delegation.${task}`] = delegationTier; + patches[`agents.background_models.${task}.enabled`] = enabled; + if (provider) { + patches[`agents.background_models.${task}.provider`] = provider; + } + if (model) { + patches[`agents.background_models.${task}.model`] = model; + } + patches[`agents.background_models.${task}.fallback_tier`] = fallbackTier; + } } if (!patches) {return;} await applyAssistantPatch(patches, statusEl);