662 lines · 20.9 KB · TypeScript
RawDownload
import { addPushToStartTokenListener, type LiveActivity } from "expo-widgets";import Constants from "expo-constants";import * as Notifications from "expo-notifications";import * as Effect from "effect/Effect";import { Platform } from "react-native";import type { EnvironmentId } from "@t3tools/contracts";import {  type RelayDeviceRegistrationRequest,  type RelayLiveActivityRegistrationRequest,} from "@t3tools/contracts/relay";import { findErrorTraceId } from "@t3tools/client-runtime/errors";import { ManagedRelay } from "@t3tools/client-runtime/relay";import {  isAtomCommandInterrupted,  settleAsyncResult,  squashAtomCommandFailure,} from "@t3tools/client-runtime/state/runtime"; import type { SavedRemoteConnection } from "../../lib/connection";import { runtime } from "../../lib/runtime";import {  loadAgentAwarenessDeviceId,  loadOrCreateAgentAwarenessDeviceId,  loadPreferences,} from "../../lib/storage";import AgentActivity, { type AgentActivityProps } from "../../widgets/AgentActivity";import { resolveCloudPublicConfig } from "../cloud/publicConfig";import { makeRelayDeviceRegistrationRequest } from "./registrationPayload"; const REMOTE_ACTIVITY_REGISTRATION_RETRY_MS = 15_000;const environmentConnections = new Map<EnvironmentId, SavedRemoteConnection>();const activityPushTokenListeners = new WeakSet<LiveActivity<AgentActivityProps>>();let pushToStartSubscription: { remove: () => void } | null = null;let pushTokenSubscription: { remove: () => void } | null = null;let activeLiveActivityRegistrationRetry: ReturnType<typeof setTimeout> | null = null;let relayTokenProvider: (() => Promise<string | null>) | null = null;let relayTokenProviderIdentity: string | null = null;let deviceRegistrationGeneration = 0;let activeDeviceRegistration: {  readonly input: DeviceRegistrationInput;  operation: Promise<void>;} | null = null;let pendingDeviceRegistration: {  readonly input: DeviceRegistrationInput;  readonly context: string;} | null = null; interface DeviceRegistrationInput {  readonly pushToStartToken?: string;  readonly observedPushToken?: string;} export function normalizeAgentAwarenessRelayBaseUrl(  value: string | null | undefined,): string | null {  const trimmed = value?.trim();  if (!trimmed) {    return null;  }  return trimmed.replace(/\/+$/g, "");} function readRelayConfig(): { readonly url: string } | null {  const relayUrl = resolveCloudPublicConfig().relay.url;  if (!relayUrl) {    logRegistrationDebug("relay registration skipped; relay config missing");    return null;  }   return { url: relayUrl };} function canRegisterRemoteLiveActivities(): boolean {  return Platform.OS === "ios";} export function shouldRegisterAgentAwarenessDeviceForProvider(  previousIdentity: string | null,  identity: string | undefined,): boolean {  return identity === undefined || identity !== previousIdentity;} export function setAgentAwarenessRelayTokenProvider(  provider: (() => Promise<string | null>) | null,  identity?: string,): void {  const isExistingIdentity =    provider !== null &&    !shouldRegisterAgentAwarenessDeviceForProvider(relayTokenProviderIdentity, identity);  if (!isExistingIdentity) {    deviceRegistrationGeneration++;    activeDeviceRegistration = null;    pendingDeviceRegistration = null;  }  relayTokenProvider = provider;  relayTokenProviderIdentity = provider ? (identity ?? null) : null;  if (!provider) {    pushToStartSubscription?.remove();    pushToStartSubscription = null;    pushTokenSubscription?.remove();    pushTokenSubscription = null;    if (activeLiveActivityRegistrationRetry) {      clearTimeout(activeLiveActivityRegistrationRetry);      activeLiveActivityRegistrationRetry = null;    }    return;  }  ensurePushToStartListener();  ensurePushTokenListener();  runRegistrationInBackground(    refreshActiveLiveActivityRemoteRegistration(),    "active live activity registration after cloud sign-in failed",  );  if (isExistingIdentity) {    return;  }  enqueueDeviceRegistration({}, "device registration after cloud sign-in failed");} function iosMajorVersion(): number {  const version = Platform.Version;  if (typeof version === "number") {    return Math.floor(version);  }  const major = Number.parseInt(version.split(".")[0] ?? "", 10);  return Number.isFinite(major) ? major : 18;} function nativePushTokenRegistration(observedPushToken?: string) {  return Effect.gen(function* () {    if (!canRegisterRemoteLiveActivities()) {      return { notificationsEnabled: false, pushToken: null };    }    if (observedPushToken) {      return { notificationsEnabled: true, pushToken: observedPushToken };    }    const permissions = yield* Effect.tryPromise({      try: () => Notifications.getPermissionsAsync(),      catch: (error) => error,    });    if (!permissions.granted) {      return { notificationsEnabled: false, pushToken: null };    }    const token = yield* Effect.tryPromise({      try: () => Notifications.getDevicePushTokenAsync(),      catch: (error) => error,    }).pipe(      Effect.tapError((error) =>        Effect.sync(() => {          logRegistrationError("native APNs token lookup failed", error);        }),      ),      Effect.orElseSucceed(() => null),    );    const pushToken =      token?.type === "ios" && typeof token.data === "string" && token.data.trim().length > 0        ? token.data.trim()        : null;    return { notificationsEnabled: pushToken !== null, pushToken };  });} const relayToken = Effect.gen(function* () {  const provider = relayTokenProvider;  if (!provider) {    return null;  }  return yield* Effect.tryPromise({    try: provider,    catch: (error) => error,  });}); function registerDeviceWithRelay(  body: RelayDeviceRegistrationRequest,  expectedGeneration: number,): Effect.Effect<void, unknown, ManagedRelay.ManagedRelayClient> {  return Effect.gen(function* () {    if (expectedGeneration !== deviceRegistrationGeneration) {      logRegistrationDebug("device registration cancelled before relay request", {        expectedGeneration,        currentGeneration: deviceRegistrationGeneration,      });      return;    }    if (!readRelayConfig()) return;    const token = yield* relayToken;    if (expectedGeneration !== deviceRegistrationGeneration) {      logRegistrationDebug("device registration cancelled after auth lookup", {        expectedGeneration,        currentGeneration: deviceRegistrationGeneration,      });      return;    }    if (!token) {      logRegistrationDebug("relay device registration skipped; user is not signed in");      return;    }     const client = yield* ManagedRelay.ManagedRelayClient;    logRegistrationDebug("relay device registration request started", {      expectedGeneration,    });    yield* client.registerDevice({      clerkToken: token,      payload: body,    });    logRegistrationDebug("relay device registration request completed", {      expectedGeneration,    });  });} function unregisterDeviceWithRelay(input: {  readonly deviceId: string;  readonly tokenProvider: () => Promise<string | null>;}): Effect.Effect<void, unknown, ManagedRelay.ManagedRelayClient> {  return Effect.gen(function* () {    if (!readRelayConfig()) return;    const token = yield* Effect.tryPromise({      try: input.tokenProvider,      catch: (error) => error,    });    if (!token) {      logRegistrationDebug("relay device unregistration skipped; user is not signed in");      return;    }     const client = yield* ManagedRelay.ManagedRelayClient;    yield* client.unregisterDevice({      clerkToken: token,      deviceId: input.deviceId,    });  });} function registerLiveActivityWithRelay(  body: RelayLiveActivityRegistrationRequest,): Effect.Effect<boolean, unknown, ManagedRelay.ManagedRelayClient> {  return Effect.gen(function* () {    if (!readRelayConfig()) return false;    const token = yield* relayToken;    if (!token) {      logRegistrationDebug("relay live activity registration skipped; user is not signed in");      return false;    }     const client = yield* ManagedRelay.ManagedRelayClient;    yield* client.registerLiveActivity({      clerkToken: token,      payload: body,    });    return true;  });} function logRegistrationError(context: string, error: unknown): void {  if (!__DEV__) {    return;  }  console.warn(`[agent-awareness] ${context}`, {    message: error instanceof Error ? error.message : String(error),    traceId: findErrorTraceId(error),    error,  });} function logRegistrationDebug(context: string, details?: unknown): void {  if (!__DEV__) {    return;  }  console.log(`[agent-awareness] ${context}`, details ?? "");} function runRegistrationInBackground(  operation: Effect.Effect<unknown, unknown, ManagedRelay.ManagedRelayClient>,  context: string,): void {  void (async () => {    const result = await settleAsyncResult(() => runtime.runPromiseExit(operation));    if (result._tag === "Failure" && !isAtomCommandInterrupted(result)) {      logRegistrationError(context, squashAtomCommandFailure(result));    }  })();} function mergeDeviceRegistrationInput(  current: DeviceRegistrationInput,  next: DeviceRegistrationInput,): DeviceRegistrationInput {  return {    ...((next.pushToStartToken ?? current.pushToStartToken)      ? { pushToStartToken: next.pushToStartToken ?? current.pushToStartToken }      : {}),    ...((next.observedPushToken ?? current.observedPushToken)      ? { observedPushToken: next.observedPushToken ?? current.observedPushToken }      : {}),  };} function registrationAddsInformation(  current: DeviceRegistrationInput,  next: DeviceRegistrationInput,): boolean {  return (    (next.pushToStartToken !== undefined && next.pushToStartToken !== current.pushToStartToken) ||    (next.observedPushToken !== undefined && next.observedPushToken !== current.observedPushToken)  );} function startPendingDeviceRegistration(): void {  if (activeDeviceRegistration || !pendingDeviceRegistration) {    return;  }   const next = pendingDeviceRegistration;  pendingDeviceRegistration = null;  const generation = deviceRegistrationGeneration;  logRegistrationDebug("device registration started", {    generation,    hasObservedPushToken: next.input.observedPushToken !== undefined,    hasPushToStartToken: next.input.pushToStartToken !== undefined,  });  const registration = {    input: next.input,    operation: Promise.resolve(),  };  activeDeviceRegistration = registration;  registration.operation = (async () => {    const result = await settleAsyncResult(() =>      runtime.runPromiseExit(registerDevice(next.input, generation)),    );    if (result._tag === "Failure" && !isAtomCommandInterrupted(result)) {      logRegistrationError(next.context, squashAtomCommandFailure(result));    }    logRegistrationDebug("device registration finished", { generation });    if (activeDeviceRegistration === registration) {      activeDeviceRegistration = null;    }    startPendingDeviceRegistration();  })();} function enqueueDeviceRegistration(input: DeviceRegistrationInput, context: string): void {  if (    activeDeviceRegistration &&    !registrationAddsInformation(activeDeviceRegistration.input, input)  ) {    logRegistrationDebug("device registration coalesced with active request", {      generation: deviceRegistrationGeneration,    });    return;  }   logRegistrationDebug("device registration enqueued", {    generation: deviceRegistrationGeneration,    hasActiveRegistration: activeDeviceRegistration !== null,    hasPendingRegistration: pendingDeviceRegistration !== null,  });  pendingDeviceRegistration = pendingDeviceRegistration    ? {        input: mergeDeviceRegistrationInput(pendingDeviceRegistration.input, input),        context,      }    : { input, context };  startPendingDeviceRegistration();} function registerDevice(  input: DeviceRegistrationInput = {},  expectedGeneration = deviceRegistrationGeneration,): Effect.Effect<void, unknown, ManagedRelay.ManagedRelayClient> {  return Effect.gen(function* () {    if (!canRegisterRemoteLiveActivities()) {      logRegistrationDebug("device registration skipped; platform does not support it");      return;    }     logRegistrationDebug("device registration loading local state", { expectedGeneration });    const [deviceId, preferences] = yield* Effect.all([      Effect.tryPromise({        try: () => loadOrCreateAgentAwarenessDeviceId(),        catch: (error) => error,      }),      Effect.tryPromise({        try: () => loadPreferences(),        catch: (error) => error,      }),    ]);    const pushTokenRegistration = yield* nativePushTokenRegistration(input?.observedPushToken);    logRegistrationDebug("device registration local state ready", {      expectedGeneration,      notificationsEnabled: pushTokenRegistration.notificationsEnabled,    });    yield* registerDeviceWithRelay(      makeRelayDeviceRegistrationRequest({        deviceId,        label: Constants.deviceName?.trim() || "iOS device",        iosMajorVersion: iosMajorVersion(),        appVersion: Constants.expoConfig?.version,        ...(pushTokenRegistration.pushToken ? { pushToken: pushTokenRegistration.pushToken } : {}),        ...(input?.pushToStartToken ? { pushToStartToken: input.pushToStartToken } : {}),        notificationsEnabled: pushTokenRegistration.notificationsEnabled,        preferences,      }),      expectedGeneration,    );  });} function registerDeviceForCurrentUser(  pushToStartToken?: string,): Effect.Effect<void, unknown, ManagedRelay.ManagedRelayClient> {  return registerDevice(pushToStartToken ? { pushToStartToken } : undefined);} function registerPushToStartTokenForCurrentUser(pushToStartToken: string): void {  enqueueDeviceRegistration({ pushToStartToken }, "push-to-start token registration failed");} function ensurePushToStartListener(): void {  if (pushToStartSubscription || !canRegisterRemoteLiveActivities()) {    return;  }   pushToStartSubscription = addPushToStartTokenListener((event) => {    const token = event.activityPushToStartToken;    if (token) {      registerPushToStartTokenForCurrentUser(token);    }  });} function ensurePushTokenListener(): void {  if (pushTokenSubscription || !canRegisterRemoteLiveActivities()) {    return;  }   pushTokenSubscription = Notifications.addPushTokenListener((token) => {    if (token.type === "ios" && typeof token.data === "string" && token.data.trim().length > 0) {      enqueueDeviceRegistration(        { observedPushToken: token.data.trim() },        "native APNs token rotation registration failed",      );    }  });} export function registerAgentAwarenessConnection(connection: SavedRemoteConnection): void {  if (!canRegisterRemoteLiveActivities()) {    return;  }   environmentConnections.set(connection.environmentId, connection);  ensurePushToStartListener();  ensurePushTokenListener();  enqueueDeviceRegistration({}, "device registration failed");  runRegistrationInBackground(    refreshActiveLiveActivityRemoteRegistration(),    "active live activity registration after environment connection failed",  );} function removeAgentAwarenessConnection(environmentId: EnvironmentId): void {  environmentConnections.delete(environmentId);} export function unregisterAgentAwarenessConnection(environmentId: EnvironmentId): void {  removeAgentAwarenessConnection(environmentId);} export function unregisterAllAgentAwarenessConnections(): void {  environmentConnections.clear();  pushToStartSubscription?.remove();  pushToStartSubscription = null;  pushTokenSubscription?.remove();  pushTokenSubscription = null;  if (activeLiveActivityRegistrationRetry) {    clearTimeout(activeLiveActivityRegistrationRetry);    activeLiveActivityRegistrationRetry = null;  }} export function refreshAgentAwarenessRegistration(): Effect.Effect<  void,  never,  ManagedRelay.ManagedRelayClient> {  return registerDeviceForCurrentUser().pipe(    Effect.catch((error) =>      Effect.sync(() => {        logRegistrationError("device registration refresh failed", error);      }),    ),  );} export function __resetAgentAwarenessRemoteRegistrationForTest(): void {  environmentConnections.clear();

Lines 1–500 of 662.