* 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
43 lines
1.4 KiB
TypeScript
43 lines
1.4 KiB
TypeScript
import type { Href } from "expo-router";
|
|
import { buildHostRootRoute, buildHostWorkspaceOpenRoute } from "@/utils/host-routes";
|
|
|
|
type NotificationData = Record<string, unknown> | null | undefined;
|
|
type NotificationRoute = Extract<Href, string>;
|
|
|
|
function readNonEmptyString(data: NotificationData, key: string): string | null {
|
|
const value = data?.[key];
|
|
if (typeof value !== "string") {
|
|
return null;
|
|
}
|
|
const trimmed = value.trim();
|
|
return trimmed.length > 0 ? trimmed : null;
|
|
}
|
|
|
|
export function resolveNotificationTarget(data: NotificationData): {
|
|
serverId: string | null;
|
|
agentId: string | null;
|
|
workspaceId: string | null;
|
|
terminalId: string | null;
|
|
} {
|
|
return {
|
|
serverId: readNonEmptyString(data, "serverId"),
|
|
agentId: readNonEmptyString(data, "agentId"),
|
|
workspaceId: readNonEmptyString(data, "workspaceId"),
|
|
terminalId: readNonEmptyString(data, "terminalId"),
|
|
};
|
|
}
|
|
|
|
export function buildNotificationRoute(data: NotificationData): NotificationRoute {
|
|
const { serverId, agentId, workspaceId, terminalId } = resolveNotificationTarget(data);
|
|
if (serverId && workspaceId && agentId) {
|
|
return buildHostWorkspaceOpenRoute(serverId, workspaceId, `agent:${agentId}`);
|
|
}
|
|
if (serverId && workspaceId && terminalId) {
|
|
return buildHostWorkspaceOpenRoute(serverId, workspaceId, `terminal:${terminalId}`);
|
|
}
|
|
if (serverId) {
|
|
return buildHostRootRoute(serverId);
|
|
}
|
|
return "/" as const;
|
|
}
|