import { HttpError } from "../errors";
import { agentUpdate } from "./room-agents";
import { canWrite, resolveEditorToken } from "./session";
import { CLOSE_DOWNGRADED, CLOSE_REAUTH, CLOSE_REVOKED } from "~/lib/editor-protocol";
import { awarenessFrame, base64, decodeAwareness, encodeAwareness, removalFrame, unbase64 } from "./room-awareness";
const MAX_CACHED_AWARENESS = 1200;
const MAX_CLIENT_ID = 2 ** 32;
/** Per-socket state; it survives hibernation, so it must stay small (attachments are capped at 2 KiB). */
export type Attachment = {
token: string;
userId: string;
name: string;
kind: "human" | "agent";
writable: boolean;
checkedAt: number;
expiresAt: number;
aw?: string;
awClient?: number;
awClock?: number;
};
export type RoomJoin = Omit<Attachment, "checkedAt" | "aw" | "awClient" | "awClock"> & {
repoId: string;
branch: string;
head: string;
};
export type Participant = { id: string; name: string; kind: "human" | "agent"; path: string | null };
type AgentRow = Parameters<typeof agentUpdate>[0];
/**
* Relays a cursor update with identity fields overwritten by the authenticated user, so nobody can
* impersonate another participant. The last update is cached on the socket to replay to newcomers.
*/
export function sanitizeAwareness(
attachment: Attachment,
update: Uint8Array,