function dataFromNotificationResponse(response: unknown): Record | null { if (typeof response !== "object" || response === null) { return null; } const notification = (response as { readonly notification?: unknown }).notification; if (typeof notification !== "object" || notification === null) { return null; } const request = (notification as { readonly request?: unknown }).request; if (typeof request !== "object" || request === null) { return null; } const content = (request as { readonly content?: unknown }).content; if (typeof content !== "object" || content === null) { return null; } const data = (content as { readonly data?: unknown }).data; return typeof data === "object" && data !== null ? (data as Record) : null; } function identifierFromNotificationResponse(response: unknown): string | null { if (typeof response !== "object" || response === null) { return null; } const notification = (response as { readonly notification?: unknown }).notification; if (typeof notification !== "object" || notification === null) { return null; } const request = (notification as { readonly request?: unknown }).request; if (typeof request !== "object" || request === null) { return null; } const identifier = (request as { readonly identifier?: unknown }).identifier; return typeof identifier === "string" ? identifier : null; } function encodeThreadDeepLink(input: { readonly environmentId: string; readonly threadId: string; }): string | null { if (input.environmentId.length === 0 || input.threadId.length === 0) { return null; } return `/threads/${encodeURIComponent(input.environmentId)}/${encodeURIComponent(input.threadId)}`; } function normalizeThreadDeepLink(value: string): string | null { if ( value.trim() !== value || value.startsWith("//") || value.includes("?") || value.includes("#") ) { return null; } const parts = value.split("/"); if (parts.length !== 4 || parts[0] !== "" || parts[1] !== "threads") { return null; } try { return encodeThreadDeepLink({ environmentId: decodeURIComponent(parts[2] ?? ""), threadId: decodeURIComponent(parts[3] ?? ""), }); } catch { return null; } } export function extractAgentNotificationDeepLink(response: unknown): string | null { const data = dataFromNotificationResponse(response); const deepLink = data?.deepLink; if (typeof deepLink === "string") { const normalizedDeepLink = normalizeThreadDeepLink(deepLink); if (normalizedDeepLink) { return normalizedDeepLink; } } const environmentId = data?.environmentId; const threadId = data?.threadId; if (typeof environmentId === "string" && typeof threadId === "string") { return encodeThreadDeepLink({ environmentId, threadId }); } return null; } export function routeAgentNotificationResponseOnce(input: { readonly handledResponseIds: Set; readonly response: unknown; readonly navigate: (deepLink: string) => void; }): void { const responseId = identifierFromNotificationResponse(input.response); if (responseId && input.handledResponseIds.has(responseId)) { return; } if (responseId) { input.handledResponseIds.add(responseId); } const deepLink = extractAgentNotificationDeepLink(input.response); if (deepLink) { input.navigate(deepLink); } }