feat(watch): --ignore-from — Notifier nicht vom Watchdog zumüllen lassen
Der Architekten-Message-Notifier (`watch --await-message claude`) feuerte bei
JEDER Nachricht — auch bei den Watchdog-Erinnerungen, die alle paar Minuten
eintreffen ("review waiting 5m/10m/15m…"). Real erlebt: dreimal hintereinander
geweckt worden, ohne dass etwas Neues passiert war. Ein Signal, das im Takt
seiner eigenen Erinnerungen feuert, entwertet sich selbst.
`--ignore-from <agents>` blendet Absender aus; message-Events tragen dafür
jetzt `from` (bisher nur im title). Armung des Architekten künftig mit
`--ignore-from agenthub` — echte Agenten-Post weckt weiterhin sofort, die
Watchdog-Erinnerungen sieht man beim Pollen ohnehin.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7a4ccaeb61
commit
c2e19b3371
@ -168,10 +168,16 @@ async function fetchUnreadMessages(serverUrl: string, agent: string): Promise<Ag
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isMessageFor(event: AgentHubEvent, agent: string): boolean {
|
function isMessageFor(event: AgentHubEvent, agent: string, ignoreFrom: string[] = []): boolean {
|
||||||
if (event.type !== 'message' || event.action !== 'created') return false;
|
if (event.type !== 'message' || event.action !== 'created') return false;
|
||||||
const to = event.assignedTo;
|
const to = event.assignedTo;
|
||||||
return !!to && messageRecipientAliases(agent).has(String(to).toLowerCase());
|
if (!to || !messageRecipientAliases(agent).has(String(to).toLowerCase())) return false;
|
||||||
|
// Absender ausblenden, die den Notifier nur zumüllen. Konkreter Fall: der
|
||||||
|
// Watchdog schreibt dem Architekten alle paar Minuten Erinnerungen — ohne
|
||||||
|
// Filter weckt der Notifier ihn im Takt dieser Erinnerungen, obwohl nichts
|
||||||
|
// Neues passiert ist, und das Signal entwertet sich selbst.
|
||||||
|
const sender = String(event.from ?? (event.title ?? '').split('→')[0] ?? '').trim().toLowerCase();
|
||||||
|
return !ignoreFrom.some((ignored) => ignored.trim().toLowerCase() === sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -188,7 +194,7 @@ function isMessageFor(event: AgentHubEvent, agent: string): boolean {
|
|||||||
*/
|
*/
|
||||||
export async function watchEvents(
|
export async function watchEvents(
|
||||||
serverUrl: string,
|
serverUrl: string,
|
||||||
options: { once?: boolean; role?: string; awaitReview?: boolean; awaitMessage?: string; newOnly?: boolean } = {},
|
options: { once?: boolean; role?: string; awaitReview?: boolean; awaitMessage?: string; newOnly?: boolean; ignoreFrom?: string[] } = {},
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const url = new URL('/events', serverUrl);
|
const url = new URL('/events', serverUrl);
|
||||||
// Pass role to the server for an additional server-side filter (saves
|
// Pass role to the server for an additional server-side filter (saves
|
||||||
@ -280,7 +286,7 @@ export async function watchEvents(
|
|||||||
await reader.cancel();
|
await reader.cancel();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (options.awaitMessage && isMessageFor(event, options.awaitMessage)) {
|
if (options.awaitMessage && isMessageFor(event, options.awaitMessage, options.ignoreFrom)) {
|
||||||
await reader.cancel();
|
await reader.cancel();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -927,6 +927,7 @@ export function createProgram(cwd: string): Command {
|
|||||||
.option('--await-review', 'Exit when an implementer submits (task → review); architect review-queue notifier')
|
.option('--await-review', 'Exit when an implementer submits (task → review); architect review-queue notifier')
|
||||||
.option('--await-message <agent>', 'Exit when an unread message arrives for agent/role; architect message notifier')
|
.option('--await-message <agent>', 'Exit when an unread message arrives for agent/role; architect message notifier')
|
||||||
.option('--new-only', 'With --await-review/--await-message: ignore existing backlog on connect (re-armable without spinning)')
|
.option('--new-only', 'With --await-review/--await-message: ignore existing backlog on connect (re-armable without spinning)')
|
||||||
|
.option('--ignore-from <agents>', 'With --await-message: comma-separated senders to ignore (e.g. "agenthub" to mute watchdog reminders)')
|
||||||
.action(async (options) => {
|
.action(async (options) => {
|
||||||
const { serverUrl } = await resolveContext(program, cwd);
|
const { serverUrl } = await resolveContext(program, cwd);
|
||||||
if (!serverUrl) {
|
if (!serverUrl) {
|
||||||
@ -939,6 +940,7 @@ export function createProgram(cwd: string): Command {
|
|||||||
role: options.role as string | undefined,
|
role: options.role as string | undefined,
|
||||||
awaitReview: options.awaitReview as boolean | undefined,
|
awaitReview: options.awaitReview as boolean | undefined,
|
||||||
awaitMessage: options.awaitMessage as string | undefined,
|
awaitMessage: options.awaitMessage as string | undefined,
|
||||||
|
ignoreFrom: typeof options.ignoreFrom === 'string' ? options.ignoreFrom.split(',') : undefined,
|
||||||
newOnly: options.newOnly as boolean | undefined,
|
newOnly: options.newOnly as boolean | undefined,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -15,6 +15,8 @@ export interface AgentHubEvent {
|
|||||||
status?: string;
|
status?: string;
|
||||||
role?: string;
|
role?: string;
|
||||||
assignedTo?: string;
|
assignedTo?: string;
|
||||||
|
/** Absender bei message-Events — erlaubt Empfängern, System-Post zu filtern. */
|
||||||
|
from?: string;
|
||||||
claimedBy?: string;
|
claimedBy?: string;
|
||||||
reviewer?: string;
|
reviewer?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -675,6 +675,7 @@ export async function registerRoutes(app: FastifyInstance, cwd: string): Promise
|
|||||||
id: message.id,
|
id: message.id,
|
||||||
title: `${message.from} → ${message.to}`,
|
title: `${message.from} → ${message.to}`,
|
||||||
assignedTo: message.to,
|
assignedTo: message.to,
|
||||||
|
from: message.from,
|
||||||
},
|
},
|
||||||
message.updatedAt,
|
message.updatedAt,
|
||||||
);
|
);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user