diff --git a/desktop/src/features/agents/hooks/useCanViewAgentActivity.ts b/desktop/src/features/agents/hooks/useCanViewAgentActivity.ts
index a6bc220fd..33f0d2d48 100644
--- a/desktop/src/features/agents/hooks/useCanViewAgentActivity.ts
+++ b/desktop/src/features/agents/hooks/useCanViewAgentActivity.ts
@@ -38,6 +38,7 @@ export function useCanViewAgentActivity(
relayOwnership: ownershipQuery.data,
isManagedAgent,
isOwnershipLoading: ownershipQuery.isLoading,
+ isOwnershipError: ownershipQuery.isError,
isManagedLoading: isManagedAgent === undefined,
});
}
diff --git a/desktop/src/features/agents/lib/canViewAgentActivity.test.mjs b/desktop/src/features/agents/lib/canViewAgentActivity.test.mjs
index cfd3c8d87..5fad347de 100644
--- a/desktop/src/features/agents/lib/canViewAgentActivity.test.mjs
+++ b/desktop/src/features/agents/lib/canViewAgentActivity.test.mjs
@@ -12,6 +12,7 @@ test("resolveCanViewAgentActivity returns true when relay confirms ownership", (
},
isManagedAgent: false,
isOwnershipLoading: false,
+ isOwnershipError: false,
isManagedLoading: false,
});
@@ -28,6 +29,7 @@ test("resolveCanViewAgentActivity returns false when relay denies ownership", ()
},
isManagedAgent: true,
isOwnershipLoading: false,
+ isOwnershipError: false,
isManagedLoading: false,
});
@@ -40,6 +42,7 @@ test("resolveCanViewAgentActivity optimistically allows locally managed agents w
relayOwnership: undefined,
isManagedAgent: true,
isOwnershipLoading: true,
+ isOwnershipError: false,
isManagedLoading: false,
});
@@ -52,9 +55,36 @@ test("resolveCanViewAgentActivity stays closed for non-managed agents while load
relayOwnership: undefined,
isManagedAgent: false,
isOwnershipLoading: true,
+ isOwnershipError: false,
isManagedLoading: false,
});
assert.equal(result.canView, false);
assert.equal(result.isLoading, true);
});
+
+test("resolveCanViewAgentActivity keeps locally managed agents visible when ownership lookup errors", () => {
+ const result = resolveCanViewAgentActivity({
+ relayOwnership: undefined,
+ isManagedAgent: true,
+ isOwnershipLoading: false,
+ isOwnershipError: true,
+ isManagedLoading: false,
+ });
+
+ assert.equal(result.canView, true);
+ assert.equal(result.isLoading, false);
+});
+
+test("resolveCanViewAgentActivity stays closed for non-managed agents when ownership lookup errors", () => {
+ const result = resolveCanViewAgentActivity({
+ relayOwnership: undefined,
+ isManagedAgent: false,
+ isOwnershipLoading: false,
+ isOwnershipError: true,
+ isManagedLoading: false,
+ });
+
+ assert.equal(result.canView, false);
+ assert.equal(result.isLoading, false);
+});
diff --git a/desktop/src/features/agents/lib/canViewAgentActivity.ts b/desktop/src/features/agents/lib/canViewAgentActivity.ts
index 436a68169..fea48ecfb 100644
--- a/desktop/src/features/agents/lib/canViewAgentActivity.ts
+++ b/desktop/src/features/agents/lib/canViewAgentActivity.ts
@@ -4,6 +4,7 @@ export type CanViewAgentActivityInput = {
relayOwnership: AgentOwnershipStatus | undefined;
isManagedAgent: boolean | undefined;
isOwnershipLoading: boolean;
+ isOwnershipError: boolean;
isManagedLoading: boolean;
};
@@ -22,6 +23,7 @@ export function resolveCanViewAgentActivity({
relayOwnership,
isManagedAgent,
isOwnershipLoading,
+ isOwnershipError,
isManagedLoading,
}: CanViewAgentActivityInput): CanViewAgentActivityResult {
if (relayOwnership?.isOwner === true) {
@@ -35,8 +37,8 @@ export function resolveCanViewAgentActivity({
const isLoading =
isOwnershipLoading || (isManagedAgent === undefined && isManagedLoading);
- if (isManagedAgent === true && isOwnershipLoading) {
- return { canView: true, isLoading: true };
+ if (isManagedAgent === true && (isOwnershipLoading || isOwnershipError)) {
+ return { canView: true, isLoading };
}
return { canView: false, isLoading };
diff --git a/desktop/src/features/agents/observerRelayStore.ts b/desktop/src/features/agents/observerRelayStore.ts
index ee8483dc8..cc8905d0a 100644
--- a/desktop/src/features/agents/observerRelayStore.ts
+++ b/desktop/src/features/agents/observerRelayStore.ts
@@ -41,6 +41,7 @@ const snapshotByAgent = new Map