Remove additional agents gallery (#2098)

Signed-off-by: Wes <wesbillman@users.noreply.github.com>
Co-authored-by: Pinky <44b8e82baa6e0e254e0208d68f335c283c94e7b78dd1fa10d5a49d3f13dd0435@sprout-oss.stage.blox.sqprod.co>
This commit is contained in:
Wes
2026-07-18 16:37:52 -07:00
committed by GitHub
co-authored by Pinky
parent 284a76c1c7
commit 836cf5f6ed
5 changed files with 136 additions and 26 deletions
@@ -99,18 +99,6 @@ export function UnifiedAgentsSection(props: UnifiedAgentsSectionProps) {
() => buildUnifiedGroups(personas, agents),
[personas, agents],
);
const additionalPersonaAgents = React.useMemo(() => {
const additional: ManagedAgent[] = [];
for (const group of groups) {
const primary = pickProfileAgent(group.agents);
for (const agent of group.agents) {
if (primary?.pubkey !== agent.pubkey) {
additional.push(agent);
}
}
}
return additional;
}, [groups]);
const [collapsed, setCollapsed] = React.useState<Set<string>>(new Set());
const {
fileInputRef,
@@ -199,19 +187,6 @@ export function UnifiedAgentsSection(props: UnifiedAgentsSectionProps) {
/>
</div>
{additionalPersonaAgents.length > 0 ? (
<CollapsibleAgentGroup
agents={additionalPersonaAgents}
collapsed={collapsed}
defaultModel={defaultModel}
groupKey="__additional_persona_agents__"
label="Additional running agents"
startingAgentPubkey={startingAgentPubkey}
onToggle={toggle}
onOpenAgentProfile={onOpenAgentProfile}
onStartAgent={onStartAgent}
/>
) : null}
{unknown.length > 0 ? (
<CollapsibleAgentGroup
agents={unknown}
@@ -199,6 +199,12 @@ export function UserProfilePanel({
}
return undefined;
}, [managedAgentsQuery.data, persona, pubkey]);
const personaInstances = React.useMemo(() => {
if (!managedAgent?.personaId) return managedAgent ? [managedAgent] : [];
return (managedAgentsQuery.data ?? []).filter(
(agent) => agent.personaId === managedAgent.personaId,
);
}, [managedAgent, managedAgentsQuery.data]);
const resolvedPersonaFromSource = React.useMemo(() => {
const personaId = persona?.id ?? managedAgent?.personaId;
if (personaId) {
@@ -833,6 +839,7 @@ export function UserProfilePanel({
isFollowing={isFollowing}
isOwner={viewerIsOwner}
isSelf={isSelf}
instances={personaInstances}
activityAgent={activityAgent}
managedAgent={managedAgent}
memoriesLoading={memoryQuery.isLoading}
@@ -841,6 +848,7 @@ export function UserProfilePanel({
agentSettingsFields={agentSettingsFields}
diagnosticsFields={diagnosticsFields}
onAddToChannel={() => setAddToChannelOpen(true)}
onOpenInstance={(instancePubkey) => onOpenProfile?.(instancePubkey)}
onOpenActivity={handleOpenActivity}
onOpenChannel={handleOpenChannel}
onOpenDiagnostics={() => setView("diagnostics")}
@@ -88,6 +88,7 @@ export type ProfileSummaryViewProps = {
isFollowing: boolean;
isOwner: boolean | undefined;
isSelf: boolean;
instances: ManagedAgent[];
managedAgent: ManagedAgent | undefined;
memoriesLoading: boolean;
memoryCount: number | undefined;
@@ -95,6 +96,7 @@ export type ProfileSummaryViewProps = {
agentSettingsFields: ProfileField[];
diagnosticsFields: ProfileField[];
onAddToChannel: () => void;
onOpenInstance: (pubkey: string) => void;
onOpenActivity: (channelId?: string | null) => void;
onOpenChannel: (channelId: string) => void;
onOpenDiagnostics: () => void;
@@ -198,6 +200,7 @@ export function ProfileSummaryView({
isFollowing,
isOwner,
isSelf,
instances,
managedAgent,
memoriesLoading,
memoryCount,
@@ -205,6 +208,7 @@ export function ProfileSummaryView({
agentSettingsFields,
diagnosticsFields,
onAddToChannel,
onOpenInstance,
onOpenActivity,
onOpenChannel,
onOpenDiagnostics,
@@ -248,6 +252,7 @@ export function ProfileSummaryView({
const showActivityIngress = canViewActivity;
const showInfoTab =
agentInfoFields.length > 0 ||
instances.length > 1 ||
isArchived ||
showActivityIngress ||
!showRuntimeTab;
@@ -388,8 +393,10 @@ export function ProfileSummaryView({
agentInfoFields={agentInfoFields}
callerChannelId={callerChannelId}
channelIdToName={channelIdToName}
instances={instances}
isArchived={isArchived}
onOpenActivity={onOpenActivity}
onOpenInstance={onOpenInstance}
pubkey={pubkey}
showActivityIngress={showActivityIngress}
/>
@@ -9,6 +9,7 @@ import {
Wrench,
} from "lucide-react";
import type { ManagedAgent } from "@/shared/api/types";
import type { ActiveTurnSummary } from "@/features/agents/activeAgentTurnsStore";
import { ManagedAgentSessionPanel } from "@/features/agents/ui/ManagedAgentSessionPanel";
import {
@@ -282,8 +283,10 @@ export function ProfileInfoTabContent({
agentInfoFields,
callerChannelId,
channelIdToName,
instances,
isArchived,
onOpenActivity,
onOpenInstance,
pubkey,
showActivityIngress,
}: {
@@ -292,8 +295,10 @@ export function ProfileInfoTabContent({
agentInfoFields: ProfileField[];
callerChannelId: string | null;
channelIdToName: Record<string, string>;
instances: ManagedAgent[];
isArchived: boolean;
onOpenActivity: (channelId?: string | null) => void;
onOpenInstance: (pubkey: string) => void;
pubkey: string | null;
showActivityIngress: boolean;
}) {
@@ -310,11 +315,12 @@ export function ProfileInfoTabContent({
]
: agentInfoFields;
const hasInfoFields = infoFields.length > 0;
const hasInstances = instances.length > 1;
const feedScope = useProfileActivityFeedScope(activityAgent, activeTurns);
const showLiveActivityEmbed =
showActivityIngress && (feedScope.isLive || feedScope.hasFeedContent);
if (!hasInfoFields && !showActivityIngress) {
if (!hasInfoFields && !showActivityIngress && !hasInstances) {
return null;
}
@@ -341,6 +347,72 @@ export function ProfileInfoTabContent({
)
) : null}
{hasInfoFields ? <ProfileFieldGroup fields={infoFields} /> : null}
{hasInstances ? (
<ProfileInstancesSection
currentPubkey={pubkey}
instances={instances}
onOpenInstance={onOpenInstance}
/>
) : null}
</div>
);
}
function ProfileInstancesSection({
currentPubkey,
instances,
onOpenInstance,
}: {
currentPubkey: string | null;
instances: ManagedAgent[];
onOpenInstance: (pubkey: string) => void;
}) {
const [expanded, setExpanded] = React.useState(false);
return (
<div className="overflow-hidden rounded-2xl bg-muted/20">
<button
aria-expanded={expanded}
className="flex w-full items-center gap-3 px-4 py-3 text-left transition-colors hover:bg-muted/40"
data-testid="user-profile-instances"
onClick={() => setExpanded((value) => !value)}
type="button"
>
<span className="min-w-0 flex-1 text-sm font-medium">Instances</span>
<span className="text-sm text-muted-foreground">
{instances.length}
</span>
<ChevronRight
className={cn(
"h-4 w-4 shrink-0 text-muted-foreground transition-transform",
expanded && "rotate-90",
)}
/>
</button>
{expanded ? (
<div className="border-t border-border/60 px-2 py-2">
{instances.map((instance) => {
const isCurrent = instance.pubkey === currentPubkey;
return (
<button
className="flex w-full items-center gap-3 rounded-xl px-3 py-2 text-left transition-colors hover:bg-muted/40"
data-testid={`user-profile-instance-${instance.pubkey}`}
key={instance.pubkey}
onClick={() => onOpenInstance(instance.pubkey)}
type="button"
>
<span className="min-w-0 flex-1 truncate text-sm font-medium">
{instance.name}
</span>
<span className="text-xs capitalize text-muted-foreground">
{isCurrent ? "Current" : instance.status.replace("_", " ")}
</span>
<ChevronRight className="h-4 w-4 shrink-0 text-muted-foreground" />
</button>
);
})}
</div>
) : null}
</div>
);
}
+48
View File
@@ -1627,3 +1627,51 @@ test("personas referenced by teams cannot be deleted", async ({ page }) => {
"Analyst is still referenced by a team. Remove it from those teams first.",
);
});
test("duplicate instances move from the agents gallery into the agent profile", async ({
page,
}) => {
const personaId = "custom:duplicate-auditor";
const primaryPubkey = TEST_IDENTITIES.alice.pubkey;
const additionalPubkey = TEST_IDENTITIES.charlie.pubkey;
await installMockBridge(page, {
personas: [
{
id: personaId,
displayName: "Duplicate Auditor",
systemPrompt: "You audit duplicate instances.",
},
],
managedAgents: [
{
pubkey: primaryPubkey,
name: "Duplicate Auditor",
personaId,
status: "running",
},
{
pubkey: additionalPubkey,
name: "Duplicate Auditor",
personaId,
status: "stopped",
},
],
});
await gotoApp(page);
await page.getByTestId("open-agents-view").click();
await expect(page.getByText("Additional running agents")).toHaveCount(0);
await expect(
page.getByTestId(`managed-agent-${additionalPubkey}`),
).toHaveCount(0);
await page.getByTestId(`persona-agent-row-${personaId}`).click();
await page.getByTestId("user-profile-instances").click();
await page.getByTestId(`user-profile-instance-${additionalPubkey}`).click();
await expect(page.getByTestId("user-profile-panel")).toBeVisible();
await page.getByTestId("user-profile-settings-menu-trigger").click();
await expect(
page.getByTestId(`user-profile-agent-delete-${additionalPubkey}`),
).toBeVisible();
});