mirror of
https://github.com/block/buzz.git
synced 2026-10-27 04:30:52 +00:00
fix(acp): wake agents for mentions added by edits (#6131)
🤖 ## Summary Today an agent does not wake up when someone edits an existing message to @mention it. With this PR, adding the mention in an edit is enough to reach the agent. The agent then works on the original message, as #4741 set up. - Agents now receive message edits by default. Before, they subscribed only to new messages (and a few other event types). - The desktop app puts a mention tag on an edit only for people whom that edit newly mentions. So an agent wakes once, for the new mention. It does not wake again when the same message is edited later. This PR also fixes one case in the desktop app: when the original also mentioned someone whose profile was not loaded, every mention counted as new, so a typo fix woke the agent again. Now the recipients that the app knows from the original always count as already notified. - This default applies in normal mode, to channels the agent joins while it is running, and in setup mode. - If you give an explicit `--kinds` list, it is used without change. - Sessions do not change in this PR. An edit uses the session that #4741 chooses: with per-thread sessions, the original message's thread; with channel sessions, the channel. ## Details - The change adds the edit event kind (40003) to one shared default list. The startup rules, the relay subscription filters, and the setup rules all use that list. - An agent accepts an event only if both the relay subscription and its local rules allow it. The normal listener's startup rules now come from one function, `startup_subscription_rules`. The harness and the tests both call it, so the tests check the rules that actually run. ### Stack **2 of 3**, based on #4741. Next: #6132. ### Related issue Fixes #2540. ### Testing - `cargo test -p buzz-acp --all-targets` passes. The one test that fails when the git setting `nostr.keyfile` is set is described in #4741. - Admission tests run on the rules the harness installs, for the normal listener and for setup mode. An edit that mentions the agent is accepted. An edit that does not mention it is rejected. - I removed kind 40003 from each of the two defaults, one at a time. Each time, these tests failed. - Config tests check that edits are in the default kinds for startup channels and for channels joined later. - Desktop regression: `@Agent @Missing User please chek` edited to `check`, with only the agent's profile loaded, sends no new notification. It fails on the old code. --------- Signed-off-by: npub1em3jmyn4vu57urqf03txrwreccvejvwdy5c4er8nnrwt7rc4tncscs3ssu <cee32d92756729ee0c097c5661b879c6199931cd25315c8cf398dcbf0f155cf1@buzz.block.builderlab.xyz> Signed-off-by: Larry <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz> Signed-off-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz> Co-authored-by: npub1em3jmyn4vu57urqf03txrwreccvejvwdy5c4er8nnrwt7rc4tncscs3ssu <cee32d92756729ee0c097c5661b879c6199931cd25315c8cf398dcbf0f155cf1@buzz.block.builderlab.xyz> Co-authored-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz>
This commit is contained in:
@@ -86,6 +86,44 @@ test("edit save uses edit-target refs that resolve after edit-open", async () =>
|
||||
});
|
||||
});
|
||||
|
||||
test("an unresolved recipient does not re-notify an unchanged agent mention", async () => {
|
||||
const { buildEditMentionState } = await import("../lib/draftMentionRefs.ts");
|
||||
const agent = "c".repeat(64);
|
||||
const originalContent = "@Agent @Missing User please chek";
|
||||
const editTarget = buildEditMentionState(
|
||||
originalContent,
|
||||
[
|
||||
["p", agent],
|
||||
["p", UNRESOLVED_USER],
|
||||
],
|
||||
{ [agent]: { displayName: "Agent" } },
|
||||
(pubkey) => pubkey === agent,
|
||||
);
|
||||
assert.deepEqual(
|
||||
editTarget.mentionRefs.map((ref) => ref.pubkey),
|
||||
[agent],
|
||||
);
|
||||
assert.deepEqual(editTarget.unresolvedMentionPubkeys, [UNRESOLVED_USER]);
|
||||
const calls = [];
|
||||
await submitMessageEdit({
|
||||
...baseOptions(async (_content, tags, notifying) => {
|
||||
calls.push(["save", tags, notifying]);
|
||||
}),
|
||||
content: "@Agent @Missing User please check",
|
||||
originalContent,
|
||||
editTarget,
|
||||
extractMentionPubkeys: (text) => (text.includes("@Agent") ? [agent] : []),
|
||||
revalidateMentionPubkeys: async (pubkeys) => {
|
||||
calls.push(["revalidate", pubkeys]);
|
||||
return pubkeys;
|
||||
},
|
||||
});
|
||||
assert.deepEqual(calls[0], ["revalidate", []]);
|
||||
const [, tags, notifying] = calls[1];
|
||||
assert.deepEqual(notifying, []);
|
||||
assert.ok(tags.some(([name, key]) => name === "mention" && key === agent));
|
||||
});
|
||||
|
||||
test("edit save revalidates added mentions immediately before save", async () => {
|
||||
const agent = "c".repeat(64);
|
||||
const calls = [];
|
||||
|
||||
@@ -117,10 +117,12 @@ export async function submitMessageEdit({
|
||||
};
|
||||
// Current picker bindings must not reinterpret the original body: selecting a
|
||||
// different Scout would otherwise make that new key look already notified.
|
||||
// With unresolved history, conservatively revalidate all current recipients.
|
||||
const originalMentionPubkeys = editTarget.unresolvedMentionPubkeys?.length
|
||||
? []
|
||||
: (editTarget.mentionRefs ?? []).map((ref) => ref.pubkey);
|
||||
// Resolved historical keys are already recipients, so an unresolved neighbor
|
||||
// must not make them notify again. Unresolved keys have no trusted binding to
|
||||
// the edited text; they stay out of this set and are revalidated if present.
|
||||
const originalMentionPubkeys = (editTarget.mentionRefs ?? []).map(
|
||||
(ref) => ref.pubkey,
|
||||
);
|
||||
let addedMentionPubkeys: string[];
|
||||
try {
|
||||
addedMentionPubkeys = diffAddedMentionPubkeys(
|
||||
|
||||
Reference in New Issue
Block a user