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:
Mohamed Boudra
2026-07-23 03:32:28 +08:00
committed by GitHub
parent de69b2a2af
commit 5dfe50ca74
19 changed files with 627 additions and 110 deletions
+11 -5
View File
@@ -7,18 +7,24 @@ function normalizeSegment(value: string): string {
return value.trim();
}
export function buildAgentDeepLink(target: AgentDeepLinkTarget): string {
function normalizeAgentDeepLinkTarget(target: AgentDeepLinkTarget): AgentDeepLinkTarget {
const serverId = normalizeSegment(target.serverId);
const agentId = normalizeSegment(target.agentId);
if (!serverId || !agentId) {
throw new Error("Agent deep links require a server ID and agent ID.");
}
return `paseo://h/${encodeURIComponent(serverId)}/agent/${encodeURIComponent(agentId)}`;
return { serverId, agentId };
}
export function buildAgentDeepLinkRoute(target: AgentDeepLinkTarget): string {
const link = new URL(buildAgentDeepLink(target));
return `/h${link.pathname}`;
export function buildAgentDeepLinkRoute(
target: AgentDeepLinkTarget,
): `/h/${string}/agent/${string}` {
const { serverId, agentId } = normalizeAgentDeepLinkTarget(target);
return `/h/${encodeURIComponent(serverId)}/agent/${encodeURIComponent(agentId)}`;
}
export function buildAgentDeepLink(target: AgentDeepLinkTarget): string {
return `paseo:/${buildAgentDeepLinkRoute(target)}`;
}
export function parseAgentDeepLink(input: string): AgentDeepLinkTarget | null {