diff --git a/docs/terminal-rendering.md b/docs/terminal-rendering.md index 6ad9da54..e31501e3 100644 --- a/docs/terminal-rendering.md +++ b/docs/terminal-rendering.md @@ -56,7 +56,7 @@ parent's negative pull. | `.turn-time` | `· HH:MM:SS` on turn-start; `· HH:MM:SS · ` on turn-end (child span) | muted, smaller | per-event `ts` (unix seconds) on the live frame + history row | harness | | `.text` | (no prefix; markdown body) | fg | claude `assistant.content[].text` | stream-json | | `.thinking` | `💭 thinking …` | muted, italic | claude `assistant.content[].thinking` | stream-json | -| `.tool-use` (flat) | ` Name args…` | cyan | tool_use w/o rich renderer; `` from `toolIcon(name)` (📤 send · 📥 recv · ❓ ask · ⏰ remind · 🏷️ set_status · 🪢 loose-ends · 🖥️ bash · 💬 matrix · 📦 request_* · ⏱️ schedule · 🔧 default) | stream-json | +| `.tool-use` (flat) | ` Name args…` | cyan | tool_use w/o rich renderer; `` from `toolIcon(name)`: 📤 send · 📥 recv · ❓ ask · ⏰ remind · 🏷️ set_status · 🪢 loose-ends · ✂️ cancel_loose_end · ℹ️ get_agent_meta · ✅ ack_until · 📜 get_logs/get_host_journal · ↻ restart · ⏹️ kill · ▶️ start · 🔄 update · 📋 list_containers/list_rooms/list_room_members/list_invites · 📖 read_room/Read · 👁️ mark_read · 🛑 bash kill · 🖥️ bash other · 💬 matrix send/reply/dm · 📦 request_* · ⏱️ schedule · 🔧 default | stream-json | | `.tool-use` `
` | `💾/✏️ Write/Edit · +N` (no `→`) | cyan, body is +/- diff | `renderRichToolUse` Write/Edit | stream-json | | `.tool-use` `
` | `📤 send → to · NL`, `❓ ask → to`, `✍️ answer #id` | cyan, body is markdown | rich renderer for send / ask / answer | stream-json | | `.tool-use .ask-answer-inline-slot` | (sub-block under `ask → operator`) | inherits row | inline answer form bound by `reconcileAskBinds` to the loose-end | rich renderer | diff --git a/frontend/packages/agent/src/app.js b/frontend/packages/agent/src/app.js index 5d5b05eb..248a70e0 100644 --- a/frontend/packages/agent/src/app.js +++ b/frontend/packages/agent/src/app.js @@ -1524,6 +1524,12 @@ window.marked = marked; 'mcp__hyperhive__list_containers': '📋', 'mcp__hyperhive__get_logs': '📜', 'mcp__hyperhive__get_host_journal': '📜', + 'mcp__matrix__read_room': '📖', + 'mcp__matrix__mark_read': '👁️', + 'mcp__matrix__list_rooms': '📋', + 'mcp__matrix__list_room_members': '📋', + 'mcp__matrix__list_invites': '📋', + 'mcp__bash__kill': '🛑', Read: '📖', Write: '💾', Edit: '✏️', Glob: '🔍', Grep: '🔍', }; function toolIcon(name) { @@ -1537,6 +1543,22 @@ window.marked = marked; } return '🔧'; } + // Shorten a matrix room id or alias for display. Room ids (!xxx:server) + // are trimmed to the first 8 local chars; aliases (#name:server) are + // returned as-is (they're already readable). Falls back to the raw + // value truncated. + function fmtRoom(r) { + if (!r) return '?'; + if (r.startsWith('!')) return r.slice(0, r.indexOf(':') > 0 ? r.indexOf(':') : 9); + if (r.startsWith('#')) return r.split(':')[0] || r; + return trim(r, 20); + } + // Shorten @user:server → @user. + function fmtUser(u) { + if (!u) return '?'; + const colon = u.indexOf(':'); + return colon > 0 ? u.slice(0, colon) : u; + } // Pretty-print a tool call: per-known-tool format, fallback to JSON // for unknown tools. function fmtToolUse(c) { @@ -1546,7 +1568,9 @@ window.marked = marked; ? name.slice('mcp__hyperhive__'.length) + '*' : name.startsWith('mcp__bash__') ? name.slice('mcp__bash__'.length) + '*' - : name; + : name.startsWith('mcp__matrix__') + ? name.slice('mcp__matrix__'.length) + '*' + : name; switch (name) { case 'Read': return short + ' ' + (input.file_path || ''); case 'Write': return short + ' ' + (input.file_path || ''); @@ -1611,6 +1635,39 @@ window.marked = marked; case 'mcp__bash__status': return short + ' id:' + (input.id || '?') + (input.wait_seconds != null ? ' · wait ' + input.wait_seconds + 's' : ''); + case 'mcp__bash__kill': + return short + ' ' + (input.id || '?') + (input.force ? ' [force]' : ''); + case 'mcp__hyperhive__set_status': + return short + ' "' + trim(String(input.text || ''), 60) + '"'; + case 'mcp__hyperhive__get_loose_ends': + return short + (input.agent ? ' [' + input.agent + ']' : '()'); + case 'mcp__hyperhive__get_agent_meta': + return short + (input.name ? ' ' + input.name : '()'); + case 'mcp__hyperhive__cancel_loose_end': + return short + ' ' + (input.kind || '?') + ' #' + (input.id != null ? input.id : '?'); + case 'mcp__matrix__read_room': + return short + ' ' + fmtRoom(input.room) + + (input.limit != null ? ' [' + input.limit + ']' : ''); + case 'mcp__matrix__mark_read': + return short + ' ' + fmtRoom(input.room); + case 'mcp__matrix__send_message': + return short + ' → ' + fmtRoom(input.room) + ': ' + + JSON.stringify(trim(String(input.body || ''), 50)); + case 'mcp__matrix__send_dm': + return short + ' → ' + fmtUser(input.user_id) + ': ' + + JSON.stringify(trim(String(input.body || ''), 50)); + case 'mcp__matrix__send_reply': + return short + ' → ' + fmtRoom(input.room) + ': ' + + JSON.stringify(trim(String(input.body || ''), 50)); + case 'mcp__matrix__send_reaction': + return short + ' ' + fmtRoom(input.room) + ' ' + (input.key || '?'); + case 'mcp__matrix__join_room': + case 'mcp__matrix__open_dm': + return short + ' ' + (fmtRoom(input.room) || fmtUser(input.user_id) || '?'); + case 'mcp__matrix__invite_user': + return short + ' ' + fmtUser(input.user_id) + ' → ' + fmtRoom(input.room); + case 'mcp__matrix__download_file': + return short + ' ' + fmtRoom(input.room); default: return fmtArgsGeneric(short, input); } }