From f915433df34788fdb08ced81c9e0b609dbc5bb27 Mon Sep 17 00:00:00 2001 From: klopez4212 Date: Mon, 29 Jun 2026 16:30:15 +0100 Subject: [PATCH] Fix task route readiness and backfill --- .../channels/ui/ChannelPane.helpers.test.mjs | 40 +++++++++++++++ .../channels/ui/ChannelPane.helpers.ts | 50 ++++++++++++++++++- .../src/features/channels/ui/ChannelPane.tsx | 10 ++-- .../features/channels/ui/ChannelScreen.tsx | 2 +- 4 files changed, 95 insertions(+), 7 deletions(-) diff --git a/desktop/src/features/channels/ui/ChannelPane.helpers.test.mjs b/desktop/src/features/channels/ui/ChannelPane.helpers.test.mjs index 879c7351b..b94a8974b 100644 --- a/desktop/src/features/channels/ui/ChannelPane.helpers.test.mjs +++ b/desktop/src/features/channels/ui/ChannelPane.helpers.test.mjs @@ -3,6 +3,7 @@ import test from "node:test"; import { canOpenAgentConversationInChannel, + getDmTaskAgentPubkeys, mergeAutoRouteMentionPubkeys, } from "./ChannelPane.helpers.ts"; @@ -74,3 +75,42 @@ test("auto-routed mentions merge with explicit mentions without duplicates", () ["AGENT-ONE", "agent-two"], ); }); + +test("DM task agent inference requires exactly one other known agent", () => { + const knownAgentPubkeys = new Set(["agent-one", "agent-two"]); + + assert.deepEqual( + getDmTaskAgentPubkeys({ + channel: channel({ + channelType: "dm", + participantPubkeys: ["human", "agent-one"], + }), + currentPubkey: "human", + knownAgentPubkeys, + }), + ["agent-one"], + ); + + assert.deepEqual( + getDmTaskAgentPubkeys({ + channel: channel({ + channelType: "dm", + participantPubkeys: ["human", "agent-one", "agent-two"], + }), + currentPubkey: "human", + knownAgentPubkeys, + }), + [], + ); + + assert.deepEqual( + getDmTaskAgentPubkeys({ + channel: channel({ + participantPubkeys: ["human", "agent-one"], + }), + currentPubkey: "human", + knownAgentPubkeys, + }), + [], + ); +}); diff --git a/desktop/src/features/channels/ui/ChannelPane.helpers.ts b/desktop/src/features/channels/ui/ChannelPane.helpers.ts index 89e472a51..8643525ce 100644 --- a/desktop/src/features/channels/ui/ChannelPane.helpers.ts +++ b/desktop/src/features/channels/ui/ChannelPane.helpers.ts @@ -1,5 +1,4 @@ import { isEphemeralChannel } from "@/features/channels/lib/ephemeralChannel"; -import { collectMessageMentionPubkeys } from "@/features/messages/lib/formatTimelineMessages"; import type { TimelineMessage } from "@/features/messages/types"; import type { Channel } from "@/shared/api/types"; import { KIND_SYSTEM_MESSAGE } from "@/shared/constants/kinds"; @@ -72,6 +71,55 @@ export function mentionsKnownAgent( ); } +function singleKnownAgentPubkey( + pubkeys: Iterable, + knownAgentPubkeys: ReadonlySet, +) { + const agentPubkeys = new Map(); + + for (const pubkey of pubkeys) { + if (!pubkey) { + continue; + } + + const normalized = normalizePubkey(pubkey); + if (!knownAgentPubkeys.has(normalized)) { + continue; + } + + agentPubkeys.set(normalized, pubkey); + } + + return agentPubkeys.size === 1 ? [...agentPubkeys.values()] : []; +} + +export function getDmTaskAgentPubkeys({ + channel, + currentPubkey, + knownAgentPubkeys, +}: { + channel: Channel | null; + currentPubkey?: string; + knownAgentPubkeys: ReadonlySet; +}) { + if (channel?.channelType !== "dm") { + return []; + } + + const normalizedCurrentPubkey = currentPubkey + ? normalizePubkey(currentPubkey) + : null; + + return singleKnownAgentPubkey( + channel.participantPubkeys.filter( + (pubkey) => + !normalizedCurrentPubkey || + normalizePubkey(pubkey) !== normalizedCurrentPubkey, + ), + knownAgentPubkeys, + ); +} + export function mergeAutoRouteMentionPubkeys({ autoRouteAgentPubkeys, mentionPubkeys, diff --git a/desktop/src/features/channels/ui/ChannelPane.tsx b/desktop/src/features/channels/ui/ChannelPane.tsx index e3f95d4a2..50c020b79 100644 --- a/desktop/src/features/channels/ui/ChannelPane.tsx +++ b/desktop/src/features/channels/ui/ChannelPane.tsx @@ -41,9 +41,9 @@ import { } from "@/features/channels/ui/WelcomeComposerBanner"; import { canOpenAgentConversationInChannel, - getDmAutoRouteAgentPubkeys, getChannelIntroDescription, getChannelIntroKind, + getDmTaskAgentPubkeys, isWelcomeSetupSystemMessage, mentionsKnownAgent, } from "@/features/channels/ui/ChannelPane.helpers"; @@ -290,9 +290,9 @@ export const ChannelPane = React.memo(function ChannelPane({ return pubkeys; }, [activityAgents, agentPubkeys, agentSessionAgents]); - const dmAutoRouteAgentPubkeys = React.useMemo( + const dmTaskAgentPubkeys = React.useMemo( () => - getDmAutoRouteAgentPubkeys({ + getDmTaskAgentPubkeys({ channel: activeChannel, currentPubkey, knownAgentPubkeys, @@ -374,7 +374,7 @@ export const ChannelPane = React.memo(function ChannelPane({ } } - for (const pubkey of dmAutoRouteAgentPubkeys) { + for (const pubkey of dmTaskAgentPubkeys) { const dmAgent = knownAgentByPubkey.get(normalizePubkey(pubkey)); if (dmAgent) { return dmAgent; @@ -386,7 +386,7 @@ export const ChannelPane = React.memo(function ChannelPane({ [ activeAgentConversationMarkers, activeChannelId, - dmAutoRouteAgentPubkeys, + dmTaskAgentPubkeys, knownAgentByPubkey, ], ); diff --git a/desktop/src/features/channels/ui/ChannelScreen.tsx b/desktop/src/features/channels/ui/ChannelScreen.tsx index 834fb4e77..3d7ddc6af 100644 --- a/desktop/src/features/channels/ui/ChannelScreen.tsx +++ b/desktop/src/features/channels/ui/ChannelScreen.tsx @@ -344,7 +344,7 @@ export function ChannelScreen({ const agentLookupReady = !channelMembersQuery.isLoading && !managedAgentsQuery.isLoading && - !messageProfilesQuery.isLoading && + messageProfilesReady && !relayAgentsQuery.isLoading; const agentPubkeys = React.useMemo(() => { const pubkeys = new Set();