Fix notifications opening the wrong workspace (#2331)
* fix(app): open notifications on the right host Agent notifications previously omitted workspace ownership, so a cold target host was treated as missing and fell back to its empty home route. Carry the authoritative workspace and keep older notifications on a target-host resolver until lookup is conclusive. * fix(app): separate notification and agent URL routing Notifications use their authoritative workspace target directly. Stable agent URLs remain server-and-agent targets whose workspace is resolved by the agent route. * fix(protocol): preserve notification workspace targets Both attention message variants retain workspaceId through outbound validation so notification clicks receive the authoritative route target. * test(app): use workspace-scoped notification target * test(server): give notification agents workspace targets * test(app): target notification workspace in navigation e2e
This commit is contained in:
@@ -29,6 +29,7 @@ import type { AgentAttachment, SessionOutboundMessage } from "@getpaseo/protocol
|
||||
import { parseServerInfoStatusPayload } from "@getpaseo/protocol/messages";
|
||||
import {
|
||||
buildAgentAttentionNotificationPayload,
|
||||
type AgentAttentionReason,
|
||||
type AgentAttentionNotificationPayload,
|
||||
type NotificationPermissionRequest,
|
||||
} from "@getpaseo/protocol/agent-attention-notification";
|
||||
@@ -154,6 +155,35 @@ const getLatestPermissionRequest = (
|
||||
return null;
|
||||
};
|
||||
|
||||
interface AgentAttentionNotificationInput {
|
||||
notification?: AgentAttentionNotificationPayload;
|
||||
reason: AgentAttentionReason;
|
||||
serverId: string;
|
||||
workspaceId: string | undefined;
|
||||
agentId: string;
|
||||
assistantMessage: string | null;
|
||||
permissionRequest: NotificationPermissionRequest | null;
|
||||
}
|
||||
|
||||
function resolveAgentAttentionNotification(
|
||||
input: AgentAttentionNotificationInput,
|
||||
): AgentAttentionNotificationPayload | null {
|
||||
if (input.notification) {
|
||||
return input.notification.data.workspaceId ? input.notification : null;
|
||||
}
|
||||
if (!input.workspaceId) {
|
||||
return null;
|
||||
}
|
||||
return buildAgentAttentionNotificationPayload({
|
||||
reason: input.reason,
|
||||
serverId: input.serverId,
|
||||
workspaceId: input.workspaceId,
|
||||
agentId: input.agentId,
|
||||
assistantMessage: input.reason === "finished" ? input.assistantMessage : null,
|
||||
permissionRequest: input.reason === "permission" ? input.permissionRequest : null,
|
||||
});
|
||||
}
|
||||
|
||||
type WorkspaceSetupProgressPayload = Extract<
|
||||
SessionOutboundMessage,
|
||||
{ type: "workspace_setup_progress" }
|
||||
@@ -500,16 +530,20 @@ function SessionProviderInternal({ children, serverId, client }: SessionProvider
|
||||
const assistantMessage =
|
||||
findLatestAssistantMessageText(head) ?? findLatestAssistantMessageText(tail);
|
||||
const permissionRequest = getLatestPermissionRequest(session, params.agentId);
|
||||
const workspaceId = session?.agents?.get(params.agentId)?.workspaceId;
|
||||
|
||||
const notification =
|
||||
params.notification ??
|
||||
buildAgentAttentionNotificationPayload({
|
||||
reason: params.reason,
|
||||
serverId,
|
||||
agentId: params.agentId,
|
||||
assistantMessage: params.reason === "finished" ? assistantMessage : null,
|
||||
permissionRequest: params.reason === "permission" ? permissionRequest : null,
|
||||
});
|
||||
const notification = resolveAgentAttentionNotification({
|
||||
notification: params.notification,
|
||||
reason: params.reason,
|
||||
serverId,
|
||||
workspaceId,
|
||||
agentId: params.agentId,
|
||||
assistantMessage,
|
||||
permissionRequest,
|
||||
});
|
||||
if (!notification) {
|
||||
return;
|
||||
}
|
||||
|
||||
void sendOsNotification({
|
||||
title: notification.title,
|
||||
|
||||
Reference in New Issue
Block a user