Skip to content

feat(matrix-bridge): per-tool lifecycle status icons + Tools (M/N) header#14

Open
replicas-connector[bot] wants to merge 1 commit into
feat/replicas-telegram-bridgefrom
feat/matrix-tool-lifecycle-status-icons
Open

feat(matrix-bridge): per-tool lifecycle status icons + Tools (M/N) header#14
replicas-connector[bot] wants to merge 1 commit into
feat/replicas-telegram-bridgefrom
feat/matrix-tool-lifecycle-status-icons

Conversation

@replicas-connector

@replicas-connector replicas-connector Bot commented May 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Mirrors the OpenACP UX Jaden screenshotted in the Slack thread — each tool line ticks live, the header shows a running M/N counter. References the research doc Detailed Deep-Dive §2 (ToolCard internals) and §5 (renderToolCard layout).

Before / After

Before:

🔧 Running · step 4 · 14s

🔧 ls -la src/
🔧 grep -r "foo" src/
↳ index.ts main.ts util.ts
🔧 git status
↳ On branch main

After:

🔧 Running · step 4 · 14s

📋 Tools (2/3)

✅ 🔧 ls -la src/
✅ 🔧 grep -r "foo" src/
↳ index.ts main.ts util.ts
🔄 🔧 git status

…then when git status finishes:

📋 Tools (3/3) ✅

✅ 🔧 ls -la src/
✅ 🔧 grep -r "foo" src/
↳ index.ts main.ts util.ts
✅ 🔧 git status
↳ On branch main

Implementation

Pairing tool_use → tool_result

ContentBlock gains id (the Anthropic-assigned toolu_…) and tool_use_id (the back-pointer Anthropic carries on tool_result blocks). The poller keeps a toolLineIndex: Record<string, number> in DO storage mapping tool_use.id → row index in lines. Persisted in the writes batch; wiped on /watch fresh-spawn so a new turn doesn't inherit stale mappings.

Status prefix mutation

  • On tool_use projection: push line as 🔄 ${formatToolUseLine} and record the row index under block.id.
  • On tool_result projection: look up the row by block.tool_use_id, mutate the leading 🔄 (success) or (error). Then delete toolLineIndex[block.tool_use_id] — one-shot, so a malformed duplicate result can't keep flipping the row.

Tools (M/N) header

render.ts gains renderToolsHeader(lines: string[]): string. Stateless — scans for 🔄// prefixes, counts done and total. Returns 📋 Tools (M/N) with a trailing when M === N && N > 0 (matches OpenACP's allComplete header). Wired into both renderActive and renderTerminal above the rolling log.

Test plan

  • bun run typecheck clean
  • bun test src/render.test.ts48/48 pass (5 new for renderToolsHeader: empty input, mixed done/running, all-complete suffix, ignoring non-tool lines)
  • Deployed to matrix bridge worker bee12be7
  • Live test: send a multi-tool prompt; expect each tool line to start as 🔄 …, tick to ✅ … (or ❌ …) as it finishes, and the header counter to climb in real time
  • Live test: trigger an error in one tool (e.g., ls /nonexistent); expect that row's prefix to become

Not in this PR (deferred)

  • Telegram bridge gets the same treatment in a follow-up. It still has the focus-window code from commit 8728c39 per docs/agent-handoff.md; that needs to be reverted first so the new prefixes and header slot in cleanly.

Created by Jaden (jadengarza@pm.me) with Replicas
Workspace  ·  Slack Thread

Open in Devin Review

…ader

Mirrors the OpenACP UX Jaden shared screenshots of (see
docs/acp-telegram-status-research.md Detailed Deep-Dive § 2 + § 5).
Each tool line now ticks live: 🔄 while running, ✅ on success, ❌ on
error. A "📋 Tools (M/N) ✅" header sits above the rolling log so the
user can see how many tools have completed at a glance.

How it works:
- ContentBlock gains `id` (Anthropic-assigned `toolu_…`) and
  `tool_use_id` (the back-pointer carried by tool_result blocks).
- The poller maintains a `toolLineIndex: Record<string, number>` in DO
  storage that maps tool_use.id → the row index in `lines` where its
  rendered call lives. Persisted in the writes batch; wiped on /watch
  fresh-spawn alongside `lines`/`plan` so a new turn starts clean.
- On tool_use projection: line is pushed as `🔄 ${formatToolUseLine}`
  and the row index is recorded under the block's id.
- On tool_result projection: the original row's leading `🔄 ` is
  mutated in place to `✅ ` (success) or `❌ ` (error). The
  toolLineIndex entry is then deleted — one-shot, so a malformed
  duplicate result can't keep flipping the row.
- render.ts gains `renderToolsHeader(lines)`: scans for 🔄/✅/❌
  prefixes, returns "📋 Tools (M/N)" — with a trailing ✅ when
  M === N. Wired into both renderActive and renderTerminal above the
  rolling log.

Tests: 5 new for renderToolsHeader covering empty input, mixed
done/running states, all-complete suffix, and ignoring non-tool
lines (narration, outputs, user steers). 48/48 pass.

Telegram bridge gets the same treatment in a follow-up — needs the
focus-window revert first (still on commit 8728c39 per the handoff)
to slot in cleanly. Matrix-only for this PR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: itsablabla <itsablabla@users.noreply.github.com>
@capy-ai

capy-ai Bot commented May 29, 2026

Copy link
Copy Markdown
Contributor

Capy auto-review is paused for this organization because the monthly auto-review limit has been reached. Increase the limit or turn it off in billing settings to resume automatic reviews.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 4 additional findings.

Open in Devin Review

@replicas-connector

Copy link
Copy Markdown
Contributor Author

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 4 additional findings.

Open in Devin Review

@devin-ai-integration[bot] This repository is not connected to a Replicas organization.

To enable Replicas on this repository:

  1. Go to GitHub integration settings
  2. Add this repository to your organization

Note: Each repository can only be connected to one Replicas organization.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants