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();
|
await wsTransport.start();
|
||||||
logger.info('Connected to tracker via WebSocket');
|
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) {
|
if (wsTransport.projects.length > 0) {
|
||||||
router.setProjectMappings(wsTransport.projects);
|
router.setProjectMappings(wsTransport.projects);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,6 +21,8 @@ export class EventRouter {
|
|||||||
private wsTransport: WsClientTransport | null = null;
|
private wsTransport: WsClientTransport | null = null;
|
||||||
/** chat_id → project_id mapping (populated from auth.ok) */
|
/** chat_id → project_id mapping (populated from auth.ok) */
|
||||||
private chatToProject: Map<string, string> = new Map();
|
private chatToProject: Map<string, string> = new Map();
|
||||||
|
/** Own member_id from auth.ok */
|
||||||
|
private memberId: string | null = null;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private config: AgentConfig,
|
private config: AgentConfig,
|
||||||
@ -40,6 +42,12 @@ export class EventRouter {
|
|||||||
this.wsTransport = transport;
|
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 */
|
/** Register chat_id → project_id mappings from auth.ok */
|
||||||
setProjectMappings(projects: Array<{ id: string; chat_id?: string | null }>): void {
|
setProjectMappings(projects: Array<{ id: string; chat_id?: string | null }>): void {
|
||||||
for (const p of projects) {
|
for (const p of projects) {
|
||||||
@ -108,7 +116,6 @@ export class EventRouter {
|
|||||||
*/
|
*/
|
||||||
private async handleMessageNew(data: Record<string, unknown>): Promise<void> {
|
private async handleMessageNew(data: Record<string, unknown>): Promise<void> {
|
||||||
const content = (data.content as string) || '';
|
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 authorType = (data.author_type as string) || 'member';
|
||||||
const taskId = data.task_id as string | undefined;
|
const taskId = data.task_id as string | undefined;
|
||||||
const chatId = data.chat_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
|
// Extract author info from nested author object if present
|
||||||
const author = data.author as Record<string, unknown> | undefined;
|
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) {
|
if (!content) {
|
||||||
this.log.warn({ data }, 'message.new event missing content');
|
this.log.warn({ data }, 'message.new event missing content');
|
||||||
@ -125,25 +139,23 @@ export class EventRouter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ignore own messages (agent talking to itself)
|
// 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');
|
this.log.info('│ Skipping own message');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore messages from other agents (unless explicitly @mentioned)
|
// Ignore messages from other agents (unless explicitly mentioned)
|
||||||
// Prevents infinite reply loops between agents
|
|
||||||
if (authorType === 'agent') {
|
if (authorType === 'agent') {
|
||||||
if (!content.includes(`@${this.config.slug}`)) {
|
if (!isMentioned) {
|
||||||
this.log.info('│ Skipping agent message (not mentioned): @%s "%s"', resolvedAuthorSlug, content.slice(0, 80));
|
this.log.info('│ Skipping agent message (not mentioned): %s "%s"', authorSlug, content.slice(0, 80));
|
||||||
return;
|
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)
|
// System messages: only process if agent is explicitly mentioned
|
||||||
// This lets assignment/mention notifications through, but ignores generic lifecycle events
|
|
||||||
if (authorType === 'system') {
|
if (authorType === 'system') {
|
||||||
if (!content.includes(`@${this.config.slug}`)) {
|
if (!isMentioned) {
|
||||||
this.log.info('│ Skipping system message (not mentioned): "%s"', content.slice(0, 100));
|
this.log.info('│ Skipping system message (not mentioned): "%s"', content.slice(0, 100));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -152,7 +164,7 @@ export class EventRouter {
|
|||||||
|
|
||||||
// Build context-rich prompt for the agent
|
// Build context-rich prompt for the agent
|
||||||
const ctx = taskId ? `[задача ${taskKey || taskId}]` : chatId ? '[чат]' : '';
|
const ctx = taskId ? `[задача ${taskKey || taskId}]` : chatId ? '[чат]' : '';
|
||||||
const from = authorType === 'system' ? '[система]' : `@${resolvedAuthorSlug}`;
|
const from = authorType === 'system' ? '[система]' : `@${authorSlug}`;
|
||||||
const prompt = `${ctx} ${from}: ${content}`;
|
const prompt = `${ctx} ${from}: ${content}`;
|
||||||
|
|
||||||
this.log.info('│ %s %s: "%s"', ctx, from, content.slice(0, 200));
|
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 }> = [];
|
projects: Array<{ id: string; slug: string; name: string; chat_id?: string }> = [];
|
||||||
/** Online members from auth.ok */
|
/** Online members from auth.ok */
|
||||||
online: string[] = [];
|
online: string[] = [];
|
||||||
|
/** Own member_id from auth.ok */
|
||||||
|
memberId: string | null = null;
|
||||||
/** Remote agent config from auth.ok (if agent) */
|
/** Remote agent config from auth.ok (if agent) */
|
||||||
remoteConfig: {
|
remoteConfig: {
|
||||||
model?: string;
|
model?: string;
|
||||||
@ -209,6 +211,7 @@ export class WsClientTransport implements TaskTracker {
|
|||||||
|
|
||||||
private onAuthOk(msg: Record<string, unknown>): void {
|
private onAuthOk(msg: Record<string, unknown>): void {
|
||||||
const data = (msg.data || msg.init || {}) as Record<string, unknown>;
|
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.lobbyChatId = (data.lobby_chat_id as string) || null;
|
||||||
this.projects = (data.projects as Array<{ id: string; slug: string; name: string; chat_id?: string }>) || [];
|
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[]) || [];
|
this.online = (data.online as string[]) || (data.agents_online as string[]) || [];
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user