UUID refactoring: self-identification by member_id, mention filtering by ID instead of slug
This commit is contained in:
parent
7d7fe6df42
commit
9e8307d8bc
@ -46,7 +46,10 @@ async function startAgentWs(config: AgentConfig, client: TrackerClient): Promise
|
||||
await wsTransport.start();
|
||||
logger.info('Connected to tracker via WebSocket');
|
||||
|
||||
// Register project mappings for memory context
|
||||
// Register member ID and project mappings from auth.ok
|
||||
if (wsTransport.memberId) {
|
||||
router.setMemberId(wsTransport.memberId);
|
||||
}
|
||||
if (wsTransport.projects.length > 0) {
|
||||
router.setProjectMappings(wsTransport.projects);
|
||||
}
|
||||
|
||||
@ -21,6 +21,8 @@ export class EventRouter {
|
||||
private wsTransport: WsClientTransport | null = null;
|
||||
/** chat_id → project_id mapping (populated from auth.ok) */
|
||||
private chatToProject: Map<string, string> = new Map();
|
||||
/** Own member_id from auth.ok */
|
||||
private memberId: string | null = null;
|
||||
|
||||
constructor(
|
||||
private config: AgentConfig,
|
||||
@ -40,6 +42,12 @@ export class EventRouter {
|
||||
this.wsTransport = transport;
|
||||
}
|
||||
|
||||
/** Set own member_id from auth.ok */
|
||||
setMemberId(id: string): void {
|
||||
this.memberId = id;
|
||||
this.log.info('Member ID set: %s', id);
|
||||
}
|
||||
|
||||
/** Register chat_id → project_id mappings from auth.ok */
|
||||
setProjectMappings(projects: Array<{ id: string; chat_id?: string | null }>): void {
|
||||
for (const p of projects) {
|
||||
@ -108,7 +116,6 @@ export class EventRouter {
|
||||
*/
|
||||
private async handleMessageNew(data: Record<string, unknown>): Promise<void> {
|
||||
const content = (data.content as string) || '';
|
||||
const authorSlug = (data.author_slug as string) || (data.sender_slug as string) || '';
|
||||
const authorType = (data.author_type as string) || 'member';
|
||||
const taskId = data.task_id as string | undefined;
|
||||
const chatId = data.chat_id as string | undefined;
|
||||
@ -117,7 +124,14 @@ export class EventRouter {
|
||||
|
||||
// Extract author info from nested author object if present
|
||||
const author = data.author as Record<string, unknown> | undefined;
|
||||
const resolvedAuthorSlug = authorSlug || (author?.slug as string) || '';
|
||||
const authorId = (data.author_id as string) || (author?.id as string) || '';
|
||||
const authorSlug = (data.author_slug as string) || (author?.slug as string) || '';
|
||||
|
||||
// Extract mention IDs from mentions array
|
||||
const mentions = (data.mentions || []) as Array<Record<string, unknown>>;
|
||||
const mentionIds = new Set(mentions.map(m => (m.id as string) || '').filter(Boolean));
|
||||
const isMentioned = (this.memberId && mentionIds.has(this.memberId)) ||
|
||||
content.includes(`@${this.config.slug}`); // text fallback
|
||||
|
||||
if (!content) {
|
||||
this.log.warn({ data }, 'message.new event missing content');
|
||||
@ -125,25 +139,23 @@ export class EventRouter {
|
||||
}
|
||||
|
||||
// Ignore own messages (agent talking to itself)
|
||||
if (resolvedAuthorSlug === this.config.slug) {
|
||||
if ((this.memberId && authorId === this.memberId) || authorSlug === this.config.slug) {
|
||||
this.log.info('│ Skipping own message');
|
||||
return;
|
||||
}
|
||||
|
||||
// Ignore messages from other agents (unless explicitly @mentioned)
|
||||
// Prevents infinite reply loops between agents
|
||||
// Ignore messages from other agents (unless explicitly mentioned)
|
||||
if (authorType === 'agent') {
|
||||
if (!content.includes(`@${this.config.slug}`)) {
|
||||
this.log.info('│ Skipping agent message (not mentioned): @%s "%s"', resolvedAuthorSlug, content.slice(0, 80));
|
||||
if (!isMentioned) {
|
||||
this.log.info('│ Skipping agent message (not mentioned): %s "%s"', authorSlug, content.slice(0, 80));
|
||||
return;
|
||||
}
|
||||
this.log.info('│ Processing agent message (mentioned): @%s', resolvedAuthorSlug);
|
||||
this.log.info('│ Processing agent message (mentioned): %s', authorSlug);
|
||||
}
|
||||
|
||||
// System messages: only process if agent is explicitly mentioned (@slug)
|
||||
// This lets assignment/mention notifications through, but ignores generic lifecycle events
|
||||
// System messages: only process if agent is explicitly mentioned
|
||||
if (authorType === 'system') {
|
||||
if (!content.includes(`@${this.config.slug}`)) {
|
||||
if (!isMentioned) {
|
||||
this.log.info('│ Skipping system message (not mentioned): "%s"', content.slice(0, 100));
|
||||
return;
|
||||
}
|
||||
@ -152,7 +164,7 @@ export class EventRouter {
|
||||
|
||||
// Build context-rich prompt for the agent
|
||||
const ctx = taskId ? `[задача ${taskKey || taskId}]` : chatId ? '[чат]' : '';
|
||||
const from = authorType === 'system' ? '[система]' : `@${resolvedAuthorSlug}`;
|
||||
const from = authorType === 'system' ? '[система]' : `@${authorSlug}`;
|
||||
const prompt = `${ctx} ${from}: ${content}`;
|
||||
|
||||
this.log.info('│ %s %s: "%s"', ctx, from, content.slice(0, 200));
|
||||
|
||||
@ -36,6 +36,8 @@ export class WsClientTransport implements TaskTracker {
|
||||
projects: Array<{ id: string; slug: string; name: string; chat_id?: string }> = [];
|
||||
/** Online members from auth.ok */
|
||||
online: string[] = [];
|
||||
/** Own member_id from auth.ok */
|
||||
memberId: string | null = null;
|
||||
/** Remote agent config from auth.ok (if agent) */
|
||||
remoteConfig: {
|
||||
model?: string;
|
||||
@ -209,6 +211,7 @@ export class WsClientTransport implements TaskTracker {
|
||||
|
||||
private onAuthOk(msg: Record<string, unknown>): void {
|
||||
const data = (msg.data || msg.init || {}) as Record<string, unknown>;
|
||||
this.memberId = (data.member_id as string) || null;
|
||||
this.lobbyChatId = (data.lobby_chat_id as string) || null;
|
||||
this.projects = (data.projects as Array<{ id: string; slug: string; name: string; chat_id?: string }>) || [];
|
||||
this.online = (data.online as string[]) || (data.agents_online as string[]) || [];
|
||||
|
||||
Loading…
Reference in New Issue
Block a user