From 236dab2c4eaf67d0b13af9c385da9e16eba6476f Mon Sep 17 00:00:00 2001 From: Alexander Whitestone Date: Tue, 24 Mar 2026 00:56:10 -0400 Subject: [PATCH] feat: add local vs cloud indicator on every agent panel Each agent panel now shows a RUNTIME indicator in the bottom-right corner: green dot + "LOCAL" for on-device agents, red dot + "CLOUD" for remote/API-backed agents. The `local` boolean field is used from agent data (defaults to cloud/red when absent). Fixes #278 --- app.js | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/app.js b/app.js index 5a405cf..e5ea2f0 100644 --- a/app.js +++ b/app.js @@ -1751,11 +1751,11 @@ loadPortals(); const AGENT_STATUS_STUB = { agents: [ - { name: 'claude', status: 'working', issue: 'Live agent status board (#199)', prs_today: 3 }, - { name: 'gemini', status: 'idle', issue: null, prs_today: 1 }, - { name: 'kimi', status: 'working', issue: 'Portal system YAML registry (#5)', prs_today: 2 }, - { name: 'groq', status: 'idle', issue: null, prs_today: 0 }, - { name: 'grok', status: 'dead', issue: null, prs_today: 0 }, + { name: 'claude', status: 'working', issue: 'Live agent status board (#199)', prs_today: 3, local: true }, + { name: 'gemini', status: 'idle', issue: null, prs_today: 1, local: false }, + { name: 'kimi', status: 'working', issue: 'Portal system YAML registry (#5)', prs_today: 2, local: false }, + { name: 'groq', status: 'idle', issue: null, prs_today: 0, local: false }, + { name: 'grok', status: 'dead', issue: null, prs_today: 0, local: false }, ] }; @@ -1843,6 +1843,27 @@ function createAgentPanelTexture(agent) { ctx.fillStyle = '#4488ff'; ctx.fillText(String(agent.prs_today), 16, 182); + // Local vs cloud indicator (bottom-right) + const isLocal = agent.local === true; + const indicatorColor = isLocal ? '#00ff88' : '#ff4444'; + const indicatorLabel = isLocal ? 'LOCAL' : 'CLOUD'; + + ctx.font = '10px "Courier New", monospace'; + ctx.fillStyle = '#556688'; + ctx.textAlign = 'right'; + ctx.fillText('RUNTIME', W - 16, 148); + + ctx.font = 'bold 13px "Courier New", monospace'; + ctx.fillStyle = indicatorColor; + ctx.fillText(indicatorLabel, W - 28, 172); + ctx.textAlign = 'left'; + + // Indicator dot + ctx.beginPath(); + ctx.arc(W - 16, 167, 6, 0, Math.PI * 2); + ctx.fillStyle = indicatorColor; + ctx.fill(); + return new THREE.CanvasTexture(canvas); }