diff --git a/server/src/__tests__/issues-service.test.ts b/server/src/__tests__/issues-service.test.ts index 9309731a6d..7aa6eaa181 100644 --- a/server/src/__tests__/issues-service.test.ts +++ b/server/src/__tests__/issues-service.test.ts @@ -864,14 +864,24 @@ describeEmbeddedPostgres("issueService.list participantAgentId", () => { }); }); - it("resolves only structured same-company agent mentions", async () => { + it("resolves only structured same-company wakeable agent mentions", async () => { const companyId = await seedAssignableAgentCompany(); const otherCompanyId = await seedAssignableAgentCompany(); const localAgentId = randomUUID(); const foreignAgentId = randomUUID(); + const terminatedAgentId = randomUUID(); + const pausedAgentId = randomUUID(); + const pendingAgentId = randomUUID(); + const invalidChainAgentId = randomUUID(); + const terminatedManagerId = randomUUID(); await db.insert(agents).values([ agentRow(companyId, { id: localAgentId, name: "LocalAgent" }), + agentRow(companyId, { id: terminatedAgentId, name: "TerminatedAgent", status: "terminated" }), + agentRow(companyId, { id: pausedAgentId, name: "PausedAgent", status: "paused" }), + agentRow(companyId, { id: pendingAgentId, name: "PendingAgent", status: "pending_approval" }), + agentRow(companyId, { id: terminatedManagerId, name: "TerminatedManager", status: "terminated" }), + agentRow(companyId, { id: invalidChainAgentId, name: "InvalidChainAgent", reportsTo: terminatedManagerId }), agentRow(otherCompanyId, { id: foreignAgentId, name: "ForeignAgent" }), ]); @@ -879,6 +889,10 @@ describeEmbeddedPostgres("issueService.list participantAgentId", () => { companyId, [ `hello [@LocalAgent](${buildAgentMentionHref(localAgentId)})`, + `skip [@TerminatedAgent](${buildAgentMentionHref(terminatedAgentId)})`, + `skip [@PausedAgent](${buildAgentMentionHref(pausedAgentId)})`, + `skip [@PendingAgent](${buildAgentMentionHref(pendingAgentId)})`, + `skip [@InvalidChainAgent](${buildAgentMentionHref(invalidChainAgentId)})`, `and [@ForeignAgent](${buildAgentMentionHref(foreignAgentId)})`, ].join(" "), ); diff --git a/server/src/services/issues.ts b/server/src/services/issues.ts index b3d297bdf4..2adcf162dd 100644 --- a/server/src/services/issues.ts +++ b/server/src/services/issues.ts @@ -93,6 +93,7 @@ import { issueCommentAuthorTypeSchema, issueCommentMetadataSchema, issueCommentPresentationSchema, + isAgentInvokable, isUuidLike, normalizeIssueIdentifier as normalizeIssueReferenceIdentifier, } from "@paperclipai/shared"; @@ -12927,14 +12928,20 @@ export function issueService(db: Db) { const explicitAgentMentionIds = extractAgentMentionIds(body); if (explicitAgentMentionIds.length === 0) return []; - const rows = await db - .select({ id: agents.id }) - .from(agents) - .where(eq(agents.companyId, companyId)); - const companyAgentIds = new Set(rows.map((agent) => agent.id)); - return explicitAgentMentionIds.filter((agentId) => - companyAgentIds.has(agentId), + const rows = await db.select({ + id: agents.id, + companyId: agents.companyId, + name: agents.name, + status: agents.status, + reportsTo: agents.reportsTo, + }) + .from(agents).where(eq(agents.companyId, companyId)); + const wakeableCompanyAgentIds = new Set( + rows + .filter((agent) => isAgentInvokable({ agent, agents: rows })) + .map((agent) => agent.id), ); + return explicitAgentMentionIds.filter((agentId) => wakeableCompanyAgentIds.has(agentId)); }, findMentionedProjectIds: async (