mirror of
https://github.com/block/buzz.git
synced 2026-10-27 04:30:52 +00:00
🤖 ## Summary When someone edits a message to add an @mention, the app does not change the original message. It publishes a separate hidden "edit" event that points back at it. An agent that handles the edit must work on the **original message**: it reacts, replies, and posts any error notice on that message or in its thread. Before this PR, an agent treated the hidden edit as a new message. It replied in the wrong place, and with per-thread sessions it started a new, empty conversation. This is the first of three PRs. It sets where agents reply to edits. It does not yet make edits wake agents by default (#6131 does that). - The agent looks up the original message once, when it accepts the edit. Every later step uses that result: the session, reactions, typing indicator, reply target, and failure notices. - **Per-thread sessions** (the `thread` session policy, where each thread has its own agent conversation): the edit joins the original message's thread session. It does not start a new session. - The original is a reply in a thread: the edit joins that thread. - The original is a top-level message: the edit joins the thread that starts at the original. - **Channel sessions** (the default policy) and DMs: nothing changes. The whole channel shares one conversation. - Setup mode (the reply that asks the owner to finish configuring the agent) now accepts edits. It replies at the original message or its thread. If the original could not be fetched, the reply posts at the top of the channel. - Error notices for an edit (sign-in failure, hard timeout, retries used up) now appear in the original's thread, or as a reply to a top-level original. Before, they appeared at the top of the channel. If the original could not be fetched when the edit was accepted, the notice looks it up once more. If it is still unknown, the notice posts at the top of the channel. - If a newer request interrupts a turn that is working on an edit, the next turn treats the edit as earlier work that the new request replaces. The old edit does not run again. ## Details - The lookup has a 2-second limit. It runs only for edits that already matched a subscription rule (by default, edits that newly mention this agent). It must finish before the edit is queued, because the session is chosen at that point. - If the lookup fails, the agent still targets the edited message's ID, never the hidden edit event. Notices and setup replies never claim that message as a thread root, because the relay rejects a root that does not match the message's real thread. **Known gap:** if that message is a reply in a thread, the agent cannot learn the thread root. So under per-thread sessions it uses a separate session rooted at that reply, and it loses the thread's earlier context. Its reply still goes to the right message. Closing this gap needs a second lookup, which is left out on purpose. - The original is fetched with an explicit kind (stream message or its edit) and a channel filter, because the relay rejects lookups without a kind. - Each queued event carries its own route, so an edit shares a batch with other events like any message. Batch order is unchanged from `main`. ### Stack **1 of 3**, based on `main`. Next: #6131 (edits wake agents by default), then #6132 (edits join a turn that is already running). ### Related issue Part of #2540. The issue is fixed when #6131 merges. ### Testing - `cargo test -p buzz-acp --all-targets` passes. One existing test, `session_new_forwards_complete_git_block_without_duplicate_names`, fails in a shell where the git setting `nostr.keyfile` is set. It passes when the setting is removed. This PR does not touch that test. - Session tests: an edit uses the original's thread for a threaded original, a top-level original, and an original that could not be fetched. It never uses the edit event. - Tests check the signed events that the agent publishes: setup-mode replies and failure notices, each for a threaded original, a top-level original, and an original that could not be fetched (including a notice whose second lookup finds the original). If either routing fix is reverted, these tests fail. - A queue-to-prompt test interrupts a turn on an edit with a newer request. The next prompt has the edit as earlier work and the new request with the "replaces earlier work" framing, and nothing is left to run again. --------- Signed-off-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz> Co-authored-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz>