Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
19cbb5f
feat(replicas-telegram-bridge): Cloudflare Worker bridging Telegram t…
replicas-connector[bot] May 29, 2026
71f7c99
chore(replicas-telegram-bridge): wire up live KV namespace id
replicas-connector[bot] May 29, 2026
ecd7939
feat(replicas-telegram-bridge): wire the outbound reply path
replicas-connector[bot] May 29, 2026
83a9da0
feat(replicas-telegram-bridge): live status streaming via editMessage…
replicas-connector[bot] May 29, 2026
8cdf761
fix(replicas-telegram-bridge): spawn fresh replica when the mapped on…
replicas-connector[bot] May 29, 2026
53d589f
fix(replicas-telegram-bridge): mount helpers from Global env, invoke …
replicas-connector[bot] May 29, 2026
77d9af0
fix(replicas-telegram-bridge): tg-reply.sh splits multi-line into man…
replicas-connector[bot] May 29, 2026
aebf74a
feat(replicas-telegram-bridge): server-side poller surfaces thinking …
replicas-connector[bot] May 29, 2026
53e6b37
chore(replicas-telegram-bridge): add observability + try/catch to poller
replicas-connector[bot] May 29, 2026
430a0c1
feat(replicas-telegram-bridge): render agent Markdown as Telegram HTML
replicas-connector[bot] May 29, 2026
3823449
feat(replicas-telegram-bridge): rolling status log + HTML formatting …
replicas-connector[bot] May 29, 2026
56d61a1
perf(replicas-telegram-bridge): tighter polling cadence + faster agen…
replicas-connector[bot] May 29, 2026
b5252e4
fix(replicas-telegram-bridge): snapshot event count on /watch so foll…
replicas-connector[bot] May 29, 2026
191b9f7
fix(replicas-telegram-bridge): kill the legacy agent helpers so the D…
replicas-connector[bot] May 29, 2026
d0bdbfd
chore(replicas-telegram-bridge): expose DO state via /debug/watcher/{…
replicas-connector[bot] May 29, 2026
6ef3047
perf(replicas-telegram-bridge): bump THINKING_OVERRIDE low -> medium
replicas-connector[bot] May 29, 2026
6a4db4a
fix(replicas-telegram-bridge): dedupe /watch by startMessageId
replicas-connector[bot] May 29, 2026
e1f2b0a
feat(replicas-telegram-bridge): aesthetic status UX — phases, keyboar…
replicas-connector[bot] May 29, 2026
5c626c0
perf(replicas-telegram-bridge): tighter cadence + ticker auto-refresh
replicas-connector[bot] May 29, 2026
74841ae
refactor(replicas-telegram-bridge): native-Telegram status redesign
replicas-connector[bot] May 29, 2026
76ccf54
perf(replicas-telegram-bridge): aggressive parallelization for faster…
replicas-connector[bot] May 29, 2026
b053606
feat(replicas-telegram-bridge): surface assistant narration text in t…
replicas-connector[bot] May 29, 2026
aaf50bf
perf(replicas-telegram-bridge): batch DO storage ops per alarm tick
replicas-connector[bot] May 29, 2026
9b6edd7
feat(replicas-telegram-bridge): render the agent's "Plan (X/N)" block
replicas-connector[bot] May 29, 2026
5f4eb6e
feat(replicas-matrix-bridge): new package — Matrix bot bridge sibling…
replicas-connector[bot] May 29, 2026
43d68e9
fix(replicas-matrix-bridge): pass filter as raw JSON to URLSearchParams
replicas-connector[bot] May 29, 2026
af39f80
feat(bridges): steer follow-ups into the live turn instead of resetting
replicas-connector[bot] May 29, 2026
287f5fc
fix(replicas-matrix-bridge): use transaction_id echo to skip our own …
replicas-connector[bot] May 29, 2026
b6118d1
feat(replicas-matrix-pantalaimon): scaffold E2EE proxy sidecar
replicas-connector[bot] May 29, 2026
982e296
feat(replicas-matrix-bridge): pure-JS Megolm decrypt for E2EE rooms
replicas-connector[bot] May 29, 2026
5bb97a1
fix(bridges): keep rolling log + plan visible after Done/Failed
replicas-connector[bot] May 29, 2026
cc855ca
fix(bridges): terminal edits bypass rate limit + STARTING transitions…
replicas-connector[bot] May 29, 2026
54c3e35
fix(bridges): drop duplicate narration on Done + matrix-rich markdown
replicas-connector[bot] May 29, 2026
2dd0eac
fix(matrix-bridge): use <br> separators in render + add /watch debug …
replicas-connector[bot] May 29, 2026
0d7e7fb
feat(replicas-matrix-bridge): @matrix-org/olm WASM running in CF Worker
replicas-connector[bot] May 29, 2026
020ffec
feat(replicas-matrix-bridge): OlmVault DO + device/OTK upload to matr…
replicas-connector[bot] May 29, 2026
47bdf0e
feat(replicas-matrix-bridge): wire to_device + live Megolm keystore
replicas-connector[bot] May 29, 2026
60df1eb
feat(replicas-matrix-bridge): dedicated bot device + vault/listener r…
replicas-connector[bot] May 29, 2026
4fc1ddf
feat(replicas-matrix-bridge): cross-sign bot device with SSSS recover…
replicas-connector[bot] May 29, 2026
439ff3f
fix(bridges): only splice trailing 💬 narration when tool-call lines e…
replicas-connector[bot] May 29, 2026
e9722e7
feat(bridges): surface every Replicas event + restyle status frame
replicas-connector[bot] May 29, 2026
17a804e
fix(bridges): retry the final markdown reply until it actually lands
replicas-connector[bot] May 29, 2026
2837f9b
feat(replicas-matrix-bridge): room-size aware dispatch + !model command
replicas-connector[bot] May 29, 2026
4a44364
fix(replicas-matrix-bridge): redact 👀 ack when placing terminal emoji
replicas-connector[bot] May 29, 2026
e4d1065
perf(replicas-matrix-bridge): tier-1 speedups — ~400ms TTFB win
replicas-connector[bot] May 29, 2026
d9708fe
perf(replicas-matrix-bridge): tier-2 speedups — pre-spawn frame + par…
replicas-connector[bot] May 29, 2026
fcf6da1
perf(replicas-telegram-bridge): tier 1 + 2 parity with matrix bridge
replicas-connector[bot] May 29, 2026
82d3256
fix(bridges): kill duplicated final-reply renders
replicas-connector[bot] May 29, 2026
9394264
fix(bridges): kill Done-frame edit loop + cross-tick narration duplic…
replicas-connector[bot] May 29, 2026
3dc3f33
fix(bridges): close setTerminal→pendingCleanup race in steering path
replicas-connector[bot] May 29, 2026
8728c39
feat(bridges): focus-window UI for status frame
replicas-connector[bot] May 29, 2026
0a552a9
feat(matrix-bridge): embed result body in Done frame (one message per…
replicas-connector[bot] May 29, 2026
d79c798
fix(matrix-bridge): stop fragmenting status frames under rate limit
replicas-connector[bot] May 29, 2026
dd74c60
revert(matrix-bridge): drop focus window; harden reactions vs 429
replicas-connector[bot] May 29, 2026
e5f0ae3
fix(matrix-bridge): terminal renders retry on 429 so Done frame lands
replicas-connector[bot] May 29, 2026
8a6ffca
docs: add comprehensive agent handoff for the bridges work
replicas-connector[bot] May 29, 2026
6e84564
docs: link bridges handoff from root + sub-folder AGENTS.md
replicas-connector[bot] May 29, 2026
ad67ac2
docs: ACP + Telegram bot status-surface research
replicas-connector[bot] May 29, 2026
b072281
docs(research): add Open-ACP/OpenACP findings to status-message research
replicas-connector[bot] May 29, 2026
11a0b41
feat(matrix-bridge): per-tool lifecycle status icons + Tools (M/N) he…
replicas-connector[bot] May 29, 2026
2e11281
merge: build on lifecycle status icons (PR #14)
replicas-connector[bot] May 29, 2026
6678625
feat(matrix-bridge): 11-feature visibility + awareness batch
replicas-connector[bot] May 29, 2026
32a9f2d
feat(matrix-bridge): admin watcher cancel + debug room-name endpoints
replicas-connector[bot] May 29, 2026
625f367
fix(matrix-bridge): land terminal frame before silent deleteAll
replicas-connector[bot] May 29, 2026
04e1c14
feat(matrix-bridge): /debug/invites + /debug/joined-rooms + /admin/jo…
replicas-connector[bot] May 29, 2026
c691ad1
feat(matrix-bridge): heartbeat spinner + live tool elapsed; never loo…
replicas-connector[bot] May 29, 2026
a803bf7
chore(matrix-bridge): bring untracked stale fixes back to head
replicas-connector[bot] May 29, 2026
208ea67
fix(matrix-bridge): drop silent sendFollowUp failure path
replicas-connector[bot] May 29, 2026
4a43c9f
fix(matrix-bridge): pre-set safety-net alarm before listener body
replicas-connector[bot] May 29, 2026
250a42f
feat(matrix-bridge): split long turns into multiple message blocks
replicas-connector[bot] May 29, 2026
72a55fa
feat(matrix-bridge): seal-on-steer so each steered prompt opens fresh…
replicas-connector[bot] May 29, 2026
5d4d2ee
feat(matrix-bridge): reply as own block + subscription usage windows
replicas-connector[bot] May 29, 2026
54c1525
feat(matrix-bridge): UI polish — quadrant heartbeat, dotted seal trai…
replicas-connector[bot] May 29, 2026
7771f8b
feat(matrix-bridge): % left in 🪙 row + configurable plan quotas
replicas-connector[bot] May 29, 2026
e258bf1
fix(matrix-bridge): pre-set safety-net alarm in watcher poller
replicas-connector[bot] May 29, 2026
4e53109
feat(matrix-bridge): use Anthropic's real rate_limit_event payload
replicas-connector[bot] May 29, 2026
2e69269
feat(matrix-bridge): cron-driven invite sweeper
replicas-connector[bot] May 29, 2026
47641e4
feat(matrix-bridge): E2EE auto-recovery via m.room_key_request
replicas-connector[bot] May 29, 2026
8c4a5c8
feat(matrix-bridge): /admin/recover-room + /debug/vault/lookup
replicas-connector[bot] May 29, 2026
44f186e
feat(matrix-bridge): delivery verification + KV collision detector
replicas-connector[bot] May 29, 2026
c5dba15
feat(matrix-bridge): sanitize JSON-bound text + clearer surrogate fai…
replicas-connector[bot] May 29, 2026
9c2ca07
feat(matrix-bridge): auto-cut on unrecoverable claude-result errors
replicas-connector[bot] May 29, 2026
dc9a624
chore(matrix-bridge): auto-cut also flushes model: override, surfaces…
replicas-connector[bot] May 29, 2026
f219f9a
fix(matrix-bridge): atomic pendingCleanup in setTerminal + orphan det…
replicas-connector[bot] May 29, 2026
2313473
fix(matrix-bridge): 6 audit findings — races, leaks, recovery gaps
replicas-connector[bot] May 29, 2026
2d7b530
fix(matrix-bridge): bump replica TTL + auto-respawn on 404
replicas-connector[bot] May 29, 2026
732f850
fix(matrix-bridge): never auto-delete replicas on inactivity
replicas-connector[bot] May 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,15 @@ A task is only "done" when **all** of these are true:
task "seems small".
- Hand-roll HTTP clients for SaaS APIs that already have a composite
tool / MCP server available.

## Project-specific deep dives

When working inside one of these subdirectories, read the linked
handoff *before* writing code — it captures the architecture, prior
decisions, things Jaden has explicitly liked/disliked, and the known
open work for that project.

- **`replicas-matrix-bridge/` + `replicas-telegram-bridge/`** —
Cloudflare Workers that bridge Beeper/Matrix and Telegram to the
Replicas agent runtime. Full handoff: [`docs/agent-handoff.md`](docs/agent-handoff.md).
Each subfolder also has its own `AGENTS.md` pointing here.
266 changes: 266 additions & 0 deletions docs/acp-telegram-status-research.md

Large diffs are not rendered by default.

279 changes: 279 additions & 0 deletions docs/agent-handoff.md

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions replicas-matrix-bridge/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules/
.wrangler/
.dev.vars
dist/
*.log
22 changes: 22 additions & 0 deletions replicas-matrix-bridge/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# AGENTS.md — replicas-matrix-bridge

Read **[`../docs/agent-handoff.md`](../docs/agent-handoff.md)** before touching
code in this directory. It covers:

- Architecture + end-to-end flow (listener → dispatch → poller)
- File-by-file index with line ranges for the hot path
- The full Durable Object storage-key model
- Recent commits with reasoning (why each fix exists)
- Production endpoints, deploy commands, log-tail filters
- Known open issues
- **Things Jaden likes vs. has explicitly disliked** — do not rebuild
the focus-window UI; do not break the prompt-reaction emojis

Then follow the universal principles in the root [`../AGENTS.md`](../AGENTS.md).

Quick orientation:

- Worker name: `replicas-matrix-bridge`
- Latest deploy at the time of handoff: matrix version `941d8c95` (commit `e5f0ae3`)
- Hot file: `src/poller.ts` (the ReplicaPoller DO state machine)
- Render: `src/render.ts` (simple line-stream rolling log — do not collapse tool calls)
110 changes: 110 additions & 0 deletions replicas-matrix-bridge/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# replicas-matrix-bridge

Cloudflare Worker that bridges a Matrix (Beeper) bot account to Replicas workspaces, mirroring the Telegram bridge UX. Sibling package to `replicas-telegram-bridge/`.

## Architecture (Phase 1 — unencrypted rooms)

```
You (Beeper/Element) → Matrix Client-Server API → MatrixListener DO (alarm-driven /sync)
/v1/replica spawn or follow-up
ReplicaPoller DO (per replica)
m.replace edit on the status message
```

Same `render.ts` / `markdown.ts` / state-machine semantics as the Telegram bridge — only the outbound calls differ. Tool-call lines, plan blocks (`Plan (X/N)` + `~item~`), narration messages, expandable old-log, phase emoji, time ticker, reactions on the user's prompt: all identical.

## Setup

### 1. Create a Beeper bot account

- Sign up `replicas-bot@…` on `beeper.com` as a second account.
- In Beeper Desktop → Settings → Help & About → **Show access token**. Format starts with `syt_…`.
- Note the bot's Matrix user ID (e.g. `@replicas-bot:beeper.com`) — visible at the top of the same page.

### 2. Wire Cloudflare

```bash
cd replicas-matrix-bridge
bun install

# Create the KV namespace (paste the returned id into wrangler.toml).
wrangler kv:namespace create MAP

# Set secrets.
wrangler secret put MATRIX_ACCESS_TOKEN # syt_…
wrangler secret put MATRIX_USER_ID # @replicas-bot:beeper.com
wrangler secret put REPLICAS_API_KEY # same key the Telegram bridge uses

# Deploy.
wrangler deploy
```

### 3. Kick the listener once

```bash
curl -X POST https://replicas-matrix-bridge.<your-worker-subdomain>.workers.dev/start-listener
```

The cron trigger (`*/1 * * * *`) will keep it alive after that.

### 4. Invite the bot to a room

From your own Beeper account, invite `@replicas-bot:beeper.com` to a new DM. The listener auto-accepts within ~1s. Send a message — should produce 👀 + a status frame, edited in place as the agent works.

## Status frame example

```
🤔 Starting · 0s
```

becomes, mid-task:

```
🔧 Running · step 3 · 14s
<i>Reading the codebase to choose strategy…</i>

📋 Plan (1/3)
✓ scaffold
◦ wire it up
◦ test

🔧 ls -la src/
📖 src/index.ts
✏️ src/server.ts
```

and finally:

```
🎉 Done · 14s
```

— with the actual answer landing as a separate Markdown-rendered message right under it. The bot also sets reactions on the user's prompt (`👀` → phase → `🎉` or `😭`), pins the active status message, and keeps a typing indicator alive throughout.

## Cancelling a run

- Reply to the status message with `!cancel`. The listener picks it up and tells the DO to `DELETE /v1/replica/{id}`.

## Limitations

- **Unencrypted rooms only**. Beeper enforces E2EE by default; Matrix's Olm/Megolm key handling doesn't fit on Cloudflare Workers. Either use a manually-unencrypted DM, or wait for v2 (hosted listener with `matrix-bot-sdk`).
- **Self-bot mode supported**. If `MATRIX_USER_ID` is your own account (no dedicated bot user), the listener still works: it skips events whose `unsigned.transaction_id` is set (those echo the bot worker's own sends) instead of filtering by `sender`. Messages you type in Element/Beeper come back without `transaction_id` set and trigger normally.
- **No inline keyboards**. Matrix has no equivalent; cancel is via `!cancel` reply.
- **No `<details>`**. Older log entries go into a plain `<blockquote>` (the user scrolls), not the expandable caret we use in Telegram.

## Files

| File | Purpose |
|------|---------|
| `src/index.ts` | Worker entrypoint + HTTP routes |
| `src/listener.ts` | `MatrixListener` DO — holds the /sync long-poll |
| `src/poller.ts` | `ReplicaPoller` DO — Matrix-flavored ReplicaPoller |
| `src/dispatch.ts` | `handleMatrixMessage` — KV lookup → spawn/follow-up |
| `src/matrix.ts` | Matrix Client-Server API client (sendMessage, editMessage via m.replace, react via m.annotation, redact, pin, unpin, typing, joinRoom, sync, whoami) |
| `src/render.ts` | Pure render functions — copied verbatim from telegram bridge |
| `src/markdown.ts` | Markdown → HTML — copied verbatim from telegram bridge |
| `src/*.test.ts` | Vitest suite — 58 tests |
| `wrangler.toml` | KV/DO bindings, env vars, cron trigger |
Loading