Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions desktop/src/features/agents/ui/AgentsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,11 @@ export function AgentsScreen() {
);

const handleOpenPersonaProfilePanel = React.useCallback(
(persona: AgentPersona) => {
(persona: AgentPersona, options?: ProfilePanelOpenOptions) => {
applyPatch({
profile: null,
profilePersona: persona.id,
profileTab: null,
profileTab: options?.tab === "info" ? null : (options?.tab ?? null),
profileView: null,
});
},
Expand Down
4 changes: 2 additions & 2 deletions desktop/src/features/agents/ui/AgentsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,8 @@ export function AgentsView() {
onOpenAgentProfile={(pubkey, options) => {
openProfilePanel?.(pubkey, options);
}}
onOpenPersonaProfile={(persona) => {
openPersonaProfilePanel?.(persona);
onOpenPersonaProfile={(persona, options) => {
openPersonaProfilePanel?.(persona, options);
}}
onStartAgent={(pubkey) => {
void agents.handleStart(pubkey);
Expand Down
37 changes: 24 additions & 13 deletions desktop/src/features/agents/ui/UnifiedAgentsSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
import { resolveAgentCardModelLabel } from "@/features/agents/lib/agentCardModelLabel";
import { friendlyAgentLastError } from "@/features/agents/lib/friendlyAgentLastError";
import { isManagedAgentActive } from "@/features/agents/lib/managedAgentControlActions";
import { useIsArchivedPredicate } from "@/features/identity-archive/hooks";
import { useUserProfileQuery } from "@/features/profile/hooks";
import type { AgentPersona, ManagedAgent } from "@/shared/api/types";
import type { ProfilePanelOpenOptions } from "@/shared/context/ProfilePanelContext";
Expand Down Expand Up @@ -35,7 +36,10 @@ type UnifiedAgentsSectionProps = {
pubkey: string,
options?: ProfilePanelOpenOptions,
) => void;
onOpenPersonaProfile: (persona: AgentPersona) => void;
onOpenPersonaProfile: (
persona: AgentPersona,
options?: ProfilePanelOpenOptions,
) => void;
onRestartAgent: (pubkey: string) => void;
onStartAgent: (pubkey: string) => void;
onStartPersona: (persona: AgentPersona) => void;
Expand Down Expand Up @@ -93,9 +97,10 @@ export function UnifiedAgentsSection(props: UnifiedAgentsSectionProps) {
onDeletePersona,
} = props;

const isArchived = useIsArchivedPredicate();
const { groups, ungrouped, unknown } = React.useMemo(
() => buildUnifiedGroups(personas, agents),
[personas, agents],
() => buildUnifiedGroups(personas, agents, isArchived),
[personas, agents, isArchived],
);
const [collapsed, setCollapsed] = React.useState<Set<string>>(new Set());
function toggle(key: string) {
Expand Down Expand Up @@ -128,7 +133,7 @@ export function UnifiedAgentsSection(props: UnifiedAgentsSectionProps) {
onClick={onOpenCatalog}
/>
{groups.map((group) => {
const profileAgent = pickProfileAgent(group.agents);
const profileAgent = pickProfileAgent(group.agents, isArchived);
return (
<AgentPersonaCard
actions={(effectiveAvatarUrl, isEffectiveAvatarLoading) => (
Expand Down Expand Up @@ -244,7 +249,10 @@ function AgentPersonaCard({
pubkey: string,
options?: ProfilePanelOpenOptions,
) => void;
onOpenPersonaProfile: (persona: AgentPersona) => void;
onOpenPersonaProfile: (
persona: AgentPersona,
options?: ProfilePanelOpenOptions,
) => void;
onRestartAgent: (pubkey: string) => void;
onStartAgent: (pubkey: string) => void;
onStartPersona: (persona: AgentPersona) => void;
Expand Down Expand Up @@ -311,14 +319,17 @@ function AgentPersonaCard({
label={title}
modelLabel={modelLabel}
onClick={() => {
if (agent) {
onOpenAgentProfile(
agent.pubkey,
opensRuntimeTab ? { tab: "runtime" } : undefined,
);
return;
}
onOpenPersonaProfile(persona);
// The card's main click always opens the PERSONA target, never an
// explicit pubkey. A pubkey target is durable in the URL, so a pick
// made during the archive-query fail-open window would strand the
// panel on an archived identity after hydration. A persona target
// re-resolves every render, so it self-corrects to a live sibling
// (or persona-only when all are archived). Explicit-pubkey navigation
// stays reserved for deliberate instance rows and the error path.
onOpenPersonaProfile(
persona,
opensRuntimeTab ? { tab: "runtime" } : undefined,
);
}}
statusBadge={
agent?.personaOrphaned ? (
Expand Down
Loading
Loading