diff --git a/pkg/miniapp/static/index.html b/pkg/miniapp/static/index.html
index b2038a5a1..d7c8639b9 100644
--- a/pkg/miniapp/static/index.html
+++ b/pkg/miniapp/static/index.html
@@ -1826,6 +1826,7 @@ function _orchInitChars() {
_orchSecretary = _orchMakeChar('secretary', '👩💼', MAP_POSITIONS.secretary);
_orchHeartbeat = _orchMakeChar('heartbeat', '🕊️', MAP_POSITIONS.heartbeat);
_orchConductor.alive = true; _orchSecretary.alive = true; _orchHeartbeat.alive = true;
+ _orchConductor.statusText = null;
_orchHeartbeat.facing = 1; _orchHeartbeat.flipTimer = 0;
var ps = [{id:'s0',emoji:'🔍'},{id:'s1',emoji:'📊'},{id:'s2',emoji:'💻'},
{id:'s3',emoji:'🔧'},{id:'s4',emoji:'🎯'}];
@@ -1845,7 +1846,15 @@ function _orchSyncBadge(id, state, alive) {
+ (state==='toolcall'? ' toolcall' : '')
+ (state==='waiting' ? ' waiting' : '');
}
-function _orchSetState(c, state) { c.state=state; _orchSyncBadge(c.id, state, c.alive); }
+function _orchSetState(c, state, tool) {
+ c.state=state; _orchSyncBadge(c.id, state, c.alive);
+ if (c === _orchConductor) {
+ if (state==='waiting') c.statusText='🤔';
+ else if (state==='toolcall') c.statusText='⌨';
+ else if (state==='user_waiting') c.statusText='⏳';
+ else c.statusText=null;
+ }
+}
function _orchMoveTo(c, pos, cb) { c.target=pos; c._onArrive=cb||null; }
function _orchSay(c, text, ttl) { c.bubble={text:text, ttl:ttl||2200}; }
@@ -1876,6 +1885,9 @@ function _orchGC(id) {
if (ch === _orchHeartbeat) {
// Heartbeat pigeon is permanent — keep alive, just return to idle.
_orchSetState(ch,'idle');
+ } else if (ch === _orchConductor) {
+ // Conductor is permanent — keep alive, show ⏳ waiting for user.
+ _orchSetState(ch,'user_waiting');
} else {
ch.alive=false; _orchSetState(ch,'idle');
}
@@ -1920,6 +1932,12 @@ function _orchUpdate(dt) {
}
});
}
+function _orchDrawStatus(c) {
+ if (!c.statusText) return;
+ var yOff=_orchBOB[c.frame], cx=Math.floor(c.x), cy=Math.floor(c.y+yOff)-20;
+ orchCtx.font='11px serif'; orchCtx.textAlign='center'; orchCtx.textBaseline='middle';
+ orchCtx.fillText(c.statusText, cx, cy);
+}
function _orchDrawBubble(c) {
if (!c.bubble) return;
var yOff=_orchBOB[c.frame], bx=c.x, by=c.y+yOff-18;
@@ -1941,6 +1959,9 @@ function _orchDrawChar(c) {
} else if (c.state==='waiting'){
orchCtx.fillStyle='rgba(96,165,250,0.25)'; orchCtx.beginPath();
orchCtx.arc(cx,cy,11,0,Math.PI*2); orchCtx.fill();
+ } else if (c.state==='user_waiting'){
+ orchCtx.fillStyle='rgba(167,139,250,0.18)'; orchCtx.beginPath();
+ orchCtx.arc(cx,cy,10,0,Math.PI*2); orchCtx.fill();
}
orchCtx.font='18px serif'; orchCtx.textAlign='center'; orchCtx.textBaseline='middle';
if (c.facing === -1) {
@@ -1954,6 +1975,7 @@ function _orchDrawChar(c) {
orchCtx.font='6px Silkscreen,monospace'; orchCtx.textAlign='center'; orchCtx.textBaseline='top';
orchCtx.fillStyle=c.state==='talking'?'#facc15':'#3a4a7a';
orchCtx.fillText(c.id.toUpperCase(), cx, cy+11);
+ _orchDrawStatus(c);
_orchDrawBubble(c);
}
function _orchRender(ts) {
@@ -1995,7 +2017,7 @@ function connectOrchWs() {
} else if (msg.type==='event') {
var ev=msg.event||{};
if (ev.type==='agent_spawn') _orchSpawn(ev.id);
- if (ev.type==='agent_state') { var c=_orchCharForId(ev.id); if(c) _orchSetState(c,ev.state); }
+ if (ev.type==='agent_state') { var c=_orchCharForId(ev.id); if(c) _orchSetState(c,ev.state,ev.tool); }
if (ev.type==='agent_gc') _orchGC(ev.id);
if (ev.type==='conversation') _orchConverse(ev.from, ev.to, ev.text);
}