@holdpoint/live-daemon 0.1.0-alpha.4 → 0.1.0-alpha.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +119 -39
- package/dist/index.js.map +1 -1
- package/dist/live-ui/assets/index-BAgfQlSi.css +2 -0
- package/dist/live-ui/assets/index-DZZKTCKK.js +405 -0
- package/dist/live-ui/assets/index-DZZKTCKK.js.map +1 -0
- package/dist/live-ui/index.html +2 -2
- package/package.json +4 -4
- package/dist/builder-ui/assets/index-34-pmyiJ.js +0 -391
- package/dist/builder-ui/assets/index-34-pmyiJ.js.map +0 -1
- package/dist/builder-ui/assets/index-Bwt9-ehF.css +0 -2
- package/dist/builder-ui/favicon.svg +0 -10
- package/dist/builder-ui/index.html +0 -14
- package/dist/live-ui/assets/index-CGJwpNcJ.js +0 -10
- package/dist/live-ui/assets/index-CGJwpNcJ.js.map +0 -1
- package/dist/live-ui/assets/index-z6W1Fyph.css +0 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/singleton.ts","../src/server.ts","../src/auth.ts","../src/store.ts","../src/conflict-tracker.ts","../src/project-identity.ts","../src/router.ts","../src/index.ts"],"sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport { createServer } from \"node:net\";\nimport os from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport { z } from \"zod\";\n\nexport const DaemonLockSchema = z.object({\n version: z.string().min(1),\n pid: z.number().int().positive(),\n port: z.number().int().positive(),\n token: z.string().min(1),\n started_at: z.number().int().nonnegative(),\n host: z.string().min(1),\n});\n\nexport type DaemonLock = z.infer<typeof DaemonLockSchema>;\n\nexport function resolveHoldpointHome(homeDir?: string): string {\n return resolve(homeDir ?? process.env.HOLDPOINT_HOME ?? join(os.homedir(), \".holdpoint\"));\n}\n\nexport function ensureHoldpointHome(homeDir?: string): string {\n const root = resolveHoldpointHome(homeDir);\n mkdirSync(root, { recursive: true, mode: 0o700 });\n return root;\n}\n\nexport function getDaemonLockPath(homeDir?: string): string {\n return join(resolveHoldpointHome(homeDir), \"daemon.lock\");\n}\n\nexport function readDaemonLock(homeDir?: string): DaemonLock | null {\n const lockPath = getDaemonLockPath(homeDir);\n if (!existsSync(lockPath)) return null;\n try {\n return DaemonLockSchema.parse(JSON.parse(readFileSync(lockPath, \"utf8\")));\n } catch {\n return null;\n }\n}\n\nexport function isProcessAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function findFreePort(host = \"127.0.0.1\"): Promise<number> {\n return await new Promise<number>((resolvePromise, reject) => {\n const server = createServer();\n server.listen(0, host, () => {\n const address = server.address();\n if (!address || typeof address === \"string\") {\n server.close();\n reject(new Error(\"Expected TCP address\"));\n return;\n }\n const { port } = address;\n server.close((err) => {\n if (err) reject(err);\n else resolvePromise(port);\n });\n });\n server.on(\"error\", reject);\n });\n}\n\nexport function createDaemonLock(port: number, version: string): DaemonLock {\n return {\n version,\n pid: process.pid,\n port,\n token: randomBytes(32).toString(\"hex\"),\n started_at: Date.now(),\n host: `${os.platform()}-${os.arch()}`,\n };\n}\n\nexport function writeDaemonLockExclusive(lock: DaemonLock, homeDir?: string): void {\n ensureHoldpointHome(homeDir);\n writeFileSync(getDaemonLockPath(homeDir), JSON.stringify(lock, null, 2) + \"\\n\", {\n encoding: \"utf8\",\n flag: \"wx\",\n mode: 0o600,\n });\n}\n\nexport function removeDaemonLock(homeDir?: string, expectedToken?: string): void {\n const lockPath = getDaemonLockPath(homeDir);\n if (!existsSync(lockPath)) return;\n if (expectedToken) {\n const lock = readDaemonLock(homeDir);\n if (!lock || lock.token !== expectedToken) {\n return;\n }\n }\n try {\n unlinkSync(lockPath);\n } catch {\n /* ignore cleanup races */\n }\n}\n\nasync function fetchHealth(port: number, timeoutMs: number): Promise<boolean> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const response = await fetch(`http://127.0.0.1:${port}/health`, {\n signal: controller.signal,\n });\n return response.ok;\n } catch {\n return false;\n } finally {\n clearTimeout(timeout);\n }\n}\n\nexport async function waitForDaemonHealthy(\n lock: DaemonLock,\n timeoutMs = 5_000,\n pollMs = 100,\n): Promise<boolean> {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n if (await fetchHealth(lock.port, Math.min(pollMs, timeoutMs))) {\n return true;\n }\n await new Promise((resolvePromise) => setTimeout(resolvePromise, pollMs));\n }\n return false;\n}\n\nexport async function readHealthyDaemonLock(homeDir?: string): Promise<DaemonLock | null> {\n const lock = readDaemonLock(homeDir);\n if (!lock) return null;\n if (!isProcessAlive(lock.pid)) {\n removeDaemonLock(homeDir);\n return null;\n }\n if (!(await waitForDaemonHealthy(lock, 300, 100))) {\n removeDaemonLock(homeDir);\n return null;\n }\n return lock;\n}\n","import { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport { randomUUID } from \"node:crypto\";\nimport { createReadStream, existsSync } from \"node:fs\";\nimport { dirname, extname, join, resolve, sep } from \"node:path\";\nimport { fileURLToPath, URL } from \"node:url\";\nimport type { EventV1, ServerMessage } from \"@holdpoint/live-protocol\";\nimport {\n ClientMessageSchema,\n ControlRequestSchema,\n EventV1Schema,\n EventsBatchSchema,\n} from \"@holdpoint/live-protocol\";\nimport { WebSocket, WebSocketServer, type RawData } from \"ws\";\nimport {\n authorizeRequest,\n authorizeWebSocket,\n readJsonBody,\n writeJson,\n writeUiAuthCookie,\n} from \"./auth.js\";\nimport { matchesSubscription, type Subscription } from \"./router.js\";\nimport type { LiveStore } from \"./store.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst LIVE_UI_DIR = join(__dirname, \"live-ui\");\nconst BUILDER_UI_DIR = join(__dirname, \"builder-ui\");\nconst CONTENT_SECURITY_POLICY =\n \"default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; connect-src 'self' ws: http:; object-src 'none'; base-uri 'none'; frame-ancestors 'none'\";\nconst MIME: Record<string, string> = {\n \".css\": \"text/css; charset=utf-8\",\n \".html\": \"text/html; charset=utf-8\",\n \".ico\": \"image/x-icon\",\n \".js\": \"text/javascript; charset=utf-8\",\n \".json\": \"application/json; charset=utf-8\",\n \".mjs\": \"text/javascript; charset=utf-8\",\n \".png\": \"image/png\",\n \".svg\": \"image/svg+xml\",\n};\n\nexport interface StartLiveServerOptions {\n host?: string;\n port: number;\n token: string;\n version: string;\n startedAt: number;\n store: LiveStore;\n}\n\nexport interface RunningLiveServer {\n host: string;\n port: number;\n close(): Promise<void>;\n closed: Promise<void>;\n}\n\ninterface RegisteredProject {\n hash: string;\n name?: string;\n root: string;\n}\n\nfunction sendSocketMessage(socket: WebSocket, message: ServerMessage): void {\n socket.send(JSON.stringify(message));\n}\n\nfunction decodeRawData(raw: RawData): string {\n if (typeof raw === \"string\") return raw;\n if (raw instanceof Buffer) return raw.toString(\"utf8\");\n if (Array.isArray(raw)) return Buffer.concat(raw).toString(\"utf8\");\n return Buffer.from(new Uint8Array(raw)).toString(\"utf8\");\n}\n\nfunction getEventsForScope(\n store: LiveStore,\n subscription: Subscription,\n sinceSeq: number,\n): EventV1[] {\n switch (subscription.scope) {\n case \"all\":\n return store.getAllEvents(sinceSeq);\n case \"project\":\n return subscription.key ? store.getProjectEvents(subscription.key, sinceSeq) : [];\n case \"session\":\n return subscription.key ? store.getSessionEvents(subscription.key, sinceSeq) : [];\n }\n}\n\nfunction buildControlStateEvent(\n session: {\n project_hash: string;\n engine: string;\n session_id: string;\n cwd: string;\n caps?: EventV1[\"caps\"];\n },\n controlOnline: boolean,\n): EventV1 {\n return {\n v: 1,\n id: randomUUID(),\n ts: Date.now(),\n engine: session.engine,\n session_id: session.session_id,\n project_hash: session.project_hash,\n cwd: session.cwd,\n caps: {\n ...(session.caps ?? {}),\n can_control: session.caps?.can_control ?? true,\n control_online: controlOnline,\n },\n type: \"meta\",\n payload: {\n kind: controlOnline ? \"control_socket_registered\" : \"control_socket_disconnected\",\n },\n };\n}\n\nfunction servePlaceholder(res: ServerResponse, appName = \"Holdpoint Live\"): void {\n res.writeHead(200, {\n \"cache-control\": \"no-store\",\n \"content-security-policy\": CONTENT_SECURITY_POLICY,\n \"content-type\": \"text/html; charset=utf-8\",\n });\n res.end(\n `<!doctype html><title>${appName}</title><body style=\"font-family:system-ui;background:#0b0f14;color:#f5f1e8;padding:32px\"><h1>${appName}</h1><p>UI assets were not found in this build. Rebuild the monorepo with <code>pnpm turbo build</code>.</p></body>`,\n );\n}\n\nfunction serveUiAsset(res: ServerResponse, filePath: string): void {\n const mime = MIME[extname(filePath)] ?? \"application/octet-stream\";\n const headers: Record<string, string> = {\n \"cache-control\": \"no-store\",\n \"content-type\": mime,\n };\n if (filePath.endsWith(\".html\")) {\n headers[\"content-security-policy\"] = CONTENT_SECURITY_POLICY;\n }\n res.writeHead(200, headers);\n createReadStream(filePath).pipe(res);\n}\n\nfunction isWithinRoot(candidate: string, root: string): boolean {\n return candidate === root || candidate.startsWith(root + sep);\n}\n\nfunction resolveUiFilePath(uiDir: string, requestedPath: string): string | null {\n const requested = requestedPath === \"\" || requestedPath === \"/\" ? \"index.html\" : requestedPath;\n const candidate = resolve(uiDir, requested.replace(/^\\//, \"\"));\n if (!isWithinRoot(candidate, uiDir)) {\n return null;\n }\n if (existsSync(candidate)) {\n return candidate;\n }\n return existsSync(join(uiDir, \"index.html\")) ? join(uiDir, \"index.html\") : null;\n}\n\nfunction normalizeUiPath(path: string | null): \"/live/\" | \"/builder/\" {\n if (!path) return \"/live/\";\n if (path === \"/live\" || path.startsWith(\"/live/\")) return \"/live/\";\n if (path === \"/builder\" || path.startsWith(\"/builder/\")) return \"/builder/\";\n return \"/live/\";\n}\n\nfunction registerProjectFromAuthUrl(\n url: URL,\n registeredProjects: Map<string, RegisteredProject>,\n): void {\n const hash = url.searchParams.get(\"project\");\n const root = url.searchParams.get(\"root\");\n if (!hash || !root || root.includes(\"\\0\")) {\n return;\n }\n const name = url.searchParams.get(\"name\");\n registeredProjects.set(hash, {\n hash,\n ...(name ? { name } : {}),\n root: resolve(root),\n });\n}\n\nfunction getProjectForRequest(\n url: URL,\n registeredProjects: Map<string, RegisteredProject>,\n): RegisteredProject | null {\n const hash = url.searchParams.get(\"project\");\n if (hash) {\n return registeredProjects.get(hash) ?? null;\n }\n if (registeredProjects.size === 1) {\n return [...registeredProjects.values()][0] ?? null;\n }\n return null;\n}\n\nexport async function startLiveServer(options: StartLiveServerOptions): Promise<RunningLiveServer> {\n const host = options.host ?? \"127.0.0.1\";\n const subscriptions = new Map<WebSocket, Subscription[]>();\n const controlSockets = new Map<string, WebSocket>();\n const socketControlKeys = new Map<WebSocket, Set<string>>();\n const registeredProjects = new Map<string, RegisteredProject>();\n const server = createServer((req, res) => {\n void handleRequest(req, res, options, subscriptions, registeredProjects).catch(\n (error: unknown) => {\n writeJson(res, 500, { ok: false, error: (error as Error).message });\n },\n );\n });\n const wss = new WebSocketServer({ noServer: true });\n\n const broadcastEvent = (event: EventV1): void => {\n for (const [socket, socketSubscriptions] of subscriptions.entries()) {\n if (socket.readyState !== WebSocket.OPEN) continue;\n if (socketSubscriptions.some((subscription) => matchesSubscription(subscription, event))) {\n sendSocketMessage(socket, { type: \"event\", event });\n }\n }\n };\n\n const ingestAndBroadcast = async (event: EventV1): Promise<EventV1[]> => {\n const accepted = await options.store.ingest(event);\n for (const acceptedEvent of accepted) {\n broadcastEvent(acceptedEvent);\n }\n return accepted;\n };\n\n const emitControlState = async (sessionKey: string, controlOnline: boolean): Promise<void> => {\n const summary = options.store.getSessionSummary(sessionKey);\n if (!summary) return;\n await ingestAndBroadcast(buildControlStateEvent(summary, controlOnline));\n };\n\n const registerControlSocket = async (sessionKey: string, socket: WebSocket): Promise<void> => {\n const previous = controlSockets.get(sessionKey);\n if (previous && previous !== socket) {\n socketControlKeys.get(previous)?.delete(sessionKey);\n }\n controlSockets.set(sessionKey, socket);\n const keys = socketControlKeys.get(socket) ?? new Set<string>();\n keys.add(sessionKey);\n socketControlKeys.set(socket, keys);\n await emitControlState(sessionKey, true);\n };\n\n const unregisterControlSocket = async (sessionKey: string, socket: WebSocket): Promise<void> => {\n if (controlSockets.get(sessionKey) !== socket) return;\n controlSockets.delete(sessionKey);\n const keys = socketControlKeys.get(socket);\n keys?.delete(sessionKey);\n if (keys && keys.size === 0) {\n socketControlKeys.delete(socket);\n }\n await emitControlState(sessionKey, false);\n };\n\n const unregisterSocketControls = async (socket: WebSocket): Promise<void> => {\n const keys = [...(socketControlKeys.get(socket) ?? [])];\n for (const sessionKey of keys) {\n await unregisterControlSocket(sessionKey, socket);\n }\n };\n\n wss.on(\"connection\", (socket: WebSocket) => {\n subscriptions.set(socket, []);\n socket.on(\"message\", (raw: RawData) => {\n void (async () => {\n let message: unknown;\n try {\n message = JSON.parse(decodeRawData(raw));\n } catch {\n sendSocketMessage(socket, {\n type: \"error\",\n code: \"invalid_json\",\n message: \"Expected JSON message\",\n });\n return;\n }\n\n const parsed = ClientMessageSchema.safeParse(message);\n if (!parsed.success) {\n sendSocketMessage(socket, {\n type: \"error\",\n code: \"invalid_message\",\n message: parsed.error.issues[0]?.message ?? \"Invalid message\",\n });\n return;\n }\n\n switch (parsed.data.type) {\n case \"subscribe\": {\n if (parsed.data.scope !== \"all\" && !parsed.data.key) {\n sendSocketMessage(socket, {\n type: \"error\",\n code: \"missing_key\",\n message: \"Expected a key for session/project subscriptions\",\n });\n return;\n }\n\n const subscription =\n parsed.data.key !== undefined\n ? { scope: parsed.data.scope, key: parsed.data.key }\n : { scope: parsed.data.scope };\n const next = subscriptions.get(socket) ?? [];\n next.push(subscription);\n subscriptions.set(socket, next);\n\n const backlog = getEventsForScope(\n options.store,\n subscription,\n parsed.data.since_seq ?? 0,\n );\n if (backlog.length > 0) {\n sendSocketMessage(socket, { type: \"events_batch\", events: backlog });\n }\n sendSocketMessage(socket, {\n type: \"ack\",\n for: parsed.data.scope === \"all\" ? \"all\" : (parsed.data.key ?? parsed.data.scope),\n });\n break;\n }\n case \"register_control\": {\n await registerControlSocket(parsed.data.session_key, socket);\n sendSocketMessage(socket, { type: \"ack\", for: parsed.data.session_key });\n break;\n }\n case \"unsubscribe\": {\n const key = parsed.data.key;\n const next = (subscriptions.get(socket) ?? []).filter(\n (subscription) => subscription.key !== key,\n );\n subscriptions.set(socket, next);\n sendSocketMessage(socket, { type: \"ack\", for: key });\n break;\n }\n case \"publish_event\": {\n const accepted = await options.store.ingest(parsed.data.event);\n for (const event of accepted) {\n broadcastEvent(event);\n }\n sendSocketMessage(socket, { type: \"ack\", for: parsed.data.event.id });\n break;\n }\n case \"ping\":\n sendSocketMessage(socket, { type: \"pong\" });\n break;\n }\n })();\n });\n\n socket.on(\"close\", () => {\n subscriptions.delete(socket);\n void unregisterSocketControls(socket).catch(() => {});\n });\n });\n\n server.on(\"upgrade\", (req, socket, head) => {\n const url = new URL(req.url ?? \"/\", `http://${host}:${options.port}`);\n if (url.pathname !== \"/v1/stream\" || !authorizeWebSocket(req, options.token, options.port)) {\n socket.write(\"HTTP/1.1 401 Unauthorized\\r\\n\\r\\n\");\n socket.destroy();\n return;\n }\n\n wss.handleUpgrade(req, socket, head, (ws: WebSocket) => {\n wss.emit(\"connection\", ws, req);\n });\n });\n\n await new Promise<void>((resolvePromise, reject) => {\n server.listen(options.port, host, resolvePromise);\n server.on(\"error\", reject);\n });\n\n const address = server.address();\n if (!address || typeof address === \"string\") {\n throw new Error(\"Expected TCP address\");\n }\n const actualPort = address.port;\n\n const closed = new Promise<void>((resolvePromise, reject) => {\n server.on(\"close\", () => resolvePromise());\n server.on(\"error\", reject);\n });\n\n async function close(): Promise<void> {\n for (const socket of subscriptions.keys()) {\n socket.close();\n }\n await new Promise<void>((resolvePromise, reject) => {\n wss.close((err?: Error) => (err ? reject(err) : resolvePromise()));\n });\n await new Promise<void>((resolvePromise, reject) => {\n server.close((err) => (err ? reject(err) : resolvePromise()));\n });\n }\n\n async function handleRequest(\n req: IncomingMessage,\n res: ServerResponse,\n state: StartLiveServerOptions,\n _subscriptions: Map<WebSocket, Subscription[]>,\n registered: Map<string, RegisteredProject>,\n ): Promise<void> {\n const url = new URL(req.url ?? \"/\", `http://${host}:${actualPort}`);\n if (req.method === \"GET\" && url.pathname === \"/health\") {\n writeJson(res, 200, { ok: true, version: state.version, started_at: state.startedAt });\n return;\n }\n\n if (req.method === \"GET\" && url.pathname === \"/__holdpoint/live-auth\") {\n if (url.searchParams.get(\"token\") !== state.token) {\n writeJson(res, 401, { ok: false, error: \"Unauthorized\" });\n return;\n }\n\n registerProjectFromAuthUrl(url, registered);\n\n const redirectPath = normalizeUiPath(url.searchParams.get(\"path\"));\n const redirectUrl = new URL(`http://${host}:${actualPort}`);\n redirectUrl.pathname = redirectPath;\n for (const [key, value] of url.searchParams.entries()) {\n if (key !== \"token\" && key !== \"path\") {\n redirectUrl.searchParams.set(key, value);\n }\n }\n writeUiAuthCookie(res, state.token);\n res.writeHead(302, {\n location: redirectUrl.toString(),\n \"cache-control\": \"no-store\",\n });\n res.end();\n return;\n }\n\n if (req.method === \"GET\" && url.pathname === \"/__holdpoint/initial-yaml\") {\n if (!authorizeRequest(req, res, state.token, actualPort)) {\n return;\n }\n const project = getProjectForRequest(url, registered);\n if (!project) {\n writeJson(res, 404, { ok: false, error: \"Project not registered for this UI session\" });\n return;\n }\n const checksPath = resolve(project.root, \"checks.yaml\");\n if (!isWithinRoot(checksPath, project.root) || !existsSync(checksPath)) {\n writeJson(res, 404, { ok: false, error: \"checks.yaml not found for this project\" });\n return;\n }\n res.writeHead(200, {\n \"cache-control\": \"no-store\",\n \"content-type\": \"text/yaml; charset=utf-8\",\n });\n createReadStream(checksPath).pipe(res);\n return;\n }\n\n if (req.method === \"GET\" && url.pathname === \"/__holdpoint/initial-reports\") {\n if (!authorizeRequest(req, res, state.token, actualPort)) {\n return;\n }\n const project = getProjectForRequest(url, registered);\n if (!project) {\n writeJson(res, 404, { ok: false, error: \"Project not registered for this UI session\" });\n return;\n }\n const reportsPath = resolve(project.root, \".holdpoint\", \"check-reports.json\");\n if (!isWithinRoot(reportsPath, project.root) || !existsSync(reportsPath)) {\n writeJson(res, 404, { ok: false, error: \"No check reports found for this project\" });\n return;\n }\n res.writeHead(200, {\n \"cache-control\": \"no-store\",\n \"content-type\": \"application/json; charset=utf-8\",\n });\n createReadStream(reportsPath).pipe(res);\n return;\n }\n\n if (url.pathname.startsWith(\"/v1/\") && !authorizeRequest(req, res, state.token, actualPort)) {\n return;\n }\n\n if (req.method === \"POST\" && url.pathname === \"/v1/events\") {\n const event = EventV1Schema.parse(await readJsonBody(req));\n const accepted = await ingestAndBroadcast(event);\n writeJson(res, 200, { ok: true, accepted: accepted.length });\n return;\n }\n\n if (req.method === \"POST\" && url.pathname === \"/v1/events/batch\") {\n const events = EventsBatchSchema.parse(await readJsonBody(req));\n const accepted: EventV1[] = [];\n for (const event of events) {\n accepted.push(...(await ingestAndBroadcast(event)));\n }\n writeJson(res, 200, { ok: true, accepted: accepted.length });\n return;\n }\n\n if (req.method === \"POST\" && url.pathname === \"/v1/control\") {\n const request = ControlRequestSchema.parse(await readJsonBody(req));\n const session = state.store.getSessionSummary(request.session_key);\n if (!session) {\n writeJson(res, 404, { ok: false, error: \"Session not found\" });\n return;\n }\n\n const controlSocket = controlSockets.get(request.session_key);\n if (!controlSocket || controlSocket.readyState !== WebSocket.OPEN) {\n writeJson(res, 409, { ok: false, error: \"Control socket not connected\" });\n return;\n }\n\n await ingestAndBroadcast({\n v: 1,\n id: randomUUID(),\n ts: Date.now(),\n engine: session.engine,\n session_id: session.session_id,\n project_hash: session.project_hash,\n cwd: session.cwd,\n type: \"control\",\n payload: request.command,\n });\n sendSocketMessage(controlSocket, {\n type: \"control\",\n session_key: request.session_key,\n command: request.command,\n });\n writeJson(res, 200, { ok: true, delivered: true });\n return;\n }\n\n if (req.method === \"GET\" && url.pathname === \"/v1/projects\") {\n writeJson(res, 200, { projects: state.store.listProjects() });\n return;\n }\n\n if (req.method === \"GET\" && url.pathname === \"/v1/sessions\") {\n const projectHash = url.searchParams.get(\"project_hash\") ?? undefined;\n writeJson(res, 200, { sessions: state.store.listSessions(projectHash) });\n return;\n }\n\n if (\n req.method === \"GET\" &&\n url.pathname.startsWith(\"/v1/sessions/\") &&\n url.pathname.endsWith(\"/events\")\n ) {\n const sessionKey = decodeURIComponent(\n url.pathname.replace(\"/v1/sessions/\", \"\").replace(/\\/events$/, \"\"),\n );\n const sinceSeq = Number(\n url.searchParams.get(\"since_seq\") ?? url.searchParams.get(\"since\") ?? \"0\",\n );\n const limit = Number(url.searchParams.get(\"limit\") ?? \"500\");\n writeJson(res, 200, {\n session_key: sessionKey,\n since_seq: Number.isFinite(sinceSeq) ? sinceSeq : 0,\n max_seq: state.store.getSessionLatestSeq(sessionKey),\n events: state.store.getSessionEvents(\n sessionKey,\n Number.isFinite(sinceSeq) ? sinceSeq : 0,\n Number.isFinite(limit) ? limit : 500,\n ),\n });\n return;\n }\n\n if (req.method === \"DELETE\" && url.pathname.startsWith(\"/v1/sessions/\")) {\n const sessionKey = decodeURIComponent(url.pathname.replace(\"/v1/sessions/\", \"\"));\n const removed = await state.store.purgeSession(sessionKey);\n writeJson(\n res,\n removed ? 200 : 404,\n removed ? { ok: true } : { ok: false, error: \"Session not found\" },\n );\n return;\n }\n\n if (req.method === \"GET\") {\n if (url.pathname === \"/\") {\n res.writeHead(302, { location: \"/live/\", \"cache-control\": \"no-store\" });\n res.end();\n return;\n }\n\n if (url.pathname === \"/live\" || url.pathname === \"/builder\") {\n res.writeHead(302, { location: `${url.pathname}/`, \"cache-control\": \"no-store\" });\n res.end();\n return;\n }\n\n const uiRoute = url.pathname.startsWith(\"/builder/\")\n ? {\n appName: \"Holdpoint Builder\",\n dir: BUILDER_UI_DIR,\n path: url.pathname.replace(/^\\/builder\\/?/, \"\"),\n }\n : url.pathname.startsWith(\"/live/\")\n ? {\n appName: \"Holdpoint Live\",\n dir: LIVE_UI_DIR,\n path: url.pathname.replace(/^\\/live\\/?/, \"\"),\n }\n : null;\n\n if (!uiRoute) {\n res.writeHead(302, { location: \"/live/\", \"cache-control\": \"no-store\" });\n res.end();\n return;\n }\n\n const filePath = resolveUiFilePath(uiRoute.dir, uiRoute.path);\n if (!filePath) {\n servePlaceholder(res, uiRoute.appName);\n return;\n }\n serveUiAsset(res, filePath);\n return;\n }\n\n writeJson(res, 404, { ok: false, error: \"Not found\" });\n }\n\n return {\n host,\n port: actualPort,\n close,\n closed,\n };\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\n\nexport const LIVE_UI_COOKIE = \"holdpoint_live_token\";\n\nfunction parseCookies(raw: string | undefined): Map<string, string> {\n const cookies = new Map<string, string>();\n if (!raw) {\n return cookies;\n }\n\n for (const part of raw.split(\";\")) {\n const [name, ...valueParts] = part.trim().split(\"=\");\n if (!name) continue;\n cookies.set(name, decodeURIComponent(valueParts.join(\"=\")));\n }\n\n return cookies;\n}\n\nfunction getRequestToken(req: IncomingMessage): string | null {\n const auth = req.headers.authorization;\n if (auth?.startsWith(\"Bearer \")) {\n return auth.slice(\"Bearer \".length);\n }\n\n return parseCookies(req.headers.cookie).get(LIVE_UI_COOKIE) ?? null;\n}\n\nexport function writeJson(\n res: ServerResponse,\n statusCode: number,\n body: unknown,\n headers: Record<string, string> = {},\n): void {\n res.writeHead(statusCode, {\n \"cache-control\": \"no-store\",\n \"content-type\": \"application/json; charset=utf-8\",\n ...headers,\n });\n res.end(JSON.stringify(body));\n}\n\nexport async function readJsonBody(req: IncomingMessage): Promise<unknown> {\n const chunks: Buffer[] = [];\n for await (const chunk of req) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));\n }\n if (chunks.length === 0) return null;\n return JSON.parse(Buffer.concat(chunks).toString(\"utf8\"));\n}\n\nexport function authorizeRequest(\n req: IncomingMessage,\n res: ServerResponse,\n token: string,\n port: number,\n): boolean {\n const origin = req.headers.origin;\n if (origin && origin !== `http://127.0.0.1:${port}`) {\n writeJson(res, 403, { ok: false, error: \"Origin not allowed\" });\n return false;\n }\n\n if (getRequestToken(req) !== token) {\n writeJson(res, 401, { ok: false, error: \"Unauthorized\" });\n return false;\n }\n\n return true;\n}\n\nexport function authorizeWebSocket(req: IncomingMessage, token: string, port: number): boolean {\n const origin = req.headers.origin;\n if (origin && origin !== `http://127.0.0.1:${port}`) {\n return false;\n }\n\n if (getRequestToken(req) === token) {\n return true;\n }\n\n const raw = req.headers[\"sec-websocket-protocol\"];\n const protocols = (typeof raw === \"string\" ? [raw] : [])\n .flatMap((entry) => entry.split(\",\"))\n .map((entry) => entry.trim())\n .filter(Boolean);\n\n return protocols.includes(`holdpoint-${token}`);\n}\n\nexport function writeUiAuthCookie(res: ServerResponse, token: string): void {\n res.setHeader(\n \"set-cookie\",\n `${LIVE_UI_COOKIE}=${encodeURIComponent(token)}; Path=/; HttpOnly; SameSite=Strict; Max-Age=3600`,\n );\n}\n","import { appendFile, mkdir, readFile, readdir, rm, writeFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { EventV1, ProjectSummary, SessionSummary } from \"@holdpoint/live-protocol\";\nimport { EventV1Schema } from \"@holdpoint/live-protocol\";\nimport { ConflictTracker } from \"./conflict-tracker.js\";\nimport { identifyProject } from \"./project-identity.js\";\n\ninterface StoredProject extends ProjectSummary {\n root: string;\n}\n\ninterface StoredSession extends SessionSummary {\n events: EventV1[];\n filePath: string;\n}\n\nfunction sessionFileName(engine: string, sessionId: string): string {\n return `${encodeURIComponent(engine)}-${encodeURIComponent(sessionId)}.jsonl`;\n}\n\nasync function readJsonl(filePath: string): Promise<EventV1[]> {\n const raw = await readFile(filePath, \"utf8\");\n return raw\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean)\n .flatMap((line) => {\n try {\n return [EventV1Schema.parse(JSON.parse(line))];\n } catch {\n return [];\n }\n });\n}\n\nexport function buildSessionKey(\n event: Pick<EventV1, \"project_hash\" | \"engine\" | \"session_id\">,\n): string {\n return `${event.project_hash}:${event.engine}:${event.session_id}`;\n}\n\nexport class LiveStore {\n private readonly homeDir: string;\n private readonly projects = new Map<string, StoredProject>();\n private readonly sessions = new Map<string, StoredSession>();\n private readonly projectIdentityCache = new Map<string, ReturnType<typeof identifyProject>>();\n private readonly conflictTracker = new ConflictTracker();\n private nextSeq = 1;\n\n private constructor(homeDir: string) {\n this.homeDir = homeDir;\n }\n\n static async create(homeDir: string): Promise<LiveStore> {\n const store = new LiveStore(homeDir);\n await store.hydrate();\n return store;\n }\n\n async replayPending(): Promise<void> {\n const pendingDir = join(this.homeDir, \"spool\", \"pending\");\n if (!existsSync(pendingDir)) return;\n const entries = await readdir(pendingDir);\n for (const entry of entries.filter((name) => name.endsWith(\".jsonl\"))) {\n const filePath = join(pendingDir, entry);\n const events = await readJsonl(filePath);\n if (events.length > 0) {\n await this.ingestMany(events);\n }\n await rm(filePath, { force: true });\n }\n }\n\n async ingestMany(events: EventV1[]): Promise<EventV1[]> {\n const accepted: EventV1[] = [];\n for (const event of events) {\n accepted.push(...(await this.ingest(event)));\n }\n return accepted;\n }\n\n async ingest(event: EventV1): Promise<EventV1[]> {\n const accepted: EventV1[] = [];\n const storedPrimary = await this.persistEvent(event);\n accepted.push(storedPrimary);\n\n for (const derivedEvent of this.conflictTracker.handleEvent(storedPrimary)) {\n accepted.push(await this.persistEvent(derivedEvent));\n }\n\n return accepted;\n }\n\n listProjects(): ProjectSummary[] {\n return [...this.projects.values()].sort((a, b) => b.last_active - a.last_active);\n }\n\n listSessions(projectHash?: string): SessionSummary[] {\n return [...this.sessions.values()]\n .filter((session) => !projectHash || session.project_hash === projectHash)\n .sort((a, b) => b.last_event_at - a.last_event_at)\n .map(({ events: _events, filePath: _filePath, ...summary }) => summary);\n }\n\n getSessionEvents(sessionKey: string, sinceSeq = 0, limit = 500): EventV1[] {\n const session = this.sessions.get(sessionKey);\n if (!session) return [];\n return session.events.filter((event) => (event.seq ?? 0) > sinceSeq).slice(-limit);\n }\n\n getProjectEvents(projectHash: string, sinceSeq = 0, limit = 500): EventV1[] {\n return [...this.sessions.values()]\n .filter((session) => session.project_hash === projectHash)\n .flatMap((session) => session.events)\n .filter((event) => (event.seq ?? 0) > sinceSeq)\n .sort((left, right) => (left.seq ?? 0) - (right.seq ?? 0))\n .slice(-limit);\n }\n\n getAllEvents(sinceSeq = 0, limit = 1_000): EventV1[] {\n return [...this.sessions.values()]\n .flatMap((session) => session.events)\n .filter((event) => (event.seq ?? 0) > sinceSeq)\n .sort((left, right) => (left.seq ?? 0) - (right.seq ?? 0))\n .slice(-limit);\n }\n\n getLatestSeq(projectHash?: string): number {\n const sessions = [...this.sessions.values()].filter(\n (session) => !projectHash || session.project_hash === projectHash,\n );\n return sessions.reduce((maxSeq, session) => Math.max(maxSeq, session.last_seq ?? 0), 0);\n }\n\n getSessionLatestSeq(sessionKey: string): number {\n return this.sessions.get(sessionKey)?.last_seq ?? 0;\n }\n\n getSessionSummary(sessionKey: string): SessionSummary | null {\n const session = this.sessions.get(sessionKey);\n if (!session) return null;\n return {\n key: session.key,\n project_hash: session.project_hash,\n engine: session.engine,\n session_id: session.session_id,\n cwd: session.cwd,\n last_event_at: session.last_event_at,\n last_seq: session.last_seq,\n event_count: session.event_count,\n caps: session.caps,\n };\n }\n\n async purgeSession(sessionKey: string): Promise<boolean> {\n const session = this.sessions.get(sessionKey);\n if (!session) return false;\n this.sessions.delete(sessionKey);\n await rm(session.filePath, { force: true });\n\n const project = this.projects.get(session.project_hash);\n if (!project) {\n return true;\n }\n\n const remainingSessions = [...this.sessions.values()].filter(\n (candidate) => candidate.project_hash === session.project_hash,\n );\n if (remainingSessions.length === 0) {\n this.projects.delete(session.project_hash);\n return true;\n }\n\n project.session_count = remainingSessions.length;\n project.last_active = remainingSessions.reduce(\n (latest, candidate) => Math.max(latest, candidate.last_event_at),\n 0,\n );\n\n const projectDir = join(this.homeDir, \"sessions\", session.project_hash);\n await writeFile(join(projectDir, \"meta.json\"), JSON.stringify(project, null, 2) + \"\\n\", {\n encoding: \"utf8\",\n mode: 0o600,\n });\n return true;\n }\n\n private async persistEvent(event: EventV1): Promise<EventV1> {\n const storedEvent: EventV1 = {\n ...event,\n seq: event.seq ?? this.nextSeq++,\n };\n\n this.upsertProject(storedEvent);\n const session = this.upsertSession(storedEvent);\n const projectDir = join(this.homeDir, \"sessions\", storedEvent.project_hash);\n await mkdir(projectDir, { recursive: true, mode: 0o700 });\n await appendFile(session.filePath, JSON.stringify(storedEvent) + \"\\n\", {\n encoding: \"utf8\",\n mode: 0o600,\n });\n await writeFile(\n join(projectDir, \"meta.json\"),\n JSON.stringify(this.projects.get(storedEvent.project_hash), null, 2) + \"\\n\",\n { encoding: \"utf8\", mode: 0o600 },\n );\n\n return storedEvent;\n }\n\n private upsertProject(event: EventV1): void {\n const identity = this.getProjectIdentity(event.cwd);\n const existing = this.projects.get(event.project_hash);\n const sessionCount = existing?.session_count ?? 0;\n this.projects.set(event.project_hash, {\n project_hash: event.project_hash,\n name: existing?.name ?? identity.name,\n root: existing?.root ?? identity.root,\n last_active: Math.max(existing?.last_active ?? 0, event.ts),\n session_count: sessionCount,\n });\n }\n\n private upsertSession(event: EventV1): StoredSession {\n const key = buildSessionKey(event);\n const existing = this.sessions.get(key);\n const filePath =\n existing?.filePath ??\n join(\n this.homeDir,\n \"sessions\",\n event.project_hash,\n sessionFileName(event.engine, event.session_id),\n );\n const events = [...(existing?.events ?? []), event];\n const session: StoredSession = {\n key,\n project_hash: event.project_hash,\n engine: event.engine,\n session_id: event.session_id,\n cwd: event.cwd,\n last_event_at: event.ts,\n last_seq: event.seq,\n event_count: events.length,\n caps: event.caps ?? existing?.caps,\n events,\n filePath,\n };\n this.sessions.set(key, session);\n\n const project = this.projects.get(event.project_hash);\n if (project) {\n project.session_count = [...this.sessions.values()].filter(\n (candidate) => candidate.project_hash === event.project_hash,\n ).length;\n project.last_active = Math.max(project.last_active, event.ts);\n }\n\n return session;\n }\n\n private getProjectIdentity(cwd: string): ReturnType<typeof identifyProject> {\n const cached = this.projectIdentityCache.get(cwd);\n if (cached) {\n return cached;\n }\n const identity = identifyProject(cwd);\n this.projectIdentityCache.set(cwd, identity);\n return identity;\n }\n\n private async hydrate(): Promise<void> {\n const sessionsRoot = join(this.homeDir, \"sessions\");\n if (!existsSync(sessionsRoot)) return;\n\n const projectEntries = await readdir(sessionsRoot, { withFileTypes: true });\n for (const projectDirEntry of projectEntries) {\n if (!projectDirEntry.isDirectory()) continue;\n const projectHash = projectDirEntry.name;\n const projectDir = join(sessionsRoot, projectHash);\n const files = await readdir(projectDir);\n let loadedProject: StoredProject | undefined;\n const metaPath = join(projectDir, \"meta.json\");\n if (existsSync(metaPath)) {\n try {\n loadedProject = JSON.parse(await readFile(metaPath, \"utf8\")) as StoredProject;\n } catch {\n loadedProject = undefined;\n }\n }\n\n for (const file of files.filter((entry) => entry.endsWith(\".jsonl\"))) {\n const filePath = join(projectDir, file);\n const rawEvents = await readJsonl(filePath);\n if (rawEvents.length === 0) continue;\n\n const events = rawEvents\n .sort((left, right) => {\n const leftSeq = left.seq ?? 0;\n const rightSeq = right.seq ?? 0;\n if (leftSeq !== rightSeq) return leftSeq - rightSeq;\n return left.ts - right.ts;\n })\n .map((event) => {\n const seq = event.seq ?? this.nextSeq++;\n this.nextSeq = Math.max(this.nextSeq, seq + 1);\n return {\n ...event,\n seq,\n };\n });\n\n const first = events[0];\n const last = events[events.length - 1];\n if (!first || !last) continue;\n const key = buildSessionKey(first);\n this.sessions.set(key, {\n key,\n project_hash: first.project_hash,\n engine: first.engine,\n session_id: first.session_id,\n cwd: first.cwd,\n last_event_at: last.ts,\n last_seq: last.seq,\n event_count: events.length,\n caps: last.caps,\n events,\n filePath,\n });\n\n if (!loadedProject) {\n const identity = this.getProjectIdentity(first.cwd);\n loadedProject = {\n project_hash: first.project_hash,\n name: identity.name,\n root: identity.root,\n last_active: last.ts,\n session_count: 0,\n };\n } else {\n loadedProject.last_active = Math.max(loadedProject.last_active, last.ts);\n }\n }\n\n if (loadedProject) {\n loadedProject.session_count = [...this.sessions.values()].filter(\n (session) => session.project_hash === projectHash,\n ).length;\n this.projects.set(projectHash, loadedProject);\n }\n }\n }\n}\n","import { randomUUID } from \"node:crypto\";\nimport { existsSync, realpathSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { EventV1 } from \"@holdpoint/live-protocol\";\n\nconst DEFAULT_LOCK_TTL_MS = 30_000;\n\ninterface FileLock {\n sessionKey: string;\n engine: string;\n sessionId: string;\n expiresAt: number;\n}\n\ntype LockEvent = Extract<EventV1, { type: \"tool_pre\" | \"tool_post\" | \"tool_failure\" }>;\n\nfunction buildSessionKey(event: Pick<EventV1, \"project_hash\" | \"engine\" | \"session_id\">): string {\n return `${event.project_hash}:${event.engine}:${event.session_id}`;\n}\n\nfunction normalizeWriteTarget(cwd: string, target: string): string {\n const resolved = resolve(cwd, target);\n return existsSync(resolved) ? realpathSync.native(resolved) : resolved;\n}\n\nfunction getWriteTargets(event: LockEvent, activeTargets: Map<string, string[]>): string[] {\n const toolKey = `${buildSessionKey(event)}:${event.payload.tool_use_id}`;\n if (event.type === \"tool_pre\") {\n return (event.payload.write_targets ?? []).map((target: string) =>\n normalizeWriteTarget(event.cwd, target),\n );\n }\n\n return (\n (event.type === \"tool_post\"\n ? event.payload.write_targets?.map((target: string) =>\n normalizeWriteTarget(event.cwd, target),\n )\n : undefined) ??\n activeTargets.get(toolKey) ??\n []\n );\n}\n\nexport class ConflictTracker {\n private readonly lockTtlMs: number;\n private readonly locksByProject = new Map<string, Map<string, FileLock>>();\n private readonly activeTargets = new Map<string, string[]>();\n private readonly emittedConflicts = new Map<string, number>();\n\n constructor(lockTtlMs = DEFAULT_LOCK_TTL_MS) {\n this.lockTtlMs = lockTtlMs;\n }\n\n handleEvent(event: EventV1): EventV1[] {\n switch (event.type) {\n case \"tool_pre\":\n return this.handleToolPre(event);\n case \"tool_post\":\n case \"tool_failure\":\n this.releaseLocks(event);\n return [];\n default:\n return [];\n }\n }\n\n private handleToolPre(event: Extract<EventV1, { type: \"tool_pre\" }>): EventV1[] {\n const sessionKey = buildSessionKey(event);\n const toolKey = `${sessionKey}:${event.payload.tool_use_id}`;\n const writeTargets = getWriteTargets(event, this.activeTargets);\n if (writeTargets.length === 0) {\n return [];\n }\n\n this.activeTargets.set(toolKey, writeTargets);\n const projectLocks = this.getProjectLocks(event.project_hash);\n this.pruneExpiredLocks(projectLocks, event.ts);\n\n const conflicts: EventV1[] = [];\n for (const filePath of writeTargets) {\n const existing = projectLocks.get(filePath);\n if (!existing) {\n projectLocks.set(filePath, {\n sessionKey,\n engine: event.engine,\n sessionId: event.session_id,\n expiresAt: event.ts + this.lockTtlMs,\n });\n continue;\n }\n\n if (existing.sessionKey === sessionKey) {\n existing.expiresAt = event.ts + this.lockTtlMs;\n continue;\n }\n\n const dedupeKey = `${event.project_hash}:${filePath}:${existing.sessionKey}:${sessionKey}`;\n const previousEmission = this.emittedConflicts.get(dedupeKey) ?? 0;\n if (previousEmission > event.ts) {\n continue;\n }\n\n this.emittedConflicts.set(dedupeKey, event.ts + this.lockTtlMs);\n conflicts.push({\n v: 1,\n id: randomUUID(),\n ts: event.ts,\n engine: event.engine,\n session_id: event.session_id,\n project_hash: event.project_hash,\n cwd: event.cwd,\n type: \"conflict\",\n payload: {\n kind: \"file_write\",\n file_path: filePath,\n holder: {\n engine: existing.engine,\n session_id: existing.sessionId,\n },\n requester: {\n engine: event.engine,\n session_id: event.session_id,\n },\n },\n });\n }\n\n return conflicts;\n }\n\n private releaseLocks(event: Extract<EventV1, { type: \"tool_post\" | \"tool_failure\" }>): void {\n const sessionKey = buildSessionKey(event);\n const toolKey = `${sessionKey}:${event.payload.tool_use_id}`;\n const projectLocks = this.getProjectLocks(event.project_hash);\n const writeTargets = getWriteTargets(event, this.activeTargets);\n\n for (const filePath of writeTargets) {\n const existing = projectLocks.get(filePath);\n if (existing?.sessionKey === sessionKey) {\n projectLocks.delete(filePath);\n }\n }\n\n this.activeTargets.delete(toolKey);\n this.pruneExpiredLocks(projectLocks, event.ts);\n }\n\n private getProjectLocks(projectHash: string): Map<string, FileLock> {\n let existing = this.locksByProject.get(projectHash);\n if (!existing) {\n existing = new Map<string, FileLock>();\n this.locksByProject.set(projectHash, existing);\n }\n return existing;\n }\n\n private pruneExpiredLocks(projectLocks: Map<string, FileLock>, now: number): void {\n for (const [filePath, lock] of projectLocks.entries()) {\n if (lock.expiresAt <= now) {\n projectLocks.delete(filePath);\n }\n }\n\n for (const [key, expiresAt] of this.emittedConflicts.entries()) {\n if (expiresAt <= now) {\n this.emittedConflicts.delete(key);\n }\n }\n }\n}\n","import { execFileSync } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { realpathSync } from \"node:fs\";\nimport { basename } from \"node:path\";\n\nexport interface ProjectIdentity {\n hash: string;\n name: string;\n root: string;\n}\n\nfunction sha12(value: string): string {\n return createHash(\"sha256\").update(value).digest(\"hex\").slice(0, 12);\n}\n\nexport function identifyProject(cwd: string): ProjectIdentity {\n try {\n const root = realpathSync(\n execFileSync(\"git\", [\"rev-parse\", \"--show-toplevel\"], {\n cwd,\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }).trim(),\n );\n return {\n hash: sha12(root),\n name: basename(root),\n root,\n };\n } catch {\n const root = realpathSync(cwd);\n return {\n hash: sha12(root),\n name: basename(root),\n root,\n };\n }\n}\n","import type { EventV1 } from \"@holdpoint/live-protocol\";\nimport { buildSessionKey } from \"./store.js\";\n\nexport interface Subscription {\n scope: \"project\" | \"session\" | \"all\";\n key?: string;\n}\n\nexport function matchesSubscription(subscription: Subscription, event: EventV1): boolean {\n switch (subscription.scope) {\n case \"all\":\n return true;\n case \"project\":\n return subscription.key === event.project_hash;\n case \"session\":\n return subscription.key === buildSessionKey(event);\n }\n}\n","import {\n removeDaemonLock,\n createDaemonLock,\n findFreePort,\n readHealthyDaemonLock,\n type DaemonLock,\n writeDaemonLockExclusive,\n resolveHoldpointHome,\n} from \"./singleton.js\";\nimport { startLiveServer, type RunningLiveServer } from \"./server.js\";\nimport { LiveStore } from \"./store.js\";\n\nexport class DaemonAlreadyRunningError extends Error {\n readonly info: DaemonLock;\n\n constructor(info: DaemonLock) {\n super(`Holdpoint daemon already running on port ${info.port}`);\n this.info = info;\n }\n}\n\nexport interface StartDaemonProcessOptions {\n homeDir?: string;\n port?: number;\n version: string;\n}\n\nexport interface StartedDaemon {\n info: DaemonLock;\n server: RunningLiveServer;\n store: LiveStore;\n close(): Promise<void>;\n closed: Promise<void>;\n}\n\nexport async function startDaemonProcess(\n options: StartDaemonProcessOptions,\n): Promise<StartedDaemon> {\n const existing = await readHealthyDaemonLock(options.homeDir);\n if (existing) {\n throw new DaemonAlreadyRunningError(existing);\n }\n\n const port = options.port ?? (await findFreePort());\n const info = createDaemonLock(port, options.version);\n writeDaemonLockExclusive(info, options.homeDir);\n\n const store = await LiveStore.create(resolveHoldpointHome(options.homeDir));\n await store.replayPending();\n\n let server: RunningLiveServer;\n try {\n server = await startLiveServer({\n port,\n token: info.token,\n version: options.version,\n startedAt: info.started_at,\n store,\n });\n } catch (error) {\n removeDaemonLock(options.homeDir, info.token);\n throw error;\n }\n\n let closed = false;\n const cleanup = async (): Promise<void> => {\n if (closed) return;\n closed = true;\n removeDaemonLock(options.homeDir, info.token);\n await server.close();\n };\n\n const onSignal = (): void => {\n void cleanup().finally(() => process.exit(0));\n };\n\n process.once(\"SIGTERM\", onSignal);\n process.once(\"SIGINT\", onSignal);\n\n return {\n info,\n server,\n store,\n close: cleanup,\n closed: server.closed.finally(() => {\n process.off(\"SIGTERM\", onSignal);\n process.off(\"SIGINT\", onSignal);\n }),\n };\n}\n\nexport {\n createDaemonLock,\n ensureHoldpointHome,\n findFreePort,\n getDaemonLockPath,\n isProcessAlive,\n readDaemonLock,\n readHealthyDaemonLock,\n removeDaemonLock,\n resolveHoldpointHome,\n waitForDaemonHealthy,\n writeDaemonLockExclusive,\n} from \"./singleton.js\";\nexport { identifyProject } from \"./project-identity.js\";\nexport { startLiveServer } from \"./server.js\";\nexport { buildSessionKey, LiveStore } from \"./store.js\";\nexport type { ProjectIdentity } from \"./project-identity.js\";\nexport type { RunningLiveServer } from \"./server.js\";\nexport type { DaemonLock } from \"./singleton.js\";\n"],"mappings":"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","names":["createServer","randomUUID","existsSync","join","resolve","EventV1Schema","existsSync","join","existsSync","resolve","realpathSync","buildSessionKey","join","existsSync","buildSessionKey","join","randomUUID","resolve","existsSync","createServer","EventV1Schema"]}
|
|
1
|
+
{"version":3,"sources":["../src/singleton.ts","../src/server.ts","../src/auth.ts","../src/store.ts","../src/conflict-tracker.ts","../src/project-identity.ts","../src/router.ts","../src/index.ts"],"sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport { createServer } from \"node:net\";\nimport os from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport { z } from \"zod\";\n\nexport const DaemonLockSchema = z.object({\n version: z.string().min(1),\n pid: z.number().int().positive(),\n port: z.number().int().positive(),\n token: z.string().min(1),\n started_at: z.number().int().nonnegative(),\n host: z.string().min(1),\n});\n\nexport type DaemonLock = z.infer<typeof DaemonLockSchema>;\n\nexport function resolveHoldpointHome(homeDir?: string): string {\n return resolve(homeDir ?? process.env.HOLDPOINT_HOME ?? join(os.homedir(), \".holdpoint\"));\n}\n\nexport function ensureHoldpointHome(homeDir?: string): string {\n const root = resolveHoldpointHome(homeDir);\n mkdirSync(root, { recursive: true, mode: 0o700 });\n return root;\n}\n\nexport function getDaemonLockPath(homeDir?: string): string {\n return join(resolveHoldpointHome(homeDir), \"daemon.lock\");\n}\n\nexport function readDaemonLock(homeDir?: string): DaemonLock | null {\n const lockPath = getDaemonLockPath(homeDir);\n if (!existsSync(lockPath)) return null;\n try {\n return DaemonLockSchema.parse(JSON.parse(readFileSync(lockPath, \"utf8\")));\n } catch {\n return null;\n }\n}\n\nexport function isProcessAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function findFreePort(host = \"127.0.0.1\"): Promise<number> {\n return await new Promise<number>((resolvePromise, reject) => {\n const server = createServer();\n server.listen(0, host, () => {\n const address = server.address();\n if (!address || typeof address === \"string\") {\n server.close();\n reject(new Error(\"Expected TCP address\"));\n return;\n }\n const { port } = address;\n server.close((err) => {\n if (err) reject(err);\n else resolvePromise(port);\n });\n });\n server.on(\"error\", reject);\n });\n}\n\nexport function createDaemonLock(port: number, version: string): DaemonLock {\n return {\n version,\n pid: process.pid,\n port,\n token: randomBytes(32).toString(\"hex\"),\n started_at: Date.now(),\n host: `${os.platform()}-${os.arch()}`,\n };\n}\n\nexport function writeDaemonLockExclusive(lock: DaemonLock, homeDir?: string): void {\n ensureHoldpointHome(homeDir);\n writeFileSync(getDaemonLockPath(homeDir), JSON.stringify(lock, null, 2) + \"\\n\", {\n encoding: \"utf8\",\n flag: \"wx\",\n mode: 0o600,\n });\n}\n\nexport function removeDaemonLock(homeDir?: string, expectedToken?: string): void {\n const lockPath = getDaemonLockPath(homeDir);\n if (!existsSync(lockPath)) return;\n if (expectedToken) {\n const lock = readDaemonLock(homeDir);\n if (!lock || lock.token !== expectedToken) {\n return;\n }\n }\n try {\n unlinkSync(lockPath);\n } catch {\n /* ignore cleanup races */\n }\n}\n\nasync function fetchHealth(port: number, timeoutMs: number): Promise<boolean> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const response = await fetch(`http://127.0.0.1:${port}/health`, {\n signal: controller.signal,\n });\n return response.ok;\n } catch {\n return false;\n } finally {\n clearTimeout(timeout);\n }\n}\n\nexport async function waitForDaemonHealthy(\n lock: DaemonLock,\n timeoutMs = 5_000,\n pollMs = 100,\n): Promise<boolean> {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n if (await fetchHealth(lock.port, Math.min(pollMs, timeoutMs))) {\n return true;\n }\n await new Promise((resolvePromise) => setTimeout(resolvePromise, pollMs));\n }\n return false;\n}\n\nexport async function readHealthyDaemonLock(homeDir?: string): Promise<DaemonLock | null> {\n const lock = readDaemonLock(homeDir);\n if (!lock) return null;\n if (!isProcessAlive(lock.pid)) {\n removeDaemonLock(homeDir);\n return null;\n }\n if (!(await waitForDaemonHealthy(lock, 300, 100))) {\n removeDaemonLock(homeDir);\n return null;\n }\n return lock;\n}\n","import { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport { randomUUID } from \"node:crypto\";\nimport { createReadStream, existsSync, renameSync, writeFileSync } from \"node:fs\";\nimport { dirname, extname, join, resolve, sep } from \"node:path\";\nimport { fileURLToPath, URL } from \"node:url\";\nimport type { EventV1, ServerMessage } from \"@holdpoint/live-protocol\";\nimport {\n ClientMessageSchema,\n ControlRequestSchema,\n EventV1Schema,\n EventsBatchSchema,\n} from \"@holdpoint/live-protocol\";\nimport { parseHoldpointYaml } from \"@holdpoint/yaml-core\";\nimport { WebSocket, WebSocketServer, type RawData } from \"ws\";\nimport {\n authorizeRequest,\n authorizeWebSocket,\n readJsonBody,\n readTextBody,\n writeJson,\n writeUiAuthCookie,\n} from \"./auth.js\";\nimport { matchesSubscription, type Subscription } from \"./router.js\";\nimport type { LiveStore } from \"./store.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nconst LIVE_UI_DIR = join(__dirname, \"live-ui\");\nconst CONTENT_SECURITY_POLICY =\n \"default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; connect-src 'self' ws: http:; object-src 'none'; base-uri 'none'; frame-ancestors 'none'\";\nconst MIME: Record<string, string> = {\n \".css\": \"text/css; charset=utf-8\",\n \".html\": \"text/html; charset=utf-8\",\n \".ico\": \"image/x-icon\",\n \".js\": \"text/javascript; charset=utf-8\",\n \".json\": \"application/json; charset=utf-8\",\n \".mjs\": \"text/javascript; charset=utf-8\",\n \".png\": \"image/png\",\n \".svg\": \"image/svg+xml\",\n};\n\nexport interface StartLiveServerOptions {\n host?: string;\n port: number;\n token: string;\n version: string;\n startedAt: number;\n store: LiveStore;\n}\n\nexport interface RunningLiveServer {\n host: string;\n port: number;\n close(): Promise<void>;\n closed: Promise<void>;\n}\n\ninterface RegisteredProject {\n hash: string;\n name?: string;\n root: string;\n}\n\nfunction sendSocketMessage(socket: WebSocket, message: ServerMessage): void {\n socket.send(JSON.stringify(message));\n}\n\nfunction decodeRawData(raw: RawData): string {\n if (typeof raw === \"string\") return raw;\n if (raw instanceof Buffer) return raw.toString(\"utf8\");\n if (Array.isArray(raw)) return Buffer.concat(raw).toString(\"utf8\");\n return Buffer.from(new Uint8Array(raw)).toString(\"utf8\");\n}\n\nfunction getEventsForScope(\n store: LiveStore,\n subscription: Subscription,\n sinceSeq: number,\n): EventV1[] {\n switch (subscription.scope) {\n case \"all\":\n return store.getAllEvents(sinceSeq);\n case \"project\":\n return subscription.key ? store.getProjectEvents(subscription.key, sinceSeq) : [];\n case \"session\":\n return subscription.key ? store.getSessionEvents(subscription.key, sinceSeq) : [];\n }\n}\n\nfunction buildControlStateEvent(\n session: {\n project_hash: string;\n engine: string;\n session_id: string;\n cwd: string;\n caps?: EventV1[\"caps\"];\n },\n controlOnline: boolean,\n): EventV1 {\n return {\n v: 1,\n id: randomUUID(),\n ts: Date.now(),\n engine: session.engine,\n session_id: session.session_id,\n project_hash: session.project_hash,\n cwd: session.cwd,\n caps: {\n ...(session.caps ?? {}),\n can_control: session.caps?.can_control ?? true,\n control_online: controlOnline,\n },\n type: \"meta\",\n payload: {\n kind: controlOnline ? \"control_socket_registered\" : \"control_socket_disconnected\",\n },\n };\n}\n\nfunction servePlaceholder(res: ServerResponse, appName = \"Holdpoint Live\"): void {\n res.writeHead(200, {\n \"cache-control\": \"no-store\",\n \"content-security-policy\": CONTENT_SECURITY_POLICY,\n \"content-type\": \"text/html; charset=utf-8\",\n });\n res.end(\n `<!doctype html><title>${appName}</title><body style=\"font-family:system-ui;background:#0b0f14;color:#f5f1e8;padding:32px\"><h1>${appName}</h1><p>UI assets were not found in this build. Rebuild the monorepo with <code>pnpm turbo build</code>.</p></body>`,\n );\n}\n\nfunction serveUiAsset(res: ServerResponse, filePath: string): void {\n const mime = MIME[extname(filePath)] ?? \"application/octet-stream\";\n const headers: Record<string, string> = {\n \"cache-control\": \"no-store\",\n \"content-type\": mime,\n };\n if (filePath.endsWith(\".html\")) {\n headers[\"content-security-policy\"] = CONTENT_SECURITY_POLICY;\n }\n res.writeHead(200, headers);\n createReadStream(filePath).pipe(res);\n}\n\nfunction isWithinRoot(candidate: string, root: string): boolean {\n return candidate === root || candidate.startsWith(root + sep);\n}\n\nfunction resolveUiFilePath(uiDir: string, requestedPath: string): string | null {\n const requested = requestedPath === \"\" || requestedPath === \"/\" ? \"index.html\" : requestedPath;\n const candidate = resolve(uiDir, requested.replace(/^\\//, \"\"));\n if (!isWithinRoot(candidate, uiDir)) {\n return null;\n }\n if (existsSync(candidate)) {\n return candidate;\n }\n return existsSync(join(uiDir, \"index.html\")) ? join(uiDir, \"index.html\") : null;\n}\n\n/**\n * The Builder is now a tab inside the unified Live UI, so any `/builder` intent\n * folds into `/live/` with a `tab=checks` hint instead of a separate app.\n */\nfunction normalizeUiPath(path: string | null): { pathname: \"/live/\"; tab?: \"checks\" } {\n if (path === \"/builder\" || path?.startsWith(\"/builder/\")) {\n return { pathname: \"/live/\", tab: \"checks\" };\n }\n return { pathname: \"/live/\" };\n}\n\nfunction registerProjectFromAuthUrl(\n url: URL,\n registeredProjects: Map<string, RegisteredProject>,\n): void {\n const hash = url.searchParams.get(\"project\");\n const root = url.searchParams.get(\"root\");\n if (!hash || !root || root.includes(\"\\0\")) {\n return;\n }\n const name = url.searchParams.get(\"name\");\n registeredProjects.set(hash, {\n hash,\n ...(name ? { name } : {}),\n root: resolve(root),\n });\n}\n\nfunction getProjectForRequest(\n url: URL,\n registeredProjects: Map<string, RegisteredProject>,\n): RegisteredProject | null {\n const hash = url.searchParams.get(\"project\");\n if (hash) {\n return registeredProjects.get(hash) ?? null;\n }\n if (registeredProjects.size === 1) {\n return [...registeredProjects.values()][0] ?? null;\n }\n return null;\n}\n\nexport async function startLiveServer(options: StartLiveServerOptions): Promise<RunningLiveServer> {\n const host = options.host ?? \"127.0.0.1\";\n const subscriptions = new Map<WebSocket, Subscription[]>();\n const controlSockets = new Map<string, WebSocket>();\n const socketControlKeys = new Map<WebSocket, Set<string>>();\n const registeredProjects = new Map<string, RegisteredProject>();\n const server = createServer((req, res) => {\n void handleRequest(req, res, options, subscriptions, registeredProjects).catch(\n (error: unknown) => {\n writeJson(res, 500, { ok: false, error: (error as Error).message });\n },\n );\n });\n const wss = new WebSocketServer({ noServer: true });\n\n const broadcastEvent = (event: EventV1): void => {\n for (const [socket, socketSubscriptions] of subscriptions.entries()) {\n if (socket.readyState !== WebSocket.OPEN) continue;\n if (socketSubscriptions.some((subscription) => matchesSubscription(subscription, event))) {\n sendSocketMessage(socket, { type: \"event\", event });\n }\n }\n };\n\n const ingestAndBroadcast = async (event: EventV1): Promise<EventV1[]> => {\n const accepted = await options.store.ingest(event);\n for (const acceptedEvent of accepted) {\n broadcastEvent(acceptedEvent);\n }\n return accepted;\n };\n\n const emitControlState = async (sessionKey: string, controlOnline: boolean): Promise<void> => {\n const summary = options.store.getSessionSummary(sessionKey);\n if (!summary) return;\n await ingestAndBroadcast(buildControlStateEvent(summary, controlOnline));\n };\n\n const registerControlSocket = async (sessionKey: string, socket: WebSocket): Promise<void> => {\n const previous = controlSockets.get(sessionKey);\n if (previous && previous !== socket) {\n socketControlKeys.get(previous)?.delete(sessionKey);\n }\n controlSockets.set(sessionKey, socket);\n const keys = socketControlKeys.get(socket) ?? new Set<string>();\n keys.add(sessionKey);\n socketControlKeys.set(socket, keys);\n await emitControlState(sessionKey, true);\n };\n\n const unregisterControlSocket = async (sessionKey: string, socket: WebSocket): Promise<void> => {\n if (controlSockets.get(sessionKey) !== socket) return;\n controlSockets.delete(sessionKey);\n const keys = socketControlKeys.get(socket);\n keys?.delete(sessionKey);\n if (keys && keys.size === 0) {\n socketControlKeys.delete(socket);\n }\n await emitControlState(sessionKey, false);\n };\n\n const unregisterSocketControls = async (socket: WebSocket): Promise<void> => {\n const keys = [...(socketControlKeys.get(socket) ?? [])];\n for (const sessionKey of keys) {\n await unregisterControlSocket(sessionKey, socket);\n }\n };\n\n wss.on(\"connection\", (socket: WebSocket) => {\n subscriptions.set(socket, []);\n socket.on(\"message\", (raw: RawData) => {\n void (async () => {\n let message: unknown;\n try {\n message = JSON.parse(decodeRawData(raw));\n } catch {\n sendSocketMessage(socket, {\n type: \"error\",\n code: \"invalid_json\",\n message: \"Expected JSON message\",\n });\n return;\n }\n\n const parsed = ClientMessageSchema.safeParse(message);\n if (!parsed.success) {\n sendSocketMessage(socket, {\n type: \"error\",\n code: \"invalid_message\",\n message: parsed.error.issues[0]?.message ?? \"Invalid message\",\n });\n return;\n }\n\n switch (parsed.data.type) {\n case \"subscribe\": {\n if (parsed.data.scope !== \"all\" && !parsed.data.key) {\n sendSocketMessage(socket, {\n type: \"error\",\n code: \"missing_key\",\n message: \"Expected a key for session/project subscriptions\",\n });\n return;\n }\n\n const subscription =\n parsed.data.key !== undefined\n ? { scope: parsed.data.scope, key: parsed.data.key }\n : { scope: parsed.data.scope };\n const next = subscriptions.get(socket) ?? [];\n next.push(subscription);\n subscriptions.set(socket, next);\n\n const backlog = getEventsForScope(\n options.store,\n subscription,\n parsed.data.since_seq ?? 0,\n );\n if (backlog.length > 0) {\n sendSocketMessage(socket, { type: \"events_batch\", events: backlog });\n }\n sendSocketMessage(socket, {\n type: \"ack\",\n for: parsed.data.scope === \"all\" ? \"all\" : (parsed.data.key ?? parsed.data.scope),\n });\n break;\n }\n case \"register_control\": {\n await registerControlSocket(parsed.data.session_key, socket);\n sendSocketMessage(socket, { type: \"ack\", for: parsed.data.session_key });\n break;\n }\n case \"unsubscribe\": {\n const key = parsed.data.key;\n const next = (subscriptions.get(socket) ?? []).filter(\n (subscription) => subscription.key !== key,\n );\n subscriptions.set(socket, next);\n sendSocketMessage(socket, { type: \"ack\", for: key });\n break;\n }\n case \"publish_event\": {\n const accepted = await options.store.ingest(parsed.data.event);\n for (const event of accepted) {\n broadcastEvent(event);\n }\n sendSocketMessage(socket, { type: \"ack\", for: parsed.data.event.id });\n break;\n }\n case \"ping\":\n sendSocketMessage(socket, { type: \"pong\" });\n break;\n }\n })();\n });\n\n socket.on(\"close\", () => {\n subscriptions.delete(socket);\n void unregisterSocketControls(socket).catch(() => {});\n });\n });\n\n server.on(\"upgrade\", (req, socket, head) => {\n const url = new URL(req.url ?? \"/\", `http://${host}:${options.port}`);\n if (url.pathname !== \"/v1/stream\" || !authorizeWebSocket(req, options.token, options.port)) {\n socket.write(\"HTTP/1.1 401 Unauthorized\\r\\n\\r\\n\");\n socket.destroy();\n return;\n }\n\n wss.handleUpgrade(req, socket, head, (ws: WebSocket) => {\n wss.emit(\"connection\", ws, req);\n });\n });\n\n await new Promise<void>((resolvePromise, reject) => {\n server.listen(options.port, host, resolvePromise);\n server.on(\"error\", reject);\n });\n\n const address = server.address();\n if (!address || typeof address === \"string\") {\n throw new Error(\"Expected TCP address\");\n }\n const actualPort = address.port;\n\n const closed = new Promise<void>((resolvePromise, reject) => {\n server.on(\"close\", () => resolvePromise());\n server.on(\"error\", reject);\n });\n\n async function close(): Promise<void> {\n for (const socket of subscriptions.keys()) {\n socket.close();\n }\n await new Promise<void>((resolvePromise, reject) => {\n wss.close((err?: Error) => (err ? reject(err) : resolvePromise()));\n });\n await new Promise<void>((resolvePromise, reject) => {\n server.close((err) => (err ? reject(err) : resolvePromise()));\n });\n }\n\n async function handleRequest(\n req: IncomingMessage,\n res: ServerResponse,\n state: StartLiveServerOptions,\n _subscriptions: Map<WebSocket, Subscription[]>,\n registered: Map<string, RegisteredProject>,\n ): Promise<void> {\n const url = new URL(req.url ?? \"/\", `http://${host}:${actualPort}`);\n if (req.method === \"GET\" && url.pathname === \"/health\") {\n writeJson(res, 200, { ok: true, version: state.version, started_at: state.startedAt });\n return;\n }\n\n if (req.method === \"GET\" && url.pathname === \"/__holdpoint/live-auth\") {\n if (url.searchParams.get(\"token\") !== state.token) {\n writeJson(res, 401, { ok: false, error: \"Unauthorized\" });\n return;\n }\n\n registerProjectFromAuthUrl(url, registered);\n\n const redirectTarget = normalizeUiPath(url.searchParams.get(\"path\"));\n const redirectUrl = new URL(`http://${host}:${actualPort}`);\n redirectUrl.pathname = redirectTarget.pathname;\n for (const [key, value] of url.searchParams.entries()) {\n if (key !== \"token\" && key !== \"path\") {\n redirectUrl.searchParams.set(key, value);\n }\n }\n if (redirectTarget.tab) {\n redirectUrl.searchParams.set(\"tab\", redirectTarget.tab);\n }\n writeUiAuthCookie(res, state.token);\n res.writeHead(302, {\n location: redirectUrl.toString(),\n \"cache-control\": \"no-store\",\n });\n res.end();\n return;\n }\n\n if (req.method === \"GET\" && url.pathname === \"/__holdpoint/initial-yaml\") {\n if (!authorizeRequest(req, res, state.token, actualPort)) {\n return;\n }\n const project = getProjectForRequest(url, registered);\n if (!project) {\n writeJson(res, 404, { ok: false, error: \"Project not registered for this UI session\" });\n return;\n }\n const checksPath = resolve(project.root, \"checks.yaml\");\n if (!isWithinRoot(checksPath, project.root) || !existsSync(checksPath)) {\n writeJson(res, 404, { ok: false, error: \"checks.yaml not found for this project\" });\n return;\n }\n res.writeHead(200, {\n \"cache-control\": \"no-store\",\n \"content-type\": \"text/yaml; charset=utf-8\",\n });\n createReadStream(checksPath).pipe(res);\n return;\n }\n\n if (req.method === \"GET\" && url.pathname === \"/__holdpoint/initial-reports\") {\n if (!authorizeRequest(req, res, state.token, actualPort)) {\n return;\n }\n const project = getProjectForRequest(url, registered);\n if (!project) {\n writeJson(res, 404, { ok: false, error: \"Project not registered for this UI session\" });\n return;\n }\n const reportsPath = resolve(project.root, \".holdpoint\", \"check-reports.json\");\n if (!isWithinRoot(reportsPath, project.root) || !existsSync(reportsPath)) {\n writeJson(res, 404, { ok: false, error: \"No check reports found for this project\" });\n return;\n }\n res.writeHead(200, {\n \"cache-control\": \"no-store\",\n \"content-type\": \"application/json; charset=utf-8\",\n });\n createReadStream(reportsPath).pipe(res);\n return;\n }\n\n if (req.method === \"PUT\" && url.pathname === \"/__holdpoint/checks\") {\n if (!authorizeRequest(req, res, state.token, actualPort)) {\n return;\n }\n const project = getProjectForRequest(url, registered);\n if (!project) {\n writeJson(res, 404, { ok: false, error: \"Project not registered for this UI session\" });\n return;\n }\n const checksPath = resolve(project.root, \"checks.yaml\");\n if (!isWithinRoot(checksPath, project.root)) {\n writeJson(res, 400, { ok: false, error: \"Invalid checks path\" });\n return;\n }\n let body: string;\n try {\n body = await readTextBody(req);\n } catch {\n writeJson(res, 413, { ok: false, error: \"checks.yaml is too large\" });\n return;\n }\n try {\n // Validate against the schema so the dashboard can never write a\n // checks.yaml that would break the gate for this repo.\n parseHoldpointYaml(body);\n } catch (parseError) {\n writeJson(res, 422, {\n ok: false,\n error: `Invalid checks.yaml: ${(parseError as Error).message}`,\n });\n return;\n }\n try {\n // Write atomically via a temp file + rename so a crash mid-write can't\n // leave a half-written checks.yaml on disk.\n const tmpPath = `${checksPath}.holdpoint-tmp-${randomUUID().slice(0, 8)}`;\n writeFileSync(tmpPath, body, \"utf8\");\n renameSync(tmpPath, checksPath);\n } catch (writeError) {\n writeJson(res, 500, { ok: false, error: (writeError as Error).message });\n return;\n }\n writeJson(res, 200, { ok: true });\n return;\n }\n\n if (url.pathname.startsWith(\"/v1/\") && !authorizeRequest(req, res, state.token, actualPort)) {\n return;\n }\n\n if (req.method === \"POST\" && url.pathname === \"/v1/events\") {\n const event = EventV1Schema.parse(await readJsonBody(req));\n const accepted = await ingestAndBroadcast(event);\n writeJson(res, 200, { ok: true, accepted: accepted.length });\n return;\n }\n\n if (req.method === \"POST\" && url.pathname === \"/v1/events/batch\") {\n const events = EventsBatchSchema.parse(await readJsonBody(req));\n const accepted: EventV1[] = [];\n for (const event of events) {\n accepted.push(...(await ingestAndBroadcast(event)));\n }\n writeJson(res, 200, { ok: true, accepted: accepted.length });\n return;\n }\n\n if (req.method === \"POST\" && url.pathname === \"/v1/control\") {\n const request = ControlRequestSchema.parse(await readJsonBody(req));\n const session = state.store.getSessionSummary(request.session_key);\n if (!session) {\n writeJson(res, 404, { ok: false, error: \"Session not found\" });\n return;\n }\n\n const controlSocket = controlSockets.get(request.session_key);\n if (!controlSocket || controlSocket.readyState !== WebSocket.OPEN) {\n writeJson(res, 409, { ok: false, error: \"Control socket not connected\" });\n return;\n }\n\n await ingestAndBroadcast({\n v: 1,\n id: randomUUID(),\n ts: Date.now(),\n engine: session.engine,\n session_id: session.session_id,\n project_hash: session.project_hash,\n cwd: session.cwd,\n type: \"control\",\n payload: request.command,\n });\n sendSocketMessage(controlSocket, {\n type: \"control\",\n session_key: request.session_key,\n command: request.command,\n });\n writeJson(res, 200, { ok: true, delivered: true });\n return;\n }\n\n if (req.method === \"GET\" && url.pathname === \"/v1/projects\") {\n writeJson(res, 200, { projects: state.store.listProjects() });\n return;\n }\n\n if (req.method === \"GET\" && url.pathname === \"/v1/sessions\") {\n const projectHash = url.searchParams.get(\"project_hash\") ?? undefined;\n writeJson(res, 200, { sessions: state.store.listSessions(projectHash) });\n return;\n }\n\n if (\n req.method === \"GET\" &&\n url.pathname.startsWith(\"/v1/sessions/\") &&\n url.pathname.endsWith(\"/events\")\n ) {\n const sessionKey = decodeURIComponent(\n url.pathname.replace(\"/v1/sessions/\", \"\").replace(/\\/events$/, \"\"),\n );\n const sinceSeq = Number(\n url.searchParams.get(\"since_seq\") ?? url.searchParams.get(\"since\") ?? \"0\",\n );\n const limit = Number(url.searchParams.get(\"limit\") ?? \"500\");\n writeJson(res, 200, {\n session_key: sessionKey,\n since_seq: Number.isFinite(sinceSeq) ? sinceSeq : 0,\n max_seq: state.store.getSessionLatestSeq(sessionKey),\n events: state.store.getSessionEvents(\n sessionKey,\n Number.isFinite(sinceSeq) ? sinceSeq : 0,\n Number.isFinite(limit) ? limit : 500,\n ),\n });\n return;\n }\n\n if (req.method === \"DELETE\" && url.pathname.startsWith(\"/v1/sessions/\")) {\n const sessionKey = decodeURIComponent(url.pathname.replace(\"/v1/sessions/\", \"\"));\n const removed = await state.store.purgeSession(sessionKey);\n writeJson(\n res,\n removed ? 200 : 404,\n removed ? { ok: true } : { ok: false, error: \"Session not found\" },\n );\n return;\n }\n\n if (req.method === \"GET\") {\n if (url.pathname === \"/\") {\n res.writeHead(302, { location: \"/live/\", \"cache-control\": \"no-store\" });\n res.end();\n return;\n }\n\n // The Builder is now the \"Checks\" tab of the unified UI. Fold every\n // `/builder` request into `/live/?tab=checks`, preserving other params.\n if (url.pathname === \"/builder\" || url.pathname.startsWith(\"/builder/\")) {\n const target = new URL(\"/live/\", `http://${host}:${actualPort}`);\n for (const [key, value] of url.searchParams.entries()) target.searchParams.set(key, value);\n target.searchParams.set(\"tab\", \"checks\");\n res.writeHead(302, {\n location: `${target.pathname}${target.search}`,\n \"cache-control\": \"no-store\",\n });\n res.end();\n return;\n }\n\n if (url.pathname === \"/live\") {\n res.writeHead(302, { location: \"/live/\", \"cache-control\": \"no-store\" });\n res.end();\n return;\n }\n\n if (!url.pathname.startsWith(\"/live/\")) {\n res.writeHead(302, { location: \"/live/\", \"cache-control\": \"no-store\" });\n res.end();\n return;\n }\n\n const filePath = resolveUiFilePath(LIVE_UI_DIR, url.pathname.replace(/^\\/live\\/?/, \"\"));\n if (!filePath) {\n servePlaceholder(res, \"Holdpoint Live\");\n return;\n }\n serveUiAsset(res, filePath);\n return;\n }\n\n writeJson(res, 404, { ok: false, error: \"Not found\" });\n }\n\n return {\n host,\n port: actualPort,\n close,\n closed,\n };\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\n\nexport const LIVE_UI_COOKIE = \"holdpoint_live_token\";\n\nfunction parseCookies(raw: string | undefined): Map<string, string> {\n const cookies = new Map<string, string>();\n if (!raw) {\n return cookies;\n }\n\n for (const part of raw.split(\";\")) {\n const [name, ...valueParts] = part.trim().split(\"=\");\n if (!name) continue;\n cookies.set(name, decodeURIComponent(valueParts.join(\"=\")));\n }\n\n return cookies;\n}\n\nfunction getRequestToken(req: IncomingMessage): string | null {\n const auth = req.headers.authorization;\n if (auth?.startsWith(\"Bearer \")) {\n return auth.slice(\"Bearer \".length);\n }\n\n return parseCookies(req.headers.cookie).get(LIVE_UI_COOKIE) ?? null;\n}\n\nexport function writeJson(\n res: ServerResponse,\n statusCode: number,\n body: unknown,\n headers: Record<string, string> = {},\n): void {\n res.writeHead(statusCode, {\n \"cache-control\": \"no-store\",\n \"content-type\": \"application/json; charset=utf-8\",\n ...headers,\n });\n res.end(JSON.stringify(body));\n}\n\nexport async function readJsonBody(req: IncomingMessage): Promise<unknown> {\n const chunks: Buffer[] = [];\n for await (const chunk of req) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));\n }\n if (chunks.length === 0) return null;\n return JSON.parse(Buffer.concat(chunks).toString(\"utf8\"));\n}\n\n/** Read a raw request body as UTF-8 text, capped to guard against runaways. */\nexport async function readTextBody(req: IncomingMessage, maxBytes = 512_000): Promise<string> {\n const chunks: Buffer[] = [];\n let total = 0;\n for await (const chunk of req) {\n const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk));\n total += buf.length;\n if (total > maxBytes) throw new Error(\"Request body too large\");\n chunks.push(buf);\n }\n return Buffer.concat(chunks).toString(\"utf8\");\n}\n\nexport function authorizeRequest(\n req: IncomingMessage,\n res: ServerResponse,\n token: string,\n port: number,\n): boolean {\n const origin = req.headers.origin;\n if (origin && origin !== `http://127.0.0.1:${port}`) {\n writeJson(res, 403, { ok: false, error: \"Origin not allowed\" });\n return false;\n }\n\n if (getRequestToken(req) !== token) {\n writeJson(res, 401, { ok: false, error: \"Unauthorized\" });\n return false;\n }\n\n return true;\n}\n\nexport function authorizeWebSocket(req: IncomingMessage, token: string, port: number): boolean {\n const origin = req.headers.origin;\n if (origin && origin !== `http://127.0.0.1:${port}`) {\n return false;\n }\n\n if (getRequestToken(req) === token) {\n return true;\n }\n\n const raw = req.headers[\"sec-websocket-protocol\"];\n const protocols = (typeof raw === \"string\" ? [raw] : [])\n .flatMap((entry) => entry.split(\",\"))\n .map((entry) => entry.trim())\n .filter(Boolean);\n\n return protocols.includes(`holdpoint-${token}`);\n}\n\nexport function writeUiAuthCookie(res: ServerResponse, token: string): void {\n res.setHeader(\n \"set-cookie\",\n `${LIVE_UI_COOKIE}=${encodeURIComponent(token)}; Path=/; HttpOnly; SameSite=Strict; Max-Age=3600`,\n );\n}\n","import { appendFile, mkdir, readFile, readdir, rm, writeFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { EventV1, ProjectSummary, SessionSummary } from \"@holdpoint/live-protocol\";\nimport { EventV1Schema } from \"@holdpoint/live-protocol\";\nimport { ConflictTracker } from \"./conflict-tracker.js\";\nimport { identifyProject } from \"./project-identity.js\";\n\ninterface StoredProject extends ProjectSummary {\n root: string;\n}\n\ninterface StoredSession extends SessionSummary {\n events: EventV1[];\n filePath: string;\n}\n\nfunction sessionFileName(engine: string, sessionId: string): string {\n return `${encodeURIComponent(engine)}-${encodeURIComponent(sessionId)}.jsonl`;\n}\n\n/** Best-effort error formatter for the replayPending log lines. */\nfunction describeError(err: unknown): string {\n if (err instanceof Error) return err.message || err.name;\n return String(err);\n}\n\nasync function readJsonl(filePath: string): Promise<EventV1[]> {\n const raw = await readFile(filePath, \"utf8\");\n return raw\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean)\n .flatMap((line) => {\n try {\n return [EventV1Schema.parse(JSON.parse(line))];\n } catch {\n return [];\n }\n });\n}\n\nexport function buildSessionKey(\n event: Pick<EventV1, \"project_hash\" | \"engine\" | \"session_id\">,\n): string {\n return `${event.project_hash}:${event.engine}:${event.session_id}`;\n}\n\nexport class LiveStore {\n private readonly homeDir: string;\n private readonly projects = new Map<string, StoredProject>();\n private readonly sessions = new Map<string, StoredSession>();\n private readonly projectIdentityCache = new Map<string, ReturnType<typeof identifyProject>>();\n private readonly conflictTracker = new ConflictTracker();\n private nextSeq = 1;\n\n private constructor(homeDir: string) {\n this.homeDir = homeDir;\n }\n\n static async create(homeDir: string): Promise<LiveStore> {\n const store = new LiveStore(homeDir);\n await store.hydrate();\n return store;\n }\n\n async replayPending(): Promise<void> {\n const pendingDir = join(this.homeDir, \"spool\", \"pending\");\n if (!existsSync(pendingDir)) return;\n let entries: string[];\n try {\n entries = await readdir(pendingDir);\n } catch (err) {\n // Pending dir disappeared between existsSync and readdir, or\n // permissions changed underneath us. Not worth crashing for.\n console.error(`[holdpoint] failed to read pending dir: ${describeError(err)}`);\n return;\n }\n for (const entry of entries.filter((name) => name.endsWith(\".jsonl\"))) {\n const filePath = join(pendingDir, entry);\n let events: EventV1[] = [];\n try {\n events = await readJsonl(filePath);\n } catch (err) {\n console.error(`[holdpoint] failed to read pending file ${entry}: ${describeError(err)}`);\n }\n // Per-event try/catch — one malformed payload (e.g. a project_hash\n // pointing at a now-deleted cwd) must not poison the whole replay\n // and brick daemon startup forever. Failed events are logged and\n // dropped; the file is removed unconditionally at the end so a bad\n // payload can't loop on every restart.\n for (const event of events) {\n try {\n await this.ingest(event);\n } catch (err) {\n console.error(`[holdpoint] dropped pending event from ${entry}: ${describeError(err)}`);\n }\n }\n try {\n await rm(filePath, { force: true });\n } catch (err) {\n // Failing to delete the file means we'll re-process it next\n // startup; everything we just did was idempotent so that's\n // tolerable. Log so it's visible if it keeps happening.\n console.error(`[holdpoint] failed to remove pending file ${entry}: ${describeError(err)}`);\n }\n }\n }\n\n async ingestMany(events: EventV1[]): Promise<EventV1[]> {\n const accepted: EventV1[] = [];\n for (const event of events) {\n accepted.push(...(await this.ingest(event)));\n }\n return accepted;\n }\n\n async ingest(event: EventV1): Promise<EventV1[]> {\n const accepted: EventV1[] = [];\n const storedPrimary = await this.persistEvent(event);\n accepted.push(storedPrimary);\n\n for (const derivedEvent of this.conflictTracker.handleEvent(storedPrimary)) {\n accepted.push(await this.persistEvent(derivedEvent));\n }\n\n return accepted;\n }\n\n listProjects(): ProjectSummary[] {\n return [...this.projects.values()].sort((a, b) => b.last_active - a.last_active);\n }\n\n listSessions(projectHash?: string): SessionSummary[] {\n return [...this.sessions.values()]\n .filter((session) => !projectHash || session.project_hash === projectHash)\n .sort((a, b) => b.last_event_at - a.last_event_at)\n .map(({ events: _events, filePath: _filePath, ...summary }) => summary);\n }\n\n getSessionEvents(sessionKey: string, sinceSeq = 0, limit = 500): EventV1[] {\n const session = this.sessions.get(sessionKey);\n if (!session) return [];\n return session.events.filter((event) => (event.seq ?? 0) > sinceSeq).slice(-limit);\n }\n\n getProjectEvents(projectHash: string, sinceSeq = 0, limit = 500): EventV1[] {\n return [...this.sessions.values()]\n .filter((session) => session.project_hash === projectHash)\n .flatMap((session) => session.events)\n .filter((event) => (event.seq ?? 0) > sinceSeq)\n .sort((left, right) => (left.seq ?? 0) - (right.seq ?? 0))\n .slice(-limit);\n }\n\n getAllEvents(sinceSeq = 0, limit = 1_000): EventV1[] {\n return [...this.sessions.values()]\n .flatMap((session) => session.events)\n .filter((event) => (event.seq ?? 0) > sinceSeq)\n .sort((left, right) => (left.seq ?? 0) - (right.seq ?? 0))\n .slice(-limit);\n }\n\n getLatestSeq(projectHash?: string): number {\n const sessions = [...this.sessions.values()].filter(\n (session) => !projectHash || session.project_hash === projectHash,\n );\n return sessions.reduce((maxSeq, session) => Math.max(maxSeq, session.last_seq ?? 0), 0);\n }\n\n getSessionLatestSeq(sessionKey: string): number {\n return this.sessions.get(sessionKey)?.last_seq ?? 0;\n }\n\n getSessionSummary(sessionKey: string): SessionSummary | null {\n const session = this.sessions.get(sessionKey);\n if (!session) return null;\n return {\n key: session.key,\n project_hash: session.project_hash,\n engine: session.engine,\n session_id: session.session_id,\n cwd: session.cwd,\n last_event_at: session.last_event_at,\n last_seq: session.last_seq,\n event_count: session.event_count,\n caps: session.caps,\n };\n }\n\n async purgeSession(sessionKey: string): Promise<boolean> {\n const session = this.sessions.get(sessionKey);\n if (!session) return false;\n this.sessions.delete(sessionKey);\n await rm(session.filePath, { force: true });\n\n const project = this.projects.get(session.project_hash);\n if (!project) {\n return true;\n }\n\n const remainingSessions = [...this.sessions.values()].filter(\n (candidate) => candidate.project_hash === session.project_hash,\n );\n if (remainingSessions.length === 0) {\n this.projects.delete(session.project_hash);\n return true;\n }\n\n project.session_count = remainingSessions.length;\n project.last_active = remainingSessions.reduce(\n (latest, candidate) => Math.max(latest, candidate.last_event_at),\n 0,\n );\n\n const projectDir = join(this.homeDir, \"sessions\", session.project_hash);\n await writeFile(join(projectDir, \"meta.json\"), JSON.stringify(project, null, 2) + \"\\n\", {\n encoding: \"utf8\",\n mode: 0o600,\n });\n return true;\n }\n\n private async persistEvent(event: EventV1): Promise<EventV1> {\n const storedEvent: EventV1 = {\n ...event,\n seq: event.seq ?? this.nextSeq++,\n };\n\n this.upsertProject(storedEvent);\n const session = this.upsertSession(storedEvent);\n const projectDir = join(this.homeDir, \"sessions\", storedEvent.project_hash);\n await mkdir(projectDir, { recursive: true, mode: 0o700 });\n await appendFile(session.filePath, JSON.stringify(storedEvent) + \"\\n\", {\n encoding: \"utf8\",\n mode: 0o600,\n });\n await writeFile(\n join(projectDir, \"meta.json\"),\n JSON.stringify(this.projects.get(storedEvent.project_hash), null, 2) + \"\\n\",\n { encoding: \"utf8\", mode: 0o600 },\n );\n\n return storedEvent;\n }\n\n private upsertProject(event: EventV1): void {\n const identity = this.getProjectIdentity(event.cwd);\n const existing = this.projects.get(event.project_hash);\n const sessionCount = existing?.session_count ?? 0;\n this.projects.set(event.project_hash, {\n project_hash: event.project_hash,\n name: existing?.name ?? identity.name,\n root: existing?.root ?? identity.root,\n last_active: Math.max(existing?.last_active ?? 0, event.ts),\n session_count: sessionCount,\n });\n }\n\n private upsertSession(event: EventV1): StoredSession {\n const key = buildSessionKey(event);\n const existing = this.sessions.get(key);\n const filePath =\n existing?.filePath ??\n join(\n this.homeDir,\n \"sessions\",\n event.project_hash,\n sessionFileName(event.engine, event.session_id),\n );\n const events = [...(existing?.events ?? []), event];\n const session: StoredSession = {\n key,\n project_hash: event.project_hash,\n engine: event.engine,\n session_id: event.session_id,\n cwd: event.cwd,\n last_event_at: event.ts,\n last_seq: event.seq,\n event_count: events.length,\n caps: event.caps ?? existing?.caps,\n events,\n filePath,\n };\n this.sessions.set(key, session);\n\n const project = this.projects.get(event.project_hash);\n if (project) {\n project.session_count = [...this.sessions.values()].filter(\n (candidate) => candidate.project_hash === event.project_hash,\n ).length;\n project.last_active = Math.max(project.last_active, event.ts);\n }\n\n return session;\n }\n\n private getProjectIdentity(cwd: string): ReturnType<typeof identifyProject> {\n const cached = this.projectIdentityCache.get(cwd);\n if (cached) {\n return cached;\n }\n const identity = identifyProject(cwd);\n this.projectIdentityCache.set(cwd, identity);\n return identity;\n }\n\n private async hydrate(): Promise<void> {\n const sessionsRoot = join(this.homeDir, \"sessions\");\n if (!existsSync(sessionsRoot)) return;\n\n const projectEntries = await readdir(sessionsRoot, { withFileTypes: true });\n for (const projectDirEntry of projectEntries) {\n if (!projectDirEntry.isDirectory()) continue;\n const projectHash = projectDirEntry.name;\n const projectDir = join(sessionsRoot, projectHash);\n const files = await readdir(projectDir);\n let loadedProject: StoredProject | undefined;\n const metaPath = join(projectDir, \"meta.json\");\n if (existsSync(metaPath)) {\n try {\n loadedProject = JSON.parse(await readFile(metaPath, \"utf8\")) as StoredProject;\n } catch {\n loadedProject = undefined;\n }\n }\n\n for (const file of files.filter((entry) => entry.endsWith(\".jsonl\"))) {\n const filePath = join(projectDir, file);\n const rawEvents = await readJsonl(filePath);\n if (rawEvents.length === 0) continue;\n\n const events = rawEvents\n .sort((left, right) => {\n const leftSeq = left.seq ?? 0;\n const rightSeq = right.seq ?? 0;\n if (leftSeq !== rightSeq) return leftSeq - rightSeq;\n return left.ts - right.ts;\n })\n .map((event) => {\n const seq = event.seq ?? this.nextSeq++;\n this.nextSeq = Math.max(this.nextSeq, seq + 1);\n return {\n ...event,\n seq,\n };\n });\n\n const first = events[0];\n const last = events[events.length - 1];\n if (!first || !last) continue;\n const key = buildSessionKey(first);\n this.sessions.set(key, {\n key,\n project_hash: first.project_hash,\n engine: first.engine,\n session_id: first.session_id,\n cwd: first.cwd,\n last_event_at: last.ts,\n last_seq: last.seq,\n event_count: events.length,\n caps: last.caps,\n events,\n filePath,\n });\n\n if (!loadedProject) {\n const identity = this.getProjectIdentity(first.cwd);\n loadedProject = {\n project_hash: first.project_hash,\n name: identity.name,\n root: identity.root,\n last_active: last.ts,\n session_count: 0,\n };\n } else {\n loadedProject.last_active = Math.max(loadedProject.last_active, last.ts);\n }\n }\n\n if (loadedProject) {\n loadedProject.session_count = [...this.sessions.values()].filter(\n (session) => session.project_hash === projectHash,\n ).length;\n this.projects.set(projectHash, loadedProject);\n }\n }\n }\n}\n","import { randomUUID } from \"node:crypto\";\nimport { existsSync, realpathSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type { EventV1 } from \"@holdpoint/live-protocol\";\n\nconst DEFAULT_LOCK_TTL_MS = 30_000;\n\ninterface FileLock {\n sessionKey: string;\n engine: string;\n sessionId: string;\n expiresAt: number;\n}\n\ntype LockEvent = Extract<EventV1, { type: \"tool_pre\" | \"tool_post\" | \"tool_failure\" }>;\n\nfunction buildSessionKey(event: Pick<EventV1, \"project_hash\" | \"engine\" | \"session_id\">): string {\n return `${event.project_hash}:${event.engine}:${event.session_id}`;\n}\n\nfunction normalizeWriteTarget(cwd: string, target: string): string {\n const resolved = resolve(cwd, target);\n return existsSync(resolved) ? realpathSync.native(resolved) : resolved;\n}\n\nfunction getWriteTargets(event: LockEvent, activeTargets: Map<string, string[]>): string[] {\n const toolKey = `${buildSessionKey(event)}:${event.payload.tool_use_id}`;\n if (event.type === \"tool_pre\") {\n return (event.payload.write_targets ?? []).map((target: string) =>\n normalizeWriteTarget(event.cwd, target),\n );\n }\n\n return (\n (event.type === \"tool_post\"\n ? event.payload.write_targets?.map((target: string) =>\n normalizeWriteTarget(event.cwd, target),\n )\n : undefined) ??\n activeTargets.get(toolKey) ??\n []\n );\n}\n\nexport class ConflictTracker {\n private readonly lockTtlMs: number;\n private readonly locksByProject = new Map<string, Map<string, FileLock>>();\n private readonly activeTargets = new Map<string, string[]>();\n private readonly emittedConflicts = new Map<string, number>();\n\n constructor(lockTtlMs = DEFAULT_LOCK_TTL_MS) {\n this.lockTtlMs = lockTtlMs;\n }\n\n handleEvent(event: EventV1): EventV1[] {\n switch (event.type) {\n case \"tool_pre\":\n return this.handleToolPre(event);\n case \"tool_post\":\n case \"tool_failure\":\n this.releaseLocks(event);\n return [];\n default:\n return [];\n }\n }\n\n private handleToolPre(event: Extract<EventV1, { type: \"tool_pre\" }>): EventV1[] {\n const sessionKey = buildSessionKey(event);\n const toolKey = `${sessionKey}:${event.payload.tool_use_id}`;\n const writeTargets = getWriteTargets(event, this.activeTargets);\n if (writeTargets.length === 0) {\n return [];\n }\n\n this.activeTargets.set(toolKey, writeTargets);\n const projectLocks = this.getProjectLocks(event.project_hash);\n this.pruneExpiredLocks(projectLocks, event.ts);\n\n const conflicts: EventV1[] = [];\n for (const filePath of writeTargets) {\n const existing = projectLocks.get(filePath);\n if (!existing) {\n projectLocks.set(filePath, {\n sessionKey,\n engine: event.engine,\n sessionId: event.session_id,\n expiresAt: event.ts + this.lockTtlMs,\n });\n continue;\n }\n\n if (existing.sessionKey === sessionKey) {\n existing.expiresAt = event.ts + this.lockTtlMs;\n continue;\n }\n\n const dedupeKey = `${event.project_hash}:${filePath}:${existing.sessionKey}:${sessionKey}`;\n const previousEmission = this.emittedConflicts.get(dedupeKey) ?? 0;\n if (previousEmission > event.ts) {\n continue;\n }\n\n this.emittedConflicts.set(dedupeKey, event.ts + this.lockTtlMs);\n conflicts.push({\n v: 1,\n id: randomUUID(),\n ts: event.ts,\n engine: event.engine,\n session_id: event.session_id,\n project_hash: event.project_hash,\n cwd: event.cwd,\n type: \"conflict\",\n payload: {\n kind: \"file_write\",\n file_path: filePath,\n holder: {\n engine: existing.engine,\n session_id: existing.sessionId,\n },\n requester: {\n engine: event.engine,\n session_id: event.session_id,\n },\n },\n });\n }\n\n return conflicts;\n }\n\n private releaseLocks(event: Extract<EventV1, { type: \"tool_post\" | \"tool_failure\" }>): void {\n const sessionKey = buildSessionKey(event);\n const toolKey = `${sessionKey}:${event.payload.tool_use_id}`;\n const projectLocks = this.getProjectLocks(event.project_hash);\n const writeTargets = getWriteTargets(event, this.activeTargets);\n\n for (const filePath of writeTargets) {\n const existing = projectLocks.get(filePath);\n if (existing?.sessionKey === sessionKey) {\n projectLocks.delete(filePath);\n }\n }\n\n this.activeTargets.delete(toolKey);\n this.pruneExpiredLocks(projectLocks, event.ts);\n }\n\n private getProjectLocks(projectHash: string): Map<string, FileLock> {\n let existing = this.locksByProject.get(projectHash);\n if (!existing) {\n existing = new Map<string, FileLock>();\n this.locksByProject.set(projectHash, existing);\n }\n return existing;\n }\n\n private pruneExpiredLocks(projectLocks: Map<string, FileLock>, now: number): void {\n for (const [filePath, lock] of projectLocks.entries()) {\n if (lock.expiresAt <= now) {\n projectLocks.delete(filePath);\n }\n }\n\n for (const [key, expiresAt] of this.emittedConflicts.entries()) {\n if (expiresAt <= now) {\n this.emittedConflicts.delete(key);\n }\n }\n }\n}\n","import { execFileSync } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { realpathSync } from \"node:fs\";\nimport { basename } from \"node:path\";\n\nexport interface ProjectIdentity {\n hash: string;\n name: string;\n root: string;\n}\n\nfunction sha12(value: string): string {\n return createHash(\"sha256\").update(value).digest(\"hex\").slice(0, 12);\n}\n\nexport function identifyProject(cwd: string): ProjectIdentity {\n // Three layers of fallback, in order of preference:\n // 1. git rev-parse --show-toplevel + realpath — canonical: matches\n // whatever git considers the repo root, normalised through symlinks.\n // 2. realpath(cwd) — cwd exists but isn't\n // a git repo (or git binary missing); use the resolved cwd as root.\n // 3. raw cwd string — cwd doesn't exist\n // on disk anymore (deleted/renamed project; common when replaying\n // old pending events from `~/.holdpoint/spool/pending`). The daemon\n // still needs a stable identity so the event can be stored and\n // surfaced; the hash/name are based on the literal path.\n //\n // This function MUST NOT throw. The daemon's startup replay loop ingests\n // historical events from disk and crashing here used to brick startup\n // entirely whenever a project path had been renamed since the events\n // were spooled — see https://github.com/holdpoint-dev/holdpoint/issues\n // (daemon-unavailable on stale pending events).\n let root: string;\n try {\n root = realpathSync(\n execFileSync(\"git\", [\"rev-parse\", \"--show-toplevel\"], {\n cwd,\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }).trim(),\n );\n } catch {\n try {\n root = realpathSync(cwd);\n } catch {\n // cwd doesn't exist on disk — use the raw path string as identity.\n root = cwd;\n }\n }\n return {\n hash: sha12(root),\n name: basename(root) || root,\n root,\n };\n}\n","import type { EventV1 } from \"@holdpoint/live-protocol\";\nimport { buildSessionKey } from \"./store.js\";\n\nexport interface Subscription {\n scope: \"project\" | \"session\" | \"all\";\n key?: string;\n}\n\nexport function matchesSubscription(subscription: Subscription, event: EventV1): boolean {\n switch (subscription.scope) {\n case \"all\":\n return true;\n case \"project\":\n return subscription.key === event.project_hash;\n case \"session\":\n return subscription.key === buildSessionKey(event);\n }\n}\n","import {\n removeDaemonLock,\n createDaemonLock,\n findFreePort,\n readHealthyDaemonLock,\n type DaemonLock,\n writeDaemonLockExclusive,\n resolveHoldpointHome,\n} from \"./singleton.js\";\nimport { startLiveServer, type RunningLiveServer } from \"./server.js\";\nimport { LiveStore } from \"./store.js\";\n\nexport class DaemonAlreadyRunningError extends Error {\n readonly info: DaemonLock;\n\n constructor(info: DaemonLock) {\n super(`Holdpoint daemon already running on port ${info.port}`);\n this.info = info;\n }\n}\n\nexport interface StartDaemonProcessOptions {\n homeDir?: string;\n port?: number;\n version: string;\n}\n\nexport interface StartedDaemon {\n info: DaemonLock;\n server: RunningLiveServer;\n store: LiveStore;\n close(): Promise<void>;\n closed: Promise<void>;\n}\n\nexport async function startDaemonProcess(\n options: StartDaemonProcessOptions,\n): Promise<StartedDaemon> {\n const existing = await readHealthyDaemonLock(options.homeDir);\n if (existing) {\n throw new DaemonAlreadyRunningError(existing);\n }\n\n const port = options.port ?? (await findFreePort());\n const info = createDaemonLock(port, options.version);\n writeDaemonLockExclusive(info, options.homeDir);\n\n const store = await LiveStore.create(resolveHoldpointHome(options.homeDir));\n await store.replayPending();\n\n let server: RunningLiveServer;\n try {\n server = await startLiveServer({\n port,\n token: info.token,\n version: options.version,\n startedAt: info.started_at,\n store,\n });\n } catch (error) {\n removeDaemonLock(options.homeDir, info.token);\n throw error;\n }\n\n let closed = false;\n const cleanup = async (): Promise<void> => {\n if (closed) return;\n closed = true;\n removeDaemonLock(options.homeDir, info.token);\n await server.close();\n };\n\n const onSignal = (): void => {\n void cleanup().finally(() => process.exit(0));\n };\n\n process.once(\"SIGTERM\", onSignal);\n process.once(\"SIGINT\", onSignal);\n\n return {\n info,\n server,\n store,\n close: cleanup,\n closed: server.closed.finally(() => {\n process.off(\"SIGTERM\", onSignal);\n process.off(\"SIGINT\", onSignal);\n }),\n };\n}\n\nexport {\n createDaemonLock,\n ensureHoldpointHome,\n findFreePort,\n getDaemonLockPath,\n isProcessAlive,\n readDaemonLock,\n readHealthyDaemonLock,\n removeDaemonLock,\n resolveHoldpointHome,\n waitForDaemonHealthy,\n writeDaemonLockExclusive,\n} from \"./singleton.js\";\nexport { identifyProject } from \"./project-identity.js\";\nexport { startLiveServer } from \"./server.js\";\nexport { buildSessionKey, LiveStore } from \"./store.js\";\nexport type { ProjectIdentity } from \"./project-identity.js\";\nexport type { RunningLiveServer } from \"./server.js\";\nexport type { DaemonLock } from \"./singleton.js\";\n"],"mappings":"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","names":["createServer","randomUUID","existsSync","writeFileSync","join","resolve","EventV1Schema","existsSync","join","existsSync","resolve","realpathSync","buildSessionKey","join","existsSync","buildSessionKey","join","randomUUID","resolve","existsSync","createServer","writeFileSync","EventV1Schema"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */
|
|
2
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial}}}@layer theme{:root,:host{--font-sans:Inter, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;--font-mono:"JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;--color-red-300:oklch(80.8% .114 19.571);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-black:#000;--spacing:.25rem;--container-xs:20rem;--container-sm:24rem;--container-3xl:48rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--font-weight-medium:500;--font-weight-semibold:600;--tracking-tight:-.025em;--tracking-wide:.025em;--leading-relaxed:1.625;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--animate-spin:spin 1s linear infinite;--animate-ping:ping 1s cubic-bezier(0, 0, .2, 1) infinite;--blur-sm:8px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--radius:.75rem;--color-background:#0b0f14;--color-foreground:#f5f1e8;--color-card:#14181f;--color-card-foreground:#f5f1e8;--color-popover:#181d25;--color-popover-foreground:#f5f1e8;--color-muted:#1b212a;--color-muted-foreground:#8b929c;--color-border:#232b36;--color-input:#2a323d;--color-ring:#e04e2a;--color-accent:#e04e2a;--color-accent-foreground:#fdf6f3;--color-success:#2fbf71;--color-warning:#f6c453;--color-danger:#ff6b6b;--color-info:#5aa9e6;--color-canvas:#0b0f14;--color-node:#14181f;--color-node-border:#232b36;--color-bone:#f5f1e8;--color-stone:#8b929c}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}*{box-sizing:border-box}html,body,#root{height:100%;margin:0}body{background:var(--color-background);color:var(--color-foreground);font-family:var(--font-sans);-webkit-font-smoothing:antialiased}button,input,textarea{font:inherit}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-thumb{background:var(--color-border);border:2px solid var(--color-background);border-radius:9999px}::-webkit-scrollbar-thumb:hover{background:var(--color-input)}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.inset-0{inset:calc(var(--spacing) * 0)}.inset-y-2{inset-block:calc(var(--spacing) * 2)}.top-1\/2{top:50%}.right-3{right:calc(var(--spacing) * 3)}.left-0{left:calc(var(--spacing) * 0)}.left-1\/2{left:50%}.left-2{left:calc(var(--spacing) * 2)}.z-50{z-index:50}.mx-2{margin-inline:calc(var(--spacing) * 2)}.mx-auto{margin-inline:auto}.my-1{margin-block:calc(var(--spacing) * 1)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-2\.5{margin-top:calc(var(--spacing) * 2.5)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-5{margin-top:calc(var(--spacing) * 5)}.mt-auto{margin-top:auto}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.ml-1{margin-left:calc(var(--spacing) * 1)}.ml-6{margin-left:calc(var(--spacing) * 6)}.ml-auto{margin-left:auto}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.inline-flex{display:inline-flex}.size-1\.5{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5)}.size-2{width:calc(var(--spacing) * 2);height:calc(var(--spacing) * 2)}.size-2\.5{width:calc(var(--spacing) * 2.5);height:calc(var(--spacing) * 2.5)}.size-3\.5{width:calc(var(--spacing) * 3.5);height:calc(var(--spacing) * 3.5)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.size-6{width:calc(var(--spacing) * 6);height:calc(var(--spacing) * 6)}.size-7{width:calc(var(--spacing) * 7);height:calc(var(--spacing) * 7)}.size-8{width:calc(var(--spacing) * 8);height:calc(var(--spacing) * 8)}.size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.size-11{width:calc(var(--spacing) * 11);height:calc(var(--spacing) * 11)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-2\.5{height:calc(var(--spacing) * 2.5)}.h-3{height:calc(var(--spacing) * 3)}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-6{height:calc(var(--spacing) * 6)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.h-full{height:100%}.h-px{height:1px}.max-h-32{max-height:calc(var(--spacing) * 32)}.max-h-\[50vh\]{max-height:50vh}.max-h-\[60vh\]{max-height:60vh}.min-h-0{min-height:calc(var(--spacing) * 0)}.w-0\.5{width:calc(var(--spacing) * .5)}.w-2\.5{width:calc(var(--spacing) * 2.5)}.w-3{width:calc(var(--spacing) * 3)}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-4{width:calc(var(--spacing) * 4)}.w-6{width:calc(var(--spacing) * 6)}.w-10{width:calc(var(--spacing) * 10)}.w-72{width:calc(var(--spacing) * 72)}.w-\[min\(720px\,92vw\)\]{width:min(720px,92vw)}.w-fit{width:fit-content}.w-full{width:100%}.w-px{width:1px}.max-w-3xl{max-width:var(--container-3xl)}.max-w-sm{max-width:var(--container-sm)}.max-w-xs{max-width:var(--container-xs)}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-56{min-width:calc(var(--spacing) * 56)}.flex-1{flex:1}.flex-shrink-0,.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.rotate-180{rotate:180deg}.animate-ping{animation:var(--animate-ping)}.animate-spin{animation:var(--animate-spin)}.cursor-pointer{cursor:pointer}.resize-none{resize:none}.appearance-none{appearance:none}.\[grid-template-columns\:repeat\(auto-fill\,minmax\(360px\,1fr\)\)\]{grid-template-columns:repeat(auto-fill,minmax(360px,1fr))}.\[grid-template-columns\:repeat\(auto-fit\,minmax\(180px\,1fr\)\)\]{grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-\[minmax\(280px\,360px\)_1fr\]{grid-template-columns:minmax(280px,360px) 1fr}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.content-start{align-content:flex-start}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1.5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:var(--radius)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-accent\/30{border-color:#e04e2a4d}@supports (color:color-mix(in lab, red, red)){.border-accent\/30{border-color:color-mix(in oklab, var(--color-accent) 30%, transparent)}}.border-accent\/40{border-color:#e04e2a66}@supports (color:color-mix(in lab, red, red)){.border-accent\/40{border-color:color-mix(in oklab, var(--color-accent) 40%, transparent)}}.border-amber-500\/30{border-color:#f99c004d}@supports (color:color-mix(in lab, red, red)){.border-amber-500\/30{border-color:color-mix(in oklab, var(--color-amber-500) 30%, transparent)}}.border-border{border-color:var(--color-border)}.border-danger\/30{border-color:#ff6b6b4d}@supports (color:color-mix(in lab, red, red)){.border-danger\/30{border-color:color-mix(in oklab, var(--color-danger) 30%, transparent)}}.border-danger\/40{border-color:#ff6b6b66}@supports (color:color-mix(in lab, red, red)){.border-danger\/40{border-color:color-mix(in oklab, var(--color-danger) 40%, transparent)}}.border-green-500\/30{border-color:#00c7584d}@supports (color:color-mix(in lab, red, red)){.border-green-500\/30{border-color:color-mix(in oklab, var(--color-green-500) 30%, transparent)}}.border-info\/40{border-color:#5aa9e666}@supports (color:color-mix(in lab, red, red)){.border-info\/40{border-color:color-mix(in oklab, var(--color-info) 40%, transparent)}}.border-input{border-color:var(--color-input)}.border-node-border{border-color:var(--color-node-border)}.border-red-500\/30{border-color:#fb2c364d}@supports (color:color-mix(in lab, red, red)){.border-red-500\/30{border-color:color-mix(in oklab, var(--color-red-500) 30%, transparent)}}.border-stone\/30{border-color:#8b929c4d}@supports (color:color-mix(in lab, red, red)){.border-stone\/30{border-color:color-mix(in oklab, var(--color-stone) 30%, transparent)}}.border-success\/40{border-color:#2fbf7166}@supports (color:color-mix(in lab, red, red)){.border-success\/40{border-color:color-mix(in oklab, var(--color-success) 40%, transparent)}}.border-warning\/40{border-color:#f6c45366}@supports (color:color-mix(in lab, red, red)){.border-warning\/40{border-color:color-mix(in oklab, var(--color-warning) 40%, transparent)}}.bg-accent{background-color:var(--color-accent)}.bg-accent\/10{background-color:#e04e2a1a}@supports (color:color-mix(in lab, red, red)){.bg-accent\/10{background-color:color-mix(in oklab, var(--color-accent) 10%, transparent)}}.bg-accent\/15{background-color:#e04e2a26}@supports (color:color-mix(in lab, red, red)){.bg-accent\/15{background-color:color-mix(in oklab, var(--color-accent) 15%, transparent)}}.bg-amber-500\/10{background-color:#f99c001a}@supports (color:color-mix(in lab, red, red)){.bg-amber-500\/10{background-color:color-mix(in oklab, var(--color-amber-500) 10%, transparent)}}.bg-background\/40{background-color:#0b0f1466}@supports (color:color-mix(in lab, red, red)){.bg-background\/40{background-color:color-mix(in oklab, var(--color-background) 40%, transparent)}}.bg-background\/60{background-color:#0b0f1499}@supports (color:color-mix(in lab, red, red)){.bg-background\/60{background-color:color-mix(in oklab, var(--color-background) 60%, transparent)}}.bg-black\/60{background-color:#0009}@supports (color:color-mix(in lab, red, red)){.bg-black\/60{background-color:color-mix(in oklab, var(--color-black) 60%, transparent)}}.bg-border{background-color:var(--color-border)}.bg-canvas{background-color:var(--color-canvas)}.bg-card{background-color:var(--color-card)}.bg-card\/40{background-color:#14181f66}@supports (color:color-mix(in lab, red, red)){.bg-card\/40{background-color:color-mix(in oklab, var(--color-card) 40%, transparent)}}.bg-danger{background-color:var(--color-danger)}.bg-danger\/10{background-color:#ff6b6b1a}@supports (color:color-mix(in lab, red, red)){.bg-danger\/10{background-color:color-mix(in oklab, var(--color-danger) 10%, transparent)}}.bg-danger\/15{background-color:#ff6b6b26}@supports (color:color-mix(in lab, red, red)){.bg-danger\/15{background-color:color-mix(in oklab, var(--color-danger) 15%, transparent)}}.bg-green-500{background-color:var(--color-green-500)}.bg-green-500\/10{background-color:#00c7581a}@supports (color:color-mix(in lab, red, red)){.bg-green-500\/10{background-color:color-mix(in oklab, var(--color-green-500) 10%, transparent)}}.bg-info{background-color:var(--color-info)}.bg-info\/10{background-color:#5aa9e61a}@supports (color:color-mix(in lab, red, red)){.bg-info\/10{background-color:color-mix(in oklab, var(--color-info) 10%, transparent)}}.bg-info\/15{background-color:#5aa9e626}@supports (color:color-mix(in lab, red, red)){.bg-info\/15{background-color:color-mix(in oklab, var(--color-info) 15%, transparent)}}.bg-muted{background-color:var(--color-muted)}.bg-muted-foreground{background-color:var(--color-muted-foreground)}.bg-muted\/40{background-color:#1b212a66}@supports (color:color-mix(in lab, red, red)){.bg-muted\/40{background-color:color-mix(in oklab, var(--color-muted) 40%, transparent)}}.bg-node{background-color:var(--color-node)}.bg-node-border{background-color:var(--color-node-border)}.bg-popover{background-color:var(--color-popover)}.bg-red-500{background-color:var(--color-red-500)}.bg-red-500\/10{background-color:#fb2c361a}@supports (color:color-mix(in lab, red, red)){.bg-red-500\/10{background-color:color-mix(in oklab, var(--color-red-500) 10%, transparent)}}.bg-stone\/10{background-color:#8b929c1a}@supports (color:color-mix(in lab, red, red)){.bg-stone\/10{background-color:color-mix(in oklab, var(--color-stone) 10%, transparent)}}.bg-success{background-color:var(--color-success)}.bg-success\/10{background-color:#2fbf711a}@supports (color:color-mix(in lab, red, red)){.bg-success\/10{background-color:color-mix(in oklab, var(--color-success) 10%, transparent)}}.bg-success\/15{background-color:#2fbf7126}@supports (color:color-mix(in lab, red, red)){.bg-success\/15{background-color:color-mix(in oklab, var(--color-success) 15%, transparent)}}.bg-transparent{background-color:#0000}.bg-warning\/15{background-color:#f6c45326}@supports (color:color-mix(in lab, red, red)){.bg-warning\/15{background-color:color-mix(in oklab, var(--color-warning) 15%, transparent)}}.p-0{padding:calc(var(--spacing) * 0)}.p-1{padding:calc(var(--spacing) * 1)}.p-2{padding:calc(var(--spacing) * 2)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-6{padding:calc(var(--spacing) * 6)}.px-1{padding-inline:calc(var(--spacing) * 1)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0{padding-block:calc(var(--spacing) * 0)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-5{padding-block:calc(var(--spacing) * 5)}.py-6{padding-block:calc(var(--spacing) * 6)}.py-10{padding-block:calc(var(--spacing) * 10)}.py-12{padding-block:calc(var(--spacing) * 12)}.pt-0{padding-top:calc(var(--spacing) * 0)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pr-2{padding-right:calc(var(--spacing) * 2)}.pr-9{padding-right:calc(var(--spacing) * 9)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pl-4{padding-left:calc(var(--spacing) * 4)}.pl-7{padding-left:calc(var(--spacing) * 7)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-accent{color:var(--color-accent)}.text-accent-foreground{color:var(--color-accent-foreground)}.text-amber-400{color:var(--color-amber-400)}.text-bone{color:var(--color-bone)}.text-card-foreground{color:var(--color-card-foreground)}.text-danger{color:var(--color-danger)}.text-danger\/80{color:#ff6b6bcc}@supports (color:color-mix(in lab, red, red)){.text-danger\/80{color:color-mix(in oklab, var(--color-danger) 80%, transparent)}}.text-foreground{color:var(--color-foreground)}.text-foreground\/70{color:#f5f1e8b3}@supports (color:color-mix(in lab, red, red)){.text-foreground\/70{color:color-mix(in oklab, var(--color-foreground) 70%, transparent)}}.text-foreground\/80{color:#f5f1e8cc}@supports (color:color-mix(in lab, red, red)){.text-foreground\/80{color:color-mix(in oklab, var(--color-foreground) 80%, transparent)}}.text-foreground\/90{color:#f5f1e8e6}@supports (color:color-mix(in lab, red, red)){.text-foreground\/90{color:color-mix(in oklab, var(--color-foreground) 90%, transparent)}}.text-green-400{color:var(--color-green-400)}.text-info{color:var(--color-info)}.text-muted-foreground{color:var(--color-muted-foreground)}.text-muted-foreground\/70{color:#8b929cb3}@supports (color:color-mix(in lab, red, red)){.text-muted-foreground\/70{color:color-mix(in oklab, var(--color-muted-foreground) 70%, transparent)}}.text-popover-foreground{color:var(--color-popover-foreground)}.text-red-300\/80{color:#ffa3a3cc}@supports (color:color-mix(in lab, red, red)){.text-red-300\/80{color:color-mix(in oklab, var(--color-red-300) 80%, transparent)}}.text-red-400{color:var(--color-red-400)}.text-red-400\/60{color:#ff656899}@supports (color:color-mix(in lab, red, red)){.text-red-400\/60{color:color-mix(in oklab, var(--color-red-400) 60%, transparent)}}.text-stone{color:var(--color-stone)}.text-stone\/30{color:#8b929c4d}@supports (color:color-mix(in lab, red, red)){.text-stone\/30{color:color-mix(in oklab, var(--color-stone) 30%, transparent)}}.text-stone\/40{color:#8b929c66}@supports (color:color-mix(in lab, red, red)){.text-stone\/40{color:color-mix(in oklab, var(--color-stone) 40%, transparent)}}.text-stone\/50{color:#8b929c80}@supports (color:color-mix(in lab, red, red)){.text-stone\/50{color:color-mix(in oklab, var(--color-stone) 50%, transparent)}}.text-stone\/60{color:#8b929c99}@supports (color:color-mix(in lab, red, red)){.text-stone\/60{color:color-mix(in oklab, var(--color-stone) 60%, transparent)}}.text-stone\/70{color:#8b929cb3}@supports (color:color-mix(in lab, red, red)){.text-stone\/70{color:color-mix(in oklab, var(--color-stone) 70%, transparent)}}.text-success{color:var(--color-success)}.text-warning{color:var(--color-warning)}.uppercase{text-transform:uppercase}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.accent-\[var\(--color-info\)\]{accent-color:var(--color-info)}.opacity-60{opacity:.6}.opacity-75{opacity:.75}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-blur-sm{--tw-backdrop-blur:blur(var(--blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.placeholder\:text-muted-foreground::placeholder{color:var(--color-muted-foreground)}@media (hover:hover){.hover\:border-accent:hover{border-color:var(--color-accent)}.hover\:bg-accent\/90:hover{background-color:#e04e2ae6}@supports (color:color-mix(in lab, red, red)){.hover\:bg-accent\/90:hover{background-color:color-mix(in oklab, var(--color-accent) 90%, transparent)}}.hover\:bg-danger\/20:hover{background-color:#ff6b6b33}@supports (color:color-mix(in lab, red, red)){.hover\:bg-danger\/20:hover{background-color:color-mix(in oklab, var(--color-danger) 20%, transparent)}}.hover\:bg-input:hover{background-color:var(--color-input)}.hover\:bg-muted:hover{background-color:var(--color-muted)}.hover\:bg-muted\/50:hover{background-color:#1b212a80}@supports (color:color-mix(in lab, red, red)){.hover\:bg-muted\/50:hover{background-color:color-mix(in oklab, var(--color-muted) 50%, transparent)}}.hover\:bg-node-border\/30:hover{background-color:#232b364d}@supports (color:color-mix(in lab, red, red)){.hover\:bg-node-border\/30:hover{background-color:color-mix(in oklab, var(--color-node-border) 30%, transparent)}}.hover\:bg-success\/20:hover{background-color:#2fbf7133}@supports (color:color-mix(in lab, red, red)){.hover\:bg-success\/20:hover{background-color:color-mix(in oklab, var(--color-success) 20%, transparent)}}.hover\:text-bone:hover{color:var(--color-bone)}.hover\:text-foreground:hover{color:var(--color-foreground)}}.focus\:bg-muted:focus{background-color:var(--color-muted)}.focus-visible\:border-ring\/60:focus-visible{border-color:#e04e2a99}@supports (color:color-mix(in lab, red, red)){.focus-visible\:border-ring\/60:focus-visible{border-color:color-mix(in oklab, var(--color-ring) 60%, transparent)}}.focus-visible\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\:ring-ring\/40:focus-visible{--tw-ring-color:#e04e2a66}@supports (color:color-mix(in lab, red, red)){.focus-visible\:ring-ring\/40:focus-visible{--tw-ring-color:color-mix(in oklab, var(--color-ring) 40%, transparent)}}.focus-visible\:ring-ring\/60:focus-visible{--tw-ring-color:#e04e2a99}@supports (color:color-mix(in lab, red, red)){.focus-visible\:ring-ring\/60:focus-visible{--tw-ring-color:color-mix(in oklab, var(--color-ring) 60%, transparent)}}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.data-\[state\=active\]\:bg-card[data-state=active]{background-color:var(--color-card)}.data-\[state\=active\]\:text-foreground[data-state=active]{color:var(--color-foreground)}.data-\[state\=active\]\:shadow-sm[data-state=active]{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.data-\[state\=checked\]\:text-foreground[data-state=checked]{color:var(--color-foreground)}@media (width>=64rem){.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}.\[\&_svg\]\:size-4 svg{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes ping{75%,to{opacity:0;transform:scale(2)}}
|